Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentif_color.c
Go to the documentation of this file.
00001 /* $Id: tif_color.c,v 1.12.2.1 2010-06-08 18:50:41 bfriesen Exp $ */ 00002 00003 /* 00004 * Copyright (c) 1988-1997 Sam Leffler 00005 * Copyright (c) 1991-1997 Silicon Graphics, Inc. 00006 * 00007 * Permission to use, copy, modify, distribute, and sell this software and 00008 * its documentation for any purpose is hereby granted without fee, provided 00009 * that (i) the above copyright notices and this permission notice appear in 00010 * all copies of the software and related documentation, and (ii) the names of 00011 * Sam Leffler and Silicon Graphics may not be used in any advertising or 00012 * publicity relating to the software without the specific, prior written 00013 * permission of Sam Leffler and Silicon Graphics. 00014 * 00015 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 00016 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 00017 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 00018 * 00019 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR 00020 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, 00021 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 00022 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 00023 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 00024 * OF THIS SOFTWARE. 00025 */ 00026 00027 /* 00028 * CIE L*a*b* to CIE XYZ and CIE XYZ to RGB conversion routines are taken 00029 * from the VIPS library (http://www.vips.ecs.soton.ac.uk) with 00030 * the permission of John Cupitt, the VIPS author. 00031 */ 00032 00033 /* 00034 * TIFF Library. 00035 * 00036 * Color space conversion routines. 00037 */ 00038 00039 #include "tiffiop.h" 00040 #include <math.h> 00041 00042 /* 00043 * Convert color value from the CIE L*a*b* 1976 space to CIE XYZ. 00044 */ 00045 void 00046 TIFFCIELabToXYZ(TIFFCIELabToRGB *cielab, uint32 l, int32 a, int32 b, 00047 float *X, float *Y, float *Z) 00048 { 00049 float L = (float)l * 100.0F / 255.0F; 00050 float cby, tmp; 00051 00052 if( L < 8.856F ) { 00053 *Y = (L * cielab->Y0) / 903.292F; 00054 cby = 7.787F * (*Y / cielab->Y0) + 16.0F / 116.0F; 00055 } else { 00056 cby = (L + 16.0F) / 116.0F; 00057 *Y = cielab->Y0 * cby * cby * cby; 00058 } 00059 00060 tmp = (float)a / 500.0F + cby; 00061 if( tmp < 0.2069F ) 00062 *X = cielab->X0 * (tmp - 0.13793F) / 7.787F; 00063 else 00064 *X = cielab->X0 * tmp * tmp * tmp; 00065 00066 tmp = cby - (float)b / 200.0F; 00067 if( tmp < 0.2069F ) 00068 *Z = cielab->Z0 * (tmp - 0.13793F) / 7.787F; 00069 else 00070 *Z = cielab->Z0 * tmp * tmp * tmp; 00071 } 00072 00073 #define RINT(R) ((uint32)((R)>0?((R)+0.5):((R)-0.5))) 00074 /* 00075 * Convert color value from the XYZ space to RGB. 00076 */ 00077 void 00078 TIFFXYZToRGB(TIFFCIELabToRGB *cielab, float X, float Y, float Z, 00079 uint32 *r, uint32 *g, uint32 *b) 00080 { 00081 int i; 00082 float Yr, Yg, Yb; 00083 float *matrix = &cielab->display.d_mat[0][0]; 00084 00085 /* Multiply through the matrix to get luminosity values. */ 00086 Yr = matrix[0] * X + matrix[1] * Y + matrix[2] * Z; 00087 Yg = matrix[3] * X + matrix[4] * Y + matrix[5] * Z; 00088 Yb = matrix[6] * X + matrix[7] * Y + matrix[8] * Z; 00089 00090 /* Clip input */ 00091 Yr = TIFFmax(Yr, cielab->display.d_Y0R); 00092 Yg = TIFFmax(Yg, cielab->display.d_Y0G); 00093 Yb = TIFFmax(Yb, cielab->display.d_Y0B); 00094 00095 /* Avoid overflow in case of wrong input values */ 00096 Yr = TIFFmin(Yr, cielab->display.d_YCR); 00097 Yg = TIFFmin(Yg, cielab->display.d_YCG); 00098 Yb = TIFFmin(Yb, cielab->display.d_YCB); 00099 00100 /* Turn luminosity to colour value. */ 00101 i = (int)((Yr - cielab->display.d_Y0R) / cielab->rstep); 00102 i = TIFFmin(cielab->range, i); 00103 *r = RINT(cielab->Yr2r[i]); 00104 00105 i = (int)((Yg - cielab->display.d_Y0G) / cielab->gstep); 00106 i = TIFFmin(cielab->range, i); 00107 *g = RINT(cielab->Yg2g[i]); 00108 00109 i = (int)((Yb - cielab->display.d_Y0B) / cielab->bstep); 00110 i = TIFFmin(cielab->range, i); 00111 *b = RINT(cielab->Yb2b[i]); 00112 00113 /* Clip output. */ 00114 *r = TIFFmin(*r, cielab->display.d_Vrwr); 00115 *g = TIFFmin(*g, cielab->display.d_Vrwg); 00116 *b = TIFFmin(*b, cielab->display.d_Vrwb); 00117 } 00118 #undef RINT 00119 00120 /* 00121 * Allocate conversion state structures and make look_up tables for 00122 * the Yr,Yb,Yg <=> r,g,b conversions. 00123 */ 00124 int 00125 TIFFCIELabToRGBInit(TIFFCIELabToRGB* cielab, 00126 TIFFDisplay *display, float *refWhite) 00127 { 00128 int i; 00129 double gamma; 00130 00131 cielab->range = CIELABTORGB_TABLE_RANGE; 00132 00133 _TIFFmemcpy(&cielab->display, display, sizeof(TIFFDisplay)); 00134 00135 /* Red */ 00136 gamma = 1.0 / cielab->display.d_gammaR ; 00137 cielab->rstep = 00138 (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; 00139 for(i = 0; i <= cielab->range; i++) { 00140 cielab->Yr2r[i] = cielab->display.d_Vrwr 00141 * ((float)pow((double)i / cielab->range, gamma)); 00142 } 00143 00144 /* Green */ 00145 gamma = 1.0 / cielab->display.d_gammaG ; 00146 cielab->gstep = 00147 (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; 00148 for(i = 0; i <= cielab->range; i++) { 00149 cielab->Yg2g[i] = cielab->display.d_Vrwg 00150 * ((float)pow((double)i / cielab->range, gamma)); 00151 } 00152 00153 /* Blue */ 00154 gamma = 1.0 / cielab->display.d_gammaB ; 00155 cielab->bstep = 00156 (cielab->display.d_YCR - cielab->display.d_Y0R) / cielab->range; 00157 for(i = 0; i <= cielab->range; i++) { 00158 cielab->Yb2b[i] = cielab->display.d_Vrwb 00159 * ((float)pow((double)i / cielab->range, gamma)); 00160 } 00161 00162 /* Init reference white point */ 00163 cielab->X0 = refWhite[0]; 00164 cielab->Y0 = refWhite[1]; 00165 cielab->Z0 = refWhite[2]; 00166 00167 return 0; 00168 } 00169 00170 /* 00171 * Convert color value from the YCbCr space to CIE XYZ. 00172 * The colorspace conversion algorithm comes from the IJG v5a code; 00173 * see below for more information on how it works. 00174 */ 00175 #define SHIFT 16 00176 #define FIX(x) ((int32)((x) * (1L<<SHIFT) + 0.5)) 00177 #define ONE_HALF ((int32)(1<<(SHIFT-1))) 00178 #define Code2V(c, RB, RW, CR) ((((c)-(int32)(RB))*(float)(CR))/(float)(((RW)-(RB)) ? ((RW)-(RB)) : 1)) 00179 #define CLAMP(f,min,max) ((f)<(min)?(min):(f)>(max)?(max):(f)) 00180 #define HICLAMP(f,max) ((f)>(max)?(max):(f)) 00181 00182 void 00183 TIFFYCbCrtoRGB(TIFFYCbCrToRGB *ycbcr, uint32 Y, int32 Cb, int32 Cr, 00184 uint32 *r, uint32 *g, uint32 *b) 00185 { 00186 /* XXX: Only 8-bit YCbCr input supported for now */ 00187 Y = HICLAMP(Y, 255), Cb = CLAMP(Cb, 0, 255), Cr = CLAMP(Cr, 0, 255); 00188 00189 *r = ycbcr->clamptab[ycbcr->Y_tab[Y] + ycbcr->Cr_r_tab[Cr]]; 00190 *g = ycbcr->clamptab[ycbcr->Y_tab[Y] 00191 + (int)((ycbcr->Cb_g_tab[Cb] + ycbcr->Cr_g_tab[Cr]) >> SHIFT)]; 00192 *b = ycbcr->clamptab[ycbcr->Y_tab[Y] + ycbcr->Cb_b_tab[Cb]]; 00193 } 00194 00195 /* 00196 * Initialize the YCbCr->RGB conversion tables. The conversion 00197 * is done according to the 6.0 spec: 00198 * 00199 * R = Y + Cr*(2 - 2*LumaRed) 00200 * B = Y + Cb*(2 - 2*LumaBlue) 00201 * G = Y 00202 * - LumaBlue*Cb*(2-2*LumaBlue)/LumaGreen 00203 * - LumaRed*Cr*(2-2*LumaRed)/LumaGreen 00204 * 00205 * To avoid floating point arithmetic the fractional constants that 00206 * come out of the equations are represented as fixed point values 00207 * in the range 0...2^16. We also eliminate multiplications by 00208 * pre-calculating possible values indexed by Cb and Cr (this code 00209 * assumes conversion is being done for 8-bit samples). 00210 */ 00211 int 00212 TIFFYCbCrToRGBInit(TIFFYCbCrToRGB* ycbcr, float *luma, float *refBlackWhite) 00213 { 00214 TIFFRGBValue* clamptab; 00215 int i; 00216 00217 #define LumaRed luma[0] 00218 #define LumaGreen luma[1] 00219 #define LumaBlue luma[2] 00220 00221 clamptab = (TIFFRGBValue*)( 00222 (tidata_t) ycbcr+TIFFroundup(sizeof (TIFFYCbCrToRGB), sizeof (long))); 00223 _TIFFmemset(clamptab, 0, 256); /* v < 0 => 0 */ 00224 ycbcr->clamptab = (clamptab += 256); 00225 for (i = 0; i < 256; i++) 00226 clamptab[i] = (TIFFRGBValue) i; 00227 _TIFFmemset(clamptab+256, 255, 2*256); /* v > 255 => 255 */ 00228 ycbcr->Cr_r_tab = (int*) (clamptab + 3*256); 00229 ycbcr->Cb_b_tab = ycbcr->Cr_r_tab + 256; 00230 ycbcr->Cr_g_tab = (int32*) (ycbcr->Cb_b_tab + 256); 00231 ycbcr->Cb_g_tab = ycbcr->Cr_g_tab + 256; 00232 ycbcr->Y_tab = ycbcr->Cb_g_tab + 256; 00233 00234 { float f1 = 2-2*LumaRed; int32 D1 = FIX(f1); 00235 float f2 = LumaRed*f1/LumaGreen; int32 D2 = -FIX(f2); 00236 float f3 = 2-2*LumaBlue; int32 D3 = FIX(f3); 00237 float f4 = LumaBlue*f3/LumaGreen; int32 D4 = -FIX(f4); 00238 int x; 00239 00240 #undef LumaBlue 00241 #undef LumaGreen 00242 #undef LumaRed 00243 00244 /* 00245 * i is the actual input pixel value in the range 0..255 00246 * Cb and Cr values are in the range -128..127 (actually 00247 * they are in a range defined by the ReferenceBlackWhite 00248 * tag) so there is some range shifting to do here when 00249 * constructing tables indexed by the raw pixel data. 00250 */ 00251 for (i = 0, x = -128; i < 256; i++, x++) { 00252 int32 Cr = (int32)Code2V(x, refBlackWhite[4] - 128.0F, 00253 refBlackWhite[5] - 128.0F, 127); 00254 int32 Cb = (int32)Code2V(x, refBlackWhite[2] - 128.0F, 00255 refBlackWhite[3] - 128.0F, 127); 00256 00257 ycbcr->Cr_r_tab[i] = (int32)((D1*Cr + ONE_HALF)>>SHIFT); 00258 ycbcr->Cb_b_tab[i] = (int32)((D3*Cb + ONE_HALF)>>SHIFT); 00259 ycbcr->Cr_g_tab[i] = D2*Cr; 00260 ycbcr->Cb_g_tab[i] = D4*Cb + ONE_HALF; 00261 ycbcr->Y_tab[i] = 00262 (int32)Code2V(x + 128, refBlackWhite[0], refBlackWhite[1], 255); 00263 } 00264 } 00265 00266 return 0; 00267 } 00268 #undef HICLAMP 00269 #undef CLAMP 00270 #undef Code2V 00271 #undef SHIFT 00272 #undef ONE_HALF 00273 #undef FIX 00274 00275 /* vim: set ts=8 sts=8 sw=8 noet: */ 00276 /* 00277 * Local Variables: 00278 * mode: c 00279 * c-basic-offset: 8 00280 * fill-column: 78 00281 * End: 00282 */ Generated on Sat May 26 2012 04:18:22 for ReactOS by
1.7.6.1
|