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