Home Page Toolkit Overview Using GML User Input Services Finger Tracker Calibrator Frame Grabber Service protocol Obtaining GML Installing GML Licence Developer Documentation Tcl/Tk API The GML Canvas Image processing Tcl Scripts Library List of Classes List of Files C/C++ API List of Classes List of Files |
gml_LRGColor.h00001 // gml_LRGColor.h -- 00002 // 00003 // Defines the gml_TColor_LRG class template. 00004 // 00005 // Copyright (c) 2004 CLIPS-IMAG 00006 // 00007 // See the file "gml_LicenseTerms.txt" for information on usage and redistribution 00008 // of this file, and for a DISCLAIMER OF ALL WARRANTIES. 00009 // 00010 // Created on March 14, 2003 (JL). 00011 // Updated to GML on January 12, 2004 (JL). 00012 00013 #ifndef __GML_LRGCOLOR__ 00014 #define __GML_LRGCOLOR__ 00015 00016 #include <assert.h> 00017 #include <stdio.h> 00018 #include <float.h> 00019 00020 #include "gml/base/gml_Types.h" 00021 #include "gml/base/gml_BytePack.h" 00022 #include "gml/base/gml_Attributes.h" 00023 #include "gml/math/gml_Tables.h" 00024 #include "gml/math/gml_Math.h" 00025 00026 /// 00027 /// gml_TColor_LRG -- 00028 /// A union type used to represent LRG-color pixels. 00029 /// LRG stands for Luminance, Normalized Red, Normalized Green colorspace. 00030 /// 00031 /// The channels' storage type is specified as template parameter <Channel>. 00032 /// The second template parameter <KSize> specifies an integer type large 00033 /// enough to hold all computations. 00034 /// 00035 /// @bug 00036 /// The following should be true, but for now we assume that: 00037 /// <pre>sChannelMax == 1 << sChannelBits</pre> in Convert(). 00038 /// This of course leads to some rounding errors, max 4/255. 00039 /// 00040 /// Note that the full range of data that a channel can represent isn't used: 00041 /// for instance L values range from 0 to <tt>2 ** (sChannelBits() - 1)</tt>. 00042 /// This is done to accelerate some computation, e.g. replacing divisions by 00043 /// sChannelMax() by bit-shifting operations. 00044 /// 00045 /// @note 00046 /// Depending on the machine, this code is 10 to 20 times faster than 00047 /// OpenCV's version, which uses euclidian divisions extensively. We use a 00048 /// small (3k) lookup table and lots of bit-shifting. 00049 /// 00050 template <typename Channel, typename KSize> 00051 class gml_TColor_LRG 00052 { 00053 public: 00054 00055 /// 00056 /// Constructor -- 00057 /// Convert a 24-bit RGB triplet into LRG and fill in the object. 00058 /// 00059 gml_TColor_LRG (const UInt8 r, const UInt8 g, const UInt8 b) { 00060 #ifndef __GML_AVOID_EUCLIDIAN_DIVISION 00061 UInt32 const sum = (UInt32) r + g + b; 00062 UInt32 const denom = Max (1UL, (UInt32) r + g + b); 00063 L = (sChannelMax() * sum + 765/2) / 765; 00064 R = (sChannelMax() * r + denom/2) / denom; 00065 G = (sChannelMax() * g + denom/2) / denom; 00066 #else 00067 UInt32 const sum = (UInt32) r + g + b; 00068 // avoid doing a division by 3*255 by noting that 3*255 ~= 2^24 / 21931 ~= 2^17 / 171 00069 // the (1<<23) allows for rounding division (rather than flooring divison) 00070 L = ShiftRight (KSize(21931) * sChannelMax() * sum + (1<<23), 24); 00071 // avoid divisions by <sum> by using a tabulated reciprocal 00072 UInt32 const mantissa = ReciprocalMantissa_15_10bit (sum); 00073 KSize const tR = ShiftRight (sChannelMax() * r * mantissa + (1<<14), 15); 00074 KSize const tG = ShiftRight (sChannelMax() * g * mantissa + (1<<14), 15); 00075 R = Min (sChannelMax(), tR); 00076 G = Min (sChannelMax(), tG); 00077 00078 // assert (R+G < sChannelMax()); // this should pass, but fails miserably 00079 #endif /* __GML_AVOID_EUCLIDIAN_DIVISION */ 00080 } 00081 00082 /// 00083 /// Constructor -- 00084 /// Fill the structure from data in memory. 00085 /// 00086 gml_TColor_LRG (const void * const ptr) { 00087 *this = *((gml_TColor_LRG<Channel,KSize>*)ptr); 00088 } 00089 00090 /// 00091 /// Constructor -- 00092 /// Leave structure `as is'. 00093 /// 00094 gml_TColor_LRG () {} 00095 00096 00097 /// 00098 /// Print -- 00099 /// Dump a representation of the pixel to stdout: channels in hex and 00100 /// in 8-bit per channel hex format. 00101 /// @warning no newline appended ! 00102 /// 00103 void Print () { 00104 printf ("% 8X % 8X % 8X (%02X %02X %02X)", 00105 L, R, G, 00106 L >> (sChannelBits() - 8), 00107 R >> (sChannelBits() - 8), 00108 G >> (sChannelBits() - 8) 00109 ); 00110 } 00111 00112 00113 /// 00114 /// Store -- 00115 /// Place the structure's data in memory 00116 /// 00117 void Store (void * const ptr) { 00118 *((gml_TColor_LRG<Channel,KSize>*)ptr) = *this; 00119 } 00120 00121 00122 /// 00123 /// Convert -- 00124 /// Convert the LRG data in this object to a 24 bit RGB triplet. 00125 /// 00126 void Convert (UInt8 &r, UInt8 &g, UInt8 &b) { 00127 /// @todo replace the ?: selector with Select() 00128 #ifndef __GML_AVOID_EUCLIDIAN_DIVISION 00129 KSize const denom = sChannelMax() * sChannelMax(); 00130 Channel const B = ((KSize) R+G >= sChannelMax()) ? 0 : (sChannelMax() - (R+G)); 00131 00132 UInt32 const tr = (KSize(765) * L * R + denom/2) / denom; 00133 UInt32 const tg = (KSize(765) * L * G + denom/2) / denom; 00134 UInt32 const tb = (KSize(765) * L * B + denom/2) / denom; 00135 r = Min (tr, 255UL); 00136 g = Min (tg, 255UL); 00137 b = Min (tb, 255UL); 00138 #else 00139 KSize const delta = (1 << (2*sChannelBits()-9)); // for rounding division 00140 Channel const B = ((KSize) R+G >= sChannelMax()) ? 0 : (sChannelMax() - (R+G)); 00141 00142 UInt32 const tr = (KSize(3) * L * R + delta) >> (2*sChannelBits()-8); 00143 UInt32 const tg = (KSize(3) * L * G + delta) >> (2*sChannelBits()-8); 00144 UInt32 const tb = (KSize(3) * L * B + delta) >> (2*sChannelBits()-8); 00145 r = Min (tr, 255UL); 00146 g = Min (tg, 255UL); 00147 b = Min (tb, 255UL); 00148 #endif 00149 } 00150 00151 00152 /// 00153 /// Distance -- 00154 /// Compute the 16-bit distance to another LRG pixel. 00155 /// Depending on __GML_LRG_USE_EUCLIDIAN_DISTANCE, 00156 /// the euclidian distance in the (Cr,Cg) plane is used, or 00157 /// the city block distance. 00158 /// 00159 UInt16 Distance (const gml_TColor_LRG<Channel,KSize> other) { 00160 return Min (65535UL, 00161 #ifdef __GML_LRGCOLOR_USE_EUCLIDIAN_DISTANCE 00162 64UL * Norm ( 00163 ShiftRight (R, sChannelBits() - 12), 00164 ShiftRight (G, sChannelBits() - 12), 00165 ShiftRight (other.R, sChannelBits() - 12), 00166 ShiftRight (other.G, sChannelBits() - 12) 00167 ) 00168 #else 00169 (UInt32) 00170 ShiftLeft ( 00171 KSize (Abs (KSize (other.R) - KSize (R)) + 00172 Abs (KSize (other.G) - KSize (G))), 00173 18 - sChannelBits() 00174 ) 00175 #endif 00176 ); 00177 } 00178 00179 inline static 00180 UInt8 sChannelBits() { return 8 * sizeof (Channel); } ///< bits per channel 00181 inline static 00182 KSize sChannelMax() { return (1ULL << sChannelBits()) - 1; } ///< max channel value 00183 00184 struct { ///< structure for transparent channel access 00185 #if BYTE_ORDER == BIG_ENDIAN 00186 Channel L; ///< luminance channel 00187 Channel R; ///< red chrominance channel 00188 Channel G; ///< green chrominance channel 00189 #else 00190 Channel G; ///< green chrominance channel 00191 Channel R; ///< red chrominance channel 00192 Channel L; ///< luminance channel 00193 #endif 00194 } GML_PACKED; 00195 00196 }; 00197 00198 00199 // 00200 // gml_TColor_LRG_888, gml_TColor_LRG_SSS, gml_TColor_LRG_LLL -- 00201 // 24-bit, 48-bit, and 96-bit structures for LRG-color pixels. 00202 // 00203 typedef gml_TColor_LRG<UInt8, SInt32> gml_TColor_LRG_888; 00204 typedef gml_TColor_LRG<UInt16, SInt64> gml_TColor_LRG_SSS; 00205 typedef gml_TColor_LRG<UInt32, SInt64> gml_TColor_LRG_LLL; 00206 00207 /// 00208 /// gml_TColor_LRG_FFF -- 00209 /// Floating-point variant of gml_TColor_LRG. 00210 /// 00211 class gml_TColor_LRG_FFF : public gml_TColor_LRG<Float32, Float32> 00212 { 00213 public: 00214 00215 /// 00216 /// Constructor -- 00217 /// Convert a 24-bit RGB triplet into LRG and fill in the object. 00218 /// 00219 gml_TColor_LRG_FFF (const UInt8 r, const UInt8 g, const UInt8 b) { 00220 Float32 const sum = (Float32) r + g + b; 00221 L = Divide (sum, 765.0F); 00222 R = Divide (r, sum + FLT_EPSILON); 00223 G = Divide (g, sum + FLT_EPSILON); 00224 assert (0.0F <= L && L <= 1.0F); 00225 assert (0.0F <= R && R <= 1.0F); 00226 assert (0.0F <= G && G <= 1.0F); 00227 } 00228 00229 /// 00230 /// Constructor -- 00231 /// Fill the structure from data in memory. 00232 /// 00233 gml_TColor_LRG_FFF (const void * const ptr) { 00234 *this = *((gml_TColor_LRG_FFF*)ptr); 00235 00236 assert (0.0F <= L && L <= 1.0F); 00237 assert (0.0F <= R && R <= 1.0F); 00238 assert (0.0F <= G && G <= 1.0F); 00239 } 00240 00241 /// 00242 /// Print -- 00243 /// Dump a representation of the pixel to stdout: channels in hex and 00244 /// in 8-bit per channel hex format. 00245 /// @warning no newline appended ! 00246 /// 00247 void Print () { 00248 printf ("%f %f %f (%02X %02X %02X)", 00249 L, R, G, 00250 (unsigned int) LFloor (255.0F * L), 00251 (unsigned int) LFloor (255.0F * R), 00252 (unsigned int) LFloor (255.0F * G) 00253 ); 00254 } 00255 00256 00257 /// 00258 /// Convert -- 00259 /// Convert the LRG data in this object to a 24 bit RGB triplet. 00260 /// 00261 void Convert (UInt8 &r, UInt8 &g, UInt8 &b) { 00262 r = LRound (765.0F * L * R); 00263 g = LRound (765.0F * L * G); 00264 b = LRound (765.0F * L * (1.0F - R - G)); 00265 } 00266 00267 00268 /// 00269 /// Distance -- 00270 /// Compute the 16-bit distance to another LRG pixel. 00271 /// Depending on __GML_LRG_USE_EUCLIDIAN_DISTANCE, 00272 /// the euclidian distance in the (Cr,Cg) plane is used, or 00273 /// the city block distance. 00274 /// 00275 UInt16 Distance (const gml_TColor_LRG_FFF other) { 00276 return Min (65535UL, 00277 #ifdef __GML_LRGCOLOR_USE_EUCLIDIAN_DISTANCE 00278 LFloor (64.0F * 255.0F * Norm (R, G, other.R, other.G)) 00279 #else 00280 LFloor (1024.0F * 255.0F * (Abs (other.R - R) + Abs (other.G - G))) 00281 #endif 00282 ); 00283 } 00284 00285 static 00286 Float32 sChannelMax() { return 1.0F; }; ///< max channel value 00287 }; 00288 00289 #endif /* __GML_LRGCOLOR__ */ 00290
Generated on Tue Jun 12 14:03:27 2007 for gml by
Doxygen 1.5.2.
|
Contact: julien (dot) letessier (at) gmail (dot) com.
Copyright (c) 2000-2007 CLIPS-IMAG Laboratory, Grenoble, France. All rights reserved. W3CXHTML 1.0 W3CCSS 2.0 |