source: golgotha/src/i4/loaders/jpg/jccolor.cc @ 80

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