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
18INLINE
19LOCAL(void)
20ycc_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
97INLINE
98LOCAL(void)
99ycc_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
183INLINE
184LOCAL(void)
185rgb_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
238INLINE
239LOCAL(void)
240rgb_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
297INLINE
298LOCAL(void)
299gray_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
337INLINE
338LOCAL(void)
339gray_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