colorspaceConverter.h

Go to the documentation of this file.
00001 
00015 #ifndef _DLRCOMPUTERVISION_COLORSPACECONVERTER_H_
00016 #define _DLRCOMPUTERVISION_COLORSPACECONVERTER_H_
00017 
00018 #include <functional>
00019 #include <dlrComputerVision/imageFormat.h>
00020 #include <dlrComputerVision/image.h>
00021 
00022 namespace dlr {
00023 
00024   namespace computerVision {
00025 
00026     template<ImageFormat FORMAT0, ImageFormat FORMAT1>
00027     class ColorspaceConverter
00028       : public std::unary_function<typename Image<FORMAT0>::PixelType,
00029                                    typename Image<FORMAT1>::PixelType>
00030     {
00031     public:
00032     
00037       ColorspaceConverter()
00038         : std::unary_function<typename Image<FORMAT0>::PixelType,
00039                               typename Image<FORMAT1>::PixelType>()
00040         {}
00041 
00042 
00049       virtual ~ColorspaceConverter()
00050         {}
00051 
00052 
00071       inline
00072       typename Image<FORMAT1>::PixelType
00073       operator()(const typename Image<FORMAT0>::PixelType& inputPixel) {
00074         typename Image<FORMAT1>::PixelType outputPixel;
00075         this->operator()(inputPixel, outputPixel);
00076         return outputPixel;
00077       }
00078     
00079 
00090       inline
00091       void
00092       operator()(const typename Image<FORMAT0>::PixelType& inputPixel,
00093                  typename Image<FORMAT1>::PixelType& outputPixel) {
00094         // Default rule should work for many format combinations.  We'll
00095         // specialize for the rest below.  If you try to convert between
00096         // formats where this static_cast isn't appropriate, and for
00097         // which we haven't written a specialization, then you'll either
00098         // get a compile error or an unexpected conversion result.
00099         outputPixel =
00100           static_cast<typename Image<FORMAT1>::PixelType>(inputPixel);
00101       }
00102     
00103     };
00104 
00105   } // namespace computerVision
00106   
00107 } // namespace dlr
00108 
00109 
00110 /* ============ Definitions of inline & template functions ============ */
00111 
00112 
00113 #include <cmath>
00114 
00115 namespace dlr {
00116 
00117   namespace computerVision {
00118     
00119     template<>
00120     inline
00121     void
00122     ColorspaceConverter<GRAY1, GRAY8>::
00123     operator()(const Image<GRAY1>::PixelType& inputPixel,
00124                Image<GRAY8>::PixelType& outputPixel)
00125     {
00126       if(inputPixel) {
00127         outputPixel = Image<GRAY8>::PixelType(255);
00128       } else {
00129         outputPixel = Image<GRAY8>::PixelType(0);
00130       }
00131     }
00132 
00133 
00134     template<>
00135     inline
00136     void
00137     ColorspaceConverter<GRAY1, RGB8>::
00138     operator()(const Image<GRAY1>::PixelType& inputPixel,
00139                Image<RGB8>::PixelType& outputPixel)
00140     {
00141       if(inputPixel) {
00142         outputPixel.red = ImageFormatTraits<RGB8>::ComponentType(255);
00143         outputPixel.green = ImageFormatTraits<RGB8>::ComponentType(255);
00144         outputPixel.blue = ImageFormatTraits<RGB8>::ComponentType(255);
00145       } else {
00146         outputPixel.red = ImageFormatTraits<RGB8>::ComponentType(0);
00147         outputPixel.green = ImageFormatTraits<RGB8>::ComponentType(0);
00148         outputPixel.blue = ImageFormatTraits<RGB8>::ComponentType(0);
00149       }
00150     }
00151 
00152 
00153     template<>
00154     inline
00155     void
00156     ColorspaceConverter<GRAY8, RGB8>::
00157     operator()(const Image<GRAY8>::PixelType& inputPixel,
00158                Image<RGB8>::PixelType& outputPixel)
00159     {
00160       outputPixel.red = inputPixel;
00161       outputPixel.green = inputPixel;
00162       outputPixel.blue = inputPixel;
00163     }
00164 
00165 
00166     template<>
00167     inline
00168     void
00169     ColorspaceConverter<RGB8, GRAY8>::
00170     operator()(const Image<RGB8>::PixelType& inputPixel,
00171                Image<GRAY8>::PixelType& outputPixel)
00172     {
00173       double accumulator = (inputPixel.red * inputPixel.red
00174                             + inputPixel.green * inputPixel.green
00175                             + inputPixel.blue * inputPixel.blue) / 3.0;
00176       outputPixel =
00177         static_cast<Image<GRAY8>::PixelType>(std::sqrt(accumulator) + 0.5);
00178     }
00179 
00180 
00181     template<>
00182     inline
00183     void
00184     ColorspaceConverter<RGB8, RGB_FLOAT32>::
00185     operator()(const Image<RGB8>::PixelType& inputPixel,
00186                Image<RGB_FLOAT32>::PixelType& outputPixel)
00187     {
00188       outputPixel.red = static_cast<Float32>(inputPixel.red);
00189       outputPixel.green = static_cast<Float32>(inputPixel.green);
00190       outputPixel.blue = static_cast<Float32>(inputPixel.blue);
00191     }
00192 
00193 
00194     template<>
00195     inline
00196     void
00197     ColorspaceConverter<RGB8, RGB_FLOAT64>::
00198     operator()(const Image<RGB8>::PixelType& inputPixel,
00199                Image<RGB_FLOAT64>::PixelType& outputPixel)
00200     {
00201       outputPixel.red = static_cast<Float64>(inputPixel.red);
00202       outputPixel.green = static_cast<Float64>(inputPixel.green);
00203       outputPixel.blue = static_cast<Float64>(inputPixel.blue);
00204     }
00205 
00206 
00207     template<>
00208     inline
00209     void
00210     ColorspaceConverter<RGB8, HSV_FLOAT64>::
00211     operator()(const Image<RGB8>::PixelType& inputPixel,
00212                Image<HSV_FLOAT64>::PixelType& outputPixel)
00213     {
00214       // "value" is the simplest to compute... it's just the max RGB value.
00215       Float64 maxVal = static_cast<Float64>(
00216         std::max(inputPixel.red, std::max(inputPixel.green, inputPixel.blue)));
00217       outputPixel.value = maxVal;
00218     
00219       // Handle first special case up-front.
00220       if(maxVal == 0.0) {
00221         outputPixel.hue = Float64(0.0);
00222         outputPixel.saturation = Float64(0.0);
00223         return;
00224       }
00225 
00226       // Now we can compute "saturation".
00227       Float64 minVal = static_cast<Float64>(
00228         std::min(inputPixel.red, std::min(inputPixel.green, inputPixel.blue)));
00229       Float64 delta = maxVal - minVal;
00230       outputPixel.saturation = delta / maxVal;
00231     
00232       // Handle second special case up-front.
00233       if(delta == 0.0) {
00234         outputPixel.hue = Float64(0.0);
00235         return;
00236       }
00237 
00238       // Warning(xxx): our definition of hue goes from 0.0 to 1.0, not
00239       // 0.0 to 360.0, as is traditional.
00240       if(inputPixel.red == maxVal) {
00241         outputPixel.hue =
00242           Float64(1.0 / 6.0)
00243           + (static_cast<Float64>(inputPixel.green)
00244              - static_cast<Float64>(inputPixel.blue)) / (6.0 * delta);
00245       } else if(inputPixel.green == maxVal) {
00246         outputPixel.hue =
00247           Float64(0.5)
00248           + (static_cast<Float64>(inputPixel.blue)
00249              - static_cast<Float64>(inputPixel.red)) / (6.0 * delta);
00250       } else {
00251         outputPixel.hue =
00252           Float64(5.0 / 6.0)
00253           + (static_cast<Float64>(inputPixel.red)
00254              - static_cast<Float64>(inputPixel.green)) / (6.0 * delta);
00255       }      
00256     }    
00257 
00258 
00259     template<>
00260     inline
00261     void
00262     ColorspaceConverter<RGB8, BGRA8>::
00263     operator()(const Image<RGB8>::PixelType& inputPixel,
00264                Image<BGRA8>::PixelType& outputPixel)
00265     {
00266       outputPixel.red = inputPixel.red;
00267       outputPixel.green = inputPixel.green;
00268       outputPixel.blue = inputPixel.blue;
00269       outputPixel.alpha = UnsignedInt8(255);
00270     }
00271 
00272 
00273     template<>
00274     inline
00275     void
00276     ColorspaceConverter<RGB8, RGBA8>::
00277     operator()(const Image<RGB8>::PixelType& inputPixel,
00278                Image<RGBA8>::PixelType& outputPixel)
00279     {
00280       outputPixel.red = inputPixel.red;
00281       outputPixel.green = inputPixel.green;
00282       outputPixel.blue = inputPixel.blue;
00283       outputPixel.alpha = UnsignedInt8(255);
00284     }
00285 
00286 
00287     template<>
00288     inline
00289     void
00290     ColorspaceConverter<RGB_FLOAT32, GRAY8>::
00291     operator()(const Image<RGB_FLOAT32>::PixelType& inputPixel,
00292                Image<GRAY8>::PixelType& outputPixel)
00293     {
00294       double accumulator = (inputPixel.red * inputPixel.red
00295                             + inputPixel.green * inputPixel.green
00296                             + inputPixel.blue * inputPixel.blue) / 3.0;
00297       outputPixel =
00298         static_cast<Image<GRAY8>::PixelType>(std::sqrt(accumulator) + 0.5);
00299     }
00300 
00301 
00302 
00303     template<>
00304     inline
00305     void
00306     ColorspaceConverter<RGB_FLOAT64, HSV_FLOAT64>::
00307     operator()(const Image<RGB_FLOAT64>::PixelType& inputPixel,
00308                Image<HSV_FLOAT64>::PixelType& outputPixel)
00309     {
00310       // "value" is the simplest to compute... it's just the max RGB value.
00311       Float64 maxVal = static_cast<Float64>(
00312         std::max(inputPixel.red, std::max(inputPixel.green, inputPixel.blue)));
00313       outputPixel.value = maxVal;
00314     
00315       // Handle first special case up-front.
00316       if(maxVal == 0.0) {
00317         outputPixel.hue = Float64(0.0);
00318         outputPixel.saturation = Float64(0.0);
00319         return;
00320       }
00321 
00322       // Now we can compute "saturation".
00323       Float64 minVal = static_cast<Float64>(
00324         std::min(inputPixel.red, std::min(inputPixel.green, inputPixel.blue)));
00325       Float64 delta = maxVal - minVal;
00326       outputPixel.saturation = delta / maxVal;
00327     
00328       // Handle second special case up-front.
00329       if(delta == 0.0) {
00330         outputPixel.hue = Float64(0.0);
00331         return;
00332       }
00333 
00334       // Warning(xxx): our definition of hue goes from 0.0 to 1.0, not
00335       // 0.0 to 360.0, as is traditional.
00336       if(inputPixel.red == maxVal) {
00337         outputPixel.hue =
00338           Float64(1.0 / 6.0)
00339           + (static_cast<Float64>(inputPixel.green)
00340              - static_cast<Float64>(inputPixel.blue)) / (6.0 * delta);
00341       } else if(inputPixel.green == maxVal) {
00342         outputPixel.hue =
00343           Float64(0.5)
00344           + (static_cast<Float64>(inputPixel.blue)
00345              - static_cast<Float64>(inputPixel.red)) / (6.0 * delta);
00346       } else {
00347         outputPixel.hue =
00348           Float64(5.0 / 6.0)
00349           + (static_cast<Float64>(inputPixel.red)
00350              - static_cast<Float64>(inputPixel.green)) / (6.0 * delta);
00351       }      
00352     }    
00353 
00354 
00355     template<>
00356     inline
00357     void
00358     ColorspaceConverter<BGRA8, RGB8>::
00359     operator()(const Image<BGRA8>::PixelType& inputPixel,
00360                Image<RGB8>::PixelType& outputPixel)
00361     {
00362       outputPixel.red = inputPixel.red;
00363       outputPixel.green = inputPixel.green;
00364       outputPixel.blue = inputPixel.blue;
00365     }
00366   
00367 
00368     template<>
00369     inline
00370     void
00371     ColorspaceConverter<RGBA8, RGB8>::
00372     operator()(const Image<RGBA8>::PixelType& inputPixel,
00373                Image<RGB8>::PixelType& outputPixel)
00374     {
00375       outputPixel.red = inputPixel.red;
00376       outputPixel.green = inputPixel.green;
00377       outputPixel.blue = inputPixel.blue;
00378     }
00379 
00380   } // namespace computerVision
00381     
00382 } // namespace dlr
00383 
00384 #endif /* #ifndef _DLRCOMPUTERVISION_COLORSPACECONVERTER_H_ */

Generated on Mon Jul 9 20:34:02 2007 for dlrLibs Utility Libraries by  doxygen 1.5.2