xref: /aosp_15_r20/external/libjpeg-turbo/jdmrgext.c (revision dfc6aa5c1cfd4bc4e2018dc74aa96e29ee49c6da)
1*dfc6aa5cSAndroid Build Coastguard Worker /*
2*dfc6aa5cSAndroid Build Coastguard Worker  * jdmrgext.c
3*dfc6aa5cSAndroid Build Coastguard Worker  *
4*dfc6aa5cSAndroid Build Coastguard Worker  * This file was part of the Independent JPEG Group's software:
5*dfc6aa5cSAndroid Build Coastguard Worker  * Copyright (C) 1994-1996, Thomas G. Lane.
6*dfc6aa5cSAndroid Build Coastguard Worker  * libjpeg-turbo Modifications:
7*dfc6aa5cSAndroid Build Coastguard Worker  * Copyright (C) 2011, 2015, 2020, 2023, D. R. Commander.
8*dfc6aa5cSAndroid Build Coastguard Worker  * For conditions of distribution and use, see the accompanying README.ijg
9*dfc6aa5cSAndroid Build Coastguard Worker  * file.
10*dfc6aa5cSAndroid Build Coastguard Worker  *
11*dfc6aa5cSAndroid Build Coastguard Worker  * This file contains code for merged upsampling/color conversion.
12*dfc6aa5cSAndroid Build Coastguard Worker  */
13*dfc6aa5cSAndroid Build Coastguard Worker 
14*dfc6aa5cSAndroid Build Coastguard Worker 
15*dfc6aa5cSAndroid Build Coastguard Worker /* This file is included by jdmerge.c */
16*dfc6aa5cSAndroid Build Coastguard Worker 
17*dfc6aa5cSAndroid Build Coastguard Worker 
18*dfc6aa5cSAndroid Build Coastguard Worker /*
19*dfc6aa5cSAndroid Build Coastguard Worker  * Upsample and color convert for the case of 2:1 horizontal and 1:1 vertical.
20*dfc6aa5cSAndroid Build Coastguard Worker  */
21*dfc6aa5cSAndroid Build Coastguard Worker 
22*dfc6aa5cSAndroid Build Coastguard Worker INLINE
LOCAL(void)23*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
24*dfc6aa5cSAndroid Build Coastguard Worker h2v1_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
25*dfc6aa5cSAndroid Build Coastguard Worker                               JDIMENSION in_row_group_ctr,
26*dfc6aa5cSAndroid Build Coastguard Worker                               JSAMPARRAY output_buf)
27*dfc6aa5cSAndroid Build Coastguard Worker {
28*dfc6aa5cSAndroid Build Coastguard Worker   my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample;
29*dfc6aa5cSAndroid Build Coastguard Worker   register int y, cred, cgreen, cblue;
30*dfc6aa5cSAndroid Build Coastguard Worker   int cb, cr;
31*dfc6aa5cSAndroid Build Coastguard Worker   register JSAMPROW outptr;
32*dfc6aa5cSAndroid Build Coastguard Worker   JSAMPROW inptr0, inptr1, inptr2;
33*dfc6aa5cSAndroid Build Coastguard Worker   JDIMENSION col;
34*dfc6aa5cSAndroid Build Coastguard Worker   /* copy these pointers into registers if possible */
35*dfc6aa5cSAndroid Build Coastguard Worker   register JSAMPLE *range_limit = cinfo->sample_range_limit;
36*dfc6aa5cSAndroid Build Coastguard Worker   int *Crrtab = upsample->Cr_r_tab;
37*dfc6aa5cSAndroid Build Coastguard Worker   int *Cbbtab = upsample->Cb_b_tab;
38*dfc6aa5cSAndroid Build Coastguard Worker   JLONG *Crgtab = upsample->Cr_g_tab;
39*dfc6aa5cSAndroid Build Coastguard Worker   JLONG *Cbgtab = upsample->Cb_g_tab;
40*dfc6aa5cSAndroid Build Coastguard Worker   SHIFT_TEMPS
41*dfc6aa5cSAndroid Build Coastguard Worker 
42*dfc6aa5cSAndroid Build Coastguard Worker   inptr0 = input_buf[0][in_row_group_ctr];
43*dfc6aa5cSAndroid Build Coastguard Worker   inptr1 = input_buf[1][in_row_group_ctr];
44*dfc6aa5cSAndroid Build Coastguard Worker   inptr2 = input_buf[2][in_row_group_ctr];
45*dfc6aa5cSAndroid Build Coastguard Worker   outptr = output_buf[0];
46*dfc6aa5cSAndroid Build Coastguard Worker   /* Loop for each pair of output pixels */
47*dfc6aa5cSAndroid Build Coastguard Worker   for (col = cinfo->output_width >> 1; col > 0; col--) {
48*dfc6aa5cSAndroid Build Coastguard Worker     /* Do the chroma part of the calculation */
49*dfc6aa5cSAndroid Build Coastguard Worker     cb = *inptr1++;
50*dfc6aa5cSAndroid Build Coastguard Worker     cr = *inptr2++;
51*dfc6aa5cSAndroid Build Coastguard Worker     cred = Crrtab[cr];
52*dfc6aa5cSAndroid Build Coastguard Worker     cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
53*dfc6aa5cSAndroid Build Coastguard Worker     cblue = Cbbtab[cb];
54*dfc6aa5cSAndroid Build Coastguard Worker     /* Fetch 2 Y values and emit 2 pixels */
55*dfc6aa5cSAndroid Build Coastguard Worker     y  = *inptr0++;
56*dfc6aa5cSAndroid Build Coastguard Worker     outptr[RGB_RED] =   range_limit[y + cred];
57*dfc6aa5cSAndroid Build Coastguard Worker     outptr[RGB_GREEN] = range_limit[y + cgreen];
58*dfc6aa5cSAndroid Build Coastguard Worker     outptr[RGB_BLUE] =  range_limit[y + cblue];
59*dfc6aa5cSAndroid Build Coastguard Worker #ifdef RGB_ALPHA
60*dfc6aa5cSAndroid Build Coastguard Worker     outptr[RGB_ALPHA] = MAXJSAMPLE;
61*dfc6aa5cSAndroid Build Coastguard Worker #endif
62*dfc6aa5cSAndroid Build Coastguard Worker     outptr += RGB_PIXELSIZE;
63*dfc6aa5cSAndroid Build Coastguard Worker     y  = *inptr0++;
64*dfc6aa5cSAndroid Build Coastguard Worker     outptr[RGB_RED] =   range_limit[y + cred];
65*dfc6aa5cSAndroid Build Coastguard Worker     outptr[RGB_GREEN] = range_limit[y + cgreen];
66*dfc6aa5cSAndroid Build Coastguard Worker     outptr[RGB_BLUE] =  range_limit[y + cblue];
67*dfc6aa5cSAndroid Build Coastguard Worker #ifdef RGB_ALPHA
68*dfc6aa5cSAndroid Build Coastguard Worker     outptr[RGB_ALPHA] = MAXJSAMPLE;
69*dfc6aa5cSAndroid Build Coastguard Worker #endif
70*dfc6aa5cSAndroid Build Coastguard Worker     outptr += RGB_PIXELSIZE;
71*dfc6aa5cSAndroid Build Coastguard Worker   }
72*dfc6aa5cSAndroid Build Coastguard Worker   /* If image width is odd, do the last output column separately */
73*dfc6aa5cSAndroid Build Coastguard Worker   if (cinfo->output_width & 1) {
74*dfc6aa5cSAndroid Build Coastguard Worker     cb = *inptr1;
75*dfc6aa5cSAndroid Build Coastguard Worker     cr = *inptr2;
76*dfc6aa5cSAndroid Build Coastguard Worker     cred = Crrtab[cr];
77*dfc6aa5cSAndroid Build Coastguard Worker     cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
78*dfc6aa5cSAndroid Build Coastguard Worker     cblue = Cbbtab[cb];
79*dfc6aa5cSAndroid Build Coastguard Worker     y  = *inptr0;
80*dfc6aa5cSAndroid Build Coastguard Worker     outptr[RGB_RED] =   range_limit[y + cred];
81*dfc6aa5cSAndroid Build Coastguard Worker     outptr[RGB_GREEN] = range_limit[y + cgreen];
82*dfc6aa5cSAndroid Build Coastguard Worker     outptr[RGB_BLUE] =  range_limit[y + cblue];
83*dfc6aa5cSAndroid Build Coastguard Worker #ifdef RGB_ALPHA
84*dfc6aa5cSAndroid Build Coastguard Worker     outptr[RGB_ALPHA] = MAXJSAMPLE;
85*dfc6aa5cSAndroid Build Coastguard Worker #endif
86*dfc6aa5cSAndroid Build Coastguard Worker   }
87*dfc6aa5cSAndroid Build Coastguard Worker }
88*dfc6aa5cSAndroid Build Coastguard Worker 
89*dfc6aa5cSAndroid Build Coastguard Worker 
90*dfc6aa5cSAndroid Build Coastguard Worker /*
91*dfc6aa5cSAndroid Build Coastguard Worker  * Upsample and color convert for the case of 2:1 horizontal and 2:1 vertical.
92*dfc6aa5cSAndroid Build Coastguard Worker  */
93*dfc6aa5cSAndroid Build Coastguard Worker 
94*dfc6aa5cSAndroid Build Coastguard Worker INLINE
LOCAL(void)95*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
96*dfc6aa5cSAndroid Build Coastguard Worker h2v2_merged_upsample_internal(j_decompress_ptr cinfo, JSAMPIMAGE input_buf,
97*dfc6aa5cSAndroid Build Coastguard Worker                               JDIMENSION in_row_group_ctr,
98*dfc6aa5cSAndroid Build Coastguard Worker                               JSAMPARRAY output_buf)
99*dfc6aa5cSAndroid Build Coastguard Worker {
100*dfc6aa5cSAndroid Build Coastguard Worker   my_merged_upsample_ptr upsample = (my_merged_upsample_ptr)cinfo->upsample;
101*dfc6aa5cSAndroid Build Coastguard Worker   register int y, cred, cgreen, cblue;
102*dfc6aa5cSAndroid Build Coastguard Worker   int cb, cr;
103*dfc6aa5cSAndroid Build Coastguard Worker   register JSAMPROW outptr0, outptr1;
104*dfc6aa5cSAndroid Build Coastguard Worker   JSAMPROW inptr00, inptr01, inptr1, inptr2;
105*dfc6aa5cSAndroid Build Coastguard Worker   JDIMENSION col;
106*dfc6aa5cSAndroid Build Coastguard Worker   /* copy these pointers into registers if possible */
107*dfc6aa5cSAndroid Build Coastguard Worker   register JSAMPLE *range_limit = cinfo->sample_range_limit;
108*dfc6aa5cSAndroid Build Coastguard Worker   int *Crrtab = upsample->Cr_r_tab;
109*dfc6aa5cSAndroid Build Coastguard Worker   int *Cbbtab = upsample->Cb_b_tab;
110*dfc6aa5cSAndroid Build Coastguard Worker   JLONG *Crgtab = upsample->Cr_g_tab;
111*dfc6aa5cSAndroid Build Coastguard Worker   JLONG *Cbgtab = upsample->Cb_g_tab;
112*dfc6aa5cSAndroid Build Coastguard Worker   SHIFT_TEMPS
113*dfc6aa5cSAndroid Build Coastguard Worker 
114*dfc6aa5cSAndroid Build Coastguard Worker   inptr00 = input_buf[0][in_row_group_ctr * 2];
115*dfc6aa5cSAndroid Build Coastguard Worker   inptr01 = input_buf[0][in_row_group_ctr * 2 + 1];
116*dfc6aa5cSAndroid Build Coastguard Worker   inptr1 = input_buf[1][in_row_group_ctr];
117*dfc6aa5cSAndroid Build Coastguard Worker   inptr2 = input_buf[2][in_row_group_ctr];
118*dfc6aa5cSAndroid Build Coastguard Worker   outptr0 = output_buf[0];
119*dfc6aa5cSAndroid Build Coastguard Worker   outptr1 = output_buf[1];
120*dfc6aa5cSAndroid Build Coastguard Worker   /* Loop for each group of output pixels */
121*dfc6aa5cSAndroid Build Coastguard Worker   for (col = cinfo->output_width >> 1; col > 0; col--) {
122*dfc6aa5cSAndroid Build Coastguard Worker     /* Do the chroma part of the calculation */
123*dfc6aa5cSAndroid Build Coastguard Worker     cb = *inptr1++;
124*dfc6aa5cSAndroid Build Coastguard Worker     cr = *inptr2++;
125*dfc6aa5cSAndroid Build Coastguard Worker     cred = Crrtab[cr];
126*dfc6aa5cSAndroid Build Coastguard Worker     cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
127*dfc6aa5cSAndroid Build Coastguard Worker     cblue = Cbbtab[cb];
128*dfc6aa5cSAndroid Build Coastguard Worker     /* Fetch 4 Y values and emit 4 pixels */
129*dfc6aa5cSAndroid Build Coastguard Worker     y  = *inptr00++;
130*dfc6aa5cSAndroid Build Coastguard Worker     outptr0[RGB_RED] =   range_limit[y + cred];
131*dfc6aa5cSAndroid Build Coastguard Worker     outptr0[RGB_GREEN] = range_limit[y + cgreen];
132*dfc6aa5cSAndroid Build Coastguard Worker     outptr0[RGB_BLUE] =  range_limit[y + cblue];
133*dfc6aa5cSAndroid Build Coastguard Worker #ifdef RGB_ALPHA
134*dfc6aa5cSAndroid Build Coastguard Worker     outptr0[RGB_ALPHA] = MAXJSAMPLE;
135*dfc6aa5cSAndroid Build Coastguard Worker #endif
136*dfc6aa5cSAndroid Build Coastguard Worker     outptr0 += RGB_PIXELSIZE;
137*dfc6aa5cSAndroid Build Coastguard Worker     y  = *inptr00++;
138*dfc6aa5cSAndroid Build Coastguard Worker     outptr0[RGB_RED] =   range_limit[y + cred];
139*dfc6aa5cSAndroid Build Coastguard Worker     outptr0[RGB_GREEN] = range_limit[y + cgreen];
140*dfc6aa5cSAndroid Build Coastguard Worker     outptr0[RGB_BLUE] =  range_limit[y + cblue];
141*dfc6aa5cSAndroid Build Coastguard Worker #ifdef RGB_ALPHA
142*dfc6aa5cSAndroid Build Coastguard Worker     outptr0[RGB_ALPHA] = MAXJSAMPLE;
143*dfc6aa5cSAndroid Build Coastguard Worker #endif
144*dfc6aa5cSAndroid Build Coastguard Worker     outptr0 += RGB_PIXELSIZE;
145*dfc6aa5cSAndroid Build Coastguard Worker     y  = *inptr01++;
146*dfc6aa5cSAndroid Build Coastguard Worker     outptr1[RGB_RED] =   range_limit[y + cred];
147*dfc6aa5cSAndroid Build Coastguard Worker     outptr1[RGB_GREEN] = range_limit[y + cgreen];
148*dfc6aa5cSAndroid Build Coastguard Worker     outptr1[RGB_BLUE] =  range_limit[y + cblue];
149*dfc6aa5cSAndroid Build Coastguard Worker #ifdef RGB_ALPHA
150*dfc6aa5cSAndroid Build Coastguard Worker     outptr1[RGB_ALPHA] = MAXJSAMPLE;
151*dfc6aa5cSAndroid Build Coastguard Worker #endif
152*dfc6aa5cSAndroid Build Coastguard Worker     outptr1 += RGB_PIXELSIZE;
153*dfc6aa5cSAndroid Build Coastguard Worker     y  = *inptr01++;
154*dfc6aa5cSAndroid Build Coastguard Worker     outptr1[RGB_RED] =   range_limit[y + cred];
155*dfc6aa5cSAndroid Build Coastguard Worker     outptr1[RGB_GREEN] = range_limit[y + cgreen];
156*dfc6aa5cSAndroid Build Coastguard Worker     outptr1[RGB_BLUE] =  range_limit[y + cblue];
157*dfc6aa5cSAndroid Build Coastguard Worker #ifdef RGB_ALPHA
158*dfc6aa5cSAndroid Build Coastguard Worker     outptr1[RGB_ALPHA] = MAXJSAMPLE;
159*dfc6aa5cSAndroid Build Coastguard Worker #endif
160*dfc6aa5cSAndroid Build Coastguard Worker     outptr1 += RGB_PIXELSIZE;
161*dfc6aa5cSAndroid Build Coastguard Worker   }
162*dfc6aa5cSAndroid Build Coastguard Worker   /* If image width is odd, do the last output column separately */
163*dfc6aa5cSAndroid Build Coastguard Worker   if (cinfo->output_width & 1) {
164*dfc6aa5cSAndroid Build Coastguard Worker     cb = *inptr1;
165*dfc6aa5cSAndroid Build Coastguard Worker     cr = *inptr2;
166*dfc6aa5cSAndroid Build Coastguard Worker     cred = Crrtab[cr];
167*dfc6aa5cSAndroid Build Coastguard Worker     cgreen = (int)RIGHT_SHIFT(Cbgtab[cb] + Crgtab[cr], SCALEBITS);
168*dfc6aa5cSAndroid Build Coastguard Worker     cblue = Cbbtab[cb];
169*dfc6aa5cSAndroid Build Coastguard Worker     y  = *inptr00;
170*dfc6aa5cSAndroid Build Coastguard Worker     outptr0[RGB_RED] =   range_limit[y + cred];
171*dfc6aa5cSAndroid Build Coastguard Worker     outptr0[RGB_GREEN] = range_limit[y + cgreen];
172*dfc6aa5cSAndroid Build Coastguard Worker     outptr0[RGB_BLUE] =  range_limit[y + cblue];
173*dfc6aa5cSAndroid Build Coastguard Worker #ifdef RGB_ALPHA
174*dfc6aa5cSAndroid Build Coastguard Worker     outptr0[RGB_ALPHA] = MAXJSAMPLE;
175*dfc6aa5cSAndroid Build Coastguard Worker #endif
176*dfc6aa5cSAndroid Build Coastguard Worker     y  = *inptr01;
177*dfc6aa5cSAndroid Build Coastguard Worker     outptr1[RGB_RED] =   range_limit[y + cred];
178*dfc6aa5cSAndroid Build Coastguard Worker     outptr1[RGB_GREEN] = range_limit[y + cgreen];
179*dfc6aa5cSAndroid Build Coastguard Worker     outptr1[RGB_BLUE] =  range_limit[y + cblue];
180*dfc6aa5cSAndroid Build Coastguard Worker #ifdef RGB_ALPHA
181*dfc6aa5cSAndroid Build Coastguard Worker     outptr1[RGB_ALPHA] = MAXJSAMPLE;
182*dfc6aa5cSAndroid Build Coastguard Worker #endif
183*dfc6aa5cSAndroid Build Coastguard Worker   }
184*dfc6aa5cSAndroid Build Coastguard Worker }
185