ReactOS 0.4.16-dev-338-g34e76ad
tif_color.c
Go to the documentation of this file.
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 <precomp.h>
38#include <math.h>
39
40/*
41 * Convert color value from the CIE L*a*b* 1976 space to CIE XYZ.
42 */
43void
45 float *X, float *Y, float *Z)
46{
47 float L = (float)l * 100.0F / 255.0F;
48 float cby, tmp;
49
50 if( L < 8.856F ) {
51 *Y = (L * cielab->Y0) / 903.292F;
52 cby = 7.787F * (*Y / cielab->Y0) + 16.0F / 116.0F;
53 } else {
54 cby = (L + 16.0F) / 116.0F;
55 *Y = cielab->Y0 * cby * cby * cby;
56 }
57
58 tmp = (float)a / 500.0F + cby;
59 if( tmp < 0.2069F )
60 *X = cielab->X0 * (tmp - 0.13793F) / 7.787F;
61 else
62 *X = cielab->X0 * tmp * tmp * tmp;
63
64 tmp = cby - (float)b / 200.0F;
65 if( tmp < 0.2069F )
66 *Z = cielab->Z0 * (tmp - 0.13793F) / 7.787F;
67 else
68 *Z = cielab->Z0 * tmp * tmp * tmp;
69}
70
71#define RINT(R) ((uint32)((R)>0?((R)+0.5):((R)-0.5)))
72/*
73 * Convert color value from the XYZ space to RGB.
74 */
75void
76TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z,
77 uint32 *r, uint32 *g, uint32 *b)
78{
79 int i;
80 float Yr, Yg, Yb;
81 float *matrix = &cielab->display.d_mat[0][0];
82
83 /* Multiply through the matrix to get luminosity values. */
84 Yr = matrix[0] * X + matrix[1] * Y + matrix[2] * Z;
85 Yg = matrix[3] * X + matrix[4] * Y + matrix[5] * Z;
86 Yb = matrix[6] * X + matrix[7] * Y + matrix[8] * Z;
87
88 /* Clip input */
89 Yr = TIFFmax(Yr, cielab->display.d_Y0R);
90 Yg = TIFFmax(Yg, cielab->display.d_Y0G);
91 Yb = TIFFmax(Yb, cielab->display.d_Y0B);
92
93 /* Avoid overflow in case of wrong input values */
94 Yr = TIFFmin(Yr, cielab->display.d_YCR);
95 Yg = TIFFmin(Yg, cielab->display.d_YCG);
96 Yb = TIFFmin(Yb, cielab->display.d_YCB);
97
98 /* Turn luminosity to colour value. */
99 i = (int)((Yr - cielab->display.d_Y0R) / cielab->rstep);
100 i = TIFFmin(cielab->range, i);
101 *r = RINT(cielab->Yr2r[i]);
102
103 i = (int)((Yg - cielab->display.d_Y0G) / cielab->gstep);
104 i = TIFFmin(cielab->range, i);
105 *g = RINT(cielab->Yg2g[i]);
106
107 i = (int)((Yb - cielab->display.d_Y0B) / cielab->bstep);
108 i = TIFFmin(cielab->range, i);
109 *b = RINT(cielab->Yb2b[i]);
110
111 /* Clip output. */
112 *r = TIFFmin(*r, cielab->display.d_Vrwr);
113 *g = TIFFmin(*g, cielab->display.d_Vrwg);
114 *b = TIFFmin(*b, cielab->display.d_Vrwb);
115}
116#undef RINT
117
118/*
119 * Allocate conversion state structures and make look_up tables for
120 * the Yr,Yb,Yg <=> r,g,b conversions.
121 */
122int
124 const TIFFDisplay *display, float *refWhite)
125{
126 int i;
127 double dfGamma;
128
130
131 _TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay));
132
133 /* Red */
134 dfGamma = 1.0 / cielab->display.d_gammaR ;
135 cielab->rstep =
136 (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
137 for(i = 0; i <= cielab->range; i++) {
138 cielab->Yr2r[i] = cielab->display.d_Vrwr
139 * ((float)pow((double)i / cielab->range, dfGamma));
140 }
141
142 /* Green */
143 dfGamma = 1.0 / cielab->display.d_gammaG ;
144 cielab->gstep =
145 (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
146 for(i = 0; i <= cielab->range; i++) {
147 cielab->Yg2g[i] = cielab->display.d_Vrwg
148 * ((float)pow((double)i / cielab->range, dfGamma));
149 }
150
151 /* Blue */
152 dfGamma = 1.0 / cielab->display.d_gammaB ;
153 cielab->bstep =
154 (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range;
155 for(i = 0; i <= cielab->range; i++) {
156 cielab->Yb2b[i] = cielab->display.d_Vrwb
157 * ((float)pow((double)i / cielab->range, dfGamma));
158 }
159
160 /* Init reference white point */
161 cielab->X0 = refWhite[0];
162 cielab->Y0 = refWhite[1];
163 cielab->Z0 = refWhite[2];
164
165 return 0;
166}
167
168/*
169 * Convert color value from the YCbCr space to RGB.
170 * The colorspace conversion algorithm comes from the IJG v5a code;
171 * see below for more information on how it works.
172 */
173#define SHIFT 16
174#define FIX(x) ((int32)((x) * (1L<<SHIFT) + 0.5))
175#define ONE_HALF ((int32)(1<<(SHIFT-1)))
176#define Code2V(c, RB, RW, CR) ((((c)-(int32)(RB))*(float)(CR))/(float)(((RW)-(RB)!=0) ? ((RW)-(RB)) : 1))
177#define CLAMP(f,min,max) ((f)<(min)?(min):(f)>(max)?(max):(f))
178#define HICLAMP(f,max) ((f)>(max)?(max):(f))
179
180void
182 uint32 *r, uint32 *g, uint32 *b)
183{
184 int32 i;
185
186 /* XXX: Only 8-bit YCbCr input supported for now */
187 Y = HICLAMP(Y, 255);
188 Cb = CLAMP(Cb, 0, 255);
189 Cr = CLAMP(Cr, 0, 255);
190
191 i = ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr];
192 *r = CLAMP(i, 0, 255);
193 i = ycbcr->Y_tab[Y]
194 + (int)((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT);
195 *g = CLAMP(i, 0, 255);
196 i = ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb];
197 *b = CLAMP(i, 0, 255);
198}
199
200/* Clamp function for sanitization purposes. Normally clamping should not */
201/* occur for well behaved chroma and refBlackWhite coefficients */
202static float CLAMPw(float v, float vmin, float vmax)
203{
204 if( v < vmin )
205 {
206 /* printf("%f clamped to %f\n", v, vmin); */
207 return vmin;
208 }
209 if( v > vmax )
210 {
211 /* printf("%f clamped to %f\n", v, vmax); */
212 return vmax;
213 }
214 return v;
215}
216
217/*
218 * Initialize the YCbCr->RGB conversion tables. The conversion
219 * is done according to the 6.0 spec:
220 *
221 * R = Y + Cr*(2 - 2*LumaRed)
222 * B = Y + Cb*(2 - 2*LumaBlue)
223 * G = Y
224 * - LumaBlue*Cb*(2-2*LumaBlue)/LumaGreen
225 * - LumaRed*Cr*(2-2*LumaRed)/LumaGreen
226 *
227 * To avoid floating point arithmetic the fractional constants that
228 * come out of the equations are represented as fixed point values
229 * in the range 0...2^16. We also eliminate multiplications by
230 * pre-calculating possible values indexed by Cb and Cr (this code
231 * assumes conversion is being done for 8-bit samples).
232 */
233int
234TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, float *luma, float *refBlackWhite)
235{
236 TIFFRGBValue* clamptab;
237 int i;
238
239#define LumaRed luma[0]
240#define LumaGreen luma[1]
241#define LumaBlue luma[2]
242
243 clamptab = (TIFFRGBValue*)(
244 (uint8*) ycbcr+TIFFroundup_32(sizeof (TIFFYCbCrToRGB), sizeof (long)));
245 _TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */
246 ycbcr->clamptab = (clamptab += 256);
247 for (i = 0; i < 256; i++)
248 clamptab[i] = (TIFFRGBValue) i;
249 _TIFFmemset(clamptab+256, 255, 2*256); /* v > 255 => 255 */
250 ycbcr->Cr_r_tab = (int*) (clamptab + 3*256);
251 ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256;
252 ycbcr->Cr_g_tab = (int32*) (ycbcr->Cb_b_tab + 256);
253 ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256;
254 ycbcr->Y_tab = ycbcr->Cb_g_tab + 256;
255
256 { float f1 = 2-2*LumaRed; int32 D1 = FIX(CLAMP(f1,0.0F,2.0F));
257 float f2 = LumaRed*f1/LumaGreen; int32 D2 = -FIX(CLAMP(f2,0.0F,2.0F));
258 float f3 = 2-2*LumaBlue; int32 D3 = FIX(CLAMP(f3,0.0F,2.0F));
259 float f4 = LumaBlue*f3/LumaGreen; int32 D4 = -FIX(CLAMP(f4,0.0F,2.0F));
260 int x;
261
262#undef LumaBlue
263#undef LumaGreen
264#undef LumaRed
265
266 /*
267 * i is the actual input pixel value in the range 0..255
268 * Cb and Cr values are in the range -128..127 (actually
269 * they are in a range defined by the ReferenceBlackWhite
270 * tag) so there is some range shifting to do here when
271 * constructing tables indexed by the raw pixel data.
272 */
273 for (i = 0, x = -128; i < 256; i++, x++) {
274 int32 Cr = (int32)CLAMPw(Code2V(x, refBlackWhite[4] - 128.0F,
275 refBlackWhite[5] - 128.0F, 127),
276 -128.0F * 32, 128.0F * 32);
277 int32 Cb = (int32)CLAMPw(Code2V(x, refBlackWhite[2] - 128.0F,
278 refBlackWhite[3] - 128.0F, 127),
279 -128.0F * 32, 128.0F * 32);
280
281 ycbcr->Cr_r_tab[i] = (int32)((D1*Cr + ONE_HALF)>>SHIFT);
282 ycbcr->Cb_b_tab[i] = (int32)((D3*Cb + ONE_HALF)>>SHIFT);
283 ycbcr->Cr_g_tab[i] = D2*Cr;
284 ycbcr->Cb_g_tab[i] = D4*Cb + ONE_HALF;
285 ycbcr->Y_tab[i] =
286 (int32)CLAMPw(Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255),
287 -128.0F * 32, 128.0F * 32);
288 }
289 }
290
291 return 0;
292}
293#undef HICLAMP
294#undef CLAMP
295#undef Code2V
296#undef SHIFT
297#undef ONE_HALF
298#undef FIX
299
300/* vim: set ts=8 sts=8 sw=8 noet: */
301/*
302 * Local Variables:
303 * mode: c
304 * c-basic-offset: 8
305 * fill-column: 78
306 * End:
307 */
unsigned int uint32
Definition: types.h:32
unsigned char uint8
Definition: types.h:28
r l[0]
Definition: byte_order.h:168
#define Z(I)
#define Y(I)
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
long int32
Definition: platform.h:12
double pow(double x, double y)
Definition: freeldr.c:110
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
const GLdouble * v
Definition: gl.h:2040
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum GLint * range
Definition: glext.h:7539
GLuint GLenum matrix
Definition: glext.h:9407
GLboolean GLboolean g
Definition: glext.h:6204
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define Yb
Definition: i386-dis.c:436
static float(__cdecl *square_half_float)(float x
#define L(x)
Definition: ntvdm.h:50
#define f2(x, y, z)
Definition: sha1.c:31
#define f1(x, y, z)
Definition: sha1.c:30
#define f4(x, y, z)
Definition: sha1.c:33
#define f3(x, y, z)
Definition: sha1.c:32
float Yb2b[CIELABTORGB_TABLE_RANGE+1]
Definition: tiffio.h:171
float bstep
Definition: tiffio.h:166
TIFFDisplay display
Definition: tiffio.h:168
float rstep
Definition: tiffio.h:166
float gstep
Definition: tiffio.h:166
float Yr2r[CIELABTORGB_TABLE_RANGE+1]
Definition: tiffio.h:169
float Yg2g[CIELABTORGB_TABLE_RANGE+1]
Definition: tiffio.h:170
float d_mat[3][3]
Definition: tiffio.h:139
uint32 d_Vrwr
Definition: tiffio.h:143
float d_gammaG
Definition: tiffio.h:150
float d_YCB
Definition: tiffio.h:142
uint32 d_Vrwb
Definition: tiffio.h:145
float d_Y0R
Definition: tiffio.h:146
float d_gammaR
Definition: tiffio.h:149
float d_YCG
Definition: tiffio.h:141
float d_YCR
Definition: tiffio.h:140
float d_Y0G
Definition: tiffio.h:147
float d_Y0B
Definition: tiffio.h:148
float d_gammaB
Definition: tiffio.h:151
uint32 d_Vrwg
Definition: tiffio.h:144
int32 * Cr_g_tab
Definition: tiffio.h:158
int * Cr_r_tab
Definition: tiffio.h:156
int32 * Cb_g_tab
Definition: tiffio.h:159
TIFFRGBValue * clamptab
Definition: tiffio.h:155
int * Cb_b_tab
Definition: tiffio.h:157
int32 * Y_tab
Definition: tiffio.h:160
void TIFFYCbCrtoRGB(TIFFYCbCrToRGB *ycbcr, uint32 Y, int32 Cb, int32 Cr, uint32 *r, uint32 *g, uint32 *b)
Definition: tif_color.c:181
static float CLAMPw(float v, float vmin, float vmax)
Definition: tif_color.c:202
#define LumaRed
#define LumaBlue
#define FIX(x)
Definition: tif_color.c:174
#define RINT(R)
Definition: tif_color.c:71
#define Code2V(c, RB, RW, CR)
Definition: tif_color.c:176
#define CLAMP(f, min, max)
Definition: tif_color.c:177
int TIFFYCbCrToRGBInit(TIFFYCbCrToRGB *ycbcr, float *luma, float *refBlackWhite)
Definition: tif_color.c:234
#define ONE_HALF
Definition: tif_color.c:175
#define SHIFT
Definition: tif_color.c:173
#define LumaGreen
void TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z, uint32 *r, uint32 *g, uint32 *b)
Definition: tif_color.c:76
#define HICLAMP(f, max)
Definition: tif_color.c:178
int TIFFCIELabToRGBInit(TIFFCIELabToRGB *cielab, const TIFFDisplay *display, float *refWhite)
Definition: tif_color.c:123
void TIFFCIELabToXYZ(TIFFCIELabToRGB *cielab, uint32 l, int32 a, int32 b, float *X, float *Y, float *Z)
Definition: tif_color.c:44
void _TIFFmemset(void *p, int v, tmsize_t c)
Definition: tif_unix.c:338
void _TIFFmemcpy(void *d, const void *s, tmsize_t c)
Definition: tif_unix.c:344
unsigned char TIFFRGBValue
Definition: tiffio.h:136
#define CIELABTORGB_TABLE_RANGE
Definition: tiffio.h:165
#define TIFFroundup_32(x, y)
Definition: tiffiop.h:272
#define TIFFmax(A, B)
Definition: tiffiop.h:280
#define TIFFmin(A, B)
Definition: tiffiop.h:281
int * display
Definition: x11stubs.c:12