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