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