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