blob: 171fbd3ab91a145c7d8b2bc334d12ee05cf2cb2c [file] [log] [blame]
Dees_Troy51a0e822012-09-05 15:24:24 -04001/*
2 * jdmerge.c
3 *
4 * Copyright (C) 1994-1996, 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 code for merged upsampling/color conversion.
10 *
11 * This file combines functions from jdsample.c and jdcolor.c;
12 * read those files first to understand what's going on.
13 *
14 * When the chroma components are to be upsampled by simple replication
15 * (ie, box filtering), we can save some work in color conversion by
16 * calculating all the output pixels corresponding to a pair of chroma
17 * samples at one time. In the conversion equations
18 * R = Y + K1 * Cr
19 * G = Y + K2 * Cb + K3 * Cr
20 * B = Y + K4 * Cb
21 * only the Y term varies among the group of pixels corresponding to a pair
22 * of chroma samples, so the rest of the terms can be calculated just once.
23 * At typical sampling ratios, this eliminates half or three-quarters of the
24 * multiplications needed for color conversion.
25 *
26 * This file currently provides implementations for the following cases:
27 * YCbCr => RGB color conversion only.
28 * Sampling ratios of 2h1v or 2h2v.
29 * No scaling needed at upsample time.
30 * Corner-aligned (non-CCIR601) sampling alignment.
31 * Other special cases could be added, but in most applications these are
32 * the only common cases. (For uncommon cases we fall back on the more
33 * general code in jdsample.c and jdcolor.c.)
34 */
35
36#define JPEG_INTERNALS
37#include "jinclude.h"
38#include "jpeglib.h"
39
40#ifdef UPSAMPLE_MERGING_SUPPORTED
41
42#ifdef ANDROID_RGB
43
44/* Declarations for ordered dithering.
45 *
46 * We use 4x4 ordered dither array packed into 32 bits. This array is
47 * sufficent for dithering RGB_888 to RGB_565.
48 */
49
50#define DITHER_MASK 0x3
51#define DITHER_ROTATE(x) (((x)<<24) | (((x)>>8)&0x00FFFFFF))
52static const INT32 dither_matrix[4] = {
53 0x0008020A,
54 0x0C040E06,
55 0x030B0109,
56 0x0F070D05
57};
58
59#endif
60
61/* Private subobject */
62
63typedef struct {
64 struct jpeg_upsampler pub; /* public fields */
65
66 /* Pointer to routine to do actual upsampling/conversion of one row group */
67 JMETHOD(void, upmethod, (j_decompress_ptr cinfo,
68 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
69 JSAMPARRAY output_buf));
70
71 /* Private state for YCC->RGB conversion */
72 int * Cr_r_tab; /* => table for Cr to R conversion */
73 int * Cb_b_tab; /* => table for Cb to B conversion */
74 INT32 * Cr_g_tab; /* => table for Cr to G conversion */
75 INT32 * Cb_g_tab; /* => table for Cb to G conversion */
76
77 /* For 2:1 vertical sampling, we produce two output rows at a time.
78 * We need a "spare" row buffer to hold the second output row if the
79 * application provides just a one-row buffer; we also use the spare
80 * to discard the dummy last row if the image height is odd.
81 */
82 JSAMPROW spare_row;
83 boolean spare_full; /* T if spare buffer is occupied */
84
85 JDIMENSION out_row_width; /* samples per output row */
86 JDIMENSION rows_to_go; /* counts rows remaining in image */
87} my_upsampler;
88
89typedef my_upsampler * my_upsample_ptr;
90
91#define SCALEBITS 16 /* speediest right-shift on some machines */
92#define ONE_HALF ((INT32) 1 << (SCALEBITS-1))
93#define FIX(x) ((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
94
95
96/*
97 * Initialize tables for YCC->RGB colorspace conversion.
98 * This is taken directly from jdcolor.c; see that file for more info.
99 */
100
101LOCAL(void)
102build_ycc_rgb_table (j_decompress_ptr cinfo)
103{
104 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
105 int i;
106 INT32 x;
107 SHIFT_TEMPS
108
109 upsample->Cr_r_tab = (int *)
110 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
111 (MAXJSAMPLE+1) * SIZEOF(int));
112 upsample->Cb_b_tab = (int *)
113 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
114 (MAXJSAMPLE+1) * SIZEOF(int));
115 upsample->Cr_g_tab = (INT32 *)
116 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
117 (MAXJSAMPLE+1) * SIZEOF(INT32));
118 upsample->Cb_g_tab = (INT32 *)
119 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
120 (MAXJSAMPLE+1) * SIZEOF(INT32));
121
122 for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
123 /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
124 /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
125 /* Cr=>R value is nearest int to 1.40200 * x */
126 upsample->Cr_r_tab[i] = (int)
127 RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
128 /* Cb=>B value is nearest int to 1.77200 * x */
129 upsample->Cb_b_tab[i] = (int)
130 RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
131 /* Cr=>G value is scaled-up -0.71414 * x */
132 upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x;
133 /* Cb=>G value is scaled-up -0.34414 * x */
134 /* We also add in ONE_HALF so that need not do it in inner loop */
135 upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
136 }
137}
138
139
140/*
141 * Initialize for an upsampling pass.
142 */
143
144METHODDEF(void)
145start_pass_merged_upsample (j_decompress_ptr cinfo)
146{
147 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
148
149 /* Mark the spare buffer empty */
150 upsample->spare_full = FALSE;
151 /* Initialize total-height counter for detecting bottom of image */
152 upsample->rows_to_go = cinfo->output_height;
153}
154
155
156/*
157 * Control routine to do upsampling (and color conversion).
158 *
159 * The control routine just handles the row buffering considerations.
160 */
161
162METHODDEF(void)
163merged_2v_upsample (j_decompress_ptr cinfo,
164 JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
165 JDIMENSION in_row_groups_avail,
166 JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
167 JDIMENSION out_rows_avail)
168/* 2:1 vertical sampling case: may need a spare row. */
169{
170 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
171 JSAMPROW work_ptrs[2];
172 JDIMENSION num_rows; /* number of rows returned to caller */
173
174 if (upsample->spare_full) {
175 /* If we have a spare row saved from a previous cycle, just return it. */
176 JDIMENSION size = upsample->out_row_width;
177#ifdef ANDROID_RGB
178 if (cinfo->out_color_space == JCS_RGB_565)
179 size = cinfo->output_width*2;
180#endif
181 jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0,
182 1, size);
183
184 num_rows = 1;
185 upsample->spare_full = FALSE;
186 } else {
187 /* Figure number of rows to return to caller. */
188 num_rows = 2;
189 /* Not more than the distance to the end of the image. */
190 if (num_rows > upsample->rows_to_go)
191 num_rows = upsample->rows_to_go;
192 /* And not more than what the client can accept: */
193 out_rows_avail -= *out_row_ctr;
194 if (num_rows > out_rows_avail)
195 num_rows = out_rows_avail;
196 /* Create output pointer array for upsampler. */
197 work_ptrs[0] = output_buf[*out_row_ctr];
198 if (num_rows > 1) {
199 work_ptrs[1] = output_buf[*out_row_ctr + 1];
200 } else {
201 work_ptrs[1] = upsample->spare_row;
202 upsample->spare_full = TRUE;
203 }
204 /* Now do the upsampling. */
205 (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs);
206 }
207
208 /* Adjust counts */
209 *out_row_ctr += num_rows;
210 upsample->rows_to_go -= num_rows;
211 /* When the buffer is emptied, declare this input row group consumed */
212 if (! upsample->spare_full)
213 (*in_row_group_ctr)++;
214}
215
216
217METHODDEF(void)
218merged_1v_upsample (j_decompress_ptr cinfo,
219 JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
220 JDIMENSION in_row_groups_avail,
221 JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
222 JDIMENSION out_rows_avail)
223/* 1:1 vertical sampling case: much easier, never need a spare row. */
224{
225 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
226
227 /* Just do the upsampling. */
228 (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr,
229 output_buf + *out_row_ctr);
230 /* Adjust counts */
231 (*out_row_ctr)++;
232 (*in_row_group_ctr)++;
233}
234
235
236/*
237 * These are the routines invoked by the control routines to do
238 * the actual upsampling/conversion. One row group is processed per call.
239 *
240 * Note: since we may be writing directly into application-supplied buffers,
241 * we have to be honest about the output width; we can't assume the buffer
242 * has been rounded up to an even width.
243 */
244
245
246/*
247 * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical.
248 */
249
250METHODDEF(void)
251h2v1_merged_upsample (j_decompress_ptr cinfo,
252 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
253 JSAMPARRAY output_buf)
254#ifdef ANDROID_JPEG_USE_VENUM
255{
256 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
257 JSAMPROW inptr0, inptr1, inptr2;
258 JSAMPROW outptr;
259
260 inptr0 = input_buf[0][in_row_group_ctr];
261 inptr1 = input_buf[1][in_row_group_ctr];
262 inptr2 = input_buf[2][in_row_group_ctr];
263 outptr = output_buf[0];
264
265#ifdef ANDROID_RGB
266 if (cinfo->out_color_space == JCS_RGBA_8888) {
267 yyvup2abgr8888_venum((UINT8*) inptr0,
268 (UINT8*) inptr2,
269 (UINT8*) inptr1,
270 (UINT8*) outptr,
271 cinfo->output_width);
272 } else
273#endif
274 {
275 yyvup2bgr888_venum((UINT8*) inptr0,
276 (UINT8*) inptr2,
277 (UINT8*) inptr1,
278 (UINT8*) outptr,
279 cinfo->output_width);
280 }
281}
282#else
283{
284 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
285 register int y, cred, cgreen, cblue;
286 int cb, cr;
287 register JSAMPROW outptr;
288 JSAMPROW inptr0, inptr1, inptr2;
289 JDIMENSION col;
290 /* copy these pointers into registers if possible */
291 register JSAMPLE * range_limit = cinfo->sample_range_limit;
292 int * Crrtab = upsample->Cr_r_tab;
293 int * Cbbtab = upsample->Cb_b_tab;
294 INT32 * Crgtab = upsample->Cr_g_tab;
295 INT32 * Cbgtab = upsample->Cb_g_tab;
296 JDIMENSION pixelWidth = RGB_PIXELSIZE;
297 SHIFT_TEMPS
298
299#ifdef ANDROID_RGB
300 if ((cinfo->out_color_components == 4) &&
301 (cinfo->out_color_space == JCS_RGBA_8888))
302 pixelWidth = 4; // RGBA pixel size
303#endif /* ANDROID_RGB */
304
305 inptr0 = input_buf[0][in_row_group_ctr];
306 inptr1 = input_buf[1][in_row_group_ctr];
307 inptr2 = input_buf[2][in_row_group_ctr];
308 outptr = output_buf[0];
309 /* Loop for each pair of output pixels */
310 for (col = cinfo->output_width >> 1; col > 0; col--) {
311 /* Do the chroma part of the calculation */
312 cb = GETJSAMPLE(*inptr1++);
313 cr = GETJSAMPLE(*inptr2++);
314 cred = Crrtab[cr];
315 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
316 cblue = Cbbtab[cb];
317 /* Fetch 2 Y values and emit 2 pixels */
318 y = GETJSAMPLE(*inptr0++);
319 outptr[RGB_RED] = range_limit[y + cred];
320 outptr[RGB_GREEN] = range_limit[y + cgreen];
321 outptr[RGB_BLUE] = range_limit[y + cblue];
322 outptr += pixelWidth;
323 y = GETJSAMPLE(*inptr0++);
324 outptr[RGB_RED] = range_limit[y + cred];
325 outptr[RGB_GREEN] = range_limit[y + cgreen];
326 outptr[RGB_BLUE] = range_limit[y + cblue];
327 outptr += pixelWidth;
328 }
329 /* If image width is odd, do the last output column separately */
330 if (cinfo->output_width & 1) {
331 cb = GETJSAMPLE(*inptr1);
332 cr = GETJSAMPLE(*inptr2);
333 cred = Crrtab[cr];
334 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
335 cblue = Cbbtab[cb];
336 y = GETJSAMPLE(*inptr0);
337 outptr[RGB_RED] = range_limit[y + cred];
338 outptr[RGB_GREEN] = range_limit[y + cgreen];
339 outptr[RGB_BLUE] = range_limit[y + cblue];
340 }
341}
342#endif /* ANDROID_JPEG_USE_VENUM */
343
344
345#ifdef ANDROID_RGB
346METHODDEF(void)
347h2v1_merged_upsample_565 (j_decompress_ptr cinfo,
348 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
349 JSAMPARRAY output_buf)
350#if defined(ANDROID_JPEG_USE_VENUM)
351{
352 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
353 JSAMPROW inptr0, inptr1, inptr2;
354 JSAMPROW outptr;
355
356 inptr0 = input_buf[0][in_row_group_ctr];
357 inptr1 = input_buf[1][in_row_group_ctr];
358 inptr2 = input_buf[2][in_row_group_ctr];
359 outptr = output_buf[0];
360
361 yyvup2rgb565_venum((UINT8*) inptr0,
362 (UINT8*) inptr2,
363 (UINT8*) inptr1,
364 (UINT8*) outptr,
365 cinfo->output_width);
366}
367#else
368{
369 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
370 register int y, cred, cgreen, cblue;
371 int cb, cr;
372 register JSAMPROW outptr;
373 JSAMPROW inptr0, inptr1, inptr2;
374 JDIMENSION col;
375 /* copy these pointers into registers if possible */
376 register JSAMPLE * range_limit = cinfo->sample_range_limit;
377 int * Crrtab = upsample->Cr_r_tab;
378 int * Cbbtab = upsample->Cb_b_tab;
379 INT32 * Crgtab = upsample->Cr_g_tab;
380 INT32 * Cbgtab = upsample->Cb_g_tab;
381 unsigned int r, g, b;
382 INT32 rgb;
383 SHIFT_TEMPS
384
385 inptr0 = input_buf[0][in_row_group_ctr];
386 inptr1 = input_buf[1][in_row_group_ctr];
387 inptr2 = input_buf[2][in_row_group_ctr];
388 outptr = output_buf[0];
389 /* Loop for each pair of output pixels */
390 for (col = cinfo->output_width >> 1; col > 0; col--) {
391 /* Do the chroma part of the calculation */
392 cb = GETJSAMPLE(*inptr1++);
393 cr = GETJSAMPLE(*inptr2++);
394 cred = Crrtab[cr];
395 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
396 cblue = Cbbtab[cb];
397 /* Fetch 2 Y values and emit 2 pixels */
398 y = GETJSAMPLE(*inptr0++);
399 r = range_limit[y + cred];
400 g = range_limit[y + cgreen];
401 b = range_limit[y + cblue];
402 rgb = PACK_SHORT_565(r,g,b);
403 y = GETJSAMPLE(*inptr0++);
404 r = range_limit[y + cred];
405 g = range_limit[y + cgreen];
406 b = range_limit[y + cblue];
407 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b));
408 WRITE_TWO_PIXELS(outptr, rgb);
409 outptr += 4;
410 }
411 /* If image width is odd, do the last output column separately */
412 if (cinfo->output_width & 1) {
413 cb = GETJSAMPLE(*inptr1);
414 cr = GETJSAMPLE(*inptr2);
415 cred = Crrtab[cr];
416 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
417 cblue = Cbbtab[cb];
418 y = GETJSAMPLE(*inptr0);
419 r = range_limit[y + cred];
420 g = range_limit[y + cgreen];
421 b = range_limit[y + cblue];
422 rgb = PACK_SHORT_565(r,g,b);
423 *(INT16*)outptr = rgb;
424 }
425}
426#endif /* ANDROID_JPEG_USE_VENUM */
427
428
429METHODDEF(void)
430h2v1_merged_upsample_565D (j_decompress_ptr cinfo,
431 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
432 JSAMPARRAY output_buf)
433{
434 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
435 register int y, cred, cgreen, cblue;
436 int cb, cr;
437 register JSAMPROW outptr;
438 JSAMPROW inptr0, inptr1, inptr2;
439 JDIMENSION col;
440 /* copy these pointers into registers if possible */
441 register JSAMPLE * range_limit = cinfo->sample_range_limit;
442 int * Crrtab = upsample->Cr_r_tab;
443 int * Cbbtab = upsample->Cb_b_tab;
444 INT32 * Crgtab = upsample->Cr_g_tab;
445 INT32 * Cbgtab = upsample->Cb_g_tab;
446 JDIMENSION col_index = 0;
447 INT32 d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
448 unsigned int r, g, b;
449 INT32 rgb;
450 SHIFT_TEMPS
451
452 inptr0 = input_buf[0][in_row_group_ctr];
453 inptr1 = input_buf[1][in_row_group_ctr];
454 inptr2 = input_buf[2][in_row_group_ctr];
455 outptr = output_buf[0];
456 /* Loop for each pair of output pixels */
457 for (col = cinfo->output_width >> 1; col > 0; col--) {
458 /* Do the chroma part of the calculation */
459 cb = GETJSAMPLE(*inptr1++);
460 cr = GETJSAMPLE(*inptr2++);
461 cred = Crrtab[cr];
462 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
463 cblue = Cbbtab[cb];
464 /* Fetch 2 Y values and emit 2 pixels */
465 y = GETJSAMPLE(*inptr0++);
466 r = range_limit[DITHER_565_R(y + cred, d0)];
467 g = range_limit[DITHER_565_G(y + cgreen, d0)];
468 b = range_limit[DITHER_565_B(y + cblue, d0)];
469 d0 = DITHER_ROTATE(d0);
470 rgb = PACK_SHORT_565(r,g,b);
471 y = GETJSAMPLE(*inptr0++);
472 r = range_limit[DITHER_565_R(y + cred, d0)];
473 g = range_limit[DITHER_565_G(y + cgreen, d0)];
474 b = range_limit[DITHER_565_B(y + cblue, d0)];
475 d0 = DITHER_ROTATE(d0);
476 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b));
477 WRITE_TWO_PIXELS(outptr, rgb);
478 outptr += 4;
479 }
480 /* If image width is odd, do the last output column separately */
481 if (cinfo->output_width & 1) {
482 cb = GETJSAMPLE(*inptr1);
483 cr = GETJSAMPLE(*inptr2);
484 cred = Crrtab[cr];
485 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
486 cblue = Cbbtab[cb];
487 y = GETJSAMPLE(*inptr0);
488 r = range_limit[DITHER_565_R(y + cred, d0)];
489 g = range_limit[DITHER_565_G(y + cgreen, d0)];
490 b = range_limit[DITHER_565_B(y + cblue, d0)];
491 rgb = PACK_SHORT_565(r,g,b);
492 *(INT16*)outptr = rgb;
493 }
494}
495
496
497#endif
498
499/*
500 * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical.
501 */
502
503METHODDEF(void)
504h2v2_merged_upsample (j_decompress_ptr cinfo,
505 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
506 JSAMPARRAY output_buf)
507#ifdef ANDROID_JPEG_USE_VENUM
508{
509 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
510 JSAMPROW outptr0, outptr1;
511 JSAMPROW inptr00, inptr01, inptr1, inptr2;
512 inptr00 = input_buf[0][in_row_group_ctr*2];
513 inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
514 inptr1 = input_buf[1][in_row_group_ctr];
515 inptr2 = input_buf[2][in_row_group_ctr];
516 outptr0 = output_buf[0];
517 outptr1 = output_buf[1];
518#ifdef ANDROID_RGB
519 if (cinfo->out_color_space == JCS_RGBA_8888) {
520 yyvup2abgr8888_venum((UINT8*) inptr00,
521 (UINT8*) inptr2,
522 (UINT8*) inptr1,
523 (UINT8*) outptr0,
524 cinfo->output_width);
525 yyvup2abgr8888_venum((UINT8*) inptr01,
526 (UINT8*) inptr2,
527 (UINT8*) inptr1,
528 (UINT8*) outptr1,
529 cinfo->output_width);
530 } else
531#endif
532 {
533 yyvup2bgr888_venum((UINT8*) inptr00,
534 (UINT8*) inptr2,
535 (UINT8*) inptr1,
536 (UINT8*) outptr0,
537 cinfo->output_width);
538
539 yyvup2bgr888_venum((UINT8*) inptr01,
540 (UINT8*) inptr2,
541 (UINT8*) inptr1,
542 (UINT8*) outptr1,
543 cinfo->output_width);
544 }
545}
546#else
547{
548 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
549 register int y, cred, cgreen, cblue;
550 int cb, cr;
551 register JSAMPROW outptr0, outptr1;
552 JSAMPROW inptr00, inptr01, inptr1, inptr2;
553 JDIMENSION col;
554 /* copy these pointers into registers if possible */
555 register JSAMPLE * range_limit = cinfo->sample_range_limit;
556 int * Crrtab = upsample->Cr_r_tab;
557 int * Cbbtab = upsample->Cb_b_tab;
558 INT32 * Crgtab = upsample->Cr_g_tab;
559 INT32 * Cbgtab = upsample->Cb_g_tab;
560 JDIMENSION pixelWidth = RGB_PIXELSIZE;
561 SHIFT_TEMPS
562
563#ifdef ANDROID_RGB
564 if ((cinfo->out_color_components == 4) &&
565 (cinfo->out_color_space == JCS_RGBA_8888))
566 pixelWidth = 4; // RGBA pixel size
567#endif /* ANDROID_RGB */
568
569 inptr00 = input_buf[0][in_row_group_ctr*2];
570 inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
571 inptr1 = input_buf[1][in_row_group_ctr];
572 inptr2 = input_buf[2][in_row_group_ctr];
573 outptr0 = output_buf[0];
574 outptr1 = output_buf[1];
575 /* Loop for each group of output pixels */
576 for (col = cinfo->output_width >> 1; col > 0; col--) {
577 /* Do the chroma part of the calculation */
578 cb = GETJSAMPLE(*inptr1++);
579 cr = GETJSAMPLE(*inptr2++);
580 cred = Crrtab[cr];
581 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
582 cblue = Cbbtab[cb];
583 /* Fetch 4 Y values and emit 4 pixels */
584 y = GETJSAMPLE(*inptr00++);
585 outptr0[RGB_RED] = range_limit[y + cred];
586 outptr0[RGB_GREEN] = range_limit[y + cgreen];
587 outptr0[RGB_BLUE] = range_limit[y + cblue];
588 outptr0 += pixelWidth;
589 y = GETJSAMPLE(*inptr00++);
590 outptr0[RGB_RED] = range_limit[y + cred];
591 outptr0[RGB_GREEN] = range_limit[y + cgreen];
592 outptr0[RGB_BLUE] = range_limit[y + cblue];
593 outptr0 += pixelWidth;
594 y = GETJSAMPLE(*inptr01++);
595 outptr1[RGB_RED] = range_limit[y + cred];
596 outptr1[RGB_GREEN] = range_limit[y + cgreen];
597 outptr1[RGB_BLUE] = range_limit[y + cblue];
598 outptr1 += pixelWidth;
599 y = GETJSAMPLE(*inptr01++);
600 outptr1[RGB_RED] = range_limit[y + cred];
601 outptr1[RGB_GREEN] = range_limit[y + cgreen];
602 outptr1[RGB_BLUE] = range_limit[y + cblue];
603 outptr1 += pixelWidth;
604 }
605 /* If image width is odd, do the last output column separately */
606 if (cinfo->output_width & 1) {
607 cb = GETJSAMPLE(*inptr1);
608 cr = GETJSAMPLE(*inptr2);
609 cred = Crrtab[cr];
610 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
611 cblue = Cbbtab[cb];
612 y = GETJSAMPLE(*inptr00);
613 outptr0[RGB_RED] = range_limit[y + cred];
614 outptr0[RGB_GREEN] = range_limit[y + cgreen];
615 outptr0[RGB_BLUE] = range_limit[y + cblue];
616 y = GETJSAMPLE(*inptr01);
617 outptr1[RGB_RED] = range_limit[y + cred];
618 outptr1[RGB_GREEN] = range_limit[y + cgreen];
619 outptr1[RGB_BLUE] = range_limit[y + cblue];
620 }
621}
622#endif /* ANDROID_JPEG_USE_VENUM */
623
624
625#ifdef ANDROID_RGB
626
627METHODDEF(void)
628h2v2_merged_upsample_565 (j_decompress_ptr cinfo,
629 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
630 JSAMPARRAY output_buf)
631#if defined(ANDROID_JPEG_USE_VENUM)
632{
633 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
634 JSAMPROW outptr0, outptr1;
635 JSAMPROW inptr00, inptr01, inptr1, inptr2;
636 inptr00 = input_buf[0][in_row_group_ctr*2];
637 inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
638 inptr1 = input_buf[1][in_row_group_ctr];
639 inptr2 = input_buf[2][in_row_group_ctr];
640 outptr0 = output_buf[0];
641 outptr1 = output_buf[1];
642
643 yyvup2rgb565_venum((UINT8*) inptr00,
644 (UINT8*) inptr2,
645 (UINT8*) inptr1,
646 (UINT8*) outptr0,
647 cinfo->output_width);
648
649 yyvup2rgb565_venum((UINT8*) inptr01,
650 (UINT8*) inptr2,
651 (UINT8*) inptr1,
652 (UINT8*) outptr1,
653 cinfo->output_width);
654}
655#else
656{
657 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
658 register int y, cred, cgreen, cblue;
659 int cb, cr;
660 register JSAMPROW outptr0, outptr1;
661 JSAMPROW inptr00, inptr01, inptr1, inptr2;
662 JDIMENSION col;
663 /* copy these pointers into registers if possible */
664 register JSAMPLE * range_limit = cinfo->sample_range_limit;
665 int * Crrtab = upsample->Cr_r_tab;
666 int * Cbbtab = upsample->Cb_b_tab;
667 INT32 * Crgtab = upsample->Cr_g_tab;
668 INT32 * Cbgtab = upsample->Cb_g_tab;
669 unsigned int r, g, b;
670 INT32 rgb;
671 SHIFT_TEMPS
672
673 inptr00 = input_buf[0][in_row_group_ctr*2];
674 inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
675 inptr1 = input_buf[1][in_row_group_ctr];
676 inptr2 = input_buf[2][in_row_group_ctr];
677 outptr0 = output_buf[0];
678 outptr1 = output_buf[1];
679 /* Loop for each group of output pixels */
680 for (col = cinfo->output_width >> 1; col > 0; col--) {
681 /* Do the chroma part of the calculation */
682 cb = GETJSAMPLE(*inptr1++);
683 cr = GETJSAMPLE(*inptr2++);
684 cred = Crrtab[cr];
685 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
686 cblue = Cbbtab[cb];
687 /* Fetch 4 Y values and emit 4 pixels */
688 y = GETJSAMPLE(*inptr00++);
689 r = range_limit[y + cred];
690 g = range_limit[y + cgreen];
691 b = range_limit[y + cblue];
692 rgb = PACK_SHORT_565(r,g,b);
693 y = GETJSAMPLE(*inptr00++);
694 r = range_limit[y + cred];
695 g = range_limit[y + cgreen];
696 b = range_limit[y + cblue];
697 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b));
698 WRITE_TWO_PIXELS(outptr0, rgb);
699 outptr0 += 4;
700 y = GETJSAMPLE(*inptr01++);
701 r = range_limit[y + cred];
702 g = range_limit[y + cgreen];
703 b = range_limit[y + cblue];
704 rgb = PACK_SHORT_565(r,g,b);
705 y = GETJSAMPLE(*inptr01++);
706 r = range_limit[y + cred];
707 g = range_limit[y + cgreen];
708 b = range_limit[y + cblue];
709 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b));
710 WRITE_TWO_PIXELS(outptr1, rgb);
711 outptr1 += 4;
712 }
713 /* If image width is odd, do the last output column separately */
714 if (cinfo->output_width & 1) {
715 cb = GETJSAMPLE(*inptr1);
716 cr = GETJSAMPLE(*inptr2);
717 cred = Crrtab[cr];
718 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
719 cblue = Cbbtab[cb];
720 y = GETJSAMPLE(*inptr00);
721 r = range_limit[y + cred];
722 g = range_limit[y + cgreen];
723 b = range_limit[y + cblue];
724 rgb = PACK_SHORT_565(r,g,b);
725 *(INT16*)outptr0 = rgb;
726 y = GETJSAMPLE(*inptr01);
727 r = range_limit[y + cred];
728 g = range_limit[y + cgreen];
729 b = range_limit[y + cblue];
730 rgb = PACK_SHORT_565(r,g,b);
731 *(INT16*)outptr1 = rgb;
732 }
733}
734#endif /* ANDROID_JPEG_USE_VENUM */
735
736
737METHODDEF(void)
738h2v2_merged_upsample_565D (j_decompress_ptr cinfo,
739 JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
740 JSAMPARRAY output_buf)
741{
742 my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
743 register int y, cred, cgreen, cblue;
744 int cb, cr;
745 register JSAMPROW outptr0, outptr1;
746 JSAMPROW inptr00, inptr01, inptr1, inptr2;
747 JDIMENSION col;
748 /* copy these pointers into registers if possible */
749 register JSAMPLE * range_limit = cinfo->sample_range_limit;
750 int * Crrtab = upsample->Cr_r_tab;
751 int * Cbbtab = upsample->Cb_b_tab;
752 INT32 * Crgtab = upsample->Cr_g_tab;
753 INT32 * Cbgtab = upsample->Cb_g_tab;
754 JDIMENSION col_index = 0;
755 INT32 d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
756 INT32 d1 = dither_matrix[(cinfo->output_scanline+1) & DITHER_MASK];
757 unsigned int r, g, b;
758 INT32 rgb;
759 SHIFT_TEMPS
760
761 inptr00 = input_buf[0][in_row_group_ctr*2];
762 inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
763 inptr1 = input_buf[1][in_row_group_ctr];
764 inptr2 = input_buf[2][in_row_group_ctr];
765 outptr0 = output_buf[0];
766 outptr1 = output_buf[1];
767 /* Loop for each group of output pixels */
768 for (col = cinfo->output_width >> 1; col > 0; col--) {
769
770 /* Do the chroma part of the calculation */
771 cb = GETJSAMPLE(*inptr1++);
772 cr = GETJSAMPLE(*inptr2++);
773 cred = Crrtab[cr];
774 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
775 cblue = Cbbtab[cb];
776 /* Fetch 4 Y values and emit 4 pixels */
777 y = GETJSAMPLE(*inptr00++);
778 r = range_limit[DITHER_565_R(y + cred, d0)];
779 g = range_limit[DITHER_565_G(y + cgreen, d0)];
780 b = range_limit[DITHER_565_B(y + cblue, d0)];
781 d0 = DITHER_ROTATE(d0);
782 rgb = PACK_SHORT_565(r,g,b);
783 y = GETJSAMPLE(*inptr00++);
784 r = range_limit[DITHER_565_R(y + cred, d1)];
785 g = range_limit[DITHER_565_G(y + cgreen, d1)];
786 b = range_limit[DITHER_565_B(y + cblue, d1)];
787 d1 = DITHER_ROTATE(d1);
788 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b));
789 WRITE_TWO_PIXELS(outptr0, rgb);
790 outptr0 += 4;
791 y = GETJSAMPLE(*inptr01++);
792 r = range_limit[DITHER_565_R(y + cred, d0)];
793 g = range_limit[DITHER_565_G(y + cgreen, d0)];
794 b = range_limit[DITHER_565_B(y + cblue, d0)];
795 d0 = DITHER_ROTATE(d0);
796 rgb = PACK_SHORT_565(r,g,b);
797 y = GETJSAMPLE(*inptr01++);
798 r = range_limit[DITHER_565_R(y + cred, d1)];
799 g = range_limit[DITHER_565_G(y + cgreen, d1)];
800 b = range_limit[DITHER_565_B(y + cblue, d1)];
801 d1 = DITHER_ROTATE(d1);
802 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r,g,b));
803 WRITE_TWO_PIXELS(outptr1, rgb);
804 outptr1 += 4;
805 }
806 /* If image width is odd, do the last output column separately */
807 if (cinfo->output_width & 1) {
808 cb = GETJSAMPLE(*inptr1);
809 cr = GETJSAMPLE(*inptr2);
810 cred = Crrtab[cr];
811 cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
812 cblue = Cbbtab[cb];
813 y = GETJSAMPLE(*inptr00);
814 r = range_limit[DITHER_565_R(y + cred, d0)];
815 g = range_limit[DITHER_565_G(y + cgreen, d0)];
816 b = range_limit[DITHER_565_B(y + cblue, d0)];
817 rgb = PACK_SHORT_565(r,g,b);
818 *(INT16*)outptr0 = rgb;
819 y = GETJSAMPLE(*inptr01);
820 r = range_limit[DITHER_565_R(y + cred, d1)];
821 g = range_limit[DITHER_565_G(y + cgreen, d1)];
822 b = range_limit[DITHER_565_B(y + cblue, d1)];
823 rgb = PACK_SHORT_565(r,g,b);
824 *(INT16*)outptr1 = rgb;
825 }
826}
827
828#endif
829
830/*
831 * Module initialization routine for merged upsampling/color conversion.
832 *
833 * NB: this is called under the conditions determined by use_merged_upsample()
834 * in jdmaster.c. That routine MUST correspond to the actual capabilities
835 * of this module; no safety checks are made here.
836 */
837
838GLOBAL(void)
839jinit_merged_upsampler (j_decompress_ptr cinfo)
840{
841 my_upsample_ptr upsample;
842
843 upsample = (my_upsample_ptr)
844 (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
845 SIZEOF(my_upsampler));
846 cinfo->upsample = (struct jpeg_upsampler *) upsample;
847 upsample->pub.start_pass = start_pass_merged_upsample;
848 upsample->pub.need_context_rows = FALSE;
849
850 upsample->out_row_width = cinfo->output_width * cinfo->out_color_components;
851
852 if (cinfo->max_v_samp_factor == 2) {
853 upsample->pub.upsample = merged_2v_upsample;
854 upsample->upmethod = h2v2_merged_upsample;
855#ifdef ANDROID_RGB
856 if (cinfo->out_color_space == JCS_RGB_565) {
857#if !defined(ANDROID_JPEG_USE_VENUM)
858 if (cinfo->dither_mode != JDITHER_NONE) {
859 upsample->upmethod = h2v2_merged_upsample_565D;
860 } else
861#endif
862 {
863 /* If VeNum routines are enabled, use h2v2_merged_upsample_565
864 * function regardless of dither mode. */
865 upsample->upmethod = h2v2_merged_upsample_565;
866 }
867 }
868#endif
869 /* Allocate a spare row buffer */
870 upsample->spare_row = (JSAMPROW)
871 (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
872 (size_t) (upsample->out_row_width * SIZEOF(JSAMPLE)));
873 } else {
874 upsample->pub.upsample = merged_1v_upsample;
875 upsample->upmethod = h2v1_merged_upsample;
876#ifdef ANDROID_RGB
877 if (cinfo->out_color_space == JCS_RGB_565) {
878#ifndef ANDROID_JPEG_USE_VENUM
879 if (cinfo->dither_mode != JDITHER_NONE) {
880 upsample->upmethod = h2v1_merged_upsample_565D;
881 } else
882#endif
883 {
884 /* If VeNum routines are enabled, use h2v1_merged_upsample_565
885 * function regardless of dither mode. */
886 upsample->upmethod = h2v1_merged_upsample_565;
887 }
888 }
889#endif
890 /* No spare row needed */
891 upsample->spare_row = NULL;
892 }
893
894#if !defined(ANDROID_JPEG_USE_VENUM)
895 build_ycc_rgb_table(cinfo);
896#endif
897#ifdef NEEDS_ARM_ERRATA_754319_754320
898 asm volatile ( "vmov s0,s0\n" );
899#endif
900}
901
902#endif /* UPSAMPLE_MERGING_SUPPORTED */