ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

tif_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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.