3 { This file contains input colorspace conversion routines. }
5 { Original : jccolor.c ; Copyright (C) 1991-1996, Thomas G. Lane. }
18 { Module initialization routine for input colorspace conversion. }
21 procedure jinit_color_converter (cinfo
: j_compress_ptr
);
27 INT32_FIELD
= array[0..MaxInt
div SizeOf(INT32
) - 1] of INT32
;
28 INT32_FIELD_PTR
= ^INT32_FIELD
;
31 my_cconvert_ptr
= ^my_color_converter
;
32 my_color_converter
= record
33 pub
: jpeg_color_converter
; { public fields }
35 { Private state for RGB -> YCC conversion }
36 rgb_ycc_tab
: INT32_FIELD_PTR
; { => table for RGB to YCbCr conversion }
37 end; {my_color_converter;}
40 {*************** RGB -> YCbCr conversion: most common case *************}
43 YCbCr is defined per CCIR 601-1, except that Cb and Cr are
44 normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
45 The conversion equations to be implemented are therefore
46 Y = 0.29900 * R + 0.58700 * G + 0.11400 * B
47 Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE
48 Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE
49 (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
50 Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2,
51 rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and
52 negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0)
53 were not represented exactly. Now we sacrifice exact representation of
54 maximum red and maximum blue in order to get exact grayscales.
56 To avoid floating-point arithmetic, we represent the fractional constants
57 as integers scaled up by 2^16 (about 4 digits precision); we have to divide
58 the products by 2^16, with appropriate rounding, to get the correct answer.
60 For even more speed, we avoid doing any multiplications in the inner loop
61 by precalculating the constants times R,G,B for all possible values.
62 For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
63 for 12-bit samples it is still acceptable. It's not very reasonable for
64 16-bit samples, but if you want lossless storage you shouldn't be changing
66 The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included
67 in the tables to save adding them separately in the inner loop. }
69 SCALEBITS
= 16; { speediest right-shift on some machines }
70 CBCR_OFFSET
= INT32(CENTERJSAMPLE
shl SCALEBITS
);
71 ONE_HALF
= INT32(1) shl (SCALEBITS
-1);
74 { We allocate one big table and divide it up into eight parts, instead of
75 doing eight alloc_small requests. This lets us use a single table base
76 address, which can be held in a register in the inner loops on many
77 machines (more than can hold all eight addresses, anyway). }
79 R_Y_OFF
= 0; { offset to R => Y section }
80 G_Y_OFF
= 1*(MAXJSAMPLE
+1); { offset to G => Y section }
81 B_Y_OFF
= 2*(MAXJSAMPLE
+1); { etc. }
82 R_CB_OFF
= 3*(MAXJSAMPLE
+1);
83 G_CB_OFF
= 4*(MAXJSAMPLE
+1);
84 B_CB_OFF
= 5*(MAXJSAMPLE
+1);
85 R_CR_OFF
= B_CB_OFF
; { B=>Cb, R=>Cr are the same }
86 G_CR_OFF
= 6*(MAXJSAMPLE
+1);
87 B_CR_OFF
= 7*(MAXJSAMPLE
+1);
88 TABLE_SIZE
= 8*(MAXJSAMPLE
+1);
91 { Initialize for RGB->YCC colorspace conversion. }
94 procedure rgb_ycc_start (cinfo
: j_compress_ptr
);
96 FIX_0_29900
= INT32(Round(0.29900 * (1 shl SCALEBITS
)));
97 FIX_0_58700
= INT32(Round(0.58700 * (1 shl SCALEBITS
)));
98 FIX_0_11400
= INT32(Round(0.11400 * (1 shl SCALEBITS
)));
99 FIX_0_16874
= INT32(Round(0.16874 * (1 shl SCALEBITS
)));
100 FIX_0_33126
= INT32(Round(0.33126 * (1 shl SCALEBITS
)));
101 FIX_0_50000
= INT32(Round(0.50000 * (1 shl SCALEBITS
)));
102 FIX_0_41869
= INT32(Round(0.41869 * (1 shl SCALEBITS
)));
103 FIX_0_08131
= INT32(Round(0.08131 * (1 shl SCALEBITS
)));
105 cconvert
: my_cconvert_ptr
;
106 rgb_ycc_tab
: INT32_FIELD_PTR
;
109 cconvert
:= my_cconvert_ptr (cinfo
^.cconvert
);
111 { Allocate and fill in the conversion tables. }
112 rgb_ycc_tab
:= INT32_FIELD_PTR(
113 cinfo
^.mem
^.alloc_small (j_common_ptr(cinfo
), JPOOL_IMAGE
,
114 (TABLE_SIZE
* SIZEOF(INT32
))) );
115 cconvert
^.rgb_ycc_tab
:= rgb_ycc_tab
;
117 for i
:= 0 to MAXJSAMPLE
do
119 rgb_ycc_tab
^[i
+R_Y_OFF
] := FIX_0_29900
* i
;
120 rgb_ycc_tab
^[i
+G_Y_OFF
] := FIX_0_58700
* i
;
121 rgb_ycc_tab
^[i
+B_Y_OFF
] := FIX_0_11400
* i
+ ONE_HALF
;
122 rgb_ycc_tab
^[i
+R_CB_OFF
] := (-FIX_0_16874
) * i
;
123 rgb_ycc_tab
^[i
+G_CB_OFF
] := (-FIX_0_33126
) * i
;
124 { We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
125 This ensures that the maximum output will round to MAXJSAMPLE
126 not MAXJSAMPLE+1, and thus that we don't have to range-limit. }
128 rgb_ycc_tab
^[i
+B_CB_OFF
] := FIX_0_50000
* i
+ CBCR_OFFSET
+ ONE_HALF
-1;
129 { B=>Cb and R=>Cr tables are the same
130 rgb_ycc_tab^[i+R_CR_OFF] := FIX_0_50000 * i + CBCR_OFFSET + ONE_HALF-1;
132 rgb_ycc_tab
^[i
+G_CR_OFF
] := (-FIX_0_41869
) * i
;
133 rgb_ycc_tab
^[i
+B_CR_OFF
] := (-FIX_0_08131
) * i
;
138 { Convert some rows of samples to the JPEG colorspace.
140 Note that we change from the application's interleaved-pixel format
141 to our internal noninterleaved, one-plane-per-component format.
142 The input buffer is therefore three times as wide as the output buffer.
144 A starting row offset is provided only for the output buffer. The caller
145 can easily adjust the passed input_buf value to accommodate any row
146 offset required on that side. }
149 procedure rgb_ycc_convert (cinfo
: j_compress_ptr
;
150 input_buf
: JSAMPARRAY
;
151 output_buf
: JSAMPIMAGE
;
152 output_row
: JDIMENSION
;
155 cconvert
: my_cconvert_ptr
;
156 {register} r
, g
, b
: int
;
157 {register} ctab
: INT32_FIELD_PTR
;
158 {register} inptr
: JSAMPROW
;
159 {register} outptr0
, outptr1
, outptr2
: JSAMPROW
;
160 {register} col
: JDIMENSION
;
161 num_cols
: JDIMENSION
;
163 cconvert
:= my_cconvert_ptr (cinfo
^.cconvert
);
164 ctab
:= cconvert
^.rgb_ycc_tab
;
165 num_cols
:= cinfo
^.image_width
;
167 while (num_rows
> 0) do
170 inptr
:= input_buf
^[0];
171 Inc(JSAMPROW_PTR(input_buf
));
172 outptr0
:= output_buf
^[0]^[output_row
];
173 outptr1
:= output_buf
^[1]^[output_row
];
174 outptr2
:= output_buf
^[2]^[output_row
];
176 for col
:= 0 to pred(num_cols
) do
178 r
:= GETJSAMPLE(inptr
^[RGB_RED
]);
179 g
:= GETJSAMPLE(inptr
^[RGB_GREEN
]);
180 b
:= GETJSAMPLE(inptr
^[RGB_BLUE
]);
181 Inc(JSAMPLE_PTR(inptr
), RGB_PIXELSIZE
);
182 { If the inputs are 0..MAXJSAMPLE, the outputs of these equations
183 must be too; we do not need an explicit range-limiting operation.
184 Hence the value being shifted is never negative, and we don't
185 need the general RIGHT_SHIFT macro. }
188 outptr0
^[col
] := JSAMPLE(
189 ((ctab
^[r
+R_Y_OFF
] + ctab
^[g
+G_Y_OFF
] + ctab
^[b
+B_Y_OFF
])
192 outptr1
^[col
] := JSAMPLE(
193 ((ctab
^[r
+R_CB_OFF
] + ctab
^[g
+G_CB_OFF
] + ctab
^[b
+B_CB_OFF
])
196 outptr2
^[col
] := JSAMPLE(
197 ((ctab
^[r
+R_CR_OFF
] + ctab
^[g
+G_CR_OFF
] + ctab
^[b
+B_CR_OFF
])
204 {*************** Cases other than RGB -> YCbCr *************}
207 { Convert some rows of samples to the JPEG colorspace.
208 This version handles RGB -> grayscale conversion, which is the same
209 as the RGB -> Y portion of RGB -> YCbCr.
210 We assume rgb_ycc_start has been called (we only use the Y tables). }
213 procedure rgb_gray_convert (cinfo
: j_compress_ptr
;
214 input_buf
: JSAMPARRAY
;
215 output_buf
: JSAMPIMAGE
;
216 output_row
: JDIMENSION
;
219 cconvert
: my_cconvert_ptr
;
220 {register} r
, g
, b
: int
;
221 {register} ctab
:INT32_FIELD_PTR
;
222 {register} inptr
: JSAMPROW
;
223 {register} outptr
: JSAMPROW
;
224 {register} col
: JDIMENSION
;
225 num_cols
: JDIMENSION
;
227 cconvert
:= my_cconvert_ptr (cinfo
^.cconvert
);
228 ctab
:= cconvert
^.rgb_ycc_tab
;
229 num_cols
:= cinfo
^.image_width
;
231 while (num_rows
> 0) do
234 inptr
:= input_buf
[0];
235 Inc(JSAMPROW_PTR(input_buf
));
236 outptr
:= output_buf
[0][output_row
];
238 for col
:= 0 to num_cols
- 1 do
240 r
:= GETJSAMPLE(inptr
[RGB_RED
]);
241 g
:= GETJSAMPLE(inptr
[RGB_GREEN
]);
242 b
:= GETJSAMPLE(inptr
[RGB_BLUE
]);
243 Inc(JSAMPLE_PTR(inptr
), RGB_PIXELSIZE
);
245 // kylix 3 compiler crashes on this
246 // it also crashes Delphi OSX compiler 9 years later :(
247 {$IF not (Defined(DCC) and not Defined(MSWINDOWS))}
248 outptr
[col
] := JSAMPLE(((ctab
[r
+R_Y_OFF
] + ctab
[g
+G_Y_OFF
] + ctab
[b
+B_Y_OFF
]) shr SCALEBITS
));
255 { Convert some rows of samples to the JPEG colorspace.
256 This version handles Adobe-style CMYK -> YCCK conversion,
257 where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same
258 conversion as above, while passing K (black) unchanged.
259 We assume rgb_ycc_start has been called. }
262 procedure cmyk_ycck_convert (cinfo
: j_compress_ptr
;
263 input_buf
: JSAMPARRAY
;
264 output_buf
: JSAMPIMAGE
;
265 output_row
: JDIMENSION
;
268 cconvert
: my_cconvert_ptr
;
269 {register} r
, g
, b
: int
;
270 {register} ctab
: INT32_FIELD_PTR
;
271 {register} inptr
: JSAMPROW
;
272 {register} outptr0
, outptr1
, outptr2
, outptr3
: JSAMPROW
;
273 {register} col
: JDIMENSION
;
274 num_cols
: JDIMENSION
;
276 cconvert
:= my_cconvert_ptr (cinfo
^.cconvert
);
277 ctab
:= cconvert
^.rgb_ycc_tab
;
278 num_cols
:= cinfo
^.image_width
;
280 while (num_rows
> 0) do
283 inptr
:= input_buf
^[0];
284 Inc(JSAMPROW_PTR(input_buf
));
285 outptr0
:= output_buf
^[0]^[output_row
];
286 outptr1
:= output_buf
^[1]^[output_row
];
287 outptr2
:= output_buf
^[2]^[output_row
];
288 outptr3
:= output_buf
^[3]^[output_row
];
290 for col
:= 0 to pred(num_cols
) do
292 r
:= MAXJSAMPLE
- GETJSAMPLE(inptr
^[0]);
293 g
:= MAXJSAMPLE
- GETJSAMPLE(inptr
^[1]);
294 b
:= MAXJSAMPLE
- GETJSAMPLE(inptr
^[2]);
295 { K passes through as-is }
296 outptr3
^[col
] := inptr
^[3]; { don't need GETJSAMPLE here }
297 Inc(JSAMPLE_PTR(inptr
), 4);
298 { If the inputs are 0..MAXJSAMPLE, the outputs of these equations
299 must be too; we do not need an explicit range-limiting operation.
300 Hence the value being shifted is never negative, and we don't
301 need the general RIGHT_SHIFT macro. }
304 outptr0
^[col
] := JSAMPLE (
305 ((ctab
^[r
+R_Y_OFF
] + ctab
^[g
+G_Y_OFF
] + ctab
^[b
+B_Y_OFF
])
308 outptr1
^[col
] := JSAMPLE(
309 ((ctab
^[r
+R_CB_OFF
] + ctab
^[g
+G_CB_OFF
] + ctab
^[b
+B_CB_OFF
])
312 outptr2
^[col
] := JSAMPLE (
313 ((ctab
^[r
+R_CR_OFF
] + ctab
^[g
+G_CR_OFF
] + ctab
^[b
+B_CR_OFF
])
320 { Convert some rows of samples to the JPEG colorspace.
321 This version handles grayscale output with no conversion.
322 The source can be either plain grayscale or YCbCr (since Y = gray). }
325 procedure grayscale_convert (cinfo
: j_compress_ptr
;
326 input_buf
: JSAMPARRAY
;
327 output_buf
: JSAMPIMAGE
;
328 output_row
: JDIMENSION
;
331 {register} inptr
: JSAMPROW
;
332 {register} outptr
: JSAMPROW
;
333 {register} col
: JDIMENSION
;
334 num_cols
:JDIMENSION
;
337 num_cols
:= cinfo
^.image_width
;
338 instride
:= cinfo
^.input_components
;
340 while (num_rows
> 0) do
343 inptr
:= input_buf
^[0];
344 Inc(JSAMPROW_PTR(input_buf
));
345 outptr
:= output_buf
^[0]^[output_row
];
347 for col
:= 0 to pred(num_cols
) do
349 outptr
^[col
] := inptr
^[0]; { don't need GETJSAMPLE() here }
350 Inc(JSAMPLE_PTR(inptr
), instride
);
356 { Convert some rows of samples to the JPEG colorspace.
357 This version handles multi-component colorspaces without conversion.
358 We assume input_components = num_components. }
361 procedure null_convert (cinfo
: j_compress_ptr
;
362 input_buf
: JSAMPARRAY
;
363 output_buf
: JSAMPIMAGE
;
364 output_row
: JDIMENSION
;
367 {register} inptr
: JSAMPROW
;
368 {register} outptr
: JSAMPROW
;
369 {register} col
: JDIMENSION
;
372 num_cols
: JDIMENSION
;
374 nc
:= cinfo
^.num_components
;
375 num_cols
:= cinfo
^.image_width
;
377 while (num_rows
> 0) do
380 { It seems fastest to make a separate pass for each component. }
381 for ci
:= 0 to pred(nc
) do
383 inptr
:= input_buf
^[0];
384 outptr
:= output_buf
^[ci
]^[output_row
];
385 for col
:= 0 to pred(num_cols
) do
387 outptr
^[col
] := inptr
^[ci
]; { don't need GETJSAMPLE() here }
388 Inc(JSAMPLE_PTR(inptr
), nc
);
391 Inc(JSAMPROW_PTR(input_buf
));
397 { Empty method for start_pass. }
400 procedure null_method (cinfo
: j_compress_ptr
);
406 { Module initialization routine for input colorspace conversion. }
409 procedure jinit_color_converter (cinfo
: j_compress_ptr
);
411 cconvert
: my_cconvert_ptr
;
413 cconvert
:= my_cconvert_ptr(
414 cinfo
^.mem
^.alloc_small (j_common_ptr(cinfo
), JPOOL_IMAGE
,
415 SIZEOF(my_color_converter
)) );
416 cinfo
^.cconvert
:= jpeg_color_converter_ptr(cconvert
);
417 { set start_pass to null method until we find out differently }
418 cconvert
^.pub
.start_pass
:= null_method
;
420 { Make sure input_components agrees with in_color_space }
421 case (cinfo
^.in_color_space
) of
423 if (cinfo
^.input_components
<> 1) then
424 ERREXIT(j_common_ptr(cinfo
), JERR_BAD_IN_COLORSPACE
);
426 {$ifdef RGB_PIXELSIZE <> 3}
428 if (cinfo
^.input_components
<> RGB_PIXELSIZE
) then
429 ERREXIT(j_common_ptr(cinfo
), JERR_BAD_IN_COLORSPACE
);
430 {$else} { share code with YCbCr }
434 if (cinfo
^.input_components
<> 3) then
435 ERREXIT(j_common_ptr(cinfo
), JERR_BAD_IN_COLORSPACE
);
439 if (cinfo
^.input_components
<> 4) then
440 ERREXIT(j_common_ptr(cinfo
), JERR_BAD_IN_COLORSPACE
);
442 else { JCS_UNKNOWN can be anything }
443 if (cinfo
^.input_components
< 1) then
444 ERREXIT(j_common_ptr(cinfo
), JERR_BAD_IN_COLORSPACE
);
447 { Check num_components, set conversion method based on requested space }
448 case (cinfo
^.jpeg_color_space
) of
451 if (cinfo
^.num_components
<> 1) then
452 ERREXIT(j_common_ptr(cinfo
), JERR_BAD_J_COLORSPACE
);
453 if (cinfo
^.in_color_space
= JCS_GRAYSCALE
) then
454 cconvert
^.pub
.color_convert
:= grayscale_convert
456 if (cinfo
^.in_color_space
= JCS_RGB
) then
458 cconvert
^.pub
.start_pass
:= rgb_ycc_start
;
459 cconvert
^.pub
.color_convert
:= rgb_gray_convert
;
462 if (cinfo
^.in_color_space
= JCS_YCbCr
) then
463 cconvert
^.pub
.color_convert
:= grayscale_convert
465 ERREXIT(j_common_ptr(cinfo
), JERR_CONVERSION_NOTIMPL
);
470 if (cinfo
^.num_components
<> 3) then
471 ERREXIT(j_common_ptr(cinfo
), JERR_BAD_J_COLORSPACE
);
472 if (cinfo
^.in_color_space
= JCS_RGB
) and (RGB_PIXELSIZE
= 3) then
473 cconvert
^.pub
.color_convert
:= null_convert
475 ERREXIT(j_common_ptr(cinfo
), JERR_CONVERSION_NOTIMPL
);
480 if (cinfo
^.num_components
<> 3) then
481 ERREXIT(j_common_ptr(cinfo
), JERR_BAD_J_COLORSPACE
);
482 if (cinfo
^.in_color_space
= JCS_RGB
) then
484 cconvert
^.pub
.start_pass
:= rgb_ycc_start
;
485 cconvert
^.pub
.color_convert
:= rgb_ycc_convert
;
488 if (cinfo
^.in_color_space
= JCS_YCbCr
) then
489 cconvert
^.pub
.color_convert
:= null_convert
491 ERREXIT(j_common_ptr(cinfo
), JERR_CONVERSION_NOTIMPL
);
496 if (cinfo
^.num_components
<> 4) then
497 ERREXIT(j_common_ptr(cinfo
), JERR_BAD_J_COLORSPACE
);
498 if (cinfo
^.in_color_space
= JCS_CMYK
) then
499 cconvert
^.pub
.color_convert
:= null_convert
501 ERREXIT(j_common_ptr(cinfo
), JERR_CONVERSION_NOTIMPL
);
506 if (cinfo
^.num_components
<> 4) then
507 ERREXIT(j_common_ptr(cinfo
), JERR_BAD_J_COLORSPACE
);
508 if (cinfo
^.in_color_space
= JCS_CMYK
) then
510 cconvert
^.pub
.start_pass
:= rgb_ycc_start
;
511 cconvert
^.pub
.color_convert
:= cmyk_ycck_convert
;
514 if (cinfo
^.in_color_space
= JCS_YCCK
) then
515 cconvert
^.pub
.color_convert
:= null_convert
517 ERREXIT(j_common_ptr(cinfo
), JERR_CONVERSION_NOTIMPL
);
520 else { allow null conversion of JCS_UNKNOWN }
522 if (cinfo
^.jpeg_color_space
<> cinfo
^.in_color_space
) or
523 (cinfo
^.num_components
<> cinfo
^.input_components
) then
524 ERREXIT(j_common_ptr(cinfo
), JERR_CONVERSION_NOTIMPL
);
525 cconvert
^.pub
.color_convert
:= null_convert
;