Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members  

ColourSystem.cc

Go to the documentation of this file.
00001 /*
00002     File:       ColourSystem.cc
00003 
00004     Function:   Provides a class to help with colour space conversions to
00005                 and from three-primary display devices.
00006 
00007     Author:     Andrew Willmott
00008 
00009 */
00010 
00011 #include "ColourSystem.h"
00012 
00074 ColourSystem::ColourSystem(
00075         Chroma      primary1,
00076         Chroma      primary2,
00077         Chroma      primary3,
00078         Chroma      whitePoint,
00079         ClrReal     whiteLuminance
00080     )
00081 {
00082     Colour  whiteXYZ, csWhite;
00083     
00084     prim0 = primary1;
00085     prim1 = primary2; 
00086     prim2 = primary3;
00087     white = whitePoint;
00088     whiteLum = whiteLuminance;
00089     
00090     toXYZ[0] = Colour(prim0[0], prim1[0], prim2[0]);
00091     toXYZ[1] = Colour(prim0[1], prim1[1], prim2[1]);
00092     toXYZ[2] = cWhite - toXYZ[0] - toXYZ[1];
00093 
00094     fromXYZ = inv(toXYZ);
00095 
00096     // now we must scale so that the white point
00097     // maps to the cs colour [1, 1, 1].
00098 
00099     whiteXYZ = Colour(white[0], white[1], 1.0 - white[0] - white[1]);
00100     whiteXYZ *= whiteLum / white[1];
00101 
00102     csWhite = fromXYZ * whiteXYZ;
00103 
00104     fromXYZ[0] /= csWhite[0];
00105     fromXYZ[1] /= csWhite[1];
00106     fromXYZ[2] /= csWhite[2];
00107     col(toXYZ, 0) *= csWhite[0];
00108     col(toXYZ, 1) *= csWhite[1];
00109     col(toXYZ, 2) *= csWhite[2];    
00110 }
00111 
00112 Colour ColourSystem::XYZToGamut(const Colour &cieXYZ)
00120 {
00121     Colour      csClr = fromXYZ * cieXYZ;
00122     Colour      t;
00123     ClrReal     tMin;
00124 
00125     // Is the contribution of one of the primaries negative?
00126 
00127     if (MinCmpt(csClr) < 0.0)
00128     {
00129         // find how far we must move along the line through the white
00130         // point until we hit each axial plane
00131         t = cWhite / (cWhite - csClr);
00132 
00133         // find smallest +ve intercept
00134         tMin = 1.0;
00135         if (t[0] >= 0.0)                tMin = t[0];
00136         if (t[1] >= 0.0 && t[1] < tMin) tMin = t[1];
00137         if (t[2] >= 0.0 && t[2] < tMin) tMin = t[2];
00138 
00139         csClr = cWhite + (csClr - cWhite) * tMin;
00140         ClipColourZero(csClr);
00141         Assert(MinCmpt(csClr) >= 0.0, "bad correction");
00142     }
00143 
00144     return(csClr);
00145 }
00146 
00147 Colour ColourSystem::XYZToGamutClip(const Colour &cieXYZ)
00148 {
00149     Colour c = XYZToGamut(cieXYZ);
00150 
00151     if (c[0] > 1.0) c[0] = 1.0;
00152     if (c[1] > 1.0) c[1] = 1.0;
00153     if (c[2] > 1.0) c[2] = 1.0;
00154     
00155     return(c);  
00156 }
00157 
00158 Colour ColourSystem::ChromaToGamut(const Chroma &cieChroma)
00159 {
00160     Colour c;
00161 
00162     c = XYZToGamut(Colour(cieChroma, 1.0 - cieChroma[0] - cieChroma[1]));
00163     c /= cieChroma[1];
00164     
00165     return(c);
00166 }
00167 
00168 Bool ColourSystem::XYZIsOutOfGamut(const Colour &cieXYZ)
00169 {
00170     return(MinCmpt(fromXYZ * cieXYZ) < 0.0);
00171 }
00172 
00173 Bool ColourSystem::ChromaIsOutOfGamut(const Chroma &cieChroma)
00174 {
00175     return(MinCmpt(fromXYZ * Colour(cieChroma, 1.0 - cieChroma[0] - cieChroma[1]))
00176          < 0.0);
00177 }
00178 
00179 // --- CIE standard illuminants ---------------------------------------
00180 
00181 const Chroma csIllumA(0.448, 0.407);            // Incandescent light
00182 const Chroma csIllumB(0.348, 0.352);            // Solar light
00183 const Chroma csIllumC(0.3101, 0.3162);          // For NTSC television
00184 const Chroma csIllumD55(0.332, 0.348);          // Photography
00185 const Chroma csIllumD65(0.3127, 0.3291);        // Overcast Daylight
00186 const Chroma csIllumD75(0.299, 0.315);
00187 const Chroma csIllumE(0.3333333, 0.3333333);    // Uniform illuminant
00188                                             
00189 // luminances of standard illuminants, in candela/watt
00190 
00191 const ClrReal csMaxLum(683.0);          // defined maximum at 555 nm 
00192 const ClrReal csWhiteLum(179.0);        // uniform white light
00193 const ClrReal csD65Lum(203.0);
00194 const ClrReal csALum(160.0);
00195 const ClrReal csBLum(208.0);
00196 
00197 
00198 // NOTE: most of this data is simply reformatted from the delphi
00199 // source code provided by EFG's fabulous CIE page above.
00200 
00201 // The following define the x and y coordinates of the phosphors and
00202 // reference white points of various broadcast systems.
00203 
00204 // [Martindale91] notes that NTSC primaries aren't remotely similar
00205 // to those used in modern displays.
00206 //
00207 // CCIR Report 476-1
00208 // "Colorimetric Standards in Colour Television"
00209 // See http://www.igd.fhg.de/icib/tv/ccir/rep_476-1/gen.html
00210 //
00211 // CCIR Report 624-4
00212 // "Characteristics of Television Systems"
00213 // See http://www.igd.fhg.de/icib/tv/ccir/rep_624/read.html
00214 
00215 ColourSystem csNTSC(
00216     Chroma(0.67, 0.33),
00217     Chroma(0.21, 0.71),
00218     Chroma(0.14, 0.08),
00219     Chroma(0.310, 0.316)
00220 );
00221 
00222 // CCIR Report 476-1
00223 // "Colorimetric Standards in Colour Television"
00224 // See http://www.igd.fhg.de/icib/tv/ccir/rep_476-1/gen.html
00225 //
00226 // CCIR Report 624-4
00227 // "Characteristics of Television Systems"
00228 // See http://www.igd.fhg.de/icib/tv/ccir/rep_624/read.html
00229 
00230 ColourSystem csPAL_SECAM(
00231     Chroma(0.64, 0.33),
00232     Chroma(0.29, 0.60),
00233     Chroma(0.15, 0.06),
00234     Chroma(0.313, 0.329)
00235 );
00236 
00237 // CCIR Recommendation 709
00238 // "Basic Parameter Values for the HDTV Standard for the Studio and for
00239 // International Programme Exchange"
00240 // See http://www.igd.fhg.de/icib/tv/ccir/rec_709/pictures/page-2.tiff
00241 
00242 // EBU Technical Document 3271 (EBU = European Broadcasting Union)
00243 // "Interlaced version of the 1250/50 HDTV production standard"
00244 // http://www.igd.fhg.de/icib/tv/org/ebu/td_3271/pictures/page5.tiff
00245 
00246 // This is used for all HDTV stuff.
00247 
00248 ColourSystem csEBU(
00249     Chroma(0.640, 0.330),
00250     Chroma(0.300, 0.600),
00251     Chroma(0.150, 0.060),
00252     Chroma(0.3127, 0.3290)
00253 );
00254 
00255 // SMPTE 240M (SMPTE = The Society of Motion Picture and Television Engineers)
00256 // "Signal Parameters -- 1125-line High-Definition Production System"
00257 // http://www.igd.fhg.de/icib/tv/org/smpte/st_240M-1992/read.html
00258 
00259 ColourSystem csSMPTE(
00260         Chroma(0.630, 0.340),
00261         Chroma(0.310, 0.595),
00262         Chroma(0.155, 0.070),
00263         csIllumD65
00264 );
00265 
00266 
00267 ColourSystem csShortPersistencePhosphors(  // [Foley96, p. 583]
00268     Chroma(0.61, 0.35),
00269     Chroma(0.29, 0.59),
00270     Chroma(0.15, 0.063),
00271     csIllumC
00272 );
00273 
00274 ColourSystem csLongPersistencePhosphors(   // [Foley96, p. 583]
00275     Chroma(0.62, 0.33),
00276     Chroma(0.21, 0.685),
00277     Chroma(0.15, 0.063),
00278     csIllumC
00279 );
00280 
00281 ColourSystem csDellPhosphors(   // 12 Jan 99 E-mail from Dell
00282     Chroma(0.625, 0.340),       // All Dell monitors except
00283     Chroma(0.275, 0.605),       // Nokia 91862
00284     Chroma(0.150, 0.065),
00285     csIllumD65
00286 );
00287 
00288 #ifdef UNFINISHED
00289 Sony Trinitron
00290 Red   0.621 0.340 
00291                        Green 0.281 0.606 
00292                        Blue  0.152 0.067 
00293                        
00294 Hitachi CM2198 (all +- 0.02):
00295 
00296                        Red   0.624 0.339 
00297                        Green 0.285 0.604 
00298                        Blue  0.150 0.065
00299                        
00300 #endif
00301 
00302 ColourSystem &csDisplay = csEBU;
00303 
00304 #ifdef UNFINISHED
00305 ClrReal CIELumToLightness(ClrReal lum)
00306 {       
00307   float relative_luminance;
00308 
00309   if (reference_luminance == 0.)
00310     return 0.;
00311 
00312   relative_luminance = luminance / reference_luminance;
00313   if (relative_luminance > 0.008856)
00314     return (1.16 * pow(relative_luminance, 0.33) - 0.16);
00315   else
00316     return 9.033 * relative_luminance;
00317 }
00318 #endif

Generated at Sat Aug 5 00:16:58 2000 for Graphics Class Library by doxygen 1.1.0 written by Dimitri van Heesch, © 1997-2000