Line data Source code
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 : */
43 1 : void TIFFCIELabToXYZ(TIFFCIELabToRGB *cielab, uint32_t l, int32_t a, int32_t b,
44 : float *X, float *Y, float *Z)
45 : {
46 1 : TIFFCIELab16ToXYZ(cielab, l * 257, a * 256, b * 256, X, Y, Z);
47 1 : }
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 : */
55 1 : void TIFFCIELab16ToXYZ(TIFFCIELabToRGB *cielab, uint32_t l, int32_t a,
56 : int32_t b, float *X, float *Y, float *Z)
57 : {
58 1 : float L = (float)l * 100.0F / 65535.0F;
59 : float cby, tmp;
60 :
61 1 : if (L < 8.856F)
62 : {
63 0 : *Y = (L * cielab->Y0) / 903.292F;
64 0 : cby = 7.787F * (*Y / cielab->Y0) + 16.0F / 116.0F;
65 : }
66 : else
67 : {
68 1 : cby = (L + 16.0F) / 116.0F;
69 1 : *Y = cielab->Y0 * cby * cby * cby;
70 : }
71 :
72 1 : tmp = (float)a / 256.0F / 500.0F + cby;
73 1 : if (tmp < 0.2069F)
74 0 : *X = cielab->X0 * (tmp - 0.13793F) / 7.787F;
75 : else
76 1 : *X = cielab->X0 * tmp * tmp * tmp;
77 :
78 1 : tmp = cby - (float)b / 256.0F / 200.0F;
79 1 : if (tmp < 0.2069F)
80 0 : *Z = cielab->Z0 * (tmp - 0.13793F) / 7.787F;
81 : else
82 1 : *Z = cielab->Z0 * tmp * tmp * tmp;
83 1 : }
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 : */
89 1 : void TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z,
90 : uint32_t *r, uint32_t *g, uint32_t *b)
91 : {
92 : size_t i;
93 : float Yr, Yg, Yb;
94 1 : float *matrix = &cielab->display.d_mat[0][0];
95 :
96 : /* Multiply through the matrix to get luminosity values. */
97 1 : Yr = matrix[0] * X + matrix[1] * Y + matrix[2] * Z;
98 1 : Yg = matrix[3] * X + matrix[4] * Y + matrix[5] * Z;
99 1 : Yb = matrix[6] * X + matrix[7] * Y + matrix[8] * Z;
100 :
101 : /* Clip input */
102 1 : Yr = TIFFmax(Yr, cielab->display.d_Y0R);
103 1 : Yg = TIFFmax(Yg, cielab->display.d_Y0G);
104 1 : Yb = TIFFmax(Yb, cielab->display.d_Y0B);
105 :
106 : /* Avoid overflow in case of wrong input values */
107 1 : Yr = TIFFmin(Yr, cielab->display.d_YCR);
108 1 : Yg = TIFFmin(Yg, cielab->display.d_YCG);
109 1 : Yb = TIFFmin(Yb, cielab->display.d_YCB);
110 :
111 : /* Turn luminosity to colour value. */
112 1 : i = (size_t)((Yr - cielab->display.d_Y0R) / cielab->rstep);
113 1 : i = TIFFmin((size_t)cielab->range, i);
114 1 : *r = RINT(cielab->Yr2r[i]);
115 :
116 1 : i = (size_t)((Yg - cielab->display.d_Y0G) / cielab->gstep);
117 1 : i = TIFFmin((size_t)cielab->range, i);
118 1 : *g = RINT(cielab->Yg2g[i]);
119 :
120 1 : i = (size_t)((Yb - cielab->display.d_Y0B) / cielab->bstep);
121 1 : i = TIFFmin((size_t)cielab->range, i);
122 1 : *b = RINT(cielab->Yb2b[i]);
123 :
124 : /* Clip output. */
125 1 : *r = TIFFmin(*r, cielab->display.d_Vrwr);
126 1 : *g = TIFFmin(*g, cielab->display.d_Vrwg);
127 1 : *b = TIFFmin(*b, cielab->display.d_Vrwb);
128 1 : }
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 : */
135 1 : int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display,
136 : float *refWhite)
137 : {
138 : size_t i;
139 : double dfGamma;
140 :
141 1 : cielab->range = CIELABTORGB_TABLE_RANGE;
142 :
143 1 : _TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay));
144 :
145 : /* Red */
146 1 : dfGamma = 1.0 / cielab->display.d_gammaR;
147 1 : cielab->rstep =
148 1 : (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
149 1502 : for (i = 0; i <= (size_t)cielab->range; i++)
150 : {
151 1501 : cielab->Yr2r[i] = cielab->display.d_Vrwr *
152 1501 : ((float)pow((double)i / cielab->range, dfGamma));
153 : }
154 :
155 : /* Green */
156 1 : dfGamma = 1.0 / cielab->display.d_gammaG;
157 1 : cielab->gstep =
158 1 : (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
159 1502 : for (i = 0; i <= (size_t)cielab->range; i++)
160 : {
161 1501 : cielab->Yg2g[i] = cielab->display.d_Vrwg *
162 1501 : ((float)pow((double)i / cielab->range, dfGamma));
163 : }
164 :
165 : /* Blue */
166 1 : dfGamma = 1.0 / cielab->display.d_gammaB;
167 1 : cielab->bstep =
168 1 : (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
169 1502 : for (i = 0; i <= (size_t)cielab->range; i++)
170 : {
171 1501 : cielab->Yb2b[i] = cielab->display.d_Vrwb *
172 1501 : ((float)pow((double)i / cielab->range, dfGamma));
173 : }
174 :
175 : /* Init reference white point */
176 1 : cielab->X0 = refWhite[0];
177 1 : cielab->Y0 = refWhite[1];
178 1 : cielab->Z0 = refWhite[2];
179 :
180 1 : 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 :
199 65097 : 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 65097 : Y = HICLAMP(Y, 255);
206 65097 : Cb = CLAMP(Cb, 0, 255);
207 65097 : Cr = CLAMP(Cr, 0, 255);
208 :
209 65097 : i = ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr];
210 65097 : *r = CLAMP(i, 0, 255);
211 65097 : i = ycbcr->Y_tab[Y] +
212 65097 : (int)((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT);
213 65097 : *g = CLAMP(i, 0, 255);
214 65097 : i = ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb];
215 65097 : *b = CLAMP(i, 0, 255);
216 65097 : }
217 :
218 : /* Clamp function for sanitization purposes. Normally clamping should not */
219 : /* occur for well behaved chroma and refBlackWhite coefficients */
220 13056 : static float CLAMPw(float v, float vmin, float vmax)
221 : {
222 13056 : if (v < vmin)
223 : {
224 : /* printf("%f clamped to %f\n", v, vmin); */
225 0 : return vmin;
226 : }
227 13056 : if (v > vmax)
228 : {
229 : /* printf("%f clamped to %f\n", v, vmax); */
230 0 : return vmax;
231 : }
232 13056 : 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 : */
251 17 : 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 17 : clamptab =
261 : (TIFFRGBValue *)((uint8_t *)ycbcr +
262 : TIFFroundup_32(sizeof(TIFFYCbCrToRGB), sizeof(long)));
263 17 : _TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */
264 17 : ycbcr->clamptab = (clamptab += 256);
265 4369 : for (i = 0; i < 256; i++)
266 4352 : clamptab[i] = (TIFFRGBValue)i;
267 17 : _TIFFmemset(clamptab + 256, 255, 2 * 256); /* v > 255 => 255 */
268 17 : ycbcr->Cr_r_tab = (int *)(clamptab + 3 * 256);
269 17 : ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256;
270 17 : ycbcr->Cr_g_tab = (int32_t *)(ycbcr->Cb_b_tab + 256);
271 17 : ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256;
272 17 : ycbcr->Y_tab = ycbcr->Cb_g_tab + 256;
273 :
274 : {
275 17 : float f1 = 2 - 2 * LumaRed;
276 17 : int32_t D1 = FIX(CLAMP(f1, 0.0F, 2.0F));
277 17 : float f2 = LumaRed * f1 / LumaGreen;
278 17 : int32_t D2 = -FIX(CLAMP(f2, 0.0F, 2.0F));
279 17 : float f3 = 2 - 2 * LumaBlue;
280 17 : int32_t D3 = FIX(CLAMP(f3, 0.0F, 2.0F));
281 17 : float f4 = LumaBlue * f3 / LumaGreen;
282 17 : 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 4369 : for (i = 0, x = -128; i < 256; i++, x++)
297 : {
298 4352 : 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 4352 : 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 4352 : ycbcr->Cr_r_tab[i] = (int32_t)((D1 * Cr + ONE_HALF) >> SHIFT);
306 4352 : ycbcr->Cb_b_tab[i] = (int32_t)((D3 * Cb + ONE_HALF) >> SHIFT);
307 4352 : ycbcr->Cr_g_tab[i] = D2 * Cr;
308 4352 : ycbcr->Cb_g_tab[i] = D4 * Cb + ONE_HALF;
309 4352 : ycbcr->Y_tab[i] = (int32_t)CLAMPw(
310 4352 : Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255),
311 : -128.0F * 32, 128.0F * 32);
312 : }
313 : }
314 :
315 17 : return 0;
316 : }
317 : #undef HICLAMP
318 : #undef CLAMP
319 : #undef Code2V
320 : #undef SHIFT
321 : #undef ONE_HALF
322 : #undef FIX
|