• 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 
15 
16 /* Private subobject */
17 
18 typedef 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 
28 typedef 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))
41 static 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 
89 LOCAL(void)
build_ycc_rgb_table(j_decompress_ptr cinfo)90 build_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 
138 METHODDEF(void)
ycc_rgb_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)139 ycc_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
179 METHODDEF(void)
ycc_rgba_8888_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)180 ycc_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 
220 METHODDEF(void)
ycc_rgb_565_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)221 ycc_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 
292 METHODDEF(void)
ycc_rgb_565D_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)293 ycc_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
370 METHODDEF(void)
rgb_rgba_8888_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)371 rgb_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 
396 METHODDEF(void)
rgb_rgb_565_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)397 rgb_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 
447 METHODDEF(void)
rgb_rgb_565D_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)448 rgb_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 
508 METHODDEF(void)
null_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)509 null_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 
540 METHODDEF(void)
grayscale_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)541 grayscale_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 
556 METHODDEF(void)
gray_rgb_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)557 gray_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
577 METHODDEF(void)
gray_rgba_8888_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)578 gray_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 
598 METHODDEF(void)
gray_rgb_565_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)599 gray_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 
635 METHODDEF(void)
gray_rgb_565D_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)636 gray_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 
688 METHODDEF(void)
ycck_cmyk_convert(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION input_row,JSAMPARRAY output_buf,int num_rows)689 ycck_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 
736 METHODDEF(void)
start_pass_dcolor(j_decompress_ptr cinfo)737 start_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 
747 GLOBAL(void)
jinit_color_deconverter(j_decompress_ptr cinfo)748 jinit_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