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