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