• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 1988-1997 Sam Leffler
3  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
4  *
5  * Permission to use, copy, modify, distribute, and sell this software and
6  * its documentation for any purpose is hereby granted without fee, provided
7  * that (i) the above copyright notices and this permission notice appear in
8  * all copies of the software and related documentation, and (ii) the names of
9  * Sam Leffler and Silicon Graphics may not be used in any advertising or
10  * publicity relating to the software without the specific, prior written
11  * permission of Sam Leffler and Silicon Graphics.
12  *
13  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16  *
17  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22  * OF THIS SOFTWARE.
23  */
24 
25 /*
26  * CIE L*a*b* to CIE XYZ and CIE XYZ to RGB conversion routines are taken
27  * from the VIPS library (http://www.vips.ecs.soton.ac.uk) with
28  * the permission of John Cupitt, the VIPS author.
29  */
30 
31 /*
32  * TIFF Library.
33  *
34  * Color space conversion routines.
35  */
36 
37 #include "tiffiop.h"
38 #include <math.h>
39 
40 /*
41  * Convert color value from the CIE L*a*b* 1976 space to CIE XYZ.
42  */
TIFFCIELabToXYZ(TIFFCIELabToRGB * cielab,uint32_t l,int32_t a,int32_t b,float * X,float * Y,float * Z)43 void TIFFCIELabToXYZ(TIFFCIELabToRGB *cielab, uint32_t l, int32_t a, int32_t b,
44                      float *X, float *Y, float *Z)
45 {
46     TIFFCIELab16ToXYZ(cielab, l * 257, a * 256, b * 256, X, Y, Z);
47 }
48 
49 /*
50  * For CIELab encoded in 16 bits, L is an unsigned integer range [0,65535].
51  * The a* and b* components are signed integers range [-32768,32767]. The 16
52  * bit chrominance values are encoded as 256 times the 1976 CIE a* and b*
53  * values
54  */
TIFFCIELab16ToXYZ(TIFFCIELabToRGB * cielab,uint32_t l,int32_t a,int32_t b,float * X,float * Y,float * Z)55 void TIFFCIELab16ToXYZ(TIFFCIELabToRGB *cielab, uint32_t l, int32_t a,
56                        int32_t b, float *X, float *Y, float *Z)
57 {
58     float L = (float)l * 100.0F / 65535.0F;
59     float cby, tmp;
60 
61     if (L < 8.856F)
62     {
63         *Y = (L * cielab->Y0) / 903.292F;
64         cby = 7.787F * (*Y / cielab->Y0) + 16.0F / 116.0F;
65     }
66     else
67     {
68         cby = (L + 16.0F) / 116.0F;
69         *Y = cielab->Y0 * cby * cby * cby;
70     }
71 
72     tmp = (float)a / 256.0F / 500.0F + cby;
73     if (tmp < 0.2069F)
74         *X = cielab->X0 * (tmp - 0.13793F) / 7.787F;
75     else
76         *X = cielab->X0 * tmp * tmp * tmp;
77 
78     tmp = cby - (float)b / 256.0F / 200.0F;
79     if (tmp < 0.2069F)
80         *Z = cielab->Z0 * (tmp - 0.13793F) / 7.787F;
81     else
82         *Z = cielab->Z0 * tmp * tmp * tmp;
83 }
84 
85 #define RINT(R) ((uint32_t)((R) > 0 ? ((R) + 0.5) : ((R)-0.5)))
86 /*
87  * Convert color value from the XYZ space to RGB.
88  */
TIFFXYZToRGB(TIFFCIELabToRGB * cielab,float X,float Y,float Z,uint32_t * r,uint32_t * g,uint32_t * b)89 void TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z,
90                   uint32_t *r, uint32_t *g, uint32_t *b)
91 {
92     int i;
93     float Yr, Yg, Yb;
94     float *matrix = &cielab->display.d_mat[0][0];
95 
96     /* Multiply through the matrix to get luminosity values. */
97     Yr = matrix[0] * X + matrix[1] * Y + matrix[2] * Z;
98     Yg = matrix[3] * X + matrix[4] * Y + matrix[5] * Z;
99     Yb = matrix[6] * X + matrix[7] * Y + matrix[8] * Z;
100 
101     /* Clip input */
102     Yr = TIFFmax(Yr, cielab->display.d_Y0R);
103     Yg = TIFFmax(Yg, cielab->display.d_Y0G);
104     Yb = TIFFmax(Yb, cielab->display.d_Y0B);
105 
106     /* Avoid overflow in case of wrong input values */
107     Yr = TIFFmin(Yr, cielab->display.d_YCR);
108     Yg = TIFFmin(Yg, cielab->display.d_YCG);
109     Yb = TIFFmin(Yb, cielab->display.d_YCB);
110 
111     /* Turn luminosity to colour value. */
112     i = (int)((Yr - cielab->display.d_Y0R) / cielab->rstep);
113     i = TIFFmin(cielab->range, i);
114     *r = RINT(cielab->Yr2r[i]);
115 
116     i = (int)((Yg - cielab->display.d_Y0G) / cielab->gstep);
117     i = TIFFmin(cielab->range, i);
118     *g = RINT(cielab->Yg2g[i]);
119 
120     i = (int)((Yb - cielab->display.d_Y0B) / cielab->bstep);
121     i = TIFFmin(cielab->range, i);
122     *b = RINT(cielab->Yb2b[i]);
123 
124     /* Clip output. */
125     *r = TIFFmin(*r, cielab->display.d_Vrwr);
126     *g = TIFFmin(*g, cielab->display.d_Vrwg);
127     *b = TIFFmin(*b, cielab->display.d_Vrwb);
128 }
129 #undef RINT
130 
131 /*
132  * Allocate conversion state structures and make look_up tables for
133  * the Yr,Yb,Yg <=> r,g,b conversions.
134  */
TIFFCIELabToRGBInit(TIFFCIELabToRGB * cielab,const TIFFDisplay * display,float * refWhite)135 int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display,
136                         float *refWhite)
137 {
138     int i;
139     double dfGamma;
140 
141     cielab->range = CIELABTORGB_TABLE_RANGE;
142 
143     _TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay));
144 
145     /* Red */
146     dfGamma = 1.0 / cielab->display.d_gammaR;
147     cielab->rstep =
148         (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
149     for (i = 0; i <= cielab->range; i++)
150     {
151         cielab->Yr2r[i] = cielab->display.d_Vrwr *
152                           ((float)pow((double)i / cielab->range, dfGamma));
153     }
154 
155     /* Green */
156     dfGamma = 1.0 / cielab->display.d_gammaG;
157     cielab->gstep =
158         (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
159     for (i = 0; i <= cielab->range; i++)
160     {
161         cielab->Yg2g[i] = cielab->display.d_Vrwg *
162                           ((float)pow((double)i / cielab->range, dfGamma));
163     }
164 
165     /* Blue */
166     dfGamma = 1.0 / cielab->display.d_gammaB;
167     cielab->bstep =
168         (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
169     for (i = 0; i <= cielab->range; i++)
170     {
171         cielab->Yb2b[i] = cielab->display.d_Vrwb *
172                           ((float)pow((double)i / cielab->range, dfGamma));
173     }
174 
175     /* Init reference white point */
176     cielab->X0 = refWhite[0];
177     cielab->Y0 = refWhite[1];
178     cielab->Z0 = refWhite[2];
179 
180     return 0;
181 }
182 
183 /*
184  * Convert color value from the YCbCr space to RGB.
185  * The colorspace conversion algorithm comes from the IJG v5a code;
186  * see below for more information on how it works.
187  */
188 #define SHIFT 16
189 #define FIX(x) ((int32_t)((x) * (1L << SHIFT) + 0.5))
190 #define ONE_HALF ((int32_t)(1 << (SHIFT - 1)))
191 #define Code2V(c, RB, RW, CR)                                                  \
192     ((((c) - (int32_t)(RB)) * (float)(CR)) /                                   \
193      (float)(((RW) - (RB) != 0) ? ((RW) - (RB)) : 1))
194 /* !((f)>=(min)) written that way to deal with NaN */
195 #define CLAMP(f, min, max)                                                     \
196     ((!((f) >= (min))) ? (min) : (f) > (max) ? (max) : (f))
197 #define HICLAMP(f, max) ((f) > (max) ? (max) : (f))
198 
TIFFYCbCrtoRGB(TIFFYCbCrToRGB * ycbcr,uint32_t Y,int32_t Cb,int32_t Cr,uint32_t * r,uint32_t * g,uint32_t * b)199 void TIFFYCbCrtoRGB(TIFFYCbCrToRGB *ycbcr, uint32_t Y, int32_t Cb, int32_t Cr,
200                     uint32_t *r, uint32_t *g, uint32_t *b)
201 {
202     int32_t i;
203 
204     /* XXX: Only 8-bit YCbCr input supported for now */
205     Y = HICLAMP(Y, 255);
206     Cb = CLAMP(Cb, 0, 255);
207     Cr = CLAMP(Cr, 0, 255);
208 
209     i = ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr];
210     *r = CLAMP(i, 0, 255);
211     i = ycbcr->Y_tab[Y] +
212         (int)((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT);
213     *g = CLAMP(i, 0, 255);
214     i = ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb];
215     *b = CLAMP(i, 0, 255);
216 }
217 
218 /* Clamp function for sanitization purposes. Normally clamping should not */
219 /* occur for well behaved chroma and refBlackWhite coefficients */
CLAMPw(float v,float vmin,float vmax)220 static float CLAMPw(float v, float vmin, float vmax)
221 {
222     if (v < vmin)
223     {
224         /* printf("%f clamped to %f\n", v, vmin); */
225         return vmin;
226     }
227     if (v > vmax)
228     {
229         /* printf("%f clamped to %f\n", v, vmax); */
230         return vmax;
231     }
232     return v;
233 }
234 
235 /*
236  * Initialize the YCbCr->RGB conversion tables.  The conversion
237  * is done according to the 6.0 spec:
238  *
239  *    R = Y + Cr*(2 - 2*LumaRed)
240  *    B = Y + Cb*(2 - 2*LumaBlue)
241  *    G =   Y
242  *        - LumaBlue*Cb*(2-2*LumaBlue)/LumaGreen
243  *        - LumaRed*Cr*(2-2*LumaRed)/LumaGreen
244  *
245  * To avoid floating point arithmetic the fractional constants that
246  * come out of the equations are represented as fixed point values
247  * in the range 0...2^16.  We also eliminate multiplications by
248  * pre-calculating possible values indexed by Cb and Cr (this code
249  * assumes conversion is being done for 8-bit samples).
250  */
TIFFYCbCrToRGBInit(TIFFYCbCrToRGB * ycbcr,float * luma,float * refBlackWhite)251 int TIFFYCbCrToRGBInit(TIFFYCbCrToRGB *ycbcr, float *luma, float *refBlackWhite)
252 {
253     TIFFRGBValue *clamptab;
254     int i;
255 
256 #define LumaRed luma[0]
257 #define LumaGreen luma[1]
258 #define LumaBlue luma[2]
259 
260     clamptab =
261         (TIFFRGBValue *)((uint8_t *)ycbcr +
262                          TIFFroundup_32(sizeof(TIFFYCbCrToRGB), sizeof(long)));
263     _TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */
264     ycbcr->clamptab = (clamptab += 256);
265     for (i = 0; i < 256; i++)
266         clamptab[i] = (TIFFRGBValue)i;
267     _TIFFmemset(clamptab + 256, 255, 2 * 256); /* v > 255 => 255 */
268     ycbcr->Cr_r_tab = (int *)(clamptab + 3 * 256);
269     ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256;
270     ycbcr->Cr_g_tab = (int32_t *)(ycbcr->Cb_b_tab + 256);
271     ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256;
272     ycbcr->Y_tab = ycbcr->Cb_g_tab + 256;
273 
274     {
275         float f1 = 2 - 2 * LumaRed;
276         int32_t D1 = FIX(CLAMP(f1, 0.0F, 2.0F));
277         float f2 = LumaRed * f1 / LumaGreen;
278         int32_t D2 = -FIX(CLAMP(f2, 0.0F, 2.0F));
279         float f3 = 2 - 2 * LumaBlue;
280         int32_t D3 = FIX(CLAMP(f3, 0.0F, 2.0F));
281         float f4 = LumaBlue * f3 / LumaGreen;
282         int32_t D4 = -FIX(CLAMP(f4, 0.0F, 2.0F));
283         int x;
284 
285 #undef LumaBlue
286 #undef LumaGreen
287 #undef LumaRed
288 
289         /*
290          * i is the actual input pixel value in the range 0..255
291          * Cb and Cr values are in the range -128..127 (actually
292          * they are in a range defined by the ReferenceBlackWhite
293          * tag) so there is some range shifting to do here when
294          * constructing tables indexed by the raw pixel data.
295          */
296         for (i = 0, x = -128; i < 256; i++, x++)
297         {
298             int32_t Cr = (int32_t)CLAMPw(Code2V(x, refBlackWhite[4] - 128.0F,
299                                                 refBlackWhite[5] - 128.0F, 127),
300                                          -128.0F * 32, 128.0F * 32);
301             int32_t Cb = (int32_t)CLAMPw(Code2V(x, refBlackWhite[2] - 128.0F,
302                                                 refBlackWhite[3] - 128.0F, 127),
303                                          -128.0F * 32, 128.0F * 32);
304 
305             ycbcr->Cr_r_tab[i] = (int32_t)((D1 * Cr + ONE_HALF) >> SHIFT);
306             ycbcr->Cb_b_tab[i] = (int32_t)((D3 * Cb + ONE_HALF) >> SHIFT);
307             ycbcr->Cr_g_tab[i] = D2 * Cr;
308             ycbcr->Cb_g_tab[i] = D4 * Cb + ONE_HALF;
309             ycbcr->Y_tab[i] = (int32_t)CLAMPw(
310                 Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255),
311                 -128.0F * 32, 128.0F * 32);
312         }
313     }
314 
315     return 0;
316 }
317 #undef HICLAMP
318 #undef CLAMP
319 #undef Code2V
320 #undef SHIFT
321 #undef ONE_HALF
322 #undef FIX
323