OLD | NEW |
| (Empty) |
1 /* | |
2 * jdcolor.c | |
3 * | |
4 * Copyright (C) 1991-1997, Thomas G. Lane. | |
5 * This file is part of the Independent JPEG Group's software. | |
6 * For conditions of distribution and use, see the accompanying README file. | |
7 * | |
8 * This file contains output colorspace conversion routines. | |
9 */ | |
10 | |
11 #define JPEG_INTERNALS | |
12 #include "jinclude.h" | |
13 #include "jpeglib.h" | |
14 | |
15 | |
16 /* Private subobject */ | |
17 | |
18 typedef struct { | |
19 struct jpeg_color_deconverter pub; /* public fields */ | |
20 | |
21 /* Private state for YCC->RGB conversion */ | |
22 int * Cr_r_tab; /* => table for Cr to R conversion */ | |
23 int * Cb_b_tab; /* => table for Cb to B conversion */ | |
24 INT32 * Cr_g_tab; /* => table for Cr to G conversion */ | |
25 INT32 * Cb_g_tab; /* => table for Cb to G conversion */ | |
26 } my_color_deconverter; | |
27 | |
28 typedef my_color_deconverter * my_cconvert_ptr; | |
29 | |
30 | |
31 /**************** YCbCr -> RGB conversion: most common case **************/ | |
32 | |
33 /* | |
34 * YCbCr is defined per CCIR 601-1, except that Cb and Cr are | |
35 * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. | |
36 * The conversion equations to be implemented are therefore | |
37 * R = Y + 1.40200 * Cr | |
38 * G = Y - 0.34414 * Cb - 0.71414 * Cr | |
39 * B = Y + 1.77200 * Cb | |
40 * where Cb and Cr represent the incoming values less CENTERJSAMPLE. | |
41 * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.) | |
42 * | |
43 * To avoid floating-point arithmetic, we represent the fractional constants | |
44 * as integers scaled up by 2^16 (about 4 digits precision); we have to divide | |
45 * the products by 2^16, with appropriate rounding, to get the correct answer. | |
46 * Notice that Y, being an integral input, does not contribute any fraction | |
47 * so it need not participate in the rounding. | |
48 * | |
49 * For even more speed, we avoid doing any multiplications in the inner loop | |
50 * by precalculating the constants times Cb and Cr for all possible values. | |
51 * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table); | |
52 * for 12-bit samples it is still acceptable. It's not very reasonable for | |
53 * 16-bit samples, but if you want lossless storage you shouldn't be changing | |
54 * colorspace anyway. | |
55 * The Cr=>R and Cb=>B values can be rounded to integers in advance; the | |
56 * values for the G calculation are left scaled up, since we must add them | |
57 * together before rounding. | |
58 */ | |
59 | |
60 #define SCALEBITS 16 /* speediest right-shift on some machines */ | |
61 #define ONE_HALF ((INT32) 1 << (SCALEBITS-1)) | |
62 #define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5)) | |
63 | |
64 | |
65 /* | |
66 * Initialize tables for YCC->RGB colorspace conversion. | |
67 */ | |
68 | |
69 LOCAL(void) | |
70 build_ycc_rgb_table (j_decompress_ptr cinfo) | |
71 { | |
72 my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; | |
73 int i; | |
74 INT32 x; | |
75 SHIFT_TEMPS | |
76 | |
77 cconvert->Cr_r_tab = (int *) | |
78 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | |
79 (MAXJSAMPLE+1) * SIZEOF(int)); | |
80 cconvert->Cb_b_tab = (int *) | |
81 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | |
82 (MAXJSAMPLE+1) * SIZEOF(int)); | |
83 cconvert->Cr_g_tab = (INT32 *) | |
84 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | |
85 (MAXJSAMPLE+1) * SIZEOF(INT32)); | |
86 cconvert->Cb_g_tab = (INT32 *) | |
87 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | |
88 (MAXJSAMPLE+1) * SIZEOF(INT32)); | |
89 | |
90 for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) { | |
91 /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */ | |
92 /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */ | |
93 /* Cr=>R value is nearest int to 1.40200 * x */ | |
94 cconvert->Cr_r_tab[i] = (int) | |
95 RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS); | |
96 /* Cb=>B value is nearest int to 1.77200 * x */ | |
97 cconvert->Cb_b_tab[i] = (int) | |
98 RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS); | |
99 /* Cr=>G value is scaled-up -0.71414 * x */ | |
100 cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x; | |
101 /* Cb=>G value is scaled-up -0.34414 * x */ | |
102 /* We also add in ONE_HALF so that need not do it in inner loop */ | |
103 cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF; | |
104 } | |
105 } | |
106 | |
107 | |
108 /* | |
109 * Convert some rows of samples to the output colorspace. | |
110 * | |
111 * Note that we change from noninterleaved, one-plane-per-component format | |
112 * to interleaved-pixel format. The output buffer is therefore three times | |
113 * as wide as the input buffer. | |
114 * A starting row offset is provided only for the input buffer. The caller | |
115 * can easily adjust the passed output_buf value to accommodate any row | |
116 * offset required on that side. | |
117 */ | |
118 | |
119 METHODDEF(void) | |
120 ycc_rgb_convert (j_decompress_ptr cinfo, | |
121 JSAMPIMAGE input_buf, JDIMENSION input_row, | |
122 JSAMPARRAY output_buf, int num_rows) | |
123 { | |
124 my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; | |
125 register int y, cb, cr; | |
126 register JSAMPROW outptr; | |
127 register JSAMPROW inptr0, inptr1, inptr2; | |
128 register JDIMENSION col; | |
129 JDIMENSION num_cols = cinfo->output_width; | |
130 /* copy these pointers into registers if possible */ | |
131 register JSAMPLE * range_limit = cinfo->sample_range_limit; | |
132 register int * Crrtab = cconvert->Cr_r_tab; | |
133 register int * Cbbtab = cconvert->Cb_b_tab; | |
134 register INT32 * Crgtab = cconvert->Cr_g_tab; | |
135 register INT32 * Cbgtab = cconvert->Cb_g_tab; | |
136 SHIFT_TEMPS | |
137 | |
138 while (--num_rows >= 0) { | |
139 inptr0 = input_buf[0][input_row]; | |
140 inptr1 = input_buf[1][input_row]; | |
141 inptr2 = input_buf[2][input_row]; | |
142 input_row++; | |
143 outptr = *output_buf++; | |
144 for (col = 0; col < num_cols; col++) { | |
145 y = GETJSAMPLE(inptr0[col]); | |
146 cb = GETJSAMPLE(inptr1[col]); | |
147 cr = GETJSAMPLE(inptr2[col]); | |
148 /* Range-limiting is essential due to noise introduced by DCT losses. */ | |
149 outptr[RGB_RED] = range_limit[y + Crrtab[cr]]; | |
150 outptr[RGB_GREEN] = range_limit[y + | |
151 ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], | |
152 SCALEBITS))]; | |
153 outptr[RGB_BLUE] = range_limit[y + Cbbtab[cb]]; | |
154 outptr += RGB_PIXELSIZE; | |
155 } | |
156 } | |
157 } | |
158 | |
159 | |
160 /**************** Cases other than YCbCr -> RGB **************/ | |
161 | |
162 | |
163 /* | |
164 * Color conversion for no colorspace change: just copy the data, | |
165 * converting from separate-planes to interleaved representation. | |
166 */ | |
167 | |
168 METHODDEF(void) | |
169 null_convert (j_decompress_ptr cinfo, | |
170 JSAMPIMAGE input_buf, JDIMENSION input_row, | |
171 JSAMPARRAY output_buf, int num_rows) | |
172 { | |
173 register JSAMPROW inptr, outptr; | |
174 register JDIMENSION count; | |
175 register int num_components = cinfo->num_components; | |
176 JDIMENSION num_cols = cinfo->output_width; | |
177 int ci; | |
178 | |
179 while (--num_rows >= 0) { | |
180 for (ci = 0; ci < num_components; ci++) { | |
181 inptr = input_buf[ci][input_row]; | |
182 outptr = output_buf[0] + ci; | |
183 for (count = num_cols; count > 0; count--) { | |
184 *outptr = *inptr++; /* needn't bother with GETJSAMPLE() here */ | |
185 outptr += num_components; | |
186 } | |
187 } | |
188 input_row++; | |
189 output_buf++; | |
190 } | |
191 } | |
192 | |
193 | |
194 /* | |
195 * Color conversion for grayscale: just copy the data. | |
196 * This also works for YCbCr -> grayscale conversion, in which | |
197 * we just copy the Y (luminance) component and ignore chrominance. | |
198 */ | |
199 | |
200 METHODDEF(void) | |
201 grayscale_convert (j_decompress_ptr cinfo, | |
202 JSAMPIMAGE input_buf, JDIMENSION input_row, | |
203 JSAMPARRAY output_buf, int num_rows) | |
204 { | |
205 jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0, | |
206 num_rows, cinfo->output_width); | |
207 } | |
208 | |
209 | |
210 /* | |
211 * Convert grayscale to RGB: just duplicate the graylevel three times. | |
212 * This is provided to support applications that don't want to cope | |
213 * with grayscale as a separate case. | |
214 */ | |
215 | |
216 METHODDEF(void) | |
217 gray_rgb_convert (j_decompress_ptr cinfo, | |
218 JSAMPIMAGE input_buf, JDIMENSION input_row, | |
219 JSAMPARRAY output_buf, int num_rows) | |
220 { | |
221 register JSAMPROW inptr, outptr; | |
222 register JDIMENSION col; | |
223 JDIMENSION num_cols = cinfo->output_width; | |
224 | |
225 while (--num_rows >= 0) { | |
226 inptr = input_buf[0][input_row++]; | |
227 outptr = *output_buf++; | |
228 for (col = 0; col < num_cols; col++) { | |
229 /* We can dispense with GETJSAMPLE() here */ | |
230 outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col]; | |
231 outptr += RGB_PIXELSIZE; | |
232 } | |
233 } | |
234 } | |
235 | |
236 | |
237 /* | |
238 * Adobe-style YCCK->CMYK conversion. | |
239 * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same | |
240 * conversion as above, while passing K (black) unchanged. | |
241 * We assume build_ycc_rgb_table has been called. | |
242 */ | |
243 | |
244 METHODDEF(void) | |
245 ycck_cmyk_convert (j_decompress_ptr cinfo, | |
246 JSAMPIMAGE input_buf, JDIMENSION input_row, | |
247 JSAMPARRAY output_buf, int num_rows) | |
248 { | |
249 my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert; | |
250 register int y, cb, cr; | |
251 register JSAMPROW outptr; | |
252 register JSAMPROW inptr0, inptr1, inptr2, inptr3; | |
253 register JDIMENSION col; | |
254 JDIMENSION num_cols = cinfo->output_width; | |
255 /* copy these pointers into registers if possible */ | |
256 register JSAMPLE * range_limit = cinfo->sample_range_limit; | |
257 register int * Crrtab = cconvert->Cr_r_tab; | |
258 register int * Cbbtab = cconvert->Cb_b_tab; | |
259 register INT32 * Crgtab = cconvert->Cr_g_tab; | |
260 register INT32 * Cbgtab = cconvert->Cb_g_tab; | |
261 SHIFT_TEMPS | |
262 | |
263 while (--num_rows >= 0) { | |
264 inptr0 = input_buf[0][input_row]; | |
265 inptr1 = input_buf[1][input_row]; | |
266 inptr2 = input_buf[2][input_row]; | |
267 inptr3 = input_buf[3][input_row]; | |
268 input_row++; | |
269 outptr = *output_buf++; | |
270 for (col = 0; col < num_cols; col++) { | |
271 y = GETJSAMPLE(inptr0[col]); | |
272 cb = GETJSAMPLE(inptr1[col]); | |
273 cr = GETJSAMPLE(inptr2[col]); | |
274 /* Range-limiting is essential due to noise introduced by DCT losses. */ | |
275 outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])]; /* red */ | |
276 outptr[1] = range_limit[MAXJSAMPLE - (y + /* green */ | |
277 ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], | |
278 SCALEBITS)))]; | |
279 outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])]; /* blue */ | |
280 /* K passes through unchanged */ | |
281 outptr[3] = inptr3[col]; /* don't need GETJSAMPLE here */ | |
282 outptr += 4; | |
283 } | |
284 } | |
285 } | |
286 | |
287 | |
288 /* | |
289 * Empty method for start_pass. | |
290 */ | |
291 | |
292 METHODDEF(void) | |
293 start_pass_dcolor (j_decompress_ptr cinfo) | |
294 { | |
295 /* no work needed */ | |
296 } | |
297 | |
298 | |
299 /* | |
300 * Module initialization routine for output colorspace conversion. | |
301 */ | |
302 | |
303 GLOBAL(void) | |
304 jinit_color_deconverter (j_decompress_ptr cinfo) | |
305 { | |
306 my_cconvert_ptr cconvert; | |
307 int ci; | |
308 | |
309 cconvert = (my_cconvert_ptr) | |
310 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE, | |
311 SIZEOF(my_color_deconverter)); | |
312 cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert; | |
313 cconvert->pub.start_pass = start_pass_dcolor; | |
314 | |
315 /* Make sure num_components agrees with jpeg_color_space */ | |
316 switch (cinfo->jpeg_color_space) { | |
317 case JCS_GRAYSCALE: | |
318 if (cinfo->num_components != 1) | |
319 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); | |
320 break; | |
321 | |
322 case JCS_RGB: | |
323 case JCS_YCbCr: | |
324 if (cinfo->num_components != 3) | |
325 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); | |
326 break; | |
327 | |
328 case JCS_CMYK: | |
329 case JCS_YCCK: | |
330 if (cinfo->num_components != 4) | |
331 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); | |
332 break; | |
333 | |
334 default: /* JCS_UNKNOWN can be anything */ | |
335 if (cinfo->num_components < 1) | |
336 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE); | |
337 break; | |
338 } | |
339 | |
340 /* Set out_color_components and conversion method based on requested space. | |
341 * Also clear the component_needed flags for any unused components, | |
342 * so that earlier pipeline stages can avoid useless computation. | |
343 */ | |
344 | |
345 switch (cinfo->out_color_space) { | |
346 case JCS_GRAYSCALE: | |
347 cinfo->out_color_components = 1; | |
348 if (cinfo->jpeg_color_space == JCS_GRAYSCALE || | |
349 cinfo->jpeg_color_space == JCS_YCbCr) { | |
350 cconvert->pub.color_convert = grayscale_convert; | |
351 /* For color->grayscale conversion, only the Y (0) component is needed */ | |
352 for (ci = 1; ci < cinfo->num_components; ci++) | |
353 cinfo->comp_info[ci].component_needed = FALSE; | |
354 } else | |
355 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); | |
356 break; | |
357 | |
358 case JCS_RGB: | |
359 cinfo->out_color_components = RGB_PIXELSIZE; | |
360 if (cinfo->jpeg_color_space == JCS_YCbCr) { | |
361 cconvert->pub.color_convert = ycc_rgb_convert; | |
362 build_ycc_rgb_table(cinfo); | |
363 } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) { | |
364 cconvert->pub.color_convert = gray_rgb_convert; | |
365 } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) { | |
366 cconvert->pub.color_convert = null_convert; | |
367 } else | |
368 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); | |
369 break; | |
370 | |
371 case JCS_CMYK: | |
372 cinfo->out_color_components = 4; | |
373 if (cinfo->jpeg_color_space == JCS_YCCK) { | |
374 cconvert->pub.color_convert = ycck_cmyk_convert; | |
375 build_ycc_rgb_table(cinfo); | |
376 } else if (cinfo->jpeg_color_space == JCS_CMYK) { | |
377 cconvert->pub.color_convert = null_convert; | |
378 } else | |
379 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); | |
380 break; | |
381 | |
382 default: | |
383 /* Permit null conversion to same output space */ | |
384 if (cinfo->out_color_space == cinfo->jpeg_color_space) { | |
385 cinfo->out_color_components = cinfo->num_components; | |
386 cconvert->pub.color_convert = null_convert; | |
387 } else /* unsupported non-null conversion */ | |
388 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); | |
389 break; | |
390 } | |
391 | |
392 if (cinfo->quantize_colors) | |
393 cinfo->output_components = 1; /* single colormapped output component */ | |
394 else | |
395 cinfo->output_components = cinfo->out_color_components; | |
396 } | |
OLD | NEW |