1 #if !defined(_FX_JPEG_TURBO_)
2 /*
3  * jdmerge.c
4  *
5  * Copyright (C) 1994-1996, Thomas G. Lane.
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 _FX_MANAGED_CODE_
43 #define my_upsampler	my_upsampler_m
44 #endif
45 
46 /* Private subobject */
47 
48 typedef struct {
49   struct jpeg_upsampler pub;	/* public fields */
50 
51   /* Pointer to routine to do actual upsampling/conversion of one row group */
52   JMETHOD(void, upmethod, (j_decompress_ptr cinfo,
53 			   JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
54 			   JSAMPARRAY output_buf));
55 
56   /* Private state for YCC->RGB conversion */
57   int * Cr_r_tab;		/* => table for Cr to R conversion */
58   int * Cb_b_tab;		/* => table for Cb to B conversion */
59   INT32 * Cr_g_tab;		/* => table for Cr to G conversion */
60   INT32 * Cb_g_tab;		/* => table for Cb to G conversion */
61 
62   /* For 2:1 vertical sampling, we produce two output rows at a time.
63    * We need a "spare" row buffer to hold the second output row if the
64    * application provides just a one-row buffer; we also use the spare
65    * to discard the dummy last row if the image height is odd.
66    */
67   JSAMPROW spare_row;
68   boolean spare_full;		/* T if spare buffer is occupied */
69 
70   JDIMENSION out_row_width;	/* samples per output row */
71   JDIMENSION rows_to_go;	/* counts rows remaining in image */
72 } my_upsampler;
73 
74 typedef my_upsampler * my_upsample_ptr;
75 
76 #define SCALEBITS	16	/* speediest right-shift on some machines */
77 #define ONE_HALF	((INT32) 1 << (SCALEBITS-1))
78 #define FIX(x)		((INT32) ((x) * (1L<<SCALEBITS) + 0.5))
79 
80 
81 /*
82  * Initialize tables for YCC->RGB colorspace conversion.
83  * This is taken directly from jdcolor.c; see that file for more info.
84  */
85 
86 LOCAL(void)
build_ycc_rgb_table(j_decompress_ptr cinfo)87 build_ycc_rgb_table (j_decompress_ptr cinfo)
88 {
89   my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
90   int i;
91   INT32 x;
92   SHIFT_TEMPS
93 
94   upsample->Cr_r_tab = (int *)
95     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
96 				(MAXJSAMPLE+1) * SIZEOF(int));
97   upsample->Cb_b_tab = (int *)
98     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
99 				(MAXJSAMPLE+1) * SIZEOF(int));
100   upsample->Cr_g_tab = (INT32 *)
101     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
102 				(MAXJSAMPLE+1) * SIZEOF(INT32));
103   upsample->Cb_g_tab = (INT32 *)
104     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
105 				(MAXJSAMPLE+1) * SIZEOF(INT32));
106 
107   for (i = 0, x = -CENTERJSAMPLE; i <= MAXJSAMPLE; i++, x++) {
108     /* i is the actual input pixel value, in the range 0..MAXJSAMPLE */
109     /* The Cb or Cr value we are thinking of is x = i - CENTERJSAMPLE */
110     /* Cr=>R value is nearest int to 1.40200 * x */
111     upsample->Cr_r_tab[i] = (int)
112 		    RIGHT_SHIFT(FIX(1.40200) * x + ONE_HALF, SCALEBITS);
113     /* Cb=>B value is nearest int to 1.77200 * x */
114     upsample->Cb_b_tab[i] = (int)
115 		    RIGHT_SHIFT(FIX(1.77200) * x + ONE_HALF, SCALEBITS);
116     /* Cr=>G value is scaled-up -0.71414 * x */
117     upsample->Cr_g_tab[i] = (- FIX(0.71414)) * x;
118     /* Cb=>G value is scaled-up -0.34414 * x */
119     /* We also add in ONE_HALF so that need not do it in inner loop */
120     upsample->Cb_g_tab[i] = (- FIX(0.34414)) * x + ONE_HALF;
121   }
122 }
123 
124 
125 /*
126  * Initialize for an upsampling pass.
127  */
128 
129 METHODDEF(void)
start_pass_merged_upsample(j_decompress_ptr cinfo)130 start_pass_merged_upsample (j_decompress_ptr cinfo)
131 {
132   my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
133 
134   /* Mark the spare buffer empty */
135   upsample->spare_full = FALSE;
136   /* Initialize total-height counter for detecting bottom of image */
137   upsample->rows_to_go = cinfo->output_height;
138 }
139 
140 
141 /*
142  * Control routine to do upsampling (and color conversion).
143  *
144  * The control routine just handles the row buffering considerations.
145  */
146 
147 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)148 merged_2v_upsample (j_decompress_ptr cinfo,
149 		    JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
150 		    JDIMENSION in_row_groups_avail,
151 		    JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
152 		    JDIMENSION out_rows_avail)
153 /* 2:1 vertical sampling case: may need a spare row. */
154 {
155   my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
156   JSAMPROW work_ptrs[2];
157   JDIMENSION num_rows;		/* number of rows returned to caller */
158 
159   if (upsample->spare_full) {
160     /* If we have a spare row saved from a previous cycle, just return it. */
161     jcopy_sample_rows(& upsample->spare_row, 0, output_buf + *out_row_ctr, 0,
162 		      1, upsample->out_row_width);
163     num_rows = 1;
164     upsample->spare_full = FALSE;
165   } else {
166     /* Figure number of rows to return to caller. */
167     num_rows = 2;
168     /* Not more than the distance to the end of the image. */
169     if (num_rows > upsample->rows_to_go)
170       num_rows = upsample->rows_to_go;
171     /* And not more than what the client can accept: */
172     out_rows_avail -= *out_row_ctr;
173     if (num_rows > out_rows_avail)
174       num_rows = out_rows_avail;
175     /* Create output pointer array for upsampler. */
176     work_ptrs[0] = output_buf[*out_row_ctr];
177     if (num_rows > 1) {
178       work_ptrs[1] = output_buf[*out_row_ctr + 1];
179     } else {
180       work_ptrs[1] = upsample->spare_row;
181       upsample->spare_full = TRUE;
182     }
183     /* Now do the upsampling. */
184     (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr, work_ptrs);
185   }
186 
187   /* Adjust counts */
188   *out_row_ctr += num_rows;
189   upsample->rows_to_go -= num_rows;
190   /* When the buffer is emptied, declare this input row group consumed */
191   if (! upsample->spare_full)
192     (*in_row_group_ctr)++;
193 }
194 
195 
196 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)197 merged_1v_upsample (j_decompress_ptr cinfo,
198 		    JSAMPIMAGE input_buf, JDIMENSION *in_row_group_ctr,
199 		    JDIMENSION in_row_groups_avail,
200 		    JSAMPARRAY output_buf, JDIMENSION *out_row_ctr,
201 		    JDIMENSION out_rows_avail)
202 /* 1:1 vertical sampling case: much easier, never need a spare row. */
203 {
204   my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
205 
206   /* Just do the upsampling. */
207   (*upsample->upmethod) (cinfo, input_buf, *in_row_group_ctr,
208 			 output_buf + *out_row_ctr);
209   /* Adjust counts */
210   (*out_row_ctr)++;
211   (*in_row_group_ctr)++;
212 }
213 
214 
215 /*
216  * These are the routines invoked by the control routines to do
217  * the actual upsampling/conversion.  One row group is processed per call.
218  *
219  * Note: since we may be writing directly into application-supplied buffers,
220  * we have to be honest about the output width; we can't assume the buffer
221  * has been rounded up to an even width.
222  */
223 
224 
225 /*
226  * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical.
227  */
228 
229 METHODDEF(void)
h2v1_merged_upsample(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION in_row_group_ctr,JSAMPARRAY output_buf)230 h2v1_merged_upsample (j_decompress_ptr cinfo,
231 		      JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
232 		      JSAMPARRAY output_buf)
233 {
234   my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
235   register int y, cred, cgreen, cblue;
236   int cb, cr;
237   register JSAMPROW outptr;
238   JSAMPROW inptr0, inptr1, inptr2;
239   JDIMENSION col;
240   /* copy these pointers into registers if possible */
241   register JSAMPLE * range_limit = cinfo->sample_range_limit;
242   int * Crrtab = upsample->Cr_r_tab;
243   int * Cbbtab = upsample->Cb_b_tab;
244   INT32 * Crgtab = upsample->Cr_g_tab;
245   INT32 * Cbgtab = upsample->Cb_g_tab;
246   SHIFT_TEMPS
247 
248   inptr0 = input_buf[0][in_row_group_ctr];
249   inptr1 = input_buf[1][in_row_group_ctr];
250   inptr2 = input_buf[2][in_row_group_ctr];
251   outptr = output_buf[0];
252   /* Loop for each pair of output pixels */
253   for (col = cinfo->output_width >> 1; col > 0; col--) {
254     /* Do the chroma part of the calculation */
255     cb = GETJSAMPLE(*inptr1++);
256     cr = GETJSAMPLE(*inptr2++);
257     cred = Crrtab[cr];
258     cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
259     cblue = Cbbtab[cb];
260     /* Fetch 2 Y values and emit 2 pixels */
261     y  = GETJSAMPLE(*inptr0++);
262     outptr[RGB_RED] =   range_limit[y + cred];
263     outptr[RGB_GREEN] = range_limit[y + cgreen];
264     outptr[RGB_BLUE] =  range_limit[y + cblue];
265     outptr += RGB_PIXELSIZE;
266     y  = GETJSAMPLE(*inptr0++);
267     outptr[RGB_RED] =   range_limit[y + cred];
268     outptr[RGB_GREEN] = range_limit[y + cgreen];
269     outptr[RGB_BLUE] =  range_limit[y + cblue];
270     outptr += RGB_PIXELSIZE;
271   }
272   /* If image width is odd, do the last output column separately */
273   if (cinfo->output_width & 1) {
274     cb = GETJSAMPLE(*inptr1);
275     cr = GETJSAMPLE(*inptr2);
276     cred = Crrtab[cr];
277     cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
278     cblue = Cbbtab[cb];
279     y  = GETJSAMPLE(*inptr0);
280     outptr[RGB_RED] =   range_limit[y + cred];
281     outptr[RGB_GREEN] = range_limit[y + cgreen];
282     outptr[RGB_BLUE] =  range_limit[y + cblue];
283   }
284 }
285 
286 
287 /*
288  * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical.
289  */
290 
291 METHODDEF(void)
h2v2_merged_upsample(j_decompress_ptr cinfo,JSAMPIMAGE input_buf,JDIMENSION in_row_group_ctr,JSAMPARRAY output_buf)292 h2v2_merged_upsample (j_decompress_ptr cinfo,
293 		      JSAMPIMAGE input_buf, JDIMENSION in_row_group_ctr,
294 		      JSAMPARRAY output_buf)
295 {
296   my_upsample_ptr upsample = (my_upsample_ptr) cinfo->upsample;
297   register int y, cred, cgreen, cblue;
298   int cb, cr;
299   register JSAMPROW outptr0, outptr1;
300   JSAMPROW inptr00, inptr01, inptr1, inptr2;
301   JDIMENSION col;
302   /* copy these pointers into registers if possible */
303   register JSAMPLE * range_limit = cinfo->sample_range_limit;
304   int * Crrtab = upsample->Cr_r_tab;
305   int * Cbbtab = upsample->Cb_b_tab;
306   INT32 * Crgtab = upsample->Cr_g_tab;
307   INT32 * Cbgtab = upsample->Cb_g_tab;
308   SHIFT_TEMPS
309 
310   inptr00 = input_buf[0][in_row_group_ctr*2];
311   inptr01 = input_buf[0][in_row_group_ctr*2 + 1];
312   inptr1 = input_buf[1][in_row_group_ctr];
313   inptr2 = input_buf[2][in_row_group_ctr];
314   outptr0 = output_buf[0];
315   outptr1 = output_buf[1];
316   /* Loop for each group of output pixels */
317   for (col = cinfo->output_width >> 1; col > 0; col--) {
318     /* Do the chroma part of the calculation */
319     cb = GETJSAMPLE(*inptr1++);
320     cr = GETJSAMPLE(*inptr2++);
321     cred = Crrtab[cr];
322     cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
323     cblue = Cbbtab[cb];
324     /* Fetch 4 Y values and emit 4 pixels */
325     y  = GETJSAMPLE(*inptr00++);
326     outptr0[RGB_RED] =   range_limit[y + cred];
327     outptr0[RGB_GREEN] = range_limit[y + cgreen];
328     outptr0[RGB_BLUE] =  range_limit[y + cblue];
329     outptr0 += RGB_PIXELSIZE;
330     y  = GETJSAMPLE(*inptr00++);
331     outptr0[RGB_RED] =   range_limit[y + cred];
332     outptr0[RGB_GREEN] = range_limit[y + cgreen];
333     outptr0[RGB_BLUE] =  range_limit[y + cblue];
334     outptr0 += RGB_PIXELSIZE;
335     y  = GETJSAMPLE(*inptr01++);
336     outptr1[RGB_RED] =   range_limit[y + cred];
337     outptr1[RGB_GREEN] = range_limit[y + cgreen];
338     outptr1[RGB_BLUE] =  range_limit[y + cblue];
339     outptr1 += RGB_PIXELSIZE;
340     y  = GETJSAMPLE(*inptr01++);
341     outptr1[RGB_RED] =   range_limit[y + cred];
342     outptr1[RGB_GREEN] = range_limit[y + cgreen];
343     outptr1[RGB_BLUE] =  range_limit[y + cblue];
344     outptr1 += RGB_PIXELSIZE;
345   }
346   /* If image width is odd, do the last output column separately */
347   if (cinfo->output_width & 1) {
348     cb = GETJSAMPLE(*inptr1);
349     cr = GETJSAMPLE(*inptr2);
350     cred = Crrtab[cr];
351     cgreen = (int) RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
352     cblue = Cbbtab[cb];
353     y  = GETJSAMPLE(*inptr00);
354     outptr0[RGB_RED] =   range_limit[y + cred];
355     outptr0[RGB_GREEN] = range_limit[y + cgreen];
356     outptr0[RGB_BLUE] =  range_limit[y + cblue];
357     y  = GETJSAMPLE(*inptr01);
358     outptr1[RGB_RED] =   range_limit[y + cred];
359     outptr1[RGB_GREEN] = range_limit[y + cgreen];
360     outptr1[RGB_BLUE] =  range_limit[y + cblue];
361   }
362 }
363 
364 
365 /*
366  * Module initialization routine for merged upsampling/color conversion.
367  *
368  * NB: this is called under the conditions determined by use_merged_upsample()
369  * in jdmaster.c.  That routine MUST correspond to the actual capabilities
370  * of this module; no safety checks are made here.
371  */
372 
373 GLOBAL(void)
jinit_merged_upsampler(j_decompress_ptr cinfo)374 jinit_merged_upsampler (j_decompress_ptr cinfo)
375 {
376   my_upsample_ptr upsample;
377 
378   upsample = (my_upsample_ptr)
379     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
380 				SIZEOF(my_upsampler));
381   cinfo->upsample = (struct jpeg_upsampler *) upsample;
382   upsample->pub.start_pass = start_pass_merged_upsample;
383   upsample->pub.need_context_rows = FALSE;
384 
385   upsample->out_row_width = cinfo->output_width * cinfo->out_color_components;
386 
387   if (cinfo->max_v_samp_factor == 2) {
388     upsample->pub.upsample = merged_2v_upsample;
389     upsample->upmethod = h2v2_merged_upsample;
390     /* Allocate a spare row buffer */
391     upsample->spare_row = (JSAMPROW)
392       (*cinfo->mem->alloc_large) ((j_common_ptr) cinfo, JPOOL_IMAGE,
393 		(size_t) (upsample->out_row_width * SIZEOF(JSAMPLE)));
394   } else {
395     upsample->pub.upsample = merged_1v_upsample;
396     upsample->upmethod = h2v1_merged_upsample;
397     /* No spare row needed */
398     upsample->spare_row = NULL;
399   }
400 
401   build_ycc_rgb_table(cinfo);
402 }
403 
404 #endif /* UPSAMPLE_MERGING_SUPPORTED */
405 
406 #endif //_FX_JPEG_TURBO_
407