1 /*
2  * jdmrg565.c
3  *
4  * This file was part of the Independent JPEG Group's software:
5  * Copyright (C) 1994-1996, Thomas G. Lane.
6  * libjpeg-turbo Modifications:
7  * Copyright (C) 2013, Linaro Limited.
8  * Copyright (C) 2014-2015, 2018, D. R. Commander.
9  * For conditions of distribution and use, see the accompanying README.ijg
10  * file.
11  *
12  * This file contains code for merged upsampling/color conversion.
13  */
14 
15 
16 INLINE
LOCAL(void)17 LOCAL(void)
18 h2v1_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
19                                   JDIMENSION in_row_group_ctr,
20                                   JSAMPARRAY output_buf)
21 {
22   my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
23   register int y, cred, cgreen, cblue;
24   int cb, cr;
25   register JSAMPROW outptr;
26   JSAMPROW inptr0, inptr1, inptr2;
27   JDIMENSION col;
28   /* copy these pointers into registers if possible */
29   register JSAMPLE *range_limit = cinfo->sample_range_limit;
30   int *Crrtab = upsample->Cr_r_tab;
31   int *Cbbtab = upsample->Cb_b_tab;
32   JLONG *Crgtab = upsample->Cr_g_tab;
33   JLONG *Cbgtab = upsample->Cb_g_tab;
34   unsigned int r, g, b;
35   JLONG rgb;
36   SHIFT_TEMPS
37 
38   inptr0 = input_buf[0][in_row_group_ctr];
39   inptr1 = input_buf[1][in_row_group_ctr];
40   inptr2 = input_buf[2][in_row_group_ctr];
41   outptr = output_buf[0];
42 
43   /* Loop for each pair of output pixels */
44   for (col = cinfo->output_width >> 1; col > 0; col--) {
45     /* Do the chroma part of the calculation */
46     cb = GETJSAMPLE(*inptr1++);
47     cr = GETJSAMPLE(*inptr2++);
48     cred = Crrtab[cr];
49     cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
50     cblue = Cbbtab[cb];
51 
52     /* Fetch 2 Y values and emit 2 pixels */
53     y  = GETJSAMPLE(*inptr0++);
54     r = range_limit[y + cred];
55     g = range_limit[y + cgreen];
56     b = range_limit[y + cblue];
57     rgb = PACK_SHORT_565(r, g, b);
58 
59     y  = GETJSAMPLE(*inptr0++);
60     r = range_limit[y + cred];
61     g = range_limit[y + cgreen];
62     b = range_limit[y + cblue];
63     rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
64 
65     WRITE_TWO_PIXELS(outptr, rgb);
66     outptr += 4;
67   }
68 
69   /* If image width is odd, do the last output column separately */
70   if (cinfo->output_width & 1) {
71     cb = GETJSAMPLE(*inptr1);
72     cr = GETJSAMPLE(*inptr2);
73     cred = Crrtab[cr];
74     cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
75     cblue = Cbbtab[cb];
76     y  = GETJSAMPLE(*inptr0);
77     r = range_limit[y + cred];
78     g = range_limit[y + cgreen];
79     b = range_limit[y + cblue];
80     rgb = PACK_SHORT_565(r, g, b);
81     *(INT16 *)outptr = (INT16)rgb;
82   }
83 }
84 
85 
86 INLINE
LOCAL(void)87 LOCAL(void)
88 h2v1_merged_upsample_565D_internal(j_decompress_ptr cinfo,
89                                    JSAMPIMAGE input_buf,
90                                    JDIMENSION in_row_group_ctr,
91                                    JSAMPARRAY output_buf)
92 {
93   my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
94   register int y, cred, cgreen, cblue;
95   int cb, cr;
96   register JSAMPROW outptr;
97   JSAMPROW inptr0, inptr1, inptr2;
98   JDIMENSION col;
99   /* copy these pointers into registers if possible */
100   register JSAMPLE *range_limit = cinfo->sample_range_limit;
101   int *Crrtab = upsample->Cr_r_tab;
102   int *Cbbtab = upsample->Cb_b_tab;
103   JLONG *Crgtab = upsample->Cr_g_tab;
104   JLONG *Cbgtab = upsample->Cb_g_tab;
105   JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
106   unsigned int r, g, b;
107   JLONG rgb;
108   SHIFT_TEMPS
109 
110   inptr0 = input_buf[0][in_row_group_ctr];
111   inptr1 = input_buf[1][in_row_group_ctr];
112   inptr2 = input_buf[2][in_row_group_ctr];
113   outptr = output_buf[0];
114 
115   /* Loop for each pair of output pixels */
116   for (col = cinfo->output_width >> 1; col > 0; col--) {
117     /* Do the chroma part of the calculation */
118     cb = GETJSAMPLE(*inptr1++);
119     cr = GETJSAMPLE(*inptr2++);
120     cred = Crrtab[cr];
121     cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
122     cblue = Cbbtab[cb];
123 
124     /* Fetch 2 Y values and emit 2 pixels */
125     y  = GETJSAMPLE(*inptr0++);
126     r = range_limit[DITHER_565_R(y + cred, d0)];
127     g = range_limit[DITHER_565_G(y + cgreen, d0)];
128     b = range_limit[DITHER_565_B(y + cblue, d0)];
129     d0 = DITHER_ROTATE(d0);
130     rgb = PACK_SHORT_565(r, g, b);
131 
132     y  = GETJSAMPLE(*inptr0++);
133     r = range_limit[DITHER_565_R(y + cred, d0)];
134     g = range_limit[DITHER_565_G(y + cgreen, d0)];
135     b = range_limit[DITHER_565_B(y + cblue, d0)];
136     d0 = DITHER_ROTATE(d0);
137     rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
138 
139     WRITE_TWO_PIXELS(outptr, rgb);
140     outptr += 4;
141   }
142 
143   /* If image width is odd, do the last output column separately */
144   if (cinfo->output_width & 1) {
145     cb = GETJSAMPLE(*inptr1);
146     cr = GETJSAMPLE(*inptr2);
147     cred = Crrtab[cr];
148     cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
149     cblue = Cbbtab[cb];
150     y  = GETJSAMPLE(*inptr0);
151     r = range_limit[DITHER_565_R(y + cred, d0)];
152     g = range_limit[DITHER_565_G(y + cgreen, d0)];
153     b = range_limit[DITHER_565_B(y + cblue, d0)];
154     rgb = PACK_SHORT_565(r, g, b);
155     *(INT16 *)outptr = (INT16)rgb;
156   }
157 }
158 
159 
160 INLINE
LOCAL(void)161 LOCAL(void)
162 h2v2_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
163                                   JDIMENSION in_row_group_ctr,
164                                   JSAMPARRAY output_buf)
165 {
166   my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
167   register int y, cred, cgreen, cblue;
168   int cb, cr;
169   register JSAMPROW outptr0, outptr1;
170   JSAMPROW inptr00, inptr01, inptr1, inptr2;
171   JDIMENSION col;
172   /* copy these pointers into registers if possible */
173   register JSAMPLE *range_limit = cinfo->sample_range_limit;
174   int *Crrtab = upsample->Cr_r_tab;
175   int *Cbbtab = upsample->Cb_b_tab;
176   JLONG *Crgtab = upsample->Cr_g_tab;
177   JLONG *Cbgtab = upsample->Cb_g_tab;
178   unsigned int r, g, b;
179   JLONG rgb;
180   SHIFT_TEMPS
181 
182   inptr00 = input_buf[0][in_row_group_ctr * 2];
183   inptr01 = input_buf[0][in_row_group_ctr * 2 + 1];
184   inptr1 = input_buf[1][in_row_group_ctr];
185   inptr2 = input_buf[2][in_row_group_ctr];
186   outptr0 = output_buf[0];
187   outptr1 = output_buf[1];
188 
189   /* Loop for each group of output pixels */
190   for (col = cinfo->output_width >> 1; col > 0; col--) {
191     /* Do the chroma part of the calculation */
192     cb = GETJSAMPLE(*inptr1++);
193     cr = GETJSAMPLE(*inptr2++);
194     cred = Crrtab[cr];
195     cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
196     cblue = Cbbtab[cb];
197 
198     /* Fetch 4 Y values and emit 4 pixels */
199     y  = GETJSAMPLE(*inptr00++);
200     r = range_limit[y + cred];
201     g = range_limit[y + cgreen];
202     b = range_limit[y + cblue];
203     rgb = PACK_SHORT_565(r, g, b);
204 
205     y  = GETJSAMPLE(*inptr00++);
206     r = range_limit[y + cred];
207     g = range_limit[y + cgreen];
208     b = range_limit[y + cblue];
209     rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
210 
211     WRITE_TWO_PIXELS(outptr0, rgb);
212     outptr0 += 4;
213 
214     y  = GETJSAMPLE(*inptr01++);
215     r = range_limit[y + cred];
216     g = range_limit[y + cgreen];
217     b = range_limit[y + cblue];
218     rgb = PACK_SHORT_565(r, g, b);
219 
220     y  = GETJSAMPLE(*inptr01++);
221     r = range_limit[y + cred];
222     g = range_limit[y + cgreen];
223     b = range_limit[y + cblue];
224     rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
225 
226     WRITE_TWO_PIXELS(outptr1, rgb);
227     outptr1 += 4;
228   }
229 
230   /* If image width is odd, do the last output column separately */
231   if (cinfo->output_width & 1) {
232     cb = GETJSAMPLE(*inptr1);
233     cr = GETJSAMPLE(*inptr2);
234     cred = Crrtab[cr];
235     cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
236     cblue = Cbbtab[cb];
237 
238     y  = GETJSAMPLE(*inptr00);
239     r = range_limit[y + cred];
240     g = range_limit[y + cgreen];
241     b = range_limit[y + cblue];
242     rgb = PACK_SHORT_565(r, g, b);
243     *(INT16 *)outptr0 = (INT16)rgb;
244 
245     y  = GETJSAMPLE(*inptr01);
246     r = range_limit[y + cred];
247     g = range_limit[y + cgreen];
248     b = range_limit[y + cblue];
249     rgb = PACK_SHORT_565(r, g, b);
250     *(INT16 *)outptr1 = (INT16)rgb;
251   }
252 }
253 
254 
255 INLINE
LOCAL(void)256 LOCAL(void)
257 h2v2_merged_upsample_565D_internal(j_decompress_ptr cinfo,
258                                    JSAMPIMAGE input_buf,
259                                    JDIMENSION in_row_group_ctr,
260                                    JSAMPARRAY output_buf)
261 {
262   my_upsample_ptr upsample = (my_upsample_ptr)cinfo->upsample;
263   register int y, cred, cgreen, cblue;
264   int cb, cr;
265   register JSAMPROW outptr0, outptr1;
266   JSAMPROW inptr00, inptr01, inptr1, inptr2;
267   JDIMENSION col;
268   /* copy these pointers into registers if possible */
269   register JSAMPLE *range_limit = cinfo->sample_range_limit;
270   int *Crrtab = upsample->Cr_r_tab;
271   int *Cbbtab = upsample->Cb_b_tab;
272   JLONG *Crgtab = upsample->Cr_g_tab;
273   JLONG *Cbgtab = upsample->Cb_g_tab;
274   JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
275   JLONG d1 = dither_matrix[(cinfo->output_scanline + 1) & DITHER_MASK];
276   unsigned int r, g, b;
277   JLONG rgb;
278   SHIFT_TEMPS
279 
280   inptr00 = input_buf[0][in_row_group_ctr * 2];
281   inptr01 = input_buf[0][in_row_group_ctr * 2 + 1];
282   inptr1 = input_buf[1][in_row_group_ctr];
283   inptr2 = input_buf[2][in_row_group_ctr];
284   outptr0 = output_buf[0];
285   outptr1 = output_buf[1];
286 
287   /* Loop for each group of output pixels */
288   for (col = cinfo->output_width >> 1; col > 0; col--) {
289     /* Do the chroma part of the calculation */
290     cb = GETJSAMPLE(*inptr1++);
291     cr = GETJSAMPLE(*inptr2++);
292     cred = Crrtab[cr];
293     cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
294     cblue = Cbbtab[cb];
295 
296     /* Fetch 4 Y values and emit 4 pixels */
297     y  = GETJSAMPLE(*inptr00++);
298     r = range_limit[DITHER_565_R(y + cred, d0)];
299     g = range_limit[DITHER_565_G(y + cgreen, d0)];
300     b = range_limit[DITHER_565_B(y + cblue, d0)];
301     d0 = DITHER_ROTATE(d0);
302     rgb = PACK_SHORT_565(r, g, b);
303 
304     y  = GETJSAMPLE(*inptr00++);
305     r = range_limit[DITHER_565_R(y + cred, d0)];
306     g = range_limit[DITHER_565_G(y + cgreen, d0)];
307     b = range_limit[DITHER_565_B(y + cblue, d0)];
308     d0 = DITHER_ROTATE(d0);
309     rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
310 
311     WRITE_TWO_PIXELS(outptr0, rgb);
312     outptr0 += 4;
313 
314     y  = GETJSAMPLE(*inptr01++);
315     r = range_limit[DITHER_565_R(y + cred, d1)];
316     g = range_limit[DITHER_565_G(y + cgreen, d1)];
317     b = range_limit[DITHER_565_B(y + cblue, d1)];
318     d1 = DITHER_ROTATE(d1);
319     rgb = PACK_SHORT_565(r, g, b);
320 
321     y  = GETJSAMPLE(*inptr01++);
322     r = range_limit[DITHER_565_R(y + cred, d1)];
323     g = range_limit[DITHER_565_G(y + cgreen, d1)];
324     b = range_limit[DITHER_565_B(y + cblue, d1)];
325     d1 = DITHER_ROTATE(d1);
326     rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
327 
328     WRITE_TWO_PIXELS(outptr1, rgb);
329     outptr1 += 4;
330   }
331 
332   /* If image width is odd, do the last output column separately */
333   if (cinfo->output_width & 1) {
334     cb = GETJSAMPLE(*inptr1);
335     cr = GETJSAMPLE(*inptr2);
336     cred = Crrtab[cr];
337     cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
338     cblue = Cbbtab[cb];
339 
340     y  = GETJSAMPLE(*inptr00);
341     r = range_limit[DITHER_565_R(y + cred, d0)];
342     g = range_limit[DITHER_565_G(y + cgreen, d0)];
343     b = range_limit[DITHER_565_B(y + cblue, d0)];
344     rgb = PACK_SHORT_565(r, g, b);
345     *(INT16 *)outptr0 = (INT16)rgb;
346 
347     y  = GETJSAMPLE(*inptr01);
348     r = range_limit[DITHER_565_R(y + cred, d1)];
349     g = range_limit[DITHER_565_G(y + cgreen, d1)];
350     b = range_limit[DITHER_565_B(y + cblue, d1)];
351     rgb = PACK_SHORT_565(r, g, b);
352     *(INT16 *)outptr1 = (INT16)rgb;
353   }
354 }
355