source: trunk/third/firefox/jpeg/jccolor.c @ 21695

Revision 21695, 14.5 KB checked in by rbasch, 20 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r21694, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * jccolor.c
3 *
4 * Copyright (C) 1991-1996, 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 input colorspace conversion routines.
9 */
10
11#define JPEG_INTERNALS
12#include "jinclude.h"
13#include "jpeglib.h"
14
15
16/* Private subobject */
17
18typedef struct {
19  struct jpeg_color_converter pub; /* public fields */
20
21  /* Private state for RGB->YCC conversion */
22  INT32 * rgb_ycc_tab;          /* => table for RGB to YCbCr conversion */
23} my_color_converter;
24
25typedef my_color_converter * my_cconvert_ptr;
26
27
28/**************** RGB -> YCbCr conversion: most common case **************/
29
30/*
31 * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
32 * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
33 * The conversion equations to be implemented are therefore
34 *      Y  =  0.29900 * R + 0.58700 * G + 0.11400 * B
35 *      Cb = -0.16874 * R - 0.33126 * G + 0.50000 * B  + CENTERJSAMPLE
36 *      Cr =  0.50000 * R - 0.41869 * G - 0.08131 * B  + CENTERJSAMPLE
37 * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
38 * Note: older versions of the IJG code used a zero offset of MAXJSAMPLE/2,
39 * rather than CENTERJSAMPLE, for Cb and Cr.  This gave equal positive and
40 * negative swings for Cb/Cr, but meant that grayscale values (Cb=Cr=0)
41 * were not represented exactly.  Now we sacrifice exact representation of
42 * maximum red and maximum blue in order to get exact grayscales.
43 *
44 * To avoid floating-point arithmetic, we represent the fractional constants
45 * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
46 * the products by 2^16, with appropriate rounding, to get the correct answer.
47 *
48 * For even more speed, we avoid doing any multiplications in the inner loop
49 * by precalculating the constants times R,G,B for all possible values.
50 * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
51 * for 12-bit samples it is still acceptable.  It's not very reasonable for
52 * 16-bit samples, but if you want lossless storage you shouldn't be changing
53 * colorspace anyway.
54 * The CENTERJSAMPLE offsets and the rounding fudge-factor of 0.5 are included
55 * in the tables to save adding them separately in the inner loop.
56 */
57
58#define SCALEBITS       16      /* speediest right-shift on some machines */
59#define CBCR_OFFSET     ((INT32) CENTERJSAMPLE << SCALEBITS)
60#define ONE_HALF        ((INT32) 1 << (SCALEBITS-1))
61#define FIX(x)          ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
62
63/* We allocate one big table and divide it up into eight parts, instead of
64 * doing eight alloc_small requests.  This lets us use a single table base
65 * address, which can be held in a register in the inner loops on many
66 * machines (more than can hold all eight addresses, anyway).
67 */
68
69#define R_Y_OFF         0                       /* offset to R => Y section */
70#define G_Y_OFF         (1*(MAXJSAMPLE+1))      /* offset to G => Y section */
71#define B_Y_OFF         (2*(MAXJSAMPLE+1))      /* etc. */
72#define R_CB_OFF        (3*(MAXJSAMPLE+1))
73#define G_CB_OFF        (4*(MAXJSAMPLE+1))
74#define B_CB_OFF        (5*(MAXJSAMPLE+1))
75#define R_CR_OFF        B_CB_OFF                /* B=>Cb, R=>Cr are the same */
76#define G_CR_OFF        (6*(MAXJSAMPLE+1))
77#define B_CR_OFF        (7*(MAXJSAMPLE+1))
78#define TABLE_SIZE      (8*(MAXJSAMPLE+1))
79
80
81/*
82 * Initialize for RGB->YCC colorspace conversion.
83 */
84
85METHODDEF(void)
86rgb_ycc_start (j_compress_ptr cinfo)
87{
88  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
89  INT32 * rgb_ycc_tab;
90  INT32 i;
91
92  /* Allocate and fill in the conversion tables. */
93  cconvert->rgb_ycc_tab = rgb_ycc_tab = (INT32 *)
94    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
95                                (TABLE_SIZE * SIZEOF(INT32)));
96
97  for (i = 0; i <= MAXJSAMPLE; i++) {
98    rgb_ycc_tab[i+R_Y_OFF] = FIX(0.29900) * i;
99    rgb_ycc_tab[i+G_Y_OFF] = FIX(0.58700) * i;
100    rgb_ycc_tab[i+B_Y_OFF] = FIX(0.11400) * i     + ONE_HALF;
101    rgb_ycc_tab[i+R_CB_OFF] = (-FIX(0.16874)) * i;
102    rgb_ycc_tab[i+G_CB_OFF] = (-FIX(0.33126)) * i;
103    /* We use a rounding fudge-factor of 0.5-epsilon for Cb and Cr.
104     * This ensures that the maximum output will round to MAXJSAMPLE
105     * not MAXJSAMPLE+1, and thus that we don't have to range-limit.
106     */
107    rgb_ycc_tab[i+B_CB_OFF] = FIX(0.50000) * i    + CBCR_OFFSET + ONE_HALF-1;
108/*  B=>Cb and R=>Cr tables are the same
109    rgb_ycc_tab[i+R_CR_OFF] = FIX(0.50000) * i    + CBCR_OFFSET + ONE_HALF-1;
110*/
111    rgb_ycc_tab[i+G_CR_OFF] = (-FIX(0.41869)) * i;
112    rgb_ycc_tab[i+B_CR_OFF] = (-FIX(0.08131)) * i;
113  }
114}
115
116
117/*
118 * Convert some rows of samples to the JPEG colorspace.
119 *
120 * Note that we change from the application's interleaved-pixel format
121 * to our internal noninterleaved, one-plane-per-component format.
122 * The input buffer is therefore three times as wide as the output buffer.
123 *
124 * A starting row offset is provided only for the output buffer.  The caller
125 * can easily adjust the passed input_buf value to accommodate any row
126 * offset required on that side.
127 */
128
129METHODDEF(void)
130rgb_ycc_convert (j_compress_ptr cinfo,
131                 JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
132                 JDIMENSION output_row, int num_rows)
133{
134  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
135  register int r, g, b;
136  register INT32 * ctab = cconvert->rgb_ycc_tab;
137  register JSAMPROW inptr;
138  register JSAMPROW outptr0, outptr1, outptr2;
139  register JDIMENSION col;
140  JDIMENSION num_cols = cinfo->image_width;
141
142  while (--num_rows >= 0) {
143    inptr = *input_buf++;
144    outptr0 = output_buf[0][output_row];
145    outptr1 = output_buf[1][output_row];
146    outptr2 = output_buf[2][output_row];
147    output_row++;
148    for (col = 0; col < num_cols; col++) {
149      r = GETJSAMPLE(inptr[RGB_RED]);
150      g = GETJSAMPLE(inptr[RGB_GREEN]);
151      b = GETJSAMPLE(inptr[RGB_BLUE]);
152      inptr += RGB_PIXELSIZE;
153      /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
154       * must be too; we do not need an explicit range-limiting operation.
155       * Hence the value being shifted is never negative, and we don't
156       * need the general RIGHT_SHIFT macro.
157       */
158      /* Y */
159      outptr0[col] = (JSAMPLE)
160                ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
161                 >> SCALEBITS);
162      /* Cb */
163      outptr1[col] = (JSAMPLE)
164                ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
165                 >> SCALEBITS);
166      /* Cr */
167      outptr2[col] = (JSAMPLE)
168                ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
169                 >> SCALEBITS);
170    }
171  }
172}
173
174
175/**************** Cases other than RGB -> YCbCr **************/
176
177
178/*
179 * Convert some rows of samples to the JPEG colorspace.
180 * This version handles RGB->grayscale conversion, which is the same
181 * as the RGB->Y portion of RGB->YCbCr.
182 * We assume rgb_ycc_start has been called (we only use the Y tables).
183 */
184
185METHODDEF(void)
186rgb_gray_convert (j_compress_ptr cinfo,
187                  JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
188                  JDIMENSION output_row, int num_rows)
189{
190  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
191  register int r, g, b;
192  register INT32 * ctab = cconvert->rgb_ycc_tab;
193  register JSAMPROW inptr;
194  register JSAMPROW outptr;
195  register JDIMENSION col;
196  JDIMENSION num_cols = cinfo->image_width;
197
198  while (--num_rows >= 0) {
199    inptr = *input_buf++;
200    outptr = output_buf[0][output_row];
201    output_row++;
202    for (col = 0; col < num_cols; col++) {
203      r = GETJSAMPLE(inptr[RGB_RED]);
204      g = GETJSAMPLE(inptr[RGB_GREEN]);
205      b = GETJSAMPLE(inptr[RGB_BLUE]);
206      inptr += RGB_PIXELSIZE;
207      /* Y */
208      outptr[col] = (JSAMPLE)
209                ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
210                 >> SCALEBITS);
211    }
212  }
213}
214
215
216/*
217 * Convert some rows of samples to the JPEG colorspace.
218 * This version handles Adobe-style CMYK->YCCK conversion,
219 * where we convert R=1-C, G=1-M, and B=1-Y to YCbCr using the same
220 * conversion as above, while passing K (black) unchanged.
221 * We assume rgb_ycc_start has been called.
222 */
223
224METHODDEF(void)
225cmyk_ycck_convert (j_compress_ptr cinfo,
226                   JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
227                   JDIMENSION output_row, int num_rows)
228{
229  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
230  register int r, g, b;
231  register INT32 * ctab = cconvert->rgb_ycc_tab;
232  register JSAMPROW inptr;
233  register JSAMPROW outptr0, outptr1, outptr2, outptr3;
234  register JDIMENSION col;
235  JDIMENSION num_cols = cinfo->image_width;
236
237  while (--num_rows >= 0) {
238    inptr = *input_buf++;
239    outptr0 = output_buf[0][output_row];
240    outptr1 = output_buf[1][output_row];
241    outptr2 = output_buf[2][output_row];
242    outptr3 = output_buf[3][output_row];
243    output_row++;
244    for (col = 0; col < num_cols; col++) {
245      r = MAXJSAMPLE - GETJSAMPLE(inptr[0]);
246      g = MAXJSAMPLE - GETJSAMPLE(inptr[1]);
247      b = MAXJSAMPLE - GETJSAMPLE(inptr[2]);
248      /* K passes through as-is */
249      outptr3[col] = inptr[3];  /* don't need GETJSAMPLE here */
250      inptr += 4;
251      /* If the inputs are 0..MAXJSAMPLE, the outputs of these equations
252       * must be too; we do not need an explicit range-limiting operation.
253       * Hence the value being shifted is never negative, and we don't
254       * need the general RIGHT_SHIFT macro.
255       */
256      /* Y */
257      outptr0[col] = (JSAMPLE)
258                ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
259                 >> SCALEBITS);
260      /* Cb */
261      outptr1[col] = (JSAMPLE)
262                ((ctab[r+R_CB_OFF] + ctab[g+G_CB_OFF] + ctab[b+B_CB_OFF])
263                 >> SCALEBITS);
264      /* Cr */
265      outptr2[col] = (JSAMPLE)
266                ((ctab[r+R_CR_OFF] + ctab[g+G_CR_OFF] + ctab[b+B_CR_OFF])
267                 >> SCALEBITS);
268    }
269  }
270}
271
272
273/*
274 * Convert some rows of samples to the JPEG colorspace.
275 * This version handles grayscale output with no conversion.
276 * The source can be either plain grayscale or YCbCr (since Y == gray).
277 */
278
279METHODDEF(void)
280grayscale_convert (j_compress_ptr cinfo,
281                   JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
282                   JDIMENSION output_row, int num_rows)
283{
284  register JSAMPROW inptr;
285  register JSAMPROW outptr;
286  register JDIMENSION col;
287  JDIMENSION num_cols = cinfo->image_width;
288  int instride = cinfo->input_components;
289
290  while (--num_rows >= 0) {
291    inptr = *input_buf++;
292    outptr = output_buf[0][output_row];
293    output_row++;
294    for (col = 0; col < num_cols; col++) {
295      outptr[col] = inptr[0];   /* don't need GETJSAMPLE() here */
296      inptr += instride;
297    }
298  }
299}
300
301
302/*
303 * Convert some rows of samples to the JPEG colorspace.
304 * This version handles multi-component colorspaces without conversion.
305 * We assume input_components == num_components.
306 */
307
308METHODDEF(void)
309null_convert (j_compress_ptr cinfo,
310              JSAMPARRAY input_buf, JSAMPIMAGE output_buf,
311              JDIMENSION output_row, int num_rows)
312{
313  register JSAMPROW inptr;
314  register JSAMPROW outptr;
315  register JDIMENSION col;
316  register int ci;
317  int nc = cinfo->num_components;
318  JDIMENSION num_cols = cinfo->image_width;
319
320  while (--num_rows >= 0) {
321    /* It seems fastest to make a separate pass for each component. */
322    for (ci = 0; ci < nc; ci++) {
323      inptr = *input_buf;
324      outptr = output_buf[ci][output_row];
325      for (col = 0; col < num_cols; col++) {
326        outptr[col] = inptr[ci]; /* don't need GETJSAMPLE() here */
327        inptr += nc;
328      }
329    }
330    input_buf++;
331    output_row++;
332  }
333}
334
335
336/*
337 * Empty method for start_pass.
338 */
339
340METHODDEF(void)
341null_method (j_compress_ptr cinfo)
342{
343  /* no work needed */
344}
345
346
347/*
348 * Module initialization routine for input colorspace conversion.
349 */
350
351GLOBAL(void)
352jinit_color_converter (j_compress_ptr cinfo)
353{
354  my_cconvert_ptr cconvert;
355
356  cconvert = (my_cconvert_ptr)
357    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
358                                SIZEOF(my_color_converter));
359  cinfo->cconvert = (struct jpeg_color_converter *) cconvert;
360  /* set start_pass to null method until we find out differently */
361  cconvert->pub.start_pass = null_method;
362
363  /* Make sure input_components agrees with in_color_space */
364  switch (cinfo->in_color_space) {
365  case JCS_GRAYSCALE:
366    if (cinfo->input_components != 1)
367      ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
368    break;
369
370  case JCS_RGB:
371#if RGB_PIXELSIZE != 3
372    if (cinfo->input_components != RGB_PIXELSIZE)
373      ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
374    break;
375#endif /* else share code with YCbCr */
376
377  case JCS_YCbCr:
378    if (cinfo->input_components != 3)
379      ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
380    break;
381
382  case JCS_CMYK:
383  case JCS_YCCK:
384    if (cinfo->input_components != 4)
385      ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
386    break;
387
388  default:                      /* JCS_UNKNOWN can be anything */
389    if (cinfo->input_components < 1)
390      ERREXIT(cinfo, JERR_BAD_IN_COLORSPACE);
391    break;
392  }
393
394  /* Check num_components, set conversion method based on requested space */
395  switch (cinfo->jpeg_color_space) {
396  case JCS_GRAYSCALE:
397    if (cinfo->num_components != 1)
398      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
399    if (cinfo->in_color_space == JCS_GRAYSCALE)
400      cconvert->pub.color_convert = grayscale_convert;
401    else if (cinfo->in_color_space == JCS_RGB) {
402      cconvert->pub.start_pass = rgb_ycc_start;
403      cconvert->pub.color_convert = rgb_gray_convert;
404    } else if (cinfo->in_color_space == JCS_YCbCr)
405      cconvert->pub.color_convert = grayscale_convert;
406    else
407      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
408    break;
409
410  case JCS_RGB:
411    if (cinfo->num_components != 3)
412      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
413    if (cinfo->in_color_space == JCS_RGB && RGB_PIXELSIZE == 3)
414      cconvert->pub.color_convert = null_convert;
415    else
416      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
417    break;
418
419  case JCS_YCbCr:
420    if (cinfo->num_components != 3)
421      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
422    if (cinfo->in_color_space == JCS_RGB) {
423      cconvert->pub.start_pass = rgb_ycc_start;
424      cconvert->pub.color_convert = rgb_ycc_convert;
425    } else if (cinfo->in_color_space == JCS_YCbCr)
426      cconvert->pub.color_convert = null_convert;
427    else
428      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
429    break;
430
431  case JCS_CMYK:
432    if (cinfo->num_components != 4)
433      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
434    if (cinfo->in_color_space == JCS_CMYK)
435      cconvert->pub.color_convert = null_convert;
436    else
437      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
438    break;
439
440  case JCS_YCCK:
441    if (cinfo->num_components != 4)
442      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
443    if (cinfo->in_color_space == JCS_CMYK) {
444      cconvert->pub.start_pass = rgb_ycc_start;
445      cconvert->pub.color_convert = cmyk_ycck_convert;
446    } else if (cinfo->in_color_space == JCS_YCCK)
447      cconvert->pub.color_convert = null_convert;
448    else
449      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
450    break;
451
452  default:                      /* allow null conversion of JCS_UNKNOWN */
453    if (cinfo->jpeg_color_space != cinfo->in_color_space ||
454        cinfo->num_components != cinfo->input_components)
455      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
456    cconvert->pub.color_convert = null_convert;
457    break;
458  }
459}
Note: See TracBrowser for help on using the repository browser.