]> git.saurik.com Git - wxWidgets.git/blame - src/tiff/libtiff/tif_color.c
Added wxRichTextTableBlock class to help with table UI operations
[wxWidgets.git] / src / tiff / libtiff / tif_color.c
CommitLineData
8414a40c
VZ
1
2/*
3 * Copyright (c) 1988-1997 Sam Leffler
4 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
5 *
6 * Permission to use, copy, modify, distribute, and sell this software and
7 * its documentation for any purpose is hereby granted without fee, provided
8 * that (i) the above copyright notices and this permission notice appear in
9 * all copies of the software and related documentation, and (ii) the names of
10 * Sam Leffler and Silicon Graphics may not be used in any advertising or
11 * publicity relating to the software without the specific, prior written
12 * permission of Sam Leffler and Silicon Graphics.
13 *
14 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
15 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
16 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
17 *
18 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
19 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
20 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
21 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
22 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
23 * OF THIS SOFTWARE.
24 */
25
26/*
27 * CIE L*a*b* to CIE XYZ and CIE XYZ to RGB conversion routines are taken
28 * from the VIPS library (http://www.vips.ecs.soton.ac.uk) with
29 * the permission of John Cupitt, the VIPS author.
30 */
31
32/*
33 * TIFF Library.
34 *
35 * Color space conversion routines.
36 */
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 */
44void
45TIFFCIELabToXYZ(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 */
76void
77TIFFXYZToRGB(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 */
123int
124TIFFCIELabToRGBInit(TIFFCIELabToRGB* cielab,
80ed523f 125 const TIFFDisplay *display, float *refWhite)
8414a40c
VZ
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
181void
182TIFFYCbCrtoRGB(TIFFYCbCrToRGB *ycbcr, uint32 Y, int32 Cb, int32 Cr,
183 uint32 *r, uint32 *g, uint32 *b)
184{
80ed523f
VZ
185 int32 i;
186
8414a40c
VZ
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
80ed523f
VZ
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);
8414a40c
VZ
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 */
215int
216TIFFYCbCrToRGBInit(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*)(
80ed523f 226 (uint8*) ycbcr+TIFFroundup_32(sizeof (TIFFYCbCrToRGB), sizeof (long)));
8414a40c
VZ
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], 255);
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: */
80ed523f
VZ
280/*
281 * Local Variables:
282 * mode: c
283 * c-basic-offset: 8
284 * fill-column: 78
285 * End:
286 */