blob: 1b87e3718d3a906b75d48d32370d13dcaea39c28 [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.
Leon Scroggins III3993b372018-07-16 10:43:45 -04008 * Copyright (C) 2014-2015, 2018, D. R. Commander.
Alex Naidis6eb7d372016-10-16 23:10:08 +02009 * 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)
Leon Scroggins III3993b372018-07-16 10:43:45 -040018h2v1_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{
Leon Scroggins III3993b372018-07-16 10:43:45 -040022 my_upsample_ptr upsample = (my_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 */
Leon Scroggins III3993b372018-07-16 10:43:45 -040029 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;
Alex Naidis6eb7d372016-10-16 23:10:08 +020035 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 */
46 cb = GETJSAMPLE(*inptr1++);
47 cr = GETJSAMPLE(*inptr2++);
48 cred = Crrtab[cr];
Leon Scroggins III3993b372018-07-16 10:43:45 -040049 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 */
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];
Leon Scroggins III3993b372018-07-16 10:43:45 -040074 cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
Aaron Gablefeec46f2015-08-06 09:54:48 -070075 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);
Leon Scroggins III3993b372018-07-16 10:43:45 -040081 *(INT16 *)outptr = (INT16)rgb;
82 }
83}
Aaron Gablefeec46f2015-08-06 09:54:48 -070084
85
86INLINE
87LOCAL(void)
Leon Scroggins III3993b372018-07-16 10:43:45 -040088h2v1_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{
Leon Scroggins III3993b372018-07-16 10:43:45 -040093 my_upsample_ptr upsample = (my_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 */
Leon Scroggins III3993b372018-07-16 10:43:45 -0400100 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;
Alex Naidis6eb7d372016-10-16 23:10:08 +0200105 JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
Aaron Gablefeec46f2015-08-06 09:54:48 -0700106 unsigned int r, g, b;
Alex Naidis6eb7d372016-10-16 23:10:08 +0200107 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 */
118 cb = GETJSAMPLE(*inptr1++);
119 cr = GETJSAMPLE(*inptr2++);
120 cred = Crrtab[cr];
Leon Scroggins III3993b372018-07-16 10:43:45 -0400121 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 */
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];
Leon Scroggins III3993b372018-07-16 10:43:45 -0400148 cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
Aaron Gablefeec46f2015-08-06 09:54:48 -0700149 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);
Leon Scroggins III3993b372018-07-16 10:43:45 -0400155 *(INT16 *)outptr = (INT16)rgb;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700156 }
157}
158
159
160INLINE
161LOCAL(void)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400162h2v2_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{
Leon Scroggins III3993b372018-07-16 10:43:45 -0400166 my_upsample_ptr upsample = (my_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 */
Leon Scroggins III3993b372018-07-16 10:43:45 -0400173 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;
Alex Naidis6eb7d372016-10-16 23:10:08 +0200179 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 */
192 cb = GETJSAMPLE(*inptr1++);
193 cr = GETJSAMPLE(*inptr2++);
194 cred = Crrtab[cr];
Leon Scroggins III3993b372018-07-16 10:43:45 -0400195 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 */
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];
Leon Scroggins III3993b372018-07-16 10:43:45 -0400235 cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
Aaron Gablefeec46f2015-08-06 09:54:48 -0700236 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);
Leon Scroggins III3993b372018-07-16 10:43:45 -0400243 *(INT16 *)outptr0 = (INT16)rgb;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700244
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);
Leon Scroggins III3993b372018-07-16 10:43:45 -0400250 *(INT16 *)outptr1 = (INT16)rgb;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700251 }
252}
253
254
255INLINE
256LOCAL(void)
Leon Scroggins III3993b372018-07-16 10:43:45 -0400257h2v2_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{
Leon Scroggins III3993b372018-07-16 10:43:45 -0400262 my_upsample_ptr upsample = (my_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 */
Leon Scroggins III3993b372018-07-16 10:43:45 -0400269 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;
Alex Naidis6eb7d372016-10-16 23:10:08 +0200274 JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
Leon Scroggins III3993b372018-07-16 10:43:45 -0400275 JLONG d1 = dither_matrix[(cinfo->output_scanline + 1) & DITHER_MASK];
Aaron Gablefeec46f2015-08-06 09:54:48 -0700276 unsigned int r, g, b;
Alex Naidis6eb7d372016-10-16 23:10:08 +0200277 JLONG rgb;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700278 SHIFT_TEMPS
279
Leon Scroggins III3993b372018-07-16 10:43:45 -0400280 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 */
290 cb = GETJSAMPLE(*inptr1++);
291 cr = GETJSAMPLE(*inptr2++);
292 cred = Crrtab[cr];
Leon Scroggins III3993b372018-07-16 10:43:45 -0400293 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 */
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++);
Leon Scroggins III3993b372018-07-16 10:43:45 -0400305 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
314 y = GETJSAMPLE(*inptr01++);
Leon Scroggins III3993b372018-07-16 10:43:45 -0400315 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
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];
Leon Scroggins III3993b372018-07-16 10:43:45 -0400337 cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
Aaron Gablefeec46f2015-08-06 09:54:48 -0700338 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);
Leon Scroggins III3993b372018-07-16 10:43:45 -0400345 *(INT16 *)outptr0 = (INT16)rgb;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700346
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);
Leon Scroggins III3993b372018-07-16 10:43:45 -0400352 *(INT16 *)outptr1 = (INT16)rgb;
Aaron Gablefeec46f2015-08-06 09:54:48 -0700353 }
354}