1 /*
2 * jdcol565.c
3 *
4 * This file was part of the Independent JPEG Group's software:
5 * Copyright (C) 1991-1997, Thomas G. Lane.
6 * 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 output colorspace conversion routines.
13 */
14
15 /* This file is included by jdcolor.c */
16
17
18 INLINE
LOCAL(void)19 LOCAL(void)
20 ycc_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
21 JDIMENSION input_row, JSAMPARRAY output_buf,
22 int num_rows)
23 {
24 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
25 register int y, cb, cr;
26 register JSAMPROW outptr;
27 register JSAMPROW inptr0, inptr1, inptr2;
28 register JDIMENSION col;
29 JDIMENSION num_cols = cinfo->output_width;
30 /* copy these pointers into registers if possible */
31 register JSAMPLE *range_limit = cinfo->sample_range_limit;
32 register int *Crrtab = cconvert->Cr_r_tab;
33 register int *Cbbtab = cconvert->Cb_b_tab;
34 register JLONG *Crgtab = cconvert->Cr_g_tab;
35 register JLONG *Cbgtab = cconvert->Cb_g_tab;
36 SHIFT_TEMPS
37
38 while (--num_rows >= 0) {
39 JLONG rgb;
40 unsigned int r, g, b;
41 inptr0 = input_buf[0][input_row];
42 inptr1 = input_buf[1][input_row];
43 inptr2 = input_buf[2][input_row];
44 input_row++;
45 outptr = *output_buf++;
46
47 if (PACK_NEED_ALIGNMENT(outptr)) {
48 y = *inptr0++;
49 cb = *inptr1++;
50 cr = *inptr2++;
51 r = range_limit[y + Crrtab[cr]];
52 g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
53 SCALEBITS))];
54 b = range_limit[y + Cbbtab[cb]];
55 rgb = PACK_SHORT_565(r, g, b);
56 *(INT16 *)outptr = (INT16)rgb;
57 outptr += 2;
58 num_cols--;
59 }
60 for (col = 0; col < (num_cols >> 1); col++) {
61 y = *inptr0++;
62 cb = *inptr1++;
63 cr = *inptr2++;
64 r = range_limit[y + Crrtab[cr]];
65 g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
66 SCALEBITS))];
67 b = range_limit[y + Cbbtab[cb]];
68 rgb = PACK_SHORT_565(r, g, b);
69
70 y = *inptr0++;
71 cb = *inptr1++;
72 cr = *inptr2++;
73 r = range_limit[y + Crrtab[cr]];
74 g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
75 SCALEBITS))];
76 b = range_limit[y + Cbbtab[cb]];
77 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
78
79 WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
80 outptr += 4;
81 }
82 if (num_cols & 1) {
83 y = *inptr0;
84 cb = *inptr1;
85 cr = *inptr2;
86 r = range_limit[y + Crrtab[cr]];
87 g = range_limit[y + ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
88 SCALEBITS))];
89 b = range_limit[y + Cbbtab[cb]];
90 rgb = PACK_SHORT_565(r, g, b);
91 *(INT16 *)outptr = (INT16)rgb;
92 }
93 }
94 }
95
96
97 INLINE
LOCAL(void)98 LOCAL(void)
99 ycc_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
100 JDIMENSION input_row, JSAMPARRAY output_buf,
101 int num_rows)
102 {
103 my_cconvert_ptr cconvert = (my_cconvert_ptr)cinfo->cconvert;
104 register int y, cb, cr;
105 register JSAMPROW outptr;
106 register JSAMPROW inptr0, inptr1, inptr2;
107 register JDIMENSION col;
108 JDIMENSION num_cols = cinfo->output_width;
109 /* copy these pointers into registers if possible */
110 register JSAMPLE *range_limit = cinfo->sample_range_limit;
111 register int *Crrtab = cconvert->Cr_r_tab;
112 register int *Cbbtab = cconvert->Cb_b_tab;
113 register JLONG *Crgtab = cconvert->Cr_g_tab;
114 register JLONG *Cbgtab = cconvert->Cb_g_tab;
115 JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
116 SHIFT_TEMPS
117
118 while (--num_rows >= 0) {
119 JLONG rgb;
120 unsigned int r, g, b;
121
122 inptr0 = input_buf[0][input_row];
123 inptr1 = input_buf[1][input_row];
124 inptr2 = input_buf[2][input_row];
125 input_row++;
126 outptr = *output_buf++;
127 if (PACK_NEED_ALIGNMENT(outptr)) {
128 y = *inptr0++;
129 cb = *inptr1++;
130 cr = *inptr2++;
131 r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
132 g = range_limit[DITHER_565_G(y +
133 ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
134 SCALEBITS)), d0)];
135 b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
136 rgb = PACK_SHORT_565(r, g, b);
137 *(INT16 *)outptr = (INT16)rgb;
138 outptr += 2;
139 num_cols--;
140 }
141 for (col = 0; col < (num_cols >> 1); col++) {
142 y = *inptr0++;
143 cb = *inptr1++;
144 cr = *inptr2++;
145 r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
146 g = range_limit[DITHER_565_G(y +
147 ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
148 SCALEBITS)), d0)];
149 b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
150 d0 = DITHER_ROTATE(d0);
151 rgb = PACK_SHORT_565(r, g, b);
152
153 y = *inptr0++;
154 cb = *inptr1++;
155 cr = *inptr2++;
156 r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
157 g = range_limit[DITHER_565_G(y +
158 ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
159 SCALEBITS)), d0)];
160 b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
161 d0 = DITHER_ROTATE(d0);
162 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
163
164 WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
165 outptr += 4;
166 }
167 if (num_cols & 1) {
168 y = *inptr0;
169 cb = *inptr1;
170 cr = *inptr2;
171 r = range_limit[DITHER_565_R(y + Crrtab[cr], d0)];
172 g = range_limit[DITHER_565_G(y +
173 ((int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr],
174 SCALEBITS)), d0)];
175 b = range_limit[DITHER_565_B(y + Cbbtab[cb], d0)];
176 rgb = PACK_SHORT_565(r, g, b);
177 *(INT16 *)outptr = (INT16)rgb;
178 }
179 }
180 }
181
182
183 INLINE
LOCAL(void)184 LOCAL(void)
185 rgb_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
186 JDIMENSION input_row, JSAMPARRAY output_buf,
187 int num_rows)
188 {
189 register JSAMPROW outptr;
190 register JSAMPROW inptr0, inptr1, inptr2;
191 register JDIMENSION col;
192 JDIMENSION num_cols = cinfo->output_width;
193 SHIFT_TEMPS
194
195 while (--num_rows >= 0) {
196 JLONG rgb;
197 unsigned int r, g, b;
198
199 inptr0 = input_buf[0][input_row];
200 inptr1 = input_buf[1][input_row];
201 inptr2 = input_buf[2][input_row];
202 input_row++;
203 outptr = *output_buf++;
204 if (PACK_NEED_ALIGNMENT(outptr)) {
205 r = *inptr0++;
206 g = *inptr1++;
207 b = *inptr2++;
208 rgb = PACK_SHORT_565(r, g, b);
209 *(INT16 *)outptr = (INT16)rgb;
210 outptr += 2;
211 num_cols--;
212 }
213 for (col = 0; col < (num_cols >> 1); col++) {
214 r = *inptr0++;
215 g = *inptr1++;
216 b = *inptr2++;
217 rgb = PACK_SHORT_565(r, g, b);
218
219 r = *inptr0++;
220 g = *inptr1++;
221 b = *inptr2++;
222 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
223
224 WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
225 outptr += 4;
226 }
227 if (num_cols & 1) {
228 r = *inptr0;
229 g = *inptr1;
230 b = *inptr2;
231 rgb = PACK_SHORT_565(r, g, b);
232 *(INT16 *)outptr = (INT16)rgb;
233 }
234 }
235 }
236
237
238 INLINE
LOCAL(void)239 LOCAL(void)
240 rgb_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
241 JDIMENSION input_row, JSAMPARRAY output_buf,
242 int num_rows)
243 {
244 register JSAMPROW outptr;
245 register JSAMPROW inptr0, inptr1, inptr2;
246 register JDIMENSION col;
247 register JSAMPLE *range_limit = cinfo->sample_range_limit;
248 JDIMENSION num_cols = cinfo->output_width;
249 JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
250 SHIFT_TEMPS
251
252 while (--num_rows >= 0) {
253 JLONG rgb;
254 unsigned int r, g, b;
255
256 inptr0 = input_buf[0][input_row];
257 inptr1 = input_buf[1][input_row];
258 inptr2 = input_buf[2][input_row];
259 input_row++;
260 outptr = *output_buf++;
261 if (PACK_NEED_ALIGNMENT(outptr)) {
262 r = range_limit[DITHER_565_R(*inptr0++, d0)];
263 g = range_limit[DITHER_565_G(*inptr1++, d0)];
264 b = range_limit[DITHER_565_B(*inptr2++, d0)];
265 rgb = PACK_SHORT_565(r, g, b);
266 *(INT16 *)outptr = (INT16)rgb;
267 outptr += 2;
268 num_cols--;
269 }
270 for (col = 0; col < (num_cols >> 1); col++) {
271 r = range_limit[DITHER_565_R(*inptr0++, d0)];
272 g = range_limit[DITHER_565_G(*inptr1++, d0)];
273 b = range_limit[DITHER_565_B(*inptr2++, d0)];
274 d0 = DITHER_ROTATE(d0);
275 rgb = PACK_SHORT_565(r, g, b);
276
277 r = range_limit[DITHER_565_R(*inptr0++, d0)];
278 g = range_limit[DITHER_565_G(*inptr1++, d0)];
279 b = range_limit[DITHER_565_B(*inptr2++, d0)];
280 d0 = DITHER_ROTATE(d0);
281 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(r, g, b));
282
283 WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
284 outptr += 4;
285 }
286 if (num_cols & 1) {
287 r = range_limit[DITHER_565_R(*inptr0, d0)];
288 g = range_limit[DITHER_565_G(*inptr1, d0)];
289 b = range_limit[DITHER_565_B(*inptr2, d0)];
290 rgb = PACK_SHORT_565(r, g, b);
291 *(INT16 *)outptr = (INT16)rgb;
292 }
293 }
294 }
295
296
297 INLINE
LOCAL(void)298 LOCAL(void)
299 gray_rgb565_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
300 JDIMENSION input_row, JSAMPARRAY output_buf,
301 int num_rows)
302 {
303 register JSAMPROW inptr, outptr;
304 register JDIMENSION col;
305 JDIMENSION num_cols = cinfo->output_width;
306
307 while (--num_rows >= 0) {
308 JLONG rgb;
309 unsigned int g;
310
311 inptr = input_buf[0][input_row++];
312 outptr = *output_buf++;
313 if (PACK_NEED_ALIGNMENT(outptr)) {
314 g = *inptr++;
315 rgb = PACK_SHORT_565(g, g, g);
316 *(INT16 *)outptr = (INT16)rgb;
317 outptr += 2;
318 num_cols--;
319 }
320 for (col = 0; col < (num_cols >> 1); col++) {
321 g = *inptr++;
322 rgb = PACK_SHORT_565(g, g, g);
323 g = *inptr++;
324 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(g, g, g));
325 WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
326 outptr += 4;
327 }
328 if (num_cols & 1) {
329 g = *inptr;
330 rgb = PACK_SHORT_565(g, g, g);
331 *(INT16 *)outptr = (INT16)rgb;
332 }
333 }
334 }
335
336
337 INLINE
LOCAL(void)338 LOCAL(void)
339 gray_rgb565D_convert_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
340 JDIMENSION input_row, JSAMPARRAY output_buf,
341 int num_rows)
342 {
343 register JSAMPROW inptr, outptr;
344 register JDIMENSION col;
345 register JSAMPLE *range_limit = cinfo->sample_range_limit;
346 JDIMENSION num_cols = cinfo->output_width;
347 JLONG d0 = dither_matrix[cinfo->output_scanline & DITHER_MASK];
348
349 while (--num_rows >= 0) {
350 JLONG rgb;
351 unsigned int g;
352
353 inptr = input_buf[0][input_row++];
354 outptr = *output_buf++;
355 if (PACK_NEED_ALIGNMENT(outptr)) {
356 g = *inptr++;
357 g = range_limit[DITHER_565_R(g, d0)];
358 rgb = PACK_SHORT_565(g, g, g);
359 *(INT16 *)outptr = (INT16)rgb;
360 outptr += 2;
361 num_cols--;
362 }
363 for (col = 0; col < (num_cols >> 1); col++) {
364 g = *inptr++;
365 g = range_limit[DITHER_565_R(g, d0)];
366 rgb = PACK_SHORT_565(g, g, g);
367 d0 = DITHER_ROTATE(d0);
368
369 g = *inptr++;
370 g = range_limit[DITHER_565_R(g, d0)];
371 rgb = PACK_TWO_PIXELS(rgb, PACK_SHORT_565(g, g, g));
372 d0 = DITHER_ROTATE(d0);
373
374 WRITE_TWO_ALIGNED_PIXELS(outptr, rgb);
375 outptr += 4;
376 }
377 if (num_cols & 1) {
378 g = *inptr;
379 g = range_limit[DITHER_565_R(g, d0)];
380 rgb = PACK_SHORT_565(g, g, g);
381 *(INT16 *)outptr = (INT16)rgb;
382 }
383 }
384 }
385