]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/tiff/tif_color.c
[ 1509599 ] 'Split pickers page in widgets sample' with more icons and rebaking.
[wxWidgets.git] / src / tiff / tif_color.c
... / ...
CommitLineData
1/* $Header$ */
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
39#include "tiffiop.h"
40#include <math.h>
41
42/*
43 * Convert color value from the CIE L*a*b* 1976 space to CIE XYZ.
44 */
45void
46TIFFCIELabToXYZ(TIFFCIELabToRGB *cielab, uint32 l, int32 a, int32 b,
47 float *X, float *Y, float *Z)
48{
49 float L = (float)l * 100.0F / 255.0F;
50 float cby, tmp;
51
52 if( L < 8.856F ) {
53 *Y = (L * cielab->Y0) / 903.292F;
54 cby = 7.787F * (*Y / cielab->Y0) + 16.0F / 116.0F;
55 } else {
56 cby = (L + 16.0F) / 116.0F;
57 *Y = cielab->Y0 * cby * cby * cby;
58 }
59
60 tmp = (float)a / 500.0F + cby;
61 if( tmp < 0.2069F )
62 *X = cielab->X0 * (tmp - 0.13793F) / 7.787F;
63 else
64 *X = cielab->X0 * tmp * tmp * tmp;
65
66 tmp = cby - (float)b / 200.0F;
67 if( tmp < 0.2069F )
68 *Z = cielab->Z0 * (tmp - 0.13793F) / 7.787F;
69 else
70 *Z = cielab->Z0 * tmp * tmp * tmp;
71}
72
73#define RINT(R) ((uint32)((R)>0?((R)+0.5):((R)-0.5)))
74/*
75 * Convert color value from the XYZ space to RGB.
76 */
77void
78TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z,
79 uint32 *r, uint32 *g, uint32 *b)
80{
81 int i;
82 float Yr, Yg, Yb;
83 float *matrix = &cielab->display.d_mat[0][0];
84
85 /* Multiply through the matrix to get luminosity values. */
86 Yr = matrix[0] * X + matrix[1] * Y + matrix[2] * Z;
87 Yg = matrix[3] * X + matrix[4] * Y + matrix[5] * Z;
88 Yb = matrix[6] * X + matrix[7] * Y + matrix[8] * Z;
89
90 /* Clip input */
91 Yr = TIFFmax( Yr, cielab->display.d_Y0R );
92 Yg = TIFFmax( Yg, cielab->display.d_Y0G );
93 Yb = TIFFmax( Yb, cielab->display.d_Y0B );
94
95 /* Turn luminosity to colour value. */
96 i = TIFFmin(cielab->range,
97 (int)((Yr - cielab->display.d_Y0R) / cielab->rstep));
98 *r = RINT(cielab->Yr2r[i]);
99
100 i = TIFFmin(cielab->range,
101 (int)((Yg - cielab->display.d_Y0G) / cielab->gstep));
102 *g = RINT(cielab->Yg2g[i]);
103
104 i = TIFFmin(cielab->range,
105 (int)((Yb - cielab->display.d_Y0B) / cielab->bstep));
106 *b = RINT(cielab->Yb2b[i]);
107
108 /* Clip output. */
109 *r = TIFFmin( *r, cielab->display.d_Vrwr );
110 *g = TIFFmin( *g, cielab->display.d_Vrwg );
111 *b = TIFFmin( *b, cielab->display.d_Vrwb );
112}
113#undef RINT
114
115/*
116 * Allocate conversion state structures and make look_up tables for
117 * the Yr,Yb,Yg <=> r,g,b conversions.
118 */
119int
120TIFFCIELabToRGBInit(TIFFCIELabToRGB* cielab,
121 TIFFDisplay *display, float *refWhite)
122{
123 int i;
124 float gamma;
125
126 cielab->range = CIELABTORGB_TABLE_RANGE;
127
128 _TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay));
129
130 /* Red */
131 gamma = 1.0F / cielab->display.d_gammaR ;
132 cielab->rstep =
133 (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
134 for(i = 0; i <= cielab->range; i++) {
135 cielab->Yr2r[i] = cielab->display.d_Vrwr
136 * ((float)pow((double)i / cielab->range, gamma));
137 }
138
139 /* Green */
140 gamma = 1.0F / cielab->display.d_gammaG ;
141 cielab->gstep =
142 (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
143 for(i = 0; i <= cielab->range; i++) {
144 cielab->Yg2g[i] = cielab->display.d_Vrwg
145 * ((float)pow((double)i / cielab->range, gamma));
146 }
147
148 /* Blue */
149 gamma = 1.0F / cielab->display.d_gammaB ;
150 cielab->bstep =
151 (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
152 for(i = 0; i <= cielab->range; i++) {
153 cielab->Yb2b[i] = cielab->display.d_Vrwb
154 * ((float)pow((double)i / cielab->range, gamma));
155 }
156
157 /* Init reference white point */
158 cielab->X0 = refWhite[0];
159 cielab->Y0 = refWhite[1];
160 cielab->Z0 = refWhite[2];
161
162 return 0;
163}
164
165/*
166 * Convert color value from the YCbCr space to CIE XYZ.
167 * The colorspace conversion algorithm comes from the IJG v5a code;
168 * see below for more information on how it works.
169 */
170#define SHIFT 16
171#define FIX(x) ((int32)((x) * (1L<<SHIFT) + 0.5))
172#define ONE_HALF ((int32)(1<<(SHIFT-1)))
173#define Code2V(c, RB, RW, CR) ((((c)-(int32)(RB))*(float)(CR))/(float)((RW)-(RB)))
174#define CLAMP(f,min,max) ((f)<(min)?(min):(f)>(max)?(max):(f))
175
176void
177TIFFYCbCrtoRGB(TIFFYCbCrToRGB *ycbcr, uint32 Y, int32 Cb, int32 Cr,
178 uint32 *r, uint32 *g, uint32 *b)
179{
180 /* XXX: Only 8-bit YCbCr input supported for now */
181 Y = CLAMP(Y, 0, 255), Cb = CLAMP(Cb, 0, 255), Cr = CLAMP(Cr, 0, 255);
182
183 *r = ycbcr->clamptab[ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr]];
184 *g = ycbcr->clamptab[ycbcr->Y_tab[Y]
185 + (int)((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT)];
186 *b = ycbcr->clamptab[ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb]];
187}
188
189/*
190 * Initialize the YCbCr->RGB conversion tables. The conversion
191 * is done according to the 6.0 spec:
192 *
193 * R = Y + Cr*(2 - 2*LumaRed)
194 * B = Y + Cb*(2 - 2*LumaBlue)
195 * G = Y
196 * - LumaBlue*Cb*(2-2*LumaBlue)/LumaGreen
197 * - LumaRed*Cr*(2-2*LumaRed)/LumaGreen
198 *
199 * To avoid floating point arithmetic the fractional constants that
200 * come out of the equations are represented as fixed point values
201 * in the range 0...2^16. We also eliminate multiplications by
202 * pre-calculating possible values indexed by Cb and Cr (this code
203 * assumes conversion is being done for 8-bit samples).
204 */
205int
206TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, float *luma, float *refBlackWhite)
207{
208 TIFFRGBValue* clamptab;
209 int i;
210
211#define LumaRed luma[0]
212#define LumaGreen luma[1]
213#define LumaBlue luma[2]
214
215 clamptab = (TIFFRGBValue*)(
216 (tidata_t) ycbcr+TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long)));
217 _TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */
218 ycbcr->clamptab = (clamptab += 256);
219 for (i = 0; i < 256; i++)
220 clamptab[i] = (TIFFRGBValue) i;
221 _TIFFmemset(clamptab+256, 255, 2*256); /* v > 255 => 255 */
222 ycbcr->Cr_r_tab = (int*) (clamptab + 3*256);
223 ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256;
224 ycbcr->Cr_g_tab = (int32*) (ycbcr->Cb_b_tab + 256);
225 ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256;
226 ycbcr->Y_tab = ycbcr->Cb_g_tab + 256;
227
228 { float f1 = 2-2*LumaRed; int32 D1 = FIX(f1);
229 float f2 = LumaRed*f1/LumaGreen; int32 D2 = -FIX(f2);
230 float f3 = 2-2*LumaBlue; int32 D3 = FIX(f3);
231 float f4 = LumaBlue*f3/LumaGreen; int32 D4 = -FIX(f4);
232 int x;
233
234#undef LumaBlue
235#undef LumaGreen
236#undef LumaRed
237
238 /*
239 * i is the actual input pixel value in the range 0..255
240 * Cb and Cr values are in the range -128..127 (actually
241 * they are in a range defined by the ReferenceBlackWhite
242 * tag) so there is some range shifting to do here when
243 * constructing tables indexed by the raw pixel data.
244 */
245 for (i = 0, x = -128; i < 256; i++, x++) {
246 int32 Cr = (int32)Code2V(x, refBlackWhite[4] - 128.0F,
247 refBlackWhite[5] - 128.0F, 127);
248 int32 Cb = (int32)Code2V(x, refBlackWhite[2] - 128.0F,
249 refBlackWhite[3] - 128.0F, 127);
250
251 ycbcr->Cr_r_tab[i] = (int32)((D1*Cr + ONE_HALF)>>SHIFT);
252 ycbcr->Cb_b_tab[i] = (int32)((D3*Cb + ONE_HALF)>>SHIFT);
253 ycbcr->Cr_g_tab[i] = D2*Cr;
254 ycbcr->Cb_g_tab[i] = D4*Cb + ONE_HALF;
255 ycbcr->Y_tab[i] =
256 (int32)Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255);
257 }
258 }
259
260 return 0;
261}
262#undef CLAMP
263#undef Code2V
264#undef SHIFT
265#undef ONE_HALF
266#undef FIX
267
268