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