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))
51static const INT32 dither_matrix[4] = {
52  0x0008020A,
53  0x0C040E06,
54  0x030B0109,
55  0x0F070D05
56};
57
58#endif
59
60/* Private subobject */
61
62typedef 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
88typedef 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
100LOCAL(void)
101build_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
143METHODDEF(void)
144start_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
161METHODDEF(void)
162merged_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
216METHODDEF(void)
217merged_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
249METHODDEF(void)
250h2v1_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
308METHODDEF(void)
309h2v1_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
372METHODDEF(void)
373h2v1_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
446METHODDEF(void)
447h2v2_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
522METHODDEF(void)
523h2v2_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
607METHODDEF(void)
608h2v2_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
708GLOBAL(void)
709jinit_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