1793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
2793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * jdcolor.c
3793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *
4793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Copyright (C) 1991-1997, Thomas G. Lane.
5793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Modified 2011-2012 by Guido Vollbeding.
6793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * This file is part of the Independent JPEG Group's software.
7793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * For conditions of distribution and use, see the accompanying README file.
8793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *
9793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * This file contains output colorspace conversion routines.
10793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
11793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
12793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define JPEG_INTERNALS
13793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "jinclude.h"
14793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#include "jpeglib.h"
15793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
16793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
17793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* Private subobject */
18793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
19793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertypedef struct {
20793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  struct jpeg_color_deconverter pub; /* public fields */
21793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
22793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  /* Private state for YCC->RGB conversion */
23793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  int * Cr_r_tab;		/* => table for Cr to R conversion */
24793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  int * Cb_b_tab;		/* => table for Cb to B conversion */
25793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  INT32 * Cr_g_tab;		/* => table for Cr to G conversion */
26793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  INT32 * Cb_g_tab;		/* => table for Cb to G conversion */
27793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
28793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  /* Private state for RGB->Y conversion */
29793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  INT32 * rgb_y_tab;		/* => table for RGB to Y conversion */
30793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler} my_color_deconverter;
31793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
32793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslertypedef my_color_deconverter * my_cconvert_ptr;
33793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
34793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
35793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/**************** YCbCr -> RGB conversion: most common case **************/
36793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/****************   RGB -> Y   conversion: less common case **************/
37793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
38793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
39793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
40793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
41793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * The conversion equations to be implemented are therefore
42793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *
43793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *	R = Y                + 1.40200 * Cr
44793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *	G = Y - 0.34414 * Cb - 0.71414 * Cr
45793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *	B = Y + 1.77200 * Cb
46793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *
47793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *	Y = 0.29900 * R + 0.58700 * G + 0.11400 * B
48793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *
49793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * where Cb and Cr represent the incoming values less CENTERJSAMPLE.
50793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
51793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *
52793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * To avoid floating-point arithmetic, we represent the fractional constants
53793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
54793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * the products by 2^16, with appropriate rounding, to get the correct answer.
55793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Notice that Y, being an integral input, does not contribute any fraction
56793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * so it need not participate in the rounding.
57793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *
58793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * For even more speed, we avoid doing any multiplications in the inner loop
59793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * by precalculating the constants times Cb and Cr for all possible values.
60793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
61793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * for 12-bit samples it is still acceptable.  It's not very reasonable for
62793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * 16-bit samples, but if you want lossless storage you shouldn't be changing
63793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * colorspace anyway.
64793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * The Cr=>R and Cb=>B values can be rounded to integers in advance; the
65793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * values for the G calculation are left scaled up, since we must add them
66793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * together before rounding.
67793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
68793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
69793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define SCALEBITS	16	/* speediest right-shift on some machines */
70793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define ONE_HALF	((INT32) 1 << (SCALEBITS-1))
71793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define FIX(x)		((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
72793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
73793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/* We allocate one big table for RGB->Y conversion and divide it up into
74793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * three parts, instead of doing three alloc_small requests.  This lets us
75793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * use a single table base address, which can be held in a register in the
76793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * inner loops on many machines (more than can hold all three addresses,
77793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * anyway).
78793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
79793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
80793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define R_Y_OFF		0			/* offset to R => Y section */
81793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define G_Y_OFF		(1*(MAXJSAMPLE+1))	/* offset to G => Y section */
82793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define B_Y_OFF		(2*(MAXJSAMPLE+1))	/* etc. */
83793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler#define TABLE_SIZE	(3*(MAXJSAMPLE+1))
84793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
85793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
86793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
87793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Initialize tables for YCC->RGB colorspace conversion.
88793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
89793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
90793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerLOCAL(void)
91793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerbuild_ycc_rgb_table (j_decompress_ptr cinfo)
92793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
93793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
94793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  int i;
95793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  INT32 x;
96793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  SHIFT_TEMPS
97793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
98793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  cconvert->Cr_r_tab = (int *)
99793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
100793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                (MAXJSAMPLE+1) * SIZEOF(int));
101793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  cconvert->Cb_b_tab = (int *)
102793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
103793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                (MAXJSAMPLE+1) * SIZEOF(int));
104793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  cconvert->Cr_g_tab = (INT32 *)
105793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
106793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                (MAXJSAMPLE+1) * SIZEOF(INT32));
107793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  cconvert->Cb_g_tab = (INT32 *)
108793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
109793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                (MAXJSAMPLE+1) * SIZEOF(INT32));
110793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
111793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
112793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
113793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
114793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* Cr=>R value is nearest int to 1.40200 * x */
115793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cconvert->Cr_r_tab[i] = (int)
116793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
117793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* Cb=>B value is nearest int to 1.77200 * x */
118793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cconvert->Cb_b_tab[i] = (int)
119793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
120793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* Cr=>G value is scaled-up -0.71414 * x */
121793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x;
122793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* Cb=>G value is scaled-up -0.34414 * x */
123793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* We also add in ONE_HALF so that need not do it in inner loop */
124793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
125793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
126793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
127793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
128793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
129793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
130793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Convert some rows of samples to the output colorspace.
131793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler *
132793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Note that we change from noninterleaved, one-plane-per-component format
133793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * to interleaved-pixel format.  The output buffer is therefore three times
134793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * as wide as the input buffer.
135793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * A starting row offset is provided only for the input buffer.  The caller
136793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * can easily adjust the passed output_buf value to accommodate any row
137793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * offset required on that side.
138793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
139793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
140793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void)
141793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerycc_rgb_convert (j_decompress_ptr cinfo,
142793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 JSAMPIMAGE input_buf, JDIMENSION input_row,
143793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 JSAMPARRAY output_buf, int num_rows)
144793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
145793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
146793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register int y, cb, cr;
147793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JSAMPROW outptr;
148793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JSAMPROW inptr0, inptr1, inptr2;
149793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JDIMENSION col;
150793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  JDIMENSION num_cols = cinfo->output_width;
151793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  /* copy these pointers into registers if possible */
152793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JSAMPLE * range_limit = cinfo->sample_range_limit;
153793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register int * Crrtab = cconvert->Cr_r_tab;
154793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register int * Cbbtab = cconvert->Cb_b_tab;
155793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register INT32 * Crgtab = cconvert->Cr_g_tab;
156793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register INT32 * Cbgtab = cconvert->Cb_g_tab;
157793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  SHIFT_TEMPS
158793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
159793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  while (--num_rows >= 0) {
160793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr0 = input_buf[0][input_row];
161793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr1 = input_buf[1][input_row];
162793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr2 = input_buf[2][input_row];
163793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    input_row++;
164793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    outptr = *output_buf++;
165793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for (col = 0; col < num_cols; col++) {
166793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      y  = GETJSAMPLE(inptr0[col]);
167793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      cb = GETJSAMPLE(inptr1[col]);
168793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      cr = GETJSAMPLE(inptr2[col]);
169793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* Range-limiting is essential due to noise introduced by DCT losses. */
170793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr[RGB_RED] =   range_limit[y + Crrtab[cr]];
171793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr[RGB_GREEN] = range_limit[y +
172793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                              ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
173793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                                 SCALEBITS))];
174793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr[RGB_BLUE] =  range_limit[y + Cbbtab[cb]];
175793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr += RGB_PIXELSIZE;
176793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
177793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
178793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
179793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
180793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
181793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/**************** Cases other than YCbCr -> RGB **************/
182793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
183793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
184793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
185793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Initialize for RGB->grayscale colorspace conversion.
186793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
187793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
188793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerLOCAL(void)
189793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerbuild_rgb_y_table (j_decompress_ptr cinfo)
190793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
191793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
192793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  INT32 * rgb_y_tab;
193793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  INT32 i;
194793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
195793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  /* Allocate and fill in the conversion tables. */
196793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  cconvert->rgb_y_tab = rgb_y_tab = (INT32 *)
197793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
198793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                (TABLE_SIZE * SIZEOF(INT32)));
199793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
200793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  for (i = 0; i <= MAXJSAMPLE; i++) {
201793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    rgb_y_tab[i+R_Y_OFF] = FIX(0.29900) * i;
202793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    rgb_y_tab[i+G_Y_OFF] = FIX(0.58700) * i;
203793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    rgb_y_tab[i+B_Y_OFF] = FIX(0.11400) * i + ONE_HALF;
204793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
205793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
206793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
207793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
208793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
209793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Convert RGB to grayscale.
210793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
211793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
212793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void)
213793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerrgb_gray_convert (j_decompress_ptr cinfo,
214793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                  JSAMPIMAGE input_buf, JDIMENSION input_row,
215793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                  JSAMPARRAY output_buf, int num_rows)
216793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
217793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
218793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register INT32 * ctab = cconvert->rgb_y_tab;
219793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register int r, g, b;
220793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JSAMPROW outptr;
221793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JSAMPROW inptr0, inptr1, inptr2;
222793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JDIMENSION col;
223793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  JDIMENSION num_cols = cinfo->output_width;
224793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
225793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  while (--num_rows >= 0) {
226793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr0 = input_buf[0][input_row];
227793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr1 = input_buf[1][input_row];
228793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr2 = input_buf[2][input_row];
229793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    input_row++;
230793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    outptr = *output_buf++;
231793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for (col = 0; col < num_cols; col++) {
232793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      r = GETJSAMPLE(inptr0[col]);
233793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      g = GETJSAMPLE(inptr1[col]);
234793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      b = GETJSAMPLE(inptr2[col]);
235793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* Y */
236793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr[col] = (JSAMPLE)
237793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
238793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 >> SCALEBITS);
239793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
240793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
241793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
242793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
243793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
244793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
245793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * [R-G,G,B-G] to [R,G,B] conversion with modulo calculation
246793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * (inverse color transform).
247793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
248793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
249793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void)
250793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerrgb1_rgb_convert (j_decompress_ptr cinfo,
251793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                  JSAMPIMAGE input_buf, JDIMENSION input_row,
252793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                  JSAMPARRAY output_buf, int num_rows)
253793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
254793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register int r, g, b;
255793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JSAMPROW outptr;
256793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JSAMPROW inptr0, inptr1, inptr2;
257793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JDIMENSION col;
258793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  JDIMENSION num_cols = cinfo->output_width;
259793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
260793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  while (--num_rows >= 0) {
261793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr0 = input_buf[0][input_row];
262793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr1 = input_buf[1][input_row];
263793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr2 = input_buf[2][input_row];
264793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    input_row++;
265793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    outptr = *output_buf++;
266793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for (col = 0; col < num_cols; col++) {
267793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      r = GETJSAMPLE(inptr0[col]);
268793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      g = GETJSAMPLE(inptr1[col]);
269793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      b = GETJSAMPLE(inptr2[col]);
270793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* Assume that MAXJSAMPLE+1 is a power of 2, so that the MOD
271793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       * (modulo) operator is equivalent to the bitmask operator AND.
272793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       */
273793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr[RGB_RED]   = (JSAMPLE) ((r + g - CENTERJSAMPLE) & MAXJSAMPLE);
274793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr[RGB_GREEN] = (JSAMPLE) g;
275793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr[RGB_BLUE]  = (JSAMPLE) ((b + g - CENTERJSAMPLE) & MAXJSAMPLE);
276793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr += RGB_PIXELSIZE;
277793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
278793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
279793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
280793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
281793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
282793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
283793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * [R-G,G,B-G] to grayscale conversion with modulo calculation
284793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * (inverse color transform).
285793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
286793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
287793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void)
288793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerrgb1_gray_convert (j_decompress_ptr cinfo,
289793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                   JSAMPIMAGE input_buf, JDIMENSION input_row,
290793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                   JSAMPARRAY output_buf, int num_rows)
291793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
292793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
293793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register INT32 * ctab = cconvert->rgb_y_tab;
294793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register int r, g, b;
295793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JSAMPROW outptr;
296793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JSAMPROW inptr0, inptr1, inptr2;
297793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JDIMENSION col;
298793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  JDIMENSION num_cols = cinfo->output_width;
299793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
300793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  while (--num_rows >= 0) {
301793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr0 = input_buf[0][input_row];
302793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr1 = input_buf[1][input_row];
303793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr2 = input_buf[2][input_row];
304793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    input_row++;
305793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    outptr = *output_buf++;
306793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for (col = 0; col < num_cols; col++) {
307793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      r = GETJSAMPLE(inptr0[col]);
308793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      g = GETJSAMPLE(inptr1[col]);
309793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      b = GETJSAMPLE(inptr2[col]);
310793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* Assume that MAXJSAMPLE+1 is a power of 2, so that the MOD
311793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       * (modulo) operator is equivalent to the bitmask operator AND.
312793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler       */
313793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      r = (r + g - CENTERJSAMPLE) & MAXJSAMPLE;
314793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      b = (b + g - CENTERJSAMPLE) & MAXJSAMPLE;
315793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* Y */
316793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr[col] = (JSAMPLE)
317793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                ((ctab[r+R_Y_OFF] + ctab[g+G_Y_OFF] + ctab[b+B_Y_OFF])
318793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                 >> SCALEBITS);
319793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
320793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
321793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
322793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
323793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
324793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
325793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * No colorspace change, but conversion from separate-planes
326793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * to interleaved representation.
327793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
328793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
329793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void)
330793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerrgb_convert (j_decompress_ptr cinfo,
331793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             JSAMPIMAGE input_buf, JDIMENSION input_row,
332793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler             JSAMPARRAY output_buf, int num_rows)
333793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
334793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JSAMPROW outptr;
335793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JSAMPROW inptr0, inptr1, inptr2;
336793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JDIMENSION col;
337793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  JDIMENSION num_cols = cinfo->output_width;
338793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
339793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  while (--num_rows >= 0) {
340793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr0 = input_buf[0][input_row];
341793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr1 = input_buf[1][input_row];
342793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr2 = input_buf[2][input_row];
343793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    input_row++;
344793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    outptr = *output_buf++;
345793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for (col = 0; col < num_cols; col++) {
346793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* We can dispense with GETJSAMPLE() here */
347793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr[RGB_RED]   = inptr0[col];
348793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr[RGB_GREEN] = inptr1[col];
349793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr[RGB_BLUE]  = inptr2[col];
350793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr += RGB_PIXELSIZE;
351793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
352793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
353793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
354793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
355793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
356793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
357793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Color conversion for no colorspace change: just copy the data,
358793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * converting from separate-planes to interleaved representation.
359793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
360793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
361793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void)
362793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslernull_convert (j_decompress_ptr cinfo,
363793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler              JSAMPIMAGE input_buf, JDIMENSION input_row,
364793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler              JSAMPARRAY output_buf, int num_rows)
365793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
366793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  int ci;
367793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register int nc = cinfo->num_components;
368793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JSAMPROW outptr;
369793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JSAMPROW inptr;
370793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JDIMENSION col;
371793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  JDIMENSION num_cols = cinfo->output_width;
372793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
373793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  while (--num_rows >= 0) {
374793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for (ci = 0; ci < nc; ci++) {
375793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      inptr = input_buf[ci][input_row];
376793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr = output_buf[0] + ci;
377793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      for (col = 0; col < num_cols; col++) {
378793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        *outptr = *inptr++;	/* needn't bother with GETJSAMPLE() here */
379793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        outptr += nc;
380793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      }
381793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
382793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    input_row++;
383793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    output_buf++;
384793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
385793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
386793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
387793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
388793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
389793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Color conversion for grayscale: just copy the data.
390793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * This also works for YCbCr -> grayscale conversion, in which
391793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * we just copy the Y (luminance) component and ignore chrominance.
392793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
393793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
394793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void)
395793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslergrayscale_convert (j_decompress_ptr cinfo,
396793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                   JSAMPIMAGE input_buf, JDIMENSION input_row,
397793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                   JSAMPARRAY output_buf, int num_rows)
398793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
399793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0,
400793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                    num_rows, cinfo->output_width);
401793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
402793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
403793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
404793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
405793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Convert grayscale to RGB: just duplicate the graylevel three times.
406793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * This is provided to support applications that don't want to cope
407793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * with grayscale as a separate case.
408793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
409793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
410793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void)
411793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslergray_rgb_convert (j_decompress_ptr cinfo,
412793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                  JSAMPIMAGE input_buf, JDIMENSION input_row,
413793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                  JSAMPARRAY output_buf, int num_rows)
414793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
415793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JSAMPROW outptr;
416793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JSAMPROW inptr;
417793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JDIMENSION col;
418793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  JDIMENSION num_cols = cinfo->output_width;
419793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
420793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  while (--num_rows >= 0) {
421793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr = input_buf[0][input_row++];
422793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    outptr = *output_buf++;
423793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for (col = 0; col < num_cols; col++) {
424793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* We can dispense with GETJSAMPLE() here */
425793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col];
426793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr += RGB_PIXELSIZE;
427793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
428793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
429793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
430793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
431793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
432793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
433793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Adobe-style YCCK->CMYK conversion.
434793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
435793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * conversion as above, while passing K (black) unchanged.
436793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * We assume build_ycc_rgb_table has been called.
437793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
438793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
439793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void)
440793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerycck_cmyk_convert (j_decompress_ptr cinfo,
441793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                   JSAMPIMAGE input_buf, JDIMENSION input_row,
442793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                   JSAMPARRAY output_buf, int num_rows)
443793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
444793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
445793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register int y, cb, cr;
446793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JSAMPROW outptr;
447793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JSAMPROW inptr0, inptr1, inptr2, inptr3;
448793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JDIMENSION col;
449793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  JDIMENSION num_cols = cinfo->output_width;
450793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  /* copy these pointers into registers if possible */
451793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register JSAMPLE * range_limit = cinfo->sample_range_limit;
452793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register int * Crrtab = cconvert->Cr_r_tab;
453793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register int * Cbbtab = cconvert->Cb_b_tab;
454793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register INT32 * Crgtab = cconvert->Cr_g_tab;
455793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  register INT32 * Cbgtab = cconvert->Cb_g_tab;
456793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  SHIFT_TEMPS
457793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
458793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  while (--num_rows >= 0) {
459793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr0 = input_buf[0][input_row];
460793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr1 = input_buf[1][input_row];
461793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr2 = input_buf[2][input_row];
462793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    inptr3 = input_buf[3][input_row];
463793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    input_row++;
464793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    outptr = *output_buf++;
465793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    for (col = 0; col < num_cols; col++) {
466793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      y  = GETJSAMPLE(inptr0[col]);
467793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      cb = GETJSAMPLE(inptr1[col]);
468793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      cr = GETJSAMPLE(inptr2[col]);
469793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* Range-limiting is essential due to noise introduced by DCT losses. */
470793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])];	/* red */
471793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr[1] = range_limit[MAXJSAMPLE - (y +			/* green */
472793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                              ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
473793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                                 SCALEBITS)))];
474793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])];	/* blue */
475793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* K passes through unchanged */
476793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr[3] = inptr3[col];	/* don't need GETJSAMPLE here */
477793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      outptr += 4;
478793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    }
479793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
480793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
481793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
482793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
483793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
484793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Empty method for start_pass.
485793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
486793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
487793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerMETHODDEF(void)
488793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerstart_pass_dcolor (j_decompress_ptr cinfo)
489793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
490793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  /* no work needed */
491793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
492793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
493793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
494793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler/*
495793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler * Module initialization routine for output colorspace conversion.
496793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler */
497793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
498793ee12c6df9cad3806238d32528c49a3ff9331dNoah PreslerGLOBAL(void)
499793ee12c6df9cad3806238d32528c49a3ff9331dNoah Preslerjinit_color_deconverter (j_decompress_ptr cinfo)
500793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler{
501793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  my_cconvert_ptr cconvert;
502793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  int ci;
503793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
504793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  cconvert = (my_cconvert_ptr)
505793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
506793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler                                SIZEOF(my_color_deconverter));
507793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  cinfo->cconvert = &cconvert->pub;
508793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  cconvert->pub.start_pass = start_pass_dcolor;
509793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
510793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  /* Make sure num_components agrees with jpeg_color_space */
511793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  switch (cinfo->jpeg_color_space) {
512793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  case JCS_GRAYSCALE:
513793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (cinfo->num_components != 1)
514793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
515793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    break;
516793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
517793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  case JCS_RGB:
518793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  case JCS_YCbCr:
519793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (cinfo->num_components != 3)
520793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
521793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    break;
522793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
523793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  case JCS_CMYK:
524793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  case JCS_YCCK:
525793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (cinfo->num_components != 4)
526793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
527793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    break;
528793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
529793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  default:			/* JCS_UNKNOWN can be anything */
530793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (cinfo->num_components < 1)
531793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
532793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    break;
533793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
534793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
535793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  /* Support color transform only for RGB colorspace */
536793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (cinfo->color_transform && cinfo->jpeg_color_space != JCS_RGB)
537793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
538793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
539793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  /* Set out_color_components and conversion method based on requested space.
540793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   * Also clear the component_needed flags for any unused components,
541793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   * so that earlier pipeline stages can avoid useless computation.
542793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler   */
543793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
544793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  switch (cinfo->out_color_space) {
545793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  case JCS_GRAYSCALE:
546793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cinfo->out_color_components = 1;
547793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
548793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        cinfo->jpeg_color_space == JCS_YCbCr) {
549793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      cconvert->pub.color_convert = grayscale_convert;
550793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      /* For color->grayscale conversion, only the Y (0) component is needed */
551793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      for (ci = 1; ci < cinfo->num_components; ci++)
552793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        cinfo->comp_info[ci].component_needed = FALSE;
553793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } else if (cinfo->jpeg_color_space == JCS_RGB) {
554793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      switch (cinfo->color_transform) {
555793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case JCT_NONE:
556793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        cconvert->pub.color_convert = rgb_gray_convert;
557793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
558793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case JCT_SUBTRACT_GREEN:
559793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        cconvert->pub.color_convert = rgb1_gray_convert;
560793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
561793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      default:
562793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
563793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
564793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      }
565793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      build_rgb_y_table(cinfo);
566793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } else
567793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
568793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    break;
569793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
570793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  case JCS_RGB:
571793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cinfo->out_color_components = RGB_PIXELSIZE;
572793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (cinfo->jpeg_color_space == JCS_YCbCr) {
573793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      cconvert->pub.color_convert = ycc_rgb_convert;
574793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      build_ycc_rgb_table(cinfo);
575793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
576793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      cconvert->pub.color_convert = gray_rgb_convert;
577793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } else if (cinfo->jpeg_color_space == JCS_RGB) {
578793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      switch (cinfo->color_transform) {
579793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case JCT_NONE:
580793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        cconvert->pub.color_convert = rgb_convert;
581793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
582793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      case JCT_SUBTRACT_GREEN:
583793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        cconvert->pub.color_convert = rgb1_rgb_convert;
584793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
585793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      default:
586793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
587793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler        break;
588793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      }
589793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } else
590793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
591793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    break;
592793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
593793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  case JCS_CMYK:
594793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cinfo->out_color_components = 4;
595793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (cinfo->jpeg_color_space == JCS_YCCK) {
596793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      cconvert->pub.color_convert = ycck_cmyk_convert;
597793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      build_ycc_rgb_table(cinfo);
598793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } else if (cinfo->jpeg_color_space == JCS_CMYK) {
599793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      cconvert->pub.color_convert = null_convert;
600793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } else
601793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
602793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    break;
603793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
604793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  default:
605793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    /* Permit null conversion to same output space */
606793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    if (cinfo->out_color_space == cinfo->jpeg_color_space) {
607793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      cinfo->out_color_components = cinfo->num_components;
608793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      cconvert->pub.color_convert = null_convert;
609793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    } else			/* unsupported non-null conversion */
610793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
611793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    break;
612793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  }
613793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler
614793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  if (cinfo->quantize_colors)
615793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cinfo->output_components = 1; /* single colormapped output component */
616793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler  else
617793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler    cinfo->output_components = cinfo->out_color_components;
618793ee12c6df9cad3806238d32528c49a3ff9331dNoah Presler}
619