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, 2020, 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
16INLINE
17LOCAL(void)
18h2v1_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
19 JDIMENSION in_row_group_ctr,
20 JSAMPARRAY output_buf)
21{
22 my_merged_upsample_ptr upsample = (my_merged_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 = *inptr1++;
47 cr = *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 = *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 = *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 = *inptr1;
72 cr = *inptr2;
73 cred = Crrtab[cr];
74 cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
75 cblue = Cbbtab[cb];
76 y = *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
86INLINE
87LOCAL(void)
88h2v1_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_merged_upsample_ptr upsample = (my_merged_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 = *inptr1++;
119 cr = *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 = *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 = *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 = *inptr1;
146 cr = *inptr2;
147 cred = Crrtab[cr];
148 cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
149 cblue = Cbbtab[cb];
150 y = *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
160INLINE
161LOCAL(void)
162h2v2_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
163 JDIMENSION in_row_group_ctr,
164 JSAMPARRAY output_buf)
165{
166 my_merged_upsample_ptr upsample = (my_merged_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 = *inptr1++;
193 cr = *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 = *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 = *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 = *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 = *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 = *inptr1;
233 cr = *inptr2;
234 cred = Crrtab[cr];
235 cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
236 cblue = Cbbtab[cb];
237
238 y = *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 = *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
255INLINE
256LOCAL(void)
257h2v2_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_merged_upsample_ptr upsample = (my_merged_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 = *inptr1++;
291 cr = *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 = *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 = *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 = *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 = *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 = *inptr1;
335 cr = *inptr2;
336 cred = Crrtab[cr];
337 cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
338 cblue = Cbbtab[cb];
339
340 y = *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 = *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