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