• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 typedef 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 
30 typedef 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))
43 static 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 
91 LOCAL(void)
build_ycc_rgb_table(j_decompress_ptr cinfo)92 build_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 
140 METHODDEF(void)
ycc_rgb_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)141 ycc_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
181 METHODDEF(void)
ycc_rgba_8888_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)182 ycc_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 
222 METHODDEF(void)
ycc_rgb_565_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)223 ycc_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 
294 METHODDEF(void)
ycc_rgb_565D_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)295 ycc_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
372 METHODDEF(void)
rgb_rgba_8888_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)373 rgb_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 
398 METHODDEF(void)
rgb_rgb_565_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)399 rgb_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 
449 METHODDEF(void)
rgb_rgb_565D_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)450 rgb_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 
510 METHODDEF(void)
null_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)511 null_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 
542 METHODDEF(void)
grayscale_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)543 grayscale_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 
558 METHODDEF(void)
gray_rgb_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)559 gray_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
579 METHODDEF(void)
gray_rgba_8888_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)580 gray_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 
600 METHODDEF(void)
gray_rgb_565_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)601 gray_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 
637 METHODDEF(void)
gray_rgb_565D_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)638 gray_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 
690 METHODDEF(void)
ycck_cmyk_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)691 ycck_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 
738 METHODDEF(void)
start_pass_dcolor(j_decompress_ptr cinfo)739 start_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 
749 GLOBAL(void)
jinit_color_deconverter(j_decompress_ptr cinfo)750 jinit_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