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