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