blob: 980a4e216e4dd7fa9885a2949033746dfd9d8309 [file] [log] [blame]
Aaron Gablefeec46f2015-08-06 09:54:48 -07001/*
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.
Jonathan Wrightbbb82822020-11-25 13:36:43 +00008 * Copyright (C) 2014-2015, 2018, 2020, D. R. Commander.
Tom Hudson0d47d2d2016-05-04 13:22:56 -04009 * For conditions of distribution and use, see the accompanying README.ijg
10 * file.
Aaron Gablefeec46f2015-08-06 09:54:48 -070011 *
12 * This file contains code for merged upsampling/color conversion.
13 */
14
15
16INLINE
17LOCAL(void)
Chris Blumecca8c4d2019-03-01 01:09:50 -080018h2v1_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
19 JDIMENSION in_row_group_ctr,
20 JSAMPARRAY output_buf)
Aaron Gablefeec46f2015-08-06 09:54:48 -070021{
Jonathan Wrightbbb82822020-11-25 13:36:43 +000022 my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample;
Aaron Gablefeec46f2015-08-06 09:54:48 -070023 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 */
Chris Blumecca8c4d2019-03-01 01:09:50 -080029 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;
Aaron Gablefeec46f2015-08-06 09:54:48 -070034 unsigned int r, g, b;
Tom Hudson0d47d2d2016-05-04 13:22:56 -040035 JLONG rgb;
Aaron Gablefeec46f2015-08-06 09:54:48 -070036 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 */
Jonathan Wrightbbb82822020-11-25 13:36:43 +000046 cb = *inptr1++;
47 cr = *inptr2++;
Aaron Gablefeec46f2015-08-06 09:54:48 -070048 cred = Crrtab[cr];
Chris Blumecca8c4d2019-03-01 01:09:50 -080049 cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
Aaron Gablefeec46f2015-08-06 09:54:48 -070050 cblue = Cbbtab[cb];
51
52 /* Fetch 2 Y values and emit 2 pixels */
Jonathan Wrightbbb82822020-11-25 13:36:43 +000053 y = *inptr0++;
Aaron Gablefeec46f2015-08-06 09:54:48 -070054 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
Jonathan Wrightbbb82822020-11-25 13:36:43 +000059 y = *inptr0++;
Aaron Gablefeec46f2015-08-06 09:54:48 -070060 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) {
Jonathan Wrightbbb82822020-11-25 13:36:43 +000071 cb = *inptr1;
72 cr = *inptr2;
Aaron Gablefeec46f2015-08-06 09:54:48 -070073 cred = Crrtab[cr];
Chris Blumecca8c4d2019-03-01 01:09:50 -080074 cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
Aaron Gablefeec46f2015-08-06 09:54:48 -070075 cblue = Cbbtab[cb];
Jonathan Wrightbbb82822020-11-25 13:36:43 +000076 y = *inptr0;
Aaron Gablefeec46f2015-08-06 09:54:48 -070077 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);
Chris Blumecca8c4d2019-03-01 01:09:50 -080081 *(INT16 *)outptr = (INT16)rgb;
82 }
83}
Aaron Gablefeec46f2015-08-06 09:54:48 -070084
85
86INLINE
87LOCAL(void)
Chris Blumecca8c4d2019-03-01 01:09:50 -080088h2v1_merged_upsample_565D_internal(j_decompress_ptr cinfo,
89 JSAMPIMAGE input_buf,
90 JDIMENSION in_row_group_ctr,
91 JSAMPARRAY output_buf)
Aaron Gablefeec46f2015-08-06 09:54:48 -070092{
Jonathan Wrightbbb82822020-11-25 13:36:43 +000093 my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample;
Aaron Gablefeec46f2015-08-06 09:54:48 -070094 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 */
Chris Blumecca8c4d2019-03-01 01:09:50 -0800100 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;
Tom Hudson0d47d2d2016-05-04 13:22:56 -0400105 JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
Aaron Gablefeec46f2015-08-06 09:54:48 -0700106 unsigned int r, g, b;
Tom Hudson0d47d2d2016-05-04 13:22:56 -0400107 JLONG rgb;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700108 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 */
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000118 cb = *inptr1++;
119 cr = *inptr2++;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700120 cred = Crrtab[cr];
Chris Blumecca8c4d2019-03-01 01:09:50 -0800121 cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
Aaron Gablefeec46f2015-08-06 09:54:48 -0700122 cblue = Cbbtab[cb];
123
124 /* Fetch 2 Y values and emit 2 pixels */
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000125 y = *inptr0++;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700126 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
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000132 y = *inptr0++;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700133 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) {
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000145 cb = *inptr1;
146 cr = *inptr2;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700147 cred = Crrtab[cr];
Chris Blumecca8c4d2019-03-01 01:09:50 -0800148 cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
Aaron Gablefeec46f2015-08-06 09:54:48 -0700149 cblue = Cbbtab[cb];
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000150 y = *inptr0;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700151 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);
Chris Blumecca8c4d2019-03-01 01:09:50 -0800155 *(INT16 *)outptr = (INT16)rgb;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700156 }
157}
158
159
160INLINE
161LOCAL(void)
Chris Blumecca8c4d2019-03-01 01:09:50 -0800162h2v2_merged_upsample_565_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
163 JDIMENSION in_row_group_ctr,
164 JSAMPARRAY output_buf)
Aaron Gablefeec46f2015-08-06 09:54:48 -0700165{
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000166 my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700167 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 */
Chris Blumecca8c4d2019-03-01 01:09:50 -0800173 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;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700178 unsigned int r, g, b;
Tom Hudson0d47d2d2016-05-04 13:22:56 -0400179 JLONG rgb;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700180 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 */
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000192 cb = *inptr1++;
193 cr = *inptr2++;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700194 cred = Crrtab[cr];
Chris Blumecca8c4d2019-03-01 01:09:50 -0800195 cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
Aaron Gablefeec46f2015-08-06 09:54:48 -0700196 cblue = Cbbtab[cb];
197
198 /* Fetch 4 Y values and emit 4 pixels */
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000199 y = *inptr00++;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700200 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
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000205 y = *inptr00++;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700206 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
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000214 y = *inptr01++;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700215 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
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000220 y = *inptr01++;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700221 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) {
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000232 cb = *inptr1;
233 cr = *inptr2;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700234 cred = Crrtab[cr];
Chris Blumecca8c4d2019-03-01 01:09:50 -0800235 cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
Aaron Gablefeec46f2015-08-06 09:54:48 -0700236 cblue = Cbbtab[cb];
237
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000238 y = *inptr00;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700239 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);
Chris Blumecca8c4d2019-03-01 01:09:50 -0800243 *(INT16 *)outptr0 = (INT16)rgb;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700244
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000245 y = *inptr01;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700246 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);
Chris Blumecca8c4d2019-03-01 01:09:50 -0800250 *(INT16 *)outptr1 = (INT16)rgb;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700251 }
252}
253
254
255INLINE
256LOCAL(void)
Chris Blumecca8c4d2019-03-01 01:09:50 -0800257h2v2_merged_upsample_565D_internal(j_decompress_ptr cinfo,
258 JSAMPIMAGE input_buf,
259 JDIMENSION in_row_group_ctr,
260 JSAMPARRAY output_buf)
Aaron Gablefeec46f2015-08-06 09:54:48 -0700261{
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000262 my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700263 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 */
Chris Blumecca8c4d2019-03-01 01:09:50 -0800269 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;
Tom Hudson0d47d2d2016-05-04 13:22:56 -0400274 JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
Chris Blumecca8c4d2019-03-01 01:09:50 -0800275 JLONG d1 = dither_matrix[(cinfo->output_scanline + 1) & DITHER_MASK];
Aaron Gablefeec46f2015-08-06 09:54:48 -0700276 unsigned int r, g, b;
Tom Hudson0d47d2d2016-05-04 13:22:56 -0400277 JLONG rgb;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700278 SHIFT_TEMPS
279
Chris Blumecca8c4d2019-03-01 01:09:50 -0800280 inptr00 = input_buf[0][in_row_group_ctr * 2];
281 inptr01 = input_buf[0][in_row_group_ctr * 2 + 1];
Aaron Gablefeec46f2015-08-06 09:54:48 -0700282 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 */
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000290 cb = *inptr1++;
291 cr = *inptr2++;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700292 cred = Crrtab[cr];
Chris Blumecca8c4d2019-03-01 01:09:50 -0800293 cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
Aaron Gablefeec46f2015-08-06 09:54:48 -0700294 cblue = Cbbtab[cb];
295
296 /* Fetch 4 Y values and emit 4 pixels */
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000297 y = *inptr00++;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700298 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
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000304 y = *inptr00++;
Chris Blumecca8c4d2019-03-01 01:09:50 -0800305 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);
Aaron Gablefeec46f2015-08-06 09:54:48 -0700309 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
310
311 WRITE_TWO_PIXELS(outptr0, rgb);
312 outptr0 += 4;
313
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000314 y = *inptr01++;
Chris Blumecca8c4d2019-03-01 01:09:50 -0800315 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);
Aaron Gablefeec46f2015-08-06 09:54:48 -0700319 rgb = PACK_SHORT_565(r, g, b);
320
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000321 y = *inptr01++;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700322 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) {
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000334 cb = *inptr1;
335 cr = *inptr2;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700336 cred = Crrtab[cr];
Chris Blumecca8c4d2019-03-01 01:09:50 -0800337 cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
Aaron Gablefeec46f2015-08-06 09:54:48 -0700338 cblue = Cbbtab[cb];
339
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000340 y = *inptr00;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700341 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);
Chris Blumecca8c4d2019-03-01 01:09:50 -0800345 *(INT16 *)outptr0 = (INT16)rgb;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700346
Jonathan Wrightbbb82822020-11-25 13:36:43 +0000347 y = *inptr01;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700348 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);
Chris Blumecca8c4d2019-03-01 01:09:50 -0800352 *(INT16 *)outptr1 = (INT16)rgb;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700353 }
354}