1 /* -*-C-*-
2 ******************************************************************************
3 *
4 * File:         process.c
5 * RCS:          $Header: /ImageMagick/delegates/fpx/jpeg/process.c,v 1.3 2000/12/23 22:37:48 bfriesen Exp $
6 * Description:  Default subsampling/YCbCr routines for the HP JPEG Encoder.
7 * Author:       Kirt Winter
8 * Created:      Fri Mar  1 09:04:22 1995
9 * Initial Source Release:     Thursday, March 7 1996
10 * Language:     C
11 * Package:      Hewlett-Packard JPEG Encoder/Decoder
12 *
13 * Copyright (c) 1999 Digital Imaging Group, Inc.
14 * For conditions of distribution and use, see copyright notice
15 * in Flashpix.h
16 *
17 ******************************************************************************
18 */
19 #include <stdlib.h>
20 #include "jpegconf.h"
21 #include "fpxmem.h"
22 #include "process.h"
23 
24 #include "ejpeg.h"      /* CHG_JPEG_MEM_FIX - added this to get error code */
25 
26 /*
27 ** This routine strips color information from an opponent color stream.  Upon completion of
28 ** its assigned duty, the destination buffer will be filled with LLLLabLLLLabLLLLab,
29 ** assuming of course that it was originally LabLabLabLabLab.  Alpha channel is
30 ** supported (as the last channel in the set), but is not subsampled.
31 **
32 */
33 int
SubSample411(const unsigned char * src,unsigned char * dst,int tileSize,int bpp)34 SubSample411(const unsigned char *src, unsigned char *dst, int tileSize, int bpp)
35 {
36   int x, y, blocks, acc, lineOffset;
37   unsigned char *dstPtr = dst;
38   const unsigned char *p1, *p2, *p3, *p4;
39 
40   blocks = tileSize / 2;
41   lineOffset = tileSize * bpp;
42   for(x = 0; x < blocks; x++)
43   {
44     for(y = 0; y < blocks; y++)
45     {
46       p1 = src;
47       p2 = p1 + bpp;
48       p3 = p1 + lineOffset;
49       p4 = p3 + bpp;
50 
51       *dstPtr++ = *p1++;
52       *dstPtr++ = *p2++;
53       *dstPtr++ = *p3++;
54       *dstPtr++ = *p4++;
55       /* p1 - p4 now point to first chroma sample
56           ** We take the average chroma of the 4 points in the quadrant
57           ** and place that in the destination buffer.
58       */
59       acc = *p1++ + *p2++ + *p3++ + *p4++;
60       *dstPtr++ = (unsigned char) ((acc + 2) >> 2);
61 
62       /* p1 - p4 now point to second chroma sample
63          ** now, we repeat the above process for second chroma
64       */
65       acc = *p1++ + *p2++ + *p3++ + *p4++;
66       *dstPtr++ = (unsigned char) ((acc + 2) >> 2);
67 
68       /* Alpha channel, if it exists, is never subsampled */
69       if (bpp == 4)
70       {
71         *dstPtr++ = *p1++;
72         *dstPtr++ = *p2++;
73         *dstPtr++ = *p3++;
74         *dstPtr++ = *p4++;
75       }
76 
77       src += 2*bpp;   /* skip over one triplet (quadlet?) and point to
78                                                  the next quadrant */
79     }
80     src += lineOffset;
81   }
82   return(0);
83 }
84 
85 int
SubSample422(const unsigned char * src,unsigned char * dst,int tileSize,int bpp)86 SubSample422(const unsigned char *src, unsigned char *dst, int tileSize, int bpp)
87 {
88   int x, y, blocks, acc;
89   unsigned char *dstPtr = dst;
90   const unsigned char *p1, *p2;
91 
92   blocks = tileSize / 2;
93   for(x = 0; x < tileSize; x++)
94   {
95     for(y = 0; y < blocks; y++)
96     {
97       p1 = src;
98       p2 = p1 + bpp;
99 
100       *dstPtr++ = *p1++;
101       *dstPtr++ = *p2++;
102 
103       /* p1,p2 now point to first chroma sample
104           ** here we take the average chroma of the two points
105           ** and place that in the destination buffer
106       */
107       acc = *p1++ + *p2++;
108       *dstPtr++ = (unsigned char) ((acc + 1) >> 1);
109 
110       /* p1,p4 now point to second chroma sample
111           ** so, we repeat the above process for second chroma
112       */
113       acc = *p1++ + *p2++;
114       *dstPtr++ = (unsigned char) ((acc + 1) >> 1);
115 
116       /* If an alpha channel, it is never subsampled.*/
117       if(bpp == 4)
118       {
119         *dstPtr++ = *p1++;
120         *dstPtr++ = *p2++;
121       }
122 
123       src += 2*bpp;   /* skip over one triplet (quadlet?) and point to
124                                                  the next quadrant. */
125     }
126   }
127   return(0);
128 }
129 
130 /*
131 ** This routine does an RGB to YCbCr conversion.  After complettion, the
132 ** destination buffer will be filled with YCbCrYCbCrYCbCrYCbCrYCbCr,
133 ** assuming of course that it was originally RGBRGBRGBRGBRGB.
134 ** The routine also handles RGBa data, and in that situation, you'll
135 ** get YCbCraYCbCraYCbCra...
136 **
137 */
138 int
RGBtoYCrCb(const unsigned char * src,unsigned char * dst,int tilerow,int bpp)139 RGBtoYCrCb(const unsigned char *src, unsigned char *dst, int tilerow, int bpp)
140 {
141   int x;
142   int tilesize = tilerow * tilerow * bpp;
143   unsigned char inpR,inpG,inpB;
144   long yo, cr, cb;
145   long A1, A2, A3, A4;
146   float F1, F2;
147 
148   /*
149   ** the rotation routine is out of section 2.4.4.2
150   ** of Pennebaker/Mitchell book.
151   ** r,g,b values of 0-255 are mapped to 0-1 range, and then
152   ** all values are left shifted by 26 bits.
153   */
154   #if 0
155   /* Pennebaker book's numbers: */
156   A1 = 78952;
157   A2 = 157903;
158   A3 = 26317;
159   A4 = 33554432;
160   F1 = (float)1.6;
161   #endif
162 
163   #if 1
164   /* IJG's numbers: */
165   A1 = 78381;
166   A2 = 153879;
167   A3 = 29884;
168   A4 = 33554432;
169   F1 = (float)1.402;
170   F2 = (float)1.772;
171   #endif
172 
173   if (bpp==3) {
174     for(x = 0; x < tilesize; x+=bpp)
175     {
176       yo = A1*(long)(src[x]) + A2*(long)(src[x+1]) + A3*(long)(src[x+2]);
177 
178       /* old (Pennebaker book's) way:
179       cb = (long)((((src[x+2])<<18) - yo) >> 1) + A4;
180       cr = (long)((((src[x])<<18) - yo) / F1) + A4;
181       */
182       cb = (long)((((src[x+2])<<18) - yo) / F2) + A4;
183       cr = (long)((((src[x])<<18) - yo) / F1) + A4;
184 
185       dst[x] = (unsigned char)(yo >> 18);
186       dst[x+1] = (unsigned char)(cb >> 18);
187       dst[x+2] = (unsigned char)(cr >> 18);
188     }
189   } else { /* bpp = 4 */
190     for(x = 0; x < tilesize; x+=bpp)
191     {
192       inpR= (unsigned char) (255-src[x]);
193       inpG= (unsigned char) (255-src[x+1]);
194       inpB= (unsigned char) (255-src[x+2]);
195       yo = A1*(long)(inpR) + A2*(long)(inpG) + A3*(long)(inpB);
196 
197       /* old (Pennebaker book's) way:
198       cb = (long)((((inpB)<<18) - yo) >> 1) + A4;
199       cr = (long)((((inpR)<<18) - yo) / F1) + A4;
200       */
201       cb = (long)((((inpB)<<18) - yo) / F2) + A4;
202       cr = (long)((((inpR)<<18) - yo) / F1) + A4;
203       dst[x] = (unsigned char)(yo >> 18);
204       dst[x+1] = (unsigned char)(cb >> 18);
205       dst[x+2] = (unsigned char)(cr >> 18);
206       dst[x+3] = src[x+3];
207     }
208   }
209   return(0);
210 
211 } /* RGBtoYCrCb() */
212 
213 
214 /*
215 ** This routine does an RGB to YCbCr conversion, then strips color information.  After
216 ** completion, the destination buffer will be filled with YYYYCbCrYYYYCbCrYYYYCbCr,
217 ** assuming of course that it was originally RGBRGBRGBRGBRGB.  Note that the routine does
218 ** support conversion in place (i.e. src and dst can be the same buffer).
219 */
220 int
RGBtoYCrCb_SubSample411(const unsigned char * src,unsigned char * dst,int tilerow,int bpp)221 RGBtoYCrCb_SubSample411(const unsigned char *src, unsigned char *dst, int tilerow, int bpp)
222 {
223   int x, y, z, blocks, lineOffset;
224   unsigned char *dstPtr = dst;
225   const unsigned char *p[4], *q[4];
226   unsigned char inpR,inpG,inpB;
227   long yo[4], cr, cb;
228   long A1, A2, A3, A4;
229   float F1, F2;
230 
231   blocks = tilerow / 2;
232   lineOffset = tilerow * bpp;
233 
234   #if 0
235   /* Pennebaker book's numbers */
236   A1 = 78952;
237   A2 = 157903;
238   A3 = 26317;
239   A4 = 33554432;
240   F1 = 1.6;
241   F2 = 2.0; /* this can be a right shift */
242   #endif
243 
244   #if 1
245   /* IJG's numbers: */
246   A1 = 78381;
247   A2 = 153879;
248   A3 = 29884;
249   A4 = 33554432;
250   F1 = (float)1.402;
251   F2 = (float)1.772;
252   #endif
253 
254   if (bpp == 3)
255   { /* 3 channel */
256     for(x = 0; x < blocks; x++)
257     {
258       for(y = 0; y < blocks; y++)
259       {
260         p[0] = src;
261         p[1] = p[0] + bpp;
262         p[2] = p[0] + lineOffset;
263         p[3] = p[2] + bpp;
264         cb = 0;
265         cr = 0;
266         for(z = 0; z < 4; z++)
267         {
268           yo[z] = A1*(long)*(p[z]) + A2*(long)*(p[z]+1) + A3*(long)*(p[z]+2);
269 
270           /* old (pink's book) way:
271           cb += ((((*(p[z]+2)<<18) - yo[z]) >> 1) + A4) >> 2;
272           cr += ((long)(((*(p[z])<<18) - yo[z]) / F1) + A4) >> 2;
273           */
274           cb += ((long)((((*(p[z]+2)<<18) - yo[z]) / F2) + A4) >> 2);
275           cr += ((long)((((*(p[z])<<18) - yo[z]) / F1) + A4) >> 2);
276 
277           *dstPtr++ = (unsigned char)(yo[z] >> 18);
278         }
279 
280         /* now it's time to write out a "u" and a "v" */
281         *dstPtr++ = (unsigned char)(cb >> 18);
282         *dstPtr++ = (unsigned char)(cr >> 18);
283 
284         src += bpp*2; /* skip over one triplet and point to the next quadrant */
285       } /* for y */
286 
287       src += lineOffset;
288     } /* for x */
289 
290   }
291   else if (bpp == 4)
292   { /* 4 channel */
293     for(x = 0; x < blocks; x++)
294     {
295       for(y = 0; y < blocks; y++)
296       {
297         p[0] = src;
298         p[1] = p[0] + bpp;
299         p[2] = p[0] + lineOffset;
300         p[3] = p[2] + bpp;
301 
302         q[0]=p[0]+3; /* used for alpha channel */
303         q[1]=p[1]+3;
304         q[2]=p[2]+3;
305         q[3]=p[3]+3;
306         cb = 0;
307         cr = 0;
308         for(z = 0; z < 4; z++)
309         {
310           inpR = (unsigned char) (255-*p[z]);
311           inpG = (unsigned char) (255-*(p[z]+1));
312           inpB = (unsigned char) (255-*(p[z]+2));
313           yo[z] = A1*(long)inpR + A2*(long)inpG + A3*(long)inpB;
314 
315           /* old (Pennebaker book's) way:
316           cb += ((((inpB<<18) - yo[z]) >> 1) + A4) >> 2;
317           cr += ((long)(((inpR<<18) - yo[z]) / F1) + A4) >> 2;
318           */
319           cb += ((long)((((inpB<<18) - yo[z]) / F2) + A4) >> 2);
320           cr += ((long)((((inpR<<18) - yo[z]) / F1) + A4) >> 2);
321 
322           *dstPtr++ = (unsigned char)(yo[z] >> 18);
323         }
324 
325         /* now it's time to write out a "u" and a "v" */
326         *dstPtr++ = (unsigned char)(cb >> 18);
327         *dstPtr++ = (unsigned char)(cr >> 18);
328 
329         /* write out the Alpha channel */
330         *dstPtr++ = *q[0];
331         *dstPtr++ = *q[1];
332         *dstPtr++ = *q[2];
333         *dstPtr++ = *q[3];
334 
335         src += bpp*2; /* skip over one triplet and point to the next quadrant */
336       }
337       src += lineOffset;
338     }
339   }
340   return(0);
341 
342 } /* RGBtoYCrCb_SubSample411() */
343 
344 
345 /*
346 ** This routine does an RGB to YCbCr conversion, then strips color information.
347 ** This is not done particularly efficiently, but it's important that it get done
348 ** correctly and on time.  So, rather than write an integrated routine like the 411
349 ** subsampling, the individual pieces are called, simplifying coding and testing.
350 */
351 int
RGBtoYCrCb_SubSample422(const unsigned char * src,unsigned char * dst,int tileSize,int bpp)352 RGBtoYCrCb_SubSample422(const unsigned char *src, unsigned char *dst, int tileSize, int bpp)
353 {
354   unsigned char *dst0;
355   int error;
356 
357   dst0 = (unsigned char *)FPX_malloc((size_t)(tileSize * tileSize * bpp));
358   if(dst0 == NULL)            /* CHG_JPEG_MEM_FIX - added check */
359     return EJPEG_ERROR_MEM;
360 
361   RGBtoYCrCb(src, dst0, tileSize, bpp);
362   error = SubSample422(dst0, dst, tileSize, bpp);
363 
364   FPX_free(dst0);
365 
366   return error;
367 
368 } /* RGBtoYCrCb_SubSample422() */
369