1 #if defined (APDK_LJJETREADY) || defined (APDK_QUICKCONNECT) || defined (APDK_PSCRIPT)
\r
5 * Copyright (C) 1991-1996, Thomas G. Lane.
\r
6 * This file is part of the Independent JPEG Group's software.
\r
7 * For conditions of distribution and use, see the accompanying README file.
\r
9 * This file contains input colorspace conversion routines.
\r
12 #define JPEG_INTERNALS
\r
13 #include "jinclude.h"
\r
14 #include "jpeglib.h"
\r
16 //#define USE_MOJAVE_CSC
\r
18 /* Private subobject */
\r
21 struct jpeg_color_converter pub; /* public fields */
\r
23 /* Private state for RGB->YCC conversion */
\r
24 INT32 * rgb_ycc_tab; /* => table for RGB to YCbCr conversion */
\r
25 } my_color_converter;
\r
27 typedef my_color_converter * my_cconvert_ptr;
\r
30 /**************** RGB -> YCbCr conversion: most common case **************/
\r
33 * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
\r
34 * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
\r
35 * The conversion equations to be implemented are therefore
\r
36 * Y = 0.29900 * R + 0.58700 * G + 0.11400 * B
\r
37 * Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B + CENTERJSAMPLE
\r
38 * Cr = 0.50000 * R - 0.41869 * G - 0.08131 * B + CENTERJSAMPLE
\r
41 * The CSC was changed to the values below as per the Mojave
\r
42 * specification. These values are enabled by the compile time flag
\r
43 * USE_MOJAVE_CSC defined below.
\r
45 * Y = 0.50000 * R + 0.00000 * G + 0.00000 * B
\r
46 * Cb = 0.50000 * R - 0.50000 * G + 0.00000 * B + CENTERJSAMPLE
\r
47 * Cr = 0.50000 * R + 0.00000 * G - 0.50000 * B + CENTERJSAMPLE
\r
49 * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
\r
50 * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2,
\r
51 * rather than CENTERJSAMPLE, for Cb and Cr. This gave equal positive and
\r
52 * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0)
\r
53 * were not represented exactly. Now we sacrifice exact representation of
\r
54 * maximum red and maximum blue in order to get exact grayscales.
\r
56 * To avoid floating-point arithmetic, we represent the fractional constants
\r
57 * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
\r
58 * the products by 2^16, with appropriate rounding, to get the correct answer.
\r
60 * For even more speed, we avoid doing any multiplications in the inner loop
\r
61 * by precalculating the constants times R,G,B for all possible values.
\r
62 * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
\r
63 * for 12-bit samples it is still acceptable. It's not very reasonable for
\r
64 * 16-bit samples, but if you want lossless storage you shouldn't be changing
\r
65 * colorspace anyway.
\r
66 * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included
\r
67 * in the tables to save adding them separately in the inner loop.
\r
70 #define SCALEBITS 16 /* speediest right-shift on some machines */
\r
71 #define CBCR_OFFSET ((INT32) CENTERJSAMPLE << SCALEBITS)
\r
72 #define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
\r
73 #define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
\r
75 /* We allocate one big table and divide it up into eight parts, instead of
\r
76 * doing eight alloc_small requests. This lets us use a single table base
\r
77 * address, which can be held in a register in the inner loops on many
\r
78 * machines (more than can hold all eight addresses, anyway).
\r
81 int iUseMojaveCsc = 1;
\r
83 int R_Y_OFF; /* offset to R => Y section */
\r
84 int G_Y_OFF; /* offset to G => Y section */
\r
85 int B_Y_OFF; /* offset to B => Y section */
\r
86 int R_CB_OFF; /* R=>Y, R=>Cb are the same */
\r
87 int G_CB_OFF; /* offset to G => Cb section */
\r
88 int B_CB_OFF; /* G=>Y, B=>Cb are the same */
\r
89 int R_CR_OFF; /* R=>Y, R=>Cr are the same */
\r
90 int G_CR_OFF; /* G=>Y, G=>Cr are the same */
\r
91 int B_CR_OFF; /* G=>Cb, B=>Cr are the same */
\r
94 void hp_rgb_ycc_setup (int iFlag)
\r
96 iUseMojaveCsc = iFlag;
\r
99 R_Y_OFF = 0; /* offset to R => Y section */
\r
100 G_Y_OFF = (1*(MAXJSAMPLE+1)); /* offset to G => Y section */
\r
101 B_Y_OFF = (2*(MAXJSAMPLE+1)); /* offset to B => Y section */
\r
102 R_CB_OFF = R_Y_OFF; /* R=>Y, R=>Cb are the same */
\r
103 G_CB_OFF = (3*(MAXJSAMPLE+1)); /* offset to G => Cb section */
\r
104 B_CB_OFF = G_Y_OFF; /* G=>Y, B=>Cb are the same */
\r
105 R_CR_OFF = R_Y_OFF; /* R=>Y, R=>Cr are the same */
\r
106 G_CR_OFF = G_Y_OFF; /* G=>Y, G=>Cr are the same */
\r
107 B_CR_OFF = G_CB_OFF; /* G=>Cb, B=>Cr are the same */
\r
108 TABLE_SIZE = (4*(MAXJSAMPLE+1));
\r
112 R_Y_OFF = 0; /* offset to R => Y section */
\r
113 G_Y_OFF = (1*(MAXJSAMPLE+1)); /* offset to G => Y section */
\r
114 B_Y_OFF= (2*(MAXJSAMPLE+1)); /* etc. */
\r
115 R_CB_OFF= (3*(MAXJSAMPLE+1));
\r
116 G_CB_OFF= (4*(MAXJSAMPLE+1));
\r
117 B_CB_OFF= (5*(MAXJSAMPLE+1));
\r
118 R_CR_OFF= B_CB_OFF; /* B=>Cb, R=>Cr are the same */
\r
119 G_CR_OFF= (6*(MAXJSAMPLE+1));
\r
120 B_CR_OFF= (7*(MAXJSAMPLE+1));
\r
121 TABLE_SIZE =(8*(MAXJSAMPLE+1));
\r
126 * Initialize for RGB->YCC colorspace conversion.
\r
130 rgb_ycc_start (j_compress_ptr cinfo)
\r
132 my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
\r
133 INT32 * rgb_ycc_tab;
\r
136 /* Allocate and fill in the conversion tables. */
\r
137 cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *)
\r
138 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
\r
139 (TABLE_SIZE * SIZEOF(INT32)));
\r
141 for (i = 0; i <= MAXJSAMPLE; i++)
\r
145 rgb_ycc_tab[i+R_Y_OFF] = FIX(0.50000) * i;
\r
146 rgb_ycc_tab[i+G_Y_OFF] = FIX(0.00000) * i;
\r
147 rgb_ycc_tab[i+B_Y_OFF] = FIX(0.00000) * i + ONE_HALF;
\r
148 /* R=>Y and R=>Cb tables are the same
\r
149 rgb_ycc_tab[i+R_CB_OFF] = (FIX(0.50000)) * i;
\r
151 rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.50000)) * i + CBCR_OFFSET + ONE_HALF-1;
\r
152 /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
\r
153 * This ensures that the maximum output will round to MAXJSAMPLE
\r
154 * not MAXJSAMPLE+1, and thus that we don't have to range-limit.
\r
156 /* G=>Y and B=>Cb tables are the same
\r
157 rgb_ycc_tab[i+B_CB_OFF] = FIX(0.00000) * i;
\r
159 /* R=>Y and R=>Cr tables are the same
\r
160 rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i;
\r
162 /* G=>Y and G=>Cr tables are the same
\r
163 rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.00000)) * i;
\r
165 /* G=>Cb and B=>Cr tables are the same
\r
166 rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.50000)) * i + CBCR_OFFSET + ONE_HALF-1;
\r
171 rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i;
\r
172 rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i;
\r
173 rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
\r
174 rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i;
\r
175 rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i;
\r
176 /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
\r
177 * This ensures that the maximum output will round to MAXJSAMPLE
\r
178 * not MAXJSAMPLE+1, and thus that we don't have to range-limit.
\r
180 rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1;
\r
181 /* B=>Cb and R=>Cr tables are the same
\r
182 rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i + CBCR_OFFSET + ONE_HALF-1;
\r
184 rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i;
\r
185 rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i;
\r
192 * Convert some rows of samples to the JPEG colorspace.
\r
194 * Note that we change from the application's interleaved-pixel format
\r
195 * to our internal noninterleaved, one-plane-per-component format.
\r
196 * The input buffer is therefore three times as wide as the output buffer.
\r
198 * A starting row offset is provided only for the output buffer. The caller
\r
199 * can easily adjust the passed input_buf value to accommodate any row
\r
200 * offset required on that side.
\r
204 rgb_ycc_convert (j_compress_ptr cinfo,
\r
205 JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
\r
206 JDIMENSION output_row, int num_rows)
\r
208 my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
\r
209 register int r, g, b;
\r
210 register INT32 * ctab = cconvert->rgb_ycc_tab;
\r
211 register JSAMPROW inptr;
\r
212 register JSAMPROW outptr0, outptr1, outptr2;
\r
213 register JDIMENSION col;
\r
214 JDIMENSION num_cols = cinfo->image_width;
\r
216 while (--num_rows >= 0) {
\r
217 inptr = *input_buf++;
\r
218 outptr0 = output_buf[0][output_row];
\r
219 outptr1 = output_buf[1][output_row];
\r
220 outptr2 = output_buf[2][output_row];
\r
222 for (col = 0; col < num_cols; col++) {
\r
223 r = GETJSAMPLE(inptr[RGB_RED]);
\r
224 g = GETJSAMPLE(inptr[RGB_GREEN]);
\r
225 b = GETJSAMPLE(inptr[RGB_BLUE]);
\r
226 inptr += RGB_PIXELSIZE;
\r
227 /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
\r
228 * must be too; we do not need an explicit range-limiting operation.
\r
229 * Hence the value being shifted is never negative, and we don't
\r
230 * need the general RIGHT_SHIFT macro.
\r
233 outptr0[col] = (JSAMPLE)
\r
234 ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
\r
237 outptr1[col] = (JSAMPLE)
\r
238 ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
\r
241 outptr2[col] = (JSAMPLE)
\r
242 ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
\r
249 /**************** Cases other than RGB -> YCbCr **************/
\r
253 * Convert some rows of samples to the JPEG colorspace.
\r
254 * This version handles RGB->grayscale conversion, which is the same
\r
255 * as the RGB->Y portion of RGB->YCbCr.
\r
256 * We assume rgb_ycc_start has been called (we only use the Y tables).
\r
260 rgb_gray_convert (j_compress_ptr cinfo,
\r
261 JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
\r
262 JDIMENSION output_row, int num_rows)
\r
264 my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
\r
265 register int r, g, b;
\r
266 register INT32 * ctab = cconvert->rgb_ycc_tab;
\r
267 register JSAMPROW inptr;
\r
268 register JSAMPROW outptr;
\r
269 register JDIMENSION col;
\r
270 JDIMENSION num_cols = cinfo->image_width;
\r
272 while (--num_rows >= 0) {
\r
273 inptr = *input_buf++;
\r
274 outptr = output_buf[0][output_row];
\r
276 for (col = 0; col < num_cols; col++) {
\r
277 r = GETJSAMPLE(inptr[RGB_RED]);
\r
278 g = GETJSAMPLE(inptr[RGB_GREEN]);
\r
279 b = GETJSAMPLE(inptr[RGB_BLUE]);
\r
280 inptr += RGB_PIXELSIZE;
\r
282 outptr[col] = (JSAMPLE)
\r
283 ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
\r
291 * Convert some rows of samples to the JPEG colorspace.
\r
292 * This version handles Adobe-style CMYK->YCCK conversion,
\r
293 * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same
\r
294 * conversion as above, while passing K (black) unchanged.
\r
295 * We assume rgb_ycc_start has been called.
\r
299 cmyk_ycck_convert (j_compress_ptr cinfo,
\r
300 JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
\r
301 JDIMENSION output_row, int num_rows)
\r
303 my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
\r
304 register int r, g, b;
\r
305 register INT32 * ctab = cconvert->rgb_ycc_tab;
\r
306 register JSAMPROW inptr;
\r
307 register JSAMPROW outptr0, outptr1, outptr2, outptr3;
\r
308 register JDIMENSION col;
\r
309 JDIMENSION num_cols = cinfo->image_width;
\r
311 while (--num_rows >= 0) {
\r
312 inptr = *input_buf++;
\r
313 outptr0 = output_buf[0][output_row];
\r
314 outptr1 = output_buf[1][output_row];
\r
315 outptr2 = output_buf[2][output_row];
\r
316 outptr3 = output_buf[3][output_row];
\r
318 for (col = 0; col < num_cols; col++) {
\r
319 r = MAXJSAMPLE - GETJSAMPLE(inptr[0]);
\r
320 g = MAXJSAMPLE - GETJSAMPLE(inptr[1]);
\r
321 b = MAXJSAMPLE - GETJSAMPLE(inptr[2]);
\r
322 /* K passes through as-is */
\r
323 outptr3[col] = inptr[3]; /* don't need GETJSAMPLE here */
\r
325 /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
\r
326 * must be too; we do not need an explicit range-limiting operation.
\r
327 * Hence the value being shifted is never negative, and we don't
\r
328 * need the general RIGHT_SHIFT macro.
\r
331 outptr0[col] = (JSAMPLE)
\r
332 ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
\r
335 outptr1[col] = (JSAMPLE)
\r
336 ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
\r
339 outptr2[col] = (JSAMPLE)
\r
340 ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
\r
348 * Convert some rows of samples to the JPEG colorspace.
\r
349 * This version handles grayscale output with no conversion.
\r
350 * The source can be either plain grayscale or YCbCr (since Y == gray).
\r
354 grayscale_convert (j_compress_ptr cinfo,
\r
355 JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
\r
356 JDIMENSION output_row, int num_rows)
\r
358 register JSAMPROW inptr;
\r
359 register JSAMPROW outptr;
\r
360 register JDIMENSION col;
\r
361 JDIMENSION num_cols = cinfo->image_width;
\r
362 int instride = cinfo->input_components;
\r
364 while (--num_rows >= 0) {
\r
365 inptr = *input_buf++;
\r
366 outptr = output_buf[0][output_row];
\r
368 for (col = 0; col < num_cols; col++) {
\r
369 outptr[col] = inptr[0]; /* don't need GETJSAMPLE() here */
\r
377 * Convert some rows of samples to the JPEG colorspace.
\r
378 * This version handles multi-component colorspaces without conversion.
\r
379 * We assume input_components == num_components.
\r
383 null_convert (j_compress_ptr cinfo,
\r
384 JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
\r
385 JDIMENSION output_row, int num_rows)
\r
387 register JSAMPROW inptr;
\r
388 register JSAMPROW outptr;
\r
389 register JDIMENSION col;
\r
391 int nc = cinfo->num_components;
\r
392 JDIMENSION num_cols = cinfo->image_width;
\r
394 while (--num_rows >= 0) {
\r
395 /* It seems fastest to make a separate pass for each component. */
\r
396 for (ci = 0; ci < nc; ci++) {
\r
397 inptr = *input_buf;
\r
398 outptr = output_buf[ci][output_row];
\r
399 for (col = 0; col < num_cols; col++) {
\r
400 outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */
\r
411 * Empty method for start_pass.
\r
415 null_method (j_compress_ptr cinfo)
\r
417 /* no work needed */
\r
422 * Module initialization routine for input colorspace conversion.
\r
426 jinit_color_converter (j_compress_ptr cinfo)
\r
428 my_cconvert_ptr cconvert;
\r
430 cconvert = (my_cconvert_ptr)
\r
431 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
\r
432 SIZEOF(my_color_converter));
\r
433 cinfo->cconvert = (struct jpeg_color_converter *) cconvert;
\r
434 /* set start_pass to null method until we find out differently */
\r
435 cconvert->pub.start_pass = null_method;
\r
437 /* Make sure input_components agrees with in_color_space */
\r
438 switch (cinfo->in_color_space) {
\r
439 case JCS_GRAYSCALE:
\r
440 if (cinfo->input_components != 1)
\r
441 ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
\r
445 #if RGB_PIXELSIZE != 3
\r
446 if (cinfo->input_components != RGB_PIXELSIZE)
\r
447 ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
\r
449 #endif /* else share code with YCbCr */
\r
452 if (cinfo->input_components != 3)
\r
453 ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
\r
458 if (cinfo->input_components != 4)
\r
459 ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
\r
462 default: /* JCS_UNKNOWN can be anything */
\r
463 if (cinfo->input_components < 1)
\r
464 ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
\r
468 /* Check num_components, set conversion method based on requested space */
\r
469 switch (cinfo->jpeg_color_space) {
\r
470 case JCS_GRAYSCALE:
\r
471 if (cinfo->num_components != 1)
\r
472 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
\r
473 if (cinfo->in_color_space == JCS_GRAYSCALE)
\r
474 cconvert->pub.color_convert = grayscale_convert;
\r
475 else if (cinfo->in_color_space == JCS_RGB) {
\r
476 cconvert->pub.start_pass = rgb_ycc_start;
\r
477 cconvert->pub.color_convert = rgb_gray_convert;
\r
478 } else if (cinfo->in_color_space == JCS_YCbCr)
\r
479 cconvert->pub.color_convert = grayscale_convert;
\r
481 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
\r
485 if (cinfo->num_components != 3)
\r
486 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
\r
487 if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3)
\r
488 cconvert->pub.color_convert = null_convert;
\r
490 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
\r
494 if (cinfo->num_components != 3)
\r
495 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
\r
496 if (cinfo->in_color_space == JCS_RGB) {
\r
497 cconvert->pub.start_pass = rgb_ycc_start;
\r
498 cconvert->pub.color_convert = rgb_ycc_convert;
\r
499 } else if (cinfo->in_color_space == JCS_YCbCr)
\r
500 cconvert->pub.color_convert = null_convert;
\r
502 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
\r
506 if (cinfo->num_components != 4)
\r
507 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
\r
508 if (cinfo->in_color_space == JCS_CMYK)
\r
509 cconvert->pub.color_convert = null_convert;
\r
511 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
\r
515 if (cinfo->num_components != 4)
\r
516 ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
\r
517 if (cinfo->in_color_space == JCS_CMYK) {
\r
518 cconvert->pub.start_pass = rgb_ycc_start;
\r
519 cconvert->pub.color_convert = cmyk_ycck_convert;
\r
520 } else if (cinfo->in_color_space == JCS_YCCK)
\r
521 cconvert->pub.color_convert = null_convert;
\r
523 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
\r
526 default: /* allow null conversion of JCS_UNKNOWN */
\r
527 if (cinfo->jpeg_color_space != cinfo->in_color_space ||
\r
528 cinfo->num_components != cinfo->input_components)
\r
529 ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
\r
530 cconvert->pub.color_convert = null_convert;
\r
534 #endif // APDK_LJJETREADY || APDK_QUICKCONNECT || APDK_PSCRIPT
\r