1/*
2 * jdcolor.c
3 *
4 * Copyright (C) 1991-1997, Thomas G. Lane.
5 * This file is part of the Independent JPEG Group's software.
6 * For conditions of distribution and use, see the accompanying README file.
7 *
8 * This file contains output colorspace conversion routines.
9 */
10
11#define JPEG_INTERNALS
12#include "jinclude.h"
13#include "jpeglib.h"
14
15
16/* Private subobject */
17
18typedef struct {
19  struct jpeg_color_deconverter pub; /* public fields */
20
21  /* Private state for YCC->RGB conversion */
22  int * Cr_r_tab;		/* => table for Cr to R conversion */
23  int * Cb_b_tab;		/* => table for Cb to B conversion */
24  INT32 * Cr_g_tab;		/* => table for Cr to G conversion */
25  INT32 * Cb_g_tab;		/* => table for Cb to G conversion */
26} my_color_deconverter;
27
28typedef my_color_deconverter * my_cconvert_ptr;
29
30
31#ifdef ANDROID_RGB
32
33/* Declarations for ordered dithering.
34 *
35 * We use 4x4 ordered dither array packed into 32 bits. This array is
36 * sufficent for dithering RGB_888 to RGB_565.
37 */
38
39#define DITHER_MASK         0x3
40#define DITHER_ROTATE(x)    (((x)<<24) | (((x)>>8)&0x00FFFFFF))
41static const INT32 dither_matrix[4] = {
42  0x0008020A,
43  0x0C040E06,
44  0x030B0109,
45  0x0F070D05
46};
47
48#endif
49
50
51/**************** YCbCr -> RGB conversion: most common case **************/
52
53/*
54 * YCbCr is defined per CCIR 601-1, except that Cb and Cr are
55 * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5.
56 * The conversion equations to be implemented are therefore
57 *	R = Y                + 1.40200 * Cr
58 *	G = Y - 0.34414 * Cb - 0.71414 * Cr
59 *	B = Y + 1.77200 * Cb
60 * where Cb and Cr represent the incoming values less CENTERJSAMPLE.
61 * (These numbers are derived from TIFF 6.0 section 21, dated 3-June-92.)
62 *
63 * To avoid floating-point arithmetic, we represent the fractional constants
64 * as integers scaled up by 2^16 (about 4 digits precision); we have to divide
65 * the products by 2^16, with appropriate rounding, to get the correct answer.
66 * Notice that Y, being an integral input, does not contribute any fraction
67 * so it need not participate in the rounding.
68 *
69 * For even more speed, we avoid doing any multiplications in the inner loop
70 * by precalculating the constants times Cb and Cr for all possible values.
71 * For 8-bit JSAMPLEs this is very reasonable (only 256 entries per table);
72 * for 12-bit samples it is still acceptable.  It's not very reasonable for
73 * 16-bit samples, but if you want lossless storage you shouldn't be changing
74 * colorspace anyway.
75 * The Cr=>R and Cb=>B values can be rounded to integers in advance; the
76 * values for the G calculation are left scaled up, since we must add them
77 * together before rounding.
78 */
79
80#define SCALEBITS	16	/* speediest right-shift on some machines */
81#define ONE_HALF	((INT32) 1 << (SCALEBITS-1))
82#define FIX(x)		((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
83
84
85/*
86 * Initialize tables for YCC->RGB colorspace conversion.
87 */
88
89LOCAL(void)
90build_ycc_rgb_table (j_decompress_ptr cinfo)
91{
92  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
93  int i;
94  INT32 x;
95  SHIFT_TEMPS
96
97  cconvert->Cr_r_tab = (int *)
98    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
99                                (MAXJSAMPLE+1) * SIZEOF(int));
100  cconvert->Cb_b_tab = (int *)
101    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
102                                (MAXJSAMPLE+1) * SIZEOF(int));
103  cconvert->Cr_g_tab = (INT32 *)
104    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
105                                (MAXJSAMPLE+1) * SIZEOF(INT32));
106  cconvert->Cb_g_tab = (INT32 *)
107    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
108                                (MAXJSAMPLE+1) * SIZEOF(INT32));
109
110  for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
111    /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
112    /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
113    /* Cr=>R value is nearest int to 1.40200 * x */
114    cconvert->Cr_r_tab[i] = (int)
115                    RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
116    /* Cb=>B value is nearest int to 1.77200 * x */
117    cconvert->Cb_b_tab[i] = (int)
118                    RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
119    /* Cr=>G value is scaled-up -0.71414 * x */
120    cconvert->Cr_g_tab[i] = (- FIX(0.71414)) * x;
121    /* Cb=>G value is scaled-up -0.34414 * x */
122    /* We also add in ONE_HALF so that need not do it in inner loop */
123    cconvert->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
124  }
125}
126
127/*
128 * Convert some rows of samples to the output colorspace.
129 *
130 * Note that we change from noninterleaved, one-plane-per-component format
131 * to interleaved-pixel format.  The output buffer is therefore three times
132 * as wide as the input buffer.
133 * A starting row offset is provided only for the input buffer.  The caller
134 * can easily adjust the passed output_buf value to accommodate any row
135 * offset required on that side.
136 */
137
138METHODDEF(void)
139ycc_rgb_convert (j_decompress_ptr cinfo,
140		 JSAMPIMAGE input_buf, JDIMENSION input_row,
141		 JSAMPARRAY output_buf, int num_rows)
142{
143  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
144  register int y, cb, cr;
145  register JSAMPROW outptr;
146  register JSAMPROW inptr0, inptr1, inptr2;
147  register JDIMENSION col;
148  JDIMENSION num_cols = cinfo->output_width;
149  /* copy these pointers into registers if possible */
150  register JSAMPLE * range_limit = cinfo->sample_range_limit;
151  register int * Crrtab = cconvert->Cr_r_tab;
152  register int * Cbbtab = cconvert->Cb_b_tab;
153  register INT32 * Crgtab = cconvert->Cr_g_tab;
154  register INT32 * Cbgtab = cconvert->Cb_g_tab;
155  SHIFT_TEMPS
156
157  while (--num_rows >= 0) {
158    inptr0 = input_buf[0][input_row];
159    inptr1 = input_buf[1][input_row];
160    inptr2 = input_buf[2][input_row];
161    input_row++;
162    outptr = *output_buf++;
163    for (col = 0; col < num_cols; col++) {
164      y  = GETJSAMPLE(inptr0[col]);
165      cb = GETJSAMPLE(inptr1[col]);
166      cr = GETJSAMPLE(inptr2[col]);
167      /* Range-limiting is essential due to noise introduced by DCT losses. */
168      outptr[RGB_RED] =   range_limit[y + Crrtab[cr]];
169      outptr[RGB_GREEN] = range_limit[y +
170                              ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
171                                                 SCALEBITS))];
172      outptr[RGB_BLUE] =  range_limit[y + Cbbtab[cb]];
173      outptr += RGB_PIXELSIZE;
174    }
175  }
176}
177
178#ifdef ANDROID_RGB
179METHODDEF(void)
180ycc_rgba_8888_convert (j_decompress_ptr cinfo,
181         JSAMPIMAGE input_buf, JDIMENSION input_row,
182         JSAMPARRAY output_buf, int num_rows)
183{
184  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
185  register int y, cb, cr;
186  register JSAMPROW outptr;
187  register JSAMPROW inptr0, inptr1, inptr2;
188  register JDIMENSION col;
189  JDIMENSION num_cols = cinfo->output_width;
190  /* copy these pointers into registers if possible */
191  register JSAMPLE * range_limit = cinfo->sample_range_limit;
192  register int * Crrtab = cconvert->Cr_r_tab;
193  register int * Cbbtab = cconvert->Cb_b_tab;
194  register INT32 * Crgtab = cconvert->Cr_g_tab;
195  register INT32 * Cbgtab = cconvert->Cb_g_tab;
196  SHIFT_TEMPS
197
198  while (--num_rows >= 0) {
199    inptr0 = input_buf[0][input_row];
200    inptr1 = input_buf[1][input_row];
201    inptr2 = input_buf[2][input_row];
202    input_row++;
203    outptr = *output_buf++;
204    for (col = 0; col < num_cols; col++) {
205      y  = GETJSAMPLE(inptr0[col]);
206      cb = GETJSAMPLE(inptr1[col]);
207      cr = GETJSAMPLE(inptr2[col]);
208      /* Range-limiting is essential due to noise introduced by DCT losses. */
209      outptr[RGB_RED] =   range_limit[y + Crrtab[cr]];
210      outptr[RGB_GREEN] = range_limit[y +
211                              ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
212                                                 SCALEBITS))];
213      outptr[RGB_BLUE] =  range_limit[y + Cbbtab[cb]];
214      outptr[RGB_ALPHA] =  0xFF;
215      outptr += 4;
216    }
217  }
218}
219
220METHODDEF(void)
221ycc_rgb_565_convert (j_decompress_ptr cinfo,
222         JSAMPIMAGE input_buf, JDIMENSION input_row,
223         JSAMPARRAY output_buf, int num_rows)
224{
225  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
226  register int y, cb, cr;
227  register JSAMPROW outptr;
228  register JSAMPROW inptr0, inptr1, inptr2;
229  register JDIMENSION col;
230  JDIMENSION num_cols = cinfo->output_width;
231  /* copy these pointers into registers if possible */
232  register JSAMPLE * range_limit = cinfo->sample_range_limit;
233  register int * Crrtab = cconvert->Cr_r_tab;
234  register int * Cbbtab = cconvert->Cb_b_tab;
235  register INT32 * Crgtab = cconvert->Cr_g_tab;
236  register INT32 * Cbgtab = cconvert->Cb_g_tab;
237  SHIFT_TEMPS
238
239  while (--num_rows >= 0) {
240    INT32 rgb;
241    unsigned int r, g, b;
242    inptr0 = input_buf[0][input_row];
243    inptr1 = input_buf[1][input_row];
244    inptr2 = input_buf[2][input_row];
245    input_row++;
246    outptr = *output_buf++;
247
248    if (PACK_NEED_ALIGNMENT(outptr)) {
249        y  = GETJSAMPLE(*inptr0++);
250        cb = GETJSAMPLE(*inptr1++);
251        cr = GETJSAMPLE(*inptr2++);
252        r = range_limit[y + Crrtab[cr]];
253        g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS))];
254        b = range_limit[y + Cbbtab[cb]];
255        rgb = PACK_SHORT_565(r,g,b);
256        *(INT16*)outptr = rgb;
257        outptr += 2;
258        num_cols--;
259    }
260    for (col = 0; col < (num_cols>>1); col++) {
261      y  = GETJSAMPLE(*inptr0++);
262      cb = GETJSAMPLE(*inptr1++);
263      cr = GETJSAMPLE(*inptr2++);
264      r = range_limit[y + Crrtab[cr]];
265      g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS))];
266      b = range_limit[y + Cbbtab[cb]];
267      rgb = PACK_SHORT_565(r,g,b);
268
269      y  = GETJSAMPLE(*inptr0++);
270      cb = GETJSAMPLE(*inptr1++);
271      cr = GETJSAMPLE(*inptr2++);
272      r = range_limit[y + Crrtab[cr]];
273      g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS))];
274      b = range_limit[y + Cbbtab[cb]];
275      rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b));
276      WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
277      outptr += 4;
278    }
279    if (num_cols&1) {
280      y  = GETJSAMPLE(*inptr0);
281      cb = GETJSAMPLE(*inptr1);
282      cr = GETJSAMPLE(*inptr2);
283      r = range_limit[y + Crrtab[cr]];
284      g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS))];
285      b = range_limit[y + Cbbtab[cb]];
286      rgb = PACK_SHORT_565(r,g,b);
287      *(INT16*)outptr = rgb;
288    }
289  }
290}
291
292METHODDEF(void)
293ycc_rgb_565D_convert (j_decompress_ptr cinfo,
294         JSAMPIMAGE input_buf, JDIMENSION input_row,
295         JSAMPARRAY output_buf, int num_rows)
296{
297  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
298  register int y, cb, cr;
299  register JSAMPROW outptr;
300  register JSAMPROW inptr0, inptr1, inptr2;
301  register JDIMENSION col;
302  JDIMENSION num_cols = cinfo->output_width;
303  /* copy these pointers into registers if possible */
304  register JSAMPLE * range_limit = cinfo->sample_range_limit;
305  register int * Crrtab = cconvert->Cr_r_tab;
306  register int * Cbbtab = cconvert->Cb_b_tab;
307  register INT32 * Crgtab = cconvert->Cr_g_tab;
308  register INT32 * Cbgtab = cconvert->Cb_g_tab;
309  INT32 d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
310  SHIFT_TEMPS
311
312  while (--num_rows >= 0) {
313    INT32 rgb;
314    unsigned int r, g, b;
315    inptr0 = input_buf[0][input_row];
316    inptr1 = input_buf[1][input_row];
317    inptr2 = input_buf[2][input_row];
318    input_row++;
319    outptr = *output_buf++;
320    if (PACK_NEED_ALIGNMENT(outptr)) {
321        y  = GETJSAMPLE(*inptr0++);
322        cb = GETJSAMPLE(*inptr1++);
323        cr = GETJSAMPLE(*inptr2++);
324        r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
325        g = range_limit[DITHER_565_G(y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS)), d0)];
326        b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
327        rgb = PACK_SHORT_565(r,g,b);
328        *(INT16*)outptr = rgb;
329        outptr += 2;
330        num_cols--;
331    }
332    for (col = 0; col < (num_cols>>1); col++) {
333      y  = GETJSAMPLE(*inptr0++);
334      cb = GETJSAMPLE(*inptr1++);
335      cr = GETJSAMPLE(*inptr2++);
336      r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
337      g = range_limit[DITHER_565_G(y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS)), d0)];
338      b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
339      d0 = DITHER_ROTATE(d0);
340      rgb = PACK_SHORT_565(r,g,b);
341      y  = GETJSAMPLE(*inptr0++);
342      cb = GETJSAMPLE(*inptr1++);
343      cr = GETJSAMPLE(*inptr2++);
344      r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
345      g = range_limit[DITHER_565_G(y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS)), d0)];
346      b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
347      d0 = DITHER_ROTATE(d0);
348      rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b));
349      WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
350      outptr += 4;
351    }
352    if (num_cols&1) {
353      y  = GETJSAMPLE(*inptr0);
354      cb = GETJSAMPLE(*inptr1);
355      cr = GETJSAMPLE(*inptr2);
356      r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
357      g = range_limit[DITHER_565_G(y + ((int)RIGHT_SHIFT(Cbgtab[cb]+Crgtab[cr], SCALEBITS)), d0)];
358      b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
359      rgb = PACK_SHORT_565(r,g,b);
360      *(INT16*)outptr = rgb;
361    }
362  }
363}
364
365#endif
366
367/**************** Cases other than YCbCr -> RGB(A) **************/
368
369#ifdef ANDROID_RGB
370METHODDEF(void)
371rgb_rgba_8888_convert (j_decompress_ptr cinfo,
372         JSAMPIMAGE input_buf, JDIMENSION input_row,
373         JSAMPARRAY output_buf, int num_rows)
374{
375  register JSAMPROW outptr;
376  register JSAMPROW inptr0, inptr1, inptr2;
377  register JDIMENSION col;
378  JDIMENSION num_cols = cinfo->output_width;
379  SHIFT_TEMPS
380
381  while (--num_rows >= 0) {
382    inptr0 = input_buf[0][input_row];
383    inptr1 = input_buf[1][input_row];
384    inptr2 = input_buf[2][input_row];
385    input_row++;
386    outptr = *output_buf++;
387    for (col = 0; col < num_cols; col++) {
388      *outptr++ = *inptr0++;
389      *outptr++ = *inptr1++;
390      *outptr++ = *inptr2++;
391      *outptr++ = 0xFF;
392    }
393  }
394}
395
396METHODDEF(void)
397rgb_rgb_565_convert (j_decompress_ptr cinfo,
398         JSAMPIMAGE input_buf, JDIMENSION input_row,
399         JSAMPARRAY output_buf, int num_rows)
400{
401  register JSAMPROW outptr;
402  register JSAMPROW inptr0, inptr1, inptr2;
403  register JDIMENSION col;
404  JDIMENSION num_cols = cinfo->output_width;
405  SHIFT_TEMPS
406
407  while (--num_rows >= 0) {
408    INT32 rgb;
409    unsigned int r, g, b;
410    inptr0 = input_buf[0][input_row];
411    inptr1 = input_buf[1][input_row];
412    inptr2 = input_buf[2][input_row];
413    input_row++;
414    outptr = *output_buf++;
415    if (PACK_NEED_ALIGNMENT(outptr)) {
416        r = GETJSAMPLE(*inptr0++);
417        g = GETJSAMPLE(*inptr1++);
418        b = GETJSAMPLE(*inptr2++);
419        rgb = PACK_SHORT_565(r,g,b);
420        *(INT16*)outptr = rgb;
421        outptr += 2;
422        num_cols--;
423    }
424    for (col = 0; col < (num_cols>>1); col++) {
425      r = GETJSAMPLE(*inptr0++);
426      g = GETJSAMPLE(*inptr1++);
427      b = GETJSAMPLE(*inptr2++);
428      rgb = PACK_SHORT_565(r,g,b);
429      r = GETJSAMPLE(*inptr0++);
430      g = GETJSAMPLE(*inptr1++);
431      b = GETJSAMPLE(*inptr2++);
432      rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b));
433      WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
434      outptr += 4;
435    }
436    if (num_cols&1) {
437      r = GETJSAMPLE(*inptr0);
438      g = GETJSAMPLE(*inptr1);
439      b = GETJSAMPLE(*inptr2);
440      rgb = PACK_SHORT_565(r,g,b);
441      *(INT16*)outptr = rgb;
442    }
443  }
444}
445
446
447METHODDEF(void)
448rgb_rgb_565D_convert (j_decompress_ptr cinfo,
449         JSAMPIMAGE input_buf, JDIMENSION input_row,
450         JSAMPARRAY output_buf, int num_rows)
451{
452  register JSAMPROW outptr;
453  register JSAMPROW inptr0, inptr1, inptr2;
454  register JDIMENSION col;
455  register JSAMPLE * range_limit = cinfo->sample_range_limit;
456  JDIMENSION num_cols = cinfo->output_width;
457  INT32 d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
458  SHIFT_TEMPS
459
460  while (--num_rows >= 0) {
461    INT32 rgb;
462    unsigned int r, g, b;
463    inptr0 = input_buf[0][input_row];
464    inptr1 = input_buf[1][input_row];
465    inptr2 = input_buf[2][input_row];
466    input_row++;
467    outptr = *output_buf++;
468    if (PACK_NEED_ALIGNMENT(outptr)) {
469        r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)];
470        g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
471        b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
472        rgb = PACK_SHORT_565(r,g,b);
473        *(INT16*)outptr = rgb;
474        outptr += 2;
475        num_cols--;
476    }
477    for (col = 0; col < (num_cols>>1); col++) {
478      r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)];
479      g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
480      b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
481      d0 = DITHER_ROTATE(d0);
482      rgb = PACK_SHORT_565(r,g,b);
483      r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0++), d0)];
484      g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1++), d0)];
485      b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2++), d0)];
486      d0 = DITHER_ROTATE(d0);
487      rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b));
488      WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
489      outptr += 4;
490    }
491    if (num_cols&1) {
492      r = range_limit[DITHER_565_R(GETJSAMPLE(*inptr0), d0)];
493      g = range_limit[DITHER_565_G(GETJSAMPLE(*inptr1), d0)];
494      b = range_limit[DITHER_565_B(GETJSAMPLE(*inptr2), d0)];
495      rgb = PACK_SHORT_565(r,g,b);
496      *(INT16*)outptr = rgb;
497    }
498  }
499}
500
501#endif
502
503/*
504 * Color conversion for no colorspace change: just copy the data,
505 * converting from separate-planes to interleaved representation.
506 */
507
508METHODDEF(void)
509null_convert (j_decompress_ptr cinfo,
510	      JSAMPIMAGE input_buf, JDIMENSION input_row,
511	      JSAMPARRAY output_buf, int num_rows)
512{
513  register JSAMPROW inptr, outptr;
514  register JDIMENSION count;
515  register int num_components = cinfo->num_components;
516  JDIMENSION num_cols = cinfo->output_width;
517  int ci;
518
519  while (--num_rows >= 0) {
520    for (ci = 0; ci < num_components; ci++) {
521      inptr = input_buf[ci][input_row];
522      outptr = output_buf[0] + ci;
523      for (count = num_cols; count > 0; count--) {
524	*outptr = *inptr++;	/* needn't bother with GETJSAMPLE() here */
525	outptr += num_components;
526      }
527    }
528    input_row++;
529    output_buf++;
530  }
531}
532
533
534/*
535 * Color conversion for grayscale: just copy the data.
536 * This also works for YCbCr -> grayscale conversion, in which
537 * we just copy the Y (luminance) component and ignore chrominance.
538 */
539
540METHODDEF(void)
541grayscale_convert (j_decompress_ptr cinfo,
542		   JSAMPIMAGE input_buf, JDIMENSION input_row,
543		   JSAMPARRAY output_buf, int num_rows)
544{
545  jcopy_sample_rows(input_buf[0], (int) input_row, output_buf, 0,
546		    num_rows, cinfo->output_width);
547}
548
549
550/*
551 * Convert grayscale to RGB: just duplicate the graylevel three times.
552 * This is provided to support applications that don't want to cope
553 * with grayscale as a separate case.
554 */
555
556METHODDEF(void)
557gray_rgb_convert (j_decompress_ptr cinfo,
558		  JSAMPIMAGE input_buf, JDIMENSION input_row,
559		  JSAMPARRAY output_buf, int num_rows)
560{
561  register JSAMPROW inptr, outptr;
562  register JDIMENSION col;
563  JDIMENSION num_cols = cinfo->output_width;
564
565  while (--num_rows >= 0) {
566    inptr = input_buf[0][input_row++];
567    outptr = *output_buf++;
568    for (col = 0; col < num_cols; col++) {
569      /* We can dispense with GETJSAMPLE() here */
570      outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col];
571      outptr += RGB_PIXELSIZE;
572    }
573  }
574}
575
576#ifdef ANDROID_RGB
577METHODDEF(void)
578gray_rgba_8888_convert (j_decompress_ptr cinfo,
579          JSAMPIMAGE input_buf, JDIMENSION input_row,
580          JSAMPARRAY output_buf, int num_rows)
581{
582  register JSAMPROW inptr, outptr;
583  register JDIMENSION col;
584  JDIMENSION num_cols = cinfo->output_width;
585
586  while (--num_rows >= 0) {
587    inptr = input_buf[0][input_row++];
588    outptr = *output_buf++;
589    for (col = 0; col < num_cols; col++) {
590      /* We can dispense with GETJSAMPLE() here */
591      outptr[RGB_RED] = outptr[RGB_GREEN] = outptr[RGB_BLUE] = inptr[col];
592      outptr[RGB_ALPHA] = 0xff;
593      outptr += 4;
594    }
595  }
596}
597
598METHODDEF(void)
599gray_rgb_565_convert (j_decompress_ptr cinfo,
600          JSAMPIMAGE input_buf, JDIMENSION input_row,
601          JSAMPARRAY output_buf, int num_rows)
602{
603  register JSAMPROW inptr, outptr;
604  register JDIMENSION col;
605  JDIMENSION num_cols = cinfo->output_width;
606
607  while (--num_rows >= 0) {
608    INT32 rgb;
609    unsigned int g;
610    inptr = input_buf[0][input_row++];
611    outptr = *output_buf++;
612    if (PACK_NEED_ALIGNMENT(outptr)) {
613        g = *inptr++;
614        rgb = PACK_SHORT_565(g, g, g);
615        *(INT16*)outptr = rgb;
616        outptr += 2;
617        num_cols--;
618    }
619    for (col = 0; col < (num_cols>>1); col++) {
620      g = *inptr++;
621      rgb = PACK_SHORT_565(g, g, g);
622      g = *inptr++;
623      rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(g, g, g));
624      WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
625      outptr += 4;
626    }
627    if (num_cols&1) {
628      g = *inptr;
629      rgb = PACK_SHORT_565(g, g, g);
630      *(INT16*)outptr = rgb;
631    }
632  }
633}
634
635METHODDEF(void)
636gray_rgb_565D_convert (j_decompress_ptr cinfo,
637          JSAMPIMAGE input_buf, JDIMENSION input_row,
638          JSAMPARRAY output_buf, int num_rows)
639{
640  register JSAMPROW inptr, outptr;
641  register JDIMENSION col;
642  register JSAMPLE * range_limit = cinfo->sample_range_limit;
643  JDIMENSION num_cols = cinfo->output_width;
644  INT32 d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
645
646  while (--num_rows >= 0) {
647    INT32 rgb;
648    unsigned int g;
649    inptr = input_buf[0][input_row++];
650    outptr = *output_buf++;
651    if (PACK_NEED_ALIGNMENT(outptr)) {
652        g = *inptr++;
653        g = range_limit[DITHER_565_R(g, d0)];
654        rgb = PACK_SHORT_565(g, g, g);
655        *(INT16*)outptr = rgb;
656        outptr += 2;
657        num_cols--;
658    }
659    for (col = 0; col < (num_cols>>1); col++) {
660      g = *inptr++;
661      g = range_limit[DITHER_565_R(g, d0)];
662      rgb = PACK_SHORT_565(g, g, g);
663      d0 = DITHER_ROTATE(d0);
664      g = *inptr++;
665      g = range_limit[DITHER_565_R(g, d0)];
666      rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(g, g, g));
667      d0 = DITHER_ROTATE(d0);
668      WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
669      outptr += 4;
670    }
671    if (num_cols&1) {
672      g = *inptr;
673      g = range_limit[DITHER_565_R(g, d0)];
674      rgb = PACK_SHORT_565(g, g, g);
675      *(INT16*)outptr = rgb;
676    }
677  }
678}
679#endif
680
681/*
682 * Adobe-style YCCK->CMYK conversion.
683 * We convert YCbCr to R=1-C, G=1-M, and B=1-Y using the same
684 * conversion as above, while passing K (black) unchanged.
685 * We assume build_ycc_rgb_table has been called.
686 */
687
688METHODDEF(void)
689ycck_cmyk_convert (j_decompress_ptr cinfo,
690		   JSAMPIMAGE input_buf, JDIMENSION input_row,
691		   JSAMPARRAY output_buf, int num_rows)
692{
693  my_cconvert_ptr cconvert = (my_cconvert_ptr) cinfo->cconvert;
694  register int y, cb, cr;
695  register JSAMPROW outptr;
696  register JSAMPROW inptr0, inptr1, inptr2, inptr3;
697  register JDIMENSION col;
698  JDIMENSION num_cols = cinfo->output_width;
699  /* copy these pointers into registers if possible */
700  register JSAMPLE * range_limit = cinfo->sample_range_limit;
701  register int * Crrtab = cconvert->Cr_r_tab;
702  register int * Cbbtab = cconvert->Cb_b_tab;
703  register INT32 * Crgtab = cconvert->Cr_g_tab;
704  register INT32 * Cbgtab = cconvert->Cb_g_tab;
705  SHIFT_TEMPS
706
707  while (--num_rows >= 0) {
708    inptr0 = input_buf[0][input_row];
709    inptr1 = input_buf[1][input_row];
710    inptr2 = input_buf[2][input_row];
711    inptr3 = input_buf[3][input_row];
712    input_row++;
713    outptr = *output_buf++;
714    for (col = 0; col < num_cols; col++) {
715      y  = GETJSAMPLE(inptr0[col]);
716      cb = GETJSAMPLE(inptr1[col]);
717      cr = GETJSAMPLE(inptr2[col]);
718      /* Range-limiting is essential due to noise introduced by DCT losses. */
719      outptr[0] = range_limit[MAXJSAMPLE - (y + Crrtab[cr])];   /* red */
720      outptr[1] = range_limit[MAXJSAMPLE - (y +                 /* green */
721                              ((int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
722                                                 SCALEBITS)))];
723      outptr[2] = range_limit[MAXJSAMPLE - (y + Cbbtab[cb])];   /* blue */
724      /* K passes through unchanged */
725      outptr[3] = inptr3[col];	/* don't need GETJSAMPLE here */
726      outptr += 4;
727    }
728  }
729}
730
731
732/*
733 * Empty method for start_pass.
734 */
735
736METHODDEF(void)
737start_pass_dcolor (j_decompress_ptr cinfo)
738{
739  /* no work needed */
740}
741
742
743/*
744 * Module initialization routine for output colorspace conversion.
745 */
746
747GLOBAL(void)
748jinit_color_deconverter (j_decompress_ptr cinfo)
749{
750  my_cconvert_ptr cconvert;
751  int ci;
752
753  cconvert = (my_cconvert_ptr)
754    (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
755				SIZEOF(my_color_deconverter));
756  cinfo->cconvert = (struct jpeg_color_deconverter *) cconvert;
757  cconvert->pub.start_pass = start_pass_dcolor;
758
759  /* Make sure num_components agrees with jpeg_color_space */
760  switch (cinfo->jpeg_color_space) {
761  case JCS_GRAYSCALE:
762    if (cinfo->num_components != 1)
763      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
764    break;
765
766  case JCS_RGB:
767  case JCS_YCbCr:
768    if (cinfo->num_components != 3)
769      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
770    break;
771
772  case JCS_CMYK:
773  case JCS_YCCK:
774    if (cinfo->num_components != 4)
775      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
776    break;
777
778  default:			/* JCS_UNKNOWN can be anything */
779    if (cinfo->num_components < 1)
780      ERREXIT(cinfo, JERR_BAD_J_COLORSPACE);
781    break;
782  }
783
784  /* Set out_color_components and conversion method based on requested space.
785   * Also clear the component_needed flags for any unused components,
786   * so that earlier pipeline stages can avoid useless computation.
787   */
788
789  switch (cinfo->out_color_space) {
790  case JCS_GRAYSCALE:
791    cinfo->out_color_components = 1;
792    if (cinfo->jpeg_color_space == JCS_GRAYSCALE ||
793	cinfo->jpeg_color_space == JCS_YCbCr) {
794      cconvert->pub.color_convert = grayscale_convert;
795      /* For color->grayscale conversion, only the Y (0) component is needed */
796      for (ci = 1; ci < cinfo->num_components; ci++)
797	cinfo->comp_info[ci].component_needed = FALSE;
798    } else
799      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
800    break;
801
802  case JCS_RGB:
803    cinfo->out_color_components = RGB_PIXELSIZE;
804    if (cinfo->jpeg_color_space == JCS_YCbCr) {
805      cconvert->pub.color_convert = ycc_rgb_convert;
806      build_ycc_rgb_table(cinfo);
807    } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
808      cconvert->pub.color_convert = gray_rgb_convert;
809    } else if (cinfo->jpeg_color_space == JCS_RGB && RGB_PIXELSIZE == 3) {
810      cconvert->pub.color_convert = null_convert;
811    } else
812      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
813    break;
814
815#ifdef ANDROID_RGB
816  case JCS_RGBA_8888:
817    cinfo->out_color_components = 4;
818    if (cinfo->jpeg_color_space == JCS_YCbCr) {
819      cconvert->pub.color_convert = ycc_rgba_8888_convert;
820      build_ycc_rgb_table(cinfo);
821    } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
822      cconvert->pub.color_convert = gray_rgba_8888_convert;
823    } else if (cinfo->jpeg_color_space == JCS_RGB) {
824      cconvert->pub.color_convert = rgb_rgba_8888_convert;
825    } else
826      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
827    break;
828
829  case JCS_RGB_565:
830    cinfo->out_color_components = RGB_PIXELSIZE;
831    if (cinfo->dither_mode == JDITHER_NONE) {
832      if (cinfo->jpeg_color_space == JCS_YCbCr) {
833        cconvert->pub.color_convert = ycc_rgb_565_convert;
834        build_ycc_rgb_table(cinfo);
835      } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
836        cconvert->pub.color_convert = gray_rgb_565_convert;
837      } else if (cinfo->jpeg_color_space == JCS_RGB) {
838        cconvert->pub.color_convert = rgb_rgb_565_convert;
839      } else
840        ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
841    } else {
842      /* only ordered dither is supported */
843      if (cinfo->jpeg_color_space == JCS_YCbCr) {
844        cconvert->pub.color_convert = ycc_rgb_565D_convert;
845        build_ycc_rgb_table(cinfo);
846      } else if (cinfo->jpeg_color_space == JCS_GRAYSCALE) {
847        cconvert->pub.color_convert = gray_rgb_565D_convert;
848      } else if (cinfo->jpeg_color_space == JCS_RGB) {
849        cconvert->pub.color_convert = rgb_rgb_565D_convert;
850      } else
851        ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
852    }
853    break;
854#endif
855
856  case JCS_CMYK:
857    cinfo->out_color_components = 4;
858    if (cinfo->jpeg_color_space == JCS_YCCK) {
859      cconvert->pub.color_convert = ycck_cmyk_convert;
860      build_ycc_rgb_table(cinfo);
861    } else if (cinfo->jpeg_color_space == JCS_CMYK) {
862      cconvert->pub.color_convert = null_convert;
863    } else
864      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
865    break;
866
867  default:
868    /* Permit null conversion to same output space */
869    if (cinfo->out_color_space == cinfo->jpeg_color_space) {
870      cinfo->out_color_components = cinfo->num_components;
871      cconvert->pub.color_convert = null_convert;
872    } else			/* unsupported non-null conversion */
873      ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL);
874    break;
875  }
876
877  if (cinfo->quantize_colors)
878    cinfo->output_components = 1; /* single colormapped output component */
879  else
880    cinfo->output_components = cinfo->out_color_components;
881}
882