• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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