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