File: jdcolor.c

package info (click to toggle)
xloadimage 4.1-25
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, buster, sid, trixie
  • size: 4,820 kB
  • sloc: ansic: 36,084; asm: 284; makefile: 282; sh: 280
file content (302 lines) | stat: -rw-r--r-- 9,439 bytes parent folder | download | duplicates (10)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
/*
 * jdcolor.c
 *
 * Copyright (C) 1991, 1992, 1993, Thomas G. Lane.
 * This file is part of the Independent JPEG Group's software.
 * For conditions of distribution and use, see the accompanying README file.
 *
 * This file contains output colorspace conversion routines.
 * These routines are invoked via the methods color_convert
 * and colorout_init/term.
 */

#include "jinclude.h"


/**************** YCbCr -> RGB conversion: most common case **************/

/*
 * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
 * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
 * The conversion equations to be implemented are therefore
 *	R = Y                + 1.40200 * Cr
 *	G = Y - 0.34414 * Cb - 0.71414 * Cr
 *	B = Y + 1.77200 * Cb
 * where Cb and Cr represent the incoming values less MAXJSAMPLE/2.
 * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
 *
 * To avoid floating-point arithmetic, we represent the fractional constants
 * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
 * the products by 2^16, with appropriate rounding, to get the correct answer.
 * Notice that Y, being an integral input, does not contribute any fraction
 * so it need not participate in the rounding.
 *
 * For even more speed, we avoid doing any multiplications in the inner loop
 * by precalculating the constants times Cb and Cr for all possible values.
 * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
 * for 12-bit samples it is still acceptable.  It's not very reasonable for
 * 16-bit samples, but if you want lossless storage you shouldn't be changing
 * colorspace anyway.
 * The Cr=>R and Cb=>B values can be rounded to integers in advance; the
 * values for the G calculation are left scaled up, since we must add them
 * together before rounding.
 */

#ifdef SIXTEEN_BIT_SAMPLES
#define SCALEBITS	14	/* avoid overflow */
#else
#define SCALEBITS	16	/* speedier right-shift on some machines */
#endif
#define ONE_HALF	((INT32) 1 << (SCALEBITS-1))
#define FIX(x)		((INT32) ((x) * (1L<<SCALEBITS) + 0.5))

static int * Cr_r_tab;		/* => table for Cr to R conversion */
static int * Cb_b_tab;		/* => table for Cb to B conversion */
static INT32 * Cr_g_tab;	/* => table for Cr to G conversion */
static INT32 * Cb_g_tab;	/* => table for Cb to G conversion */


/*
 * Initialize for colorspace conversion.
 */

METHODDEF void
ycc_rgb_init (decompress_info_ptr cinfo)
{
  INT32 i, x2;
  SHIFT_TEMPS

  Cr_r_tab = (int *) (*cinfo->emethods->alloc_small)
				((MAXJSAMPLE+1) * SIZEOF(int));
  Cb_b_tab = (int *) (*cinfo->emethods->alloc_small)
				((MAXJSAMPLE+1) * SIZEOF(int));
  Cr_g_tab = (INT32 *) (*cinfo->emethods->alloc_small)
				((MAXJSAMPLE+1) * SIZEOF(INT32));
  Cb_g_tab = (INT32 *) (*cinfo->emethods->alloc_small)
				((MAXJSAMPLE+1) * SIZEOF(INT32));

  for (i = 0; i <= MAXJSAMPLE; i++) {
    /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
    /* The Cb or Cr value we are thinking of is x = i - MAXJSAMPLE/2 */
    x2 = 2*i - MAXJSAMPLE;	/* twice x */
    /* Cr=>R value is nearest int to 1.40200 * x */
    Cr_r_tab[i] = (int)
		    RIGHT_SHIFT(FIX(1.40200/2) * x2 + ONE_HALF, SCALEBITS);
    /* Cb=>B value is nearest int to 1.77200 * x */
    Cb_b_tab[i] = (int)
		    RIGHT_SHIFT(FIX(1.77200/2) * x2 + ONE_HALF, SCALEBITS);
    /* Cr=>G value is scaled-up -0.71414 * x */
    Cr_g_tab[i] = (- FIX(0.71414/2)) * x2;
    /* Cb=>G value is scaled-up -0.34414 * x */
    /* We also add in ONE_HALF so that need not do it in inner loop */
    Cb_g_tab[i] = (- FIX(0.34414/2)) * x2 + ONE_HALF;
  }
}


/*
 * Convert some rows of samples to the output colorspace.
 */

METHODDEF void
ycc_rgb_convert (decompress_info_ptr cinfo, int num_rows, long num_cols,
		 JSAMPIMAGE input_data, JSAMPIMAGE output_data)
{
#ifdef SIXTEEN_BIT_SAMPLES
  register INT32 y;
  register UINT16 cb, cr;
#else
  register int y, cb, cr;
#endif
  register JSAMPROW inptr0, inptr1, inptr2;
  register JSAMPROW outptr0, outptr1, outptr2;
  register long col;
  /* copy these pointers into registers if possible */
  register JSAMPLE * range_limit = cinfo->sample_range_limit;
  register int * Crrtab = Cr_r_tab;
  register int * Cbbtab = Cb_b_tab;
  register INT32 * Crgtab = Cr_g_tab;
  register INT32 * Cbgtab = Cb_g_tab;
  int row;
  SHIFT_TEMPS
  
  for (row = 0; row < num_rows; row++) {
    inptr0 = input_data[0][row];
    inptr1 = input_data[1][row];
    inptr2 = input_data[2][row];
    outptr0 = output_data[0][row];
    outptr1 = output_data[1][row];
    outptr2 = output_data[2][row];
    for (col = 0; col < num_cols; col++) {
      y  = GETJSAMPLE(inptr0[col]);
      cb = GETJSAMPLE(inptr1[col]);
      cr = GETJSAMPLE(inptr2[col]);
      /* Note: if the inputs were computed directly from RGB values,
       * range-limiting would be unnecessary here; but due to possible
       * noise in the DCT/IDCT phase, we do need to apply range limits.
       */
      outptr0[col] = range_limit[y + Crrtab[cr]];	/* red */
      outptr1[col] = range_limit[y +			/* green */
				 ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
						    SCALEBITS))];
      outptr2[col] = range_limit[y + Cbbtab[cb]];	/* blue */
    }
  }
}


/*
 * Finish up at the end of the file.
 */

METHODDEF void
ycc_rgb_term (decompress_info_ptr cinfo)
{
  /* no work (we let free_all release the workspace) */
}


/**************** Cases other than YCbCr -> RGB **************/


/*
 * Initialize for colorspace conversion.
 */

METHODDEF void
null_init (decompress_info_ptr cinfo)
/* colorout_init for cases where no setup is needed */
{
  /* no work needed */
}


/*
 * Color conversion for no colorspace change: just copy the data.
 */

METHODDEF void
null_convert (decompress_info_ptr cinfo, int num_rows, long num_cols,
	      JSAMPIMAGE input_data, JSAMPIMAGE output_data)
{
  short ci;

  for (ci = 0; ci < cinfo->num_components; ci++) {
    jcopy_sample_rows(input_data[ci], 0, output_data[ci], 0,
		      num_rows, num_cols);
  }
}


/*
 * Color conversion for grayscale: just copy the data.
 * This also works for YCbCr/YIQ -> grayscale conversion, in which
 * we just copy the Y (luminance) component and ignore chrominance.
 */

METHODDEF void
grayscale_convert (decompress_info_ptr cinfo, int num_rows, long num_cols,
		   JSAMPIMAGE input_data, JSAMPIMAGE output_data)
{
  jcopy_sample_rows(input_data[0], 0, output_data[0], 0,
		    num_rows, num_cols);
}


/*
 * Finish up at the end of the file.
 */

METHODDEF void
null_term (decompress_info_ptr cinfo)
/* colorout_term for cases where no teardown is needed */
{
  /* no work needed */
}



/*
 * The method selection routine for output colorspace conversion.
 */

GLOBAL void
jseldcolor (decompress_info_ptr cinfo)
{
  int ci;

  /* Make sure num_components agrees with jpeg_color_space */
  switch (cinfo->jpeg_color_space) {
  case CS_GRAYSCALE:
    if (cinfo->num_components != 1)
      ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
    break;

  case CS_RGB:
  case CS_YCbCr:
  case CS_YIQ:
    if (cinfo->num_components != 3)
      ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
    break;

  case CS_CMYK:
    if (cinfo->num_components != 4)
      ERREXIT(cinfo->emethods, "Bogus JPEG colorspace");
    break;

  default:
    ERREXIT(cinfo->emethods, "Unsupported JPEG colorspace");
    break;
  }

  /* Set color_out_comps and conversion method based on requested space. */
  /* Also clear the component_needed flags for any unused components, */
  /* so that earlier pipeline stages can avoid useless computation. */

  switch (cinfo->out_color_space) {
  case CS_GRAYSCALE:
    cinfo->color_out_comps = 1;
    if (cinfo->jpeg_color_space == CS_GRAYSCALE ||
	cinfo->jpeg_color_space == CS_YCbCr ||
	cinfo->jpeg_color_space == CS_YIQ) {
      cinfo->methods->color_convert = grayscale_convert;
      cinfo->methods->colorout_init = null_init;
      cinfo->methods->colorout_term = null_term;
      /* For color->grayscale conversion, only the Y (0) component is needed */
      for (ci = 1; ci < cinfo->num_components; ci++)
	cinfo->cur_comp_info[ci]->component_needed = FALSE;
    } else
      ERREXIT(cinfo->emethods, "Unsupported color conversion request");
    break;

  case CS_RGB:
    cinfo->color_out_comps = 3;
    if (cinfo->jpeg_color_space == CS_YCbCr) {
      cinfo->methods->color_convert = ycc_rgb_convert;
      cinfo->methods->colorout_init = ycc_rgb_init;
      cinfo->methods->colorout_term = ycc_rgb_term;
    } else if (cinfo->jpeg_color_space == CS_RGB) {
      cinfo->methods->color_convert = null_convert;
      cinfo->methods->colorout_init = null_init;
      cinfo->methods->colorout_term = null_term;
    } else
      ERREXIT(cinfo->emethods, "Unsupported color conversion request");
    break;

  default:
    /* Permit null conversion from CMYK or YCbCr to same output space */
    if (cinfo->out_color_space == cinfo->jpeg_color_space) {
      cinfo->color_out_comps = cinfo->num_components;
      cinfo->methods->color_convert = null_convert;
      cinfo->methods->colorout_init = null_init;
      cinfo->methods->colorout_term = null_term;
    } else			/* unsupported non-null conversion */
      ERREXIT(cinfo->emethods, "Unsupported color conversion request");
    break;
  }

  if (cinfo->quantize_colors)
    cinfo->final_out_comps = 1;	/* single colormapped output component */
  else
    cinfo->final_out_comps = cinfo->color_out_comps;
}