core/vidl/vidl_color.h
Go to the documentation of this file.
00001 // This is core/vidl/vidl_color.h
00002 #ifndef vidl_color_h_
00003 #define vidl_color_h_
00004 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00005 #pragma interface
00006 #endif
00007 //:
00008 // \file
00009 // \brief Color space conversions and related functions
00010 //
00011 // \author Matt Leotta
00012 // \date 23 Jan 2006
00013 //
00014 
00015 #include "vidl_pixel_format.h"
00016 #include <vcl_cstring.h>
00017 #include <vcl_typeinfo.h>
00018 #include <vcl_cassert.h>
00019 
00020 
00021 //-----------------------------------------------------------------------------
00022 // Monochromatic type conversions
00023 //-----------------------------------------------------------------------------
00024 
00025 
00026 inline void vidl_type_convert(const vxl_byte& in, bool& out)
00027 {
00028   out = (in & 0x80) > 0; // threshold
00029 }
00030 
00031 inline void vidl_type_convert(const vxl_uint_16& in, bool& out)
00032 {
00033   out = (in & 0x8000) > 0; // threshold
00034 }
00035 
00036 inline void vidl_type_convert(const bool& in, vxl_byte& out)
00037 {
00038   out = in?0xFF:0x00;
00039 }
00040 
00041 inline void vidl_type_convert(const bool& in, vxl_uint_16& out)
00042 {
00043   out = in?0xFFFF:0x0000;
00044 }
00045 
00046 inline void vidl_type_convert(const vxl_byte& in, vxl_uint_16& out)
00047 {
00048   out = static_cast<vxl_uint_16>(in<<8);
00049 }
00050 
00051 inline void vidl_type_convert(const vxl_uint_16& in, vxl_byte& out)
00052 {
00053   out = static_cast<vxl_byte>(in>>8);
00054 }
00055 
00056 inline void vidl_type_convert(const vxl_byte& in, vxl_ieee_32& out)
00057 {
00058   out = static_cast<vxl_ieee_32>(in)/0xFF;
00059 }
00060 
00061 inline void vidl_type_convert(const vxl_uint_16& in, vxl_ieee_32& out)
00062 {
00063   out = static_cast<vxl_ieee_32>(in)/0xFFFF;
00064 }
00065 
00066 inline void vidl_type_convert(const bool& in, vxl_ieee_32& out)
00067 {
00068   out = static_cast<vxl_ieee_32>(in?1:0);
00069 }
00070 
00071 inline void vidl_type_convert(const vxl_ieee_32& in, vxl_byte& out)
00072 {
00073   out = static_cast<vxl_byte>(in*255);
00074 }
00075 
00076 inline void vidl_type_convert(const vxl_ieee_32& in, vxl_uint_16& out)
00077 {
00078   out = static_cast<vxl_uint_16>(in*65535);
00079 }
00080 
00081 inline void vidl_type_convert(const vxl_ieee_32& in, bool& out)
00082 {
00083   out = in > 0.5; // threshold
00084 }
00085 
00086 inline void vidl_type_convert(const vxl_byte& in, vxl_ieee_64& out)
00087 {
00088   out = static_cast<vxl_ieee_64>(in)/255.0;
00089 }
00090 
00091 inline void vidl_type_convert(const vxl_uint_16& in, vxl_ieee_64& out)
00092 {
00093   out = static_cast<vxl_ieee_64>(in)/0xFFFF;
00094 }
00095 
00096 inline void vidl_type_convert(const bool& in, vxl_ieee_64& out)
00097 {
00098   out = in?1:0;
00099 }
00100 
00101 inline void vidl_type_convert(const vxl_ieee_64& in, vxl_byte& out)
00102 {
00103   out = static_cast<vxl_byte>(in*255);
00104 }
00105 
00106 inline void vidl_type_convert(const vxl_ieee_64& in, vxl_uint_16& out)
00107 {
00108   out = static_cast<vxl_uint_16>(in*65535);
00109 }
00110 
00111 inline void vidl_type_convert(const vxl_ieee_64& in, bool& out)
00112 {
00113   out = in > 0.5; // threshold
00114 }
00115 
00116 template <class inT, class outT>
00117 inline void vidl_type_convert(const inT& in, outT& out)
00118 {
00119   out = static_cast<outT>(in);
00120 }
00121 
00122 
00123 //-----------------------------------------------------------------------------
00124 // Color space conversions
00125 //-----------------------------------------------------------------------------
00126 
00127 
00128 // ITU-R BT.601 (formerly CCIR 601) standard conversion
00129 template <class outT>
00130 inline void vidl_color_convert_yuv2rgb( double  y, double  u, double  v,
00131                                         double& r, double& g, double& b )
00132 {
00133   r = y + 1.1402 * v;
00134   g = y - 0.34413628620102 * u - 0.71413628620102 * v;
00135   b = y + 1.772 * u;
00136 }
00137 
00138 
00139 // ITU-R BT.601 (formerly CCIR 601) standard conversion
00140 inline void vidl_color_convert_yuv2rgb( vxl_byte y, vxl_byte u, vxl_byte v,
00141                                         double&  r, double&  g, double&  b )
00142 {
00143   double dy = y/255.0;       // 0.0 to 1.0
00144   double du = (u-128)/255.0; //-0.5 to 0.5
00145   double dv = (v-128)/255.0; //-0.5 to 0.5
00146   r = dy + 1.1402 * dv;
00147   g = dy - 0.34413628620102 * du - 0.71413628620102 * dv;
00148   b = dy + 1.772 * du;
00149 }
00150 
00151 
00152 //: faster integer-based conversion from YUV to RGB
00153 // Based on conversion used in libdc1394
00154 inline void vidl_color_convert_yuv2rgb( vxl_byte  y, vxl_byte  u, vxl_byte  v,
00155                                         vxl_byte& r, vxl_byte& g, vxl_byte& b )
00156 {
00157   register int iy = y, iu = u-128, iv = v-128, ir, ib, ig;
00158   r = ir = iy + ((iv*1436) >> 10);
00159   g = ig = iy - ((iu*352 + iv*731) >> 10);
00160   b = ib = iy + ((iu*1814) >> 10);
00161   r = ir < 0 ? 0u : r;
00162   g = ig < 0 ? 0u : g;
00163   b = ib < 0 ? 0u : b;
00164   r = ir > 255 ? 255u : r;
00165   g = ig > 255 ? 255u : g;
00166   b = ib > 255 ? 255u : b;
00167 }
00168 
00169 
00170 // ITU-R BT.601 (formerly CCIR 601) standard conversion
00171 inline void vidl_color_convert_rgb2yuv( double r,  double g,  double b,
00172                                         double& y, double& u, double& v )
00173 {
00174   y = 0.299*r + 0.587*g + 0.114*b;
00175   u = (b-y)/1.772;
00176   v = (r-y)/1.402;
00177 }
00178 
00179 
00180 // ITU-R BT.601 (formerly CCIR 601) standard conversion
00181 inline void vidl_color_convert_rgb2yuv( double r, double g, double b,
00182                                         vxl_byte& y, vxl_byte& u, vxl_byte& v )
00183 {
00184   double dy = 0.299*r + 0.587*g + 0.114*b;
00185   double du = (b-dy)/1.772;
00186   double dv = (r-dy)/1.402;
00187   vidl_type_convert(dy,y);
00188   vidl_type_convert(du+0.5,u);
00189   vidl_type_convert(dv+0.5,v);
00190 }
00191 
00192 
00193 //: faster integer-based conversion from RGB to YUV
00194 // Based on conversion used in libdc1394
00195 inline void vidl_color_convert_rgb2yuv( vxl_byte  r, vxl_byte  g, vxl_byte  b,
00196                                         vxl_byte& y, vxl_byte& u, vxl_byte& v )
00197 {
00198   register int ir = r, ib = b, ig = g, iy, iu, iv;
00199   y = iy = (306*ir + 601*ig + 117*ib)  >> 10;
00200   u = iu = ((-172*ir - 340*ig + 512*ib) >> 10) + 128u;
00201   v = iv = ((512*ir - 429*ig - 83*ib) >> 10) + 128u;
00202   y = iy < 0 ? 0u : y;
00203   u = iu < 0 ? 0u : u;
00204   v = iv < 0 ? 0u : v;
00205   y = iy > 255 ? 255u : y;
00206   u = iu > 255 ? 255u : u;
00207   v = iv > 255 ? 255u : v;
00208 }
00209 
00210 //-----------------------------------------------------------------------------
00211 // Generic interface to conversion routines
00212 //-----------------------------------------------------------------------------
00213 
00214 //: Define the function pointer for pixel format conversion functions
00215 typedef void (*vidl_color_conv_fptr)(const vxl_byte* in, vxl_byte* out);
00216 
00217 //: Returns a color conversion function based on runtime values
00218 // The function returned is always a vidl_color_conv_fptr which
00219 // converts const vxl_byte* to vxl_byte*.  Some of these function
00220 // may actually reinterpret the data as other types (i.e. bool* or
00221 // vxl_uint_16*) via reinterpret_cast
00222 vidl_color_conv_fptr
00223 vidl_color_converter_func( vidl_pixel_color in_C, const vcl_type_info& in_type,
00224                            vidl_pixel_color out_C, const vcl_type_info& out_type);
00225 
00226 
00227 template <vidl_pixel_color in_C, vidl_pixel_color out_C>
00228 struct vidl_color_converter;
00229 
00230 
00231 VCL_DEFINE_SPECIALIZATION
00232 struct vidl_color_converter<VIDL_PIXEL_COLOR_MONO,VIDL_PIXEL_COLOR_MONO>
00233 {
00234   template <class T>
00235   static inline void convert(const T in[1], T out[1])
00236   {
00237     out[0] = in[0];
00238   }
00239 
00240   template <class inT, class outT>
00241   static inline void convert(const inT in[1], outT out[1])
00242   {
00243     vidl_type_convert(*in, *out);
00244   }
00245 };
00246 
00247 
00248 VCL_DEFINE_SPECIALIZATION
00249 struct vidl_color_converter<VIDL_PIXEL_COLOR_RGB,VIDL_PIXEL_COLOR_RGB>
00250 {
00251   template <class T>
00252   static inline void convert(const T in[3], T out[3])
00253   {
00254     vcl_memcpy(out, in, sizeof(T)*3);
00255   }
00256 
00257   template <class inT, class outT>
00258   static inline void convert(const inT in[3], outT out[3])
00259   {
00260     vidl_type_convert(*in, *out);
00261     vidl_type_convert(*++in, *++out);
00262     vidl_type_convert(*++in, *++out);
00263   }
00264 };
00265 
00266 
00267 VCL_DEFINE_SPECIALIZATION
00268 struct vidl_color_converter<VIDL_PIXEL_COLOR_RGBA,VIDL_PIXEL_COLOR_RGBA>
00269 {
00270   template <class T>
00271   static inline void convert(const T in[4], T out[4])
00272   {
00273     vcl_memcpy(out, in, sizeof(T)*4);
00274   }
00275 
00276   template <class inT, class outT>
00277   static inline void convert(const inT in[4], outT out[4])
00278   {
00279     vidl_type_convert(*in, *out);
00280     vidl_type_convert(*++in, *++out);
00281     vidl_type_convert(*++in, *++out);
00282     vidl_type_convert(*++in, *++out);
00283   }
00284 };
00285 
00286 
00287 VCL_DEFINE_SPECIALIZATION
00288 struct vidl_color_converter<VIDL_PIXEL_COLOR_RGBA,VIDL_PIXEL_COLOR_RGB>
00289 {
00290   template <class T>
00291   static inline void convert(const T in[4], T out[3])
00292   {
00293     vcl_memcpy(out, in, sizeof(T)*3);
00294   }
00295 
00296   template <class inT, class outT>
00297   static inline void convert(const inT in[4], outT out[3])
00298   {
00299     vidl_type_convert(*in, *out);
00300     vidl_type_convert(*++in, *++out);
00301     vidl_type_convert(*++in, *++out);
00302   }
00303 };
00304 
00305 
00306 VCL_DEFINE_SPECIALIZATION
00307 struct vidl_color_converter<VIDL_PIXEL_COLOR_RGB,VIDL_PIXEL_COLOR_RGBA>
00308 {
00309   template <class T>
00310   static inline void convert(const T in[3], T out[4])
00311   {
00312     vcl_memcpy(out, in, sizeof(T)*3);
00313     out[3] = vidl_pixel_limits<T>::max();
00314   }
00315 
00316   template <class inT, class outT>
00317   static inline void convert(const inT in[3], outT out[4])
00318   {
00319     vidl_type_convert(*in, *out);
00320     vidl_type_convert(*++in, *++out);
00321     vidl_type_convert(*++in, *++out);
00322     out[3] = vidl_pixel_limits<outT>::max();
00323   }
00324 };
00325 
00326 
00327 VCL_DEFINE_SPECIALIZATION
00328 struct vidl_color_converter<VIDL_PIXEL_COLOR_YUV,VIDL_PIXEL_COLOR_YUV>
00329 {
00330   template <class T>
00331   static inline void convert(const T in[3], T out[3])
00332   {
00333     vcl_memcpy(out, in, sizeof(T)*3);
00334   }
00335 
00336   template <class inT, class outT>
00337   static inline void convert(const inT in[3], outT out[3])
00338   {
00339     vidl_type_convert(*in, *out);
00340     vidl_type_convert(*++in, *++out);
00341     vidl_type_convert(*++in, *++out);
00342   }
00343 };
00344 
00345 
00346 VCL_DEFINE_SPECIALIZATION
00347 struct vidl_color_converter<VIDL_PIXEL_COLOR_RGB,VIDL_PIXEL_COLOR_YUV>
00348 {
00349   template <class inT, class outT>
00350   static inline void convert(const inT in[3], outT out[3])
00351   {
00352     // use double as intermediate type
00353     double r,g,b, y,u,v;
00354     vidl_type_convert(in[0],r);
00355     vidl_type_convert(in[1],b);
00356     vidl_type_convert(in[2],g);
00357     vidl_color_convert_rgb2yuv(r,g,b,y,u,v);
00358     vidl_type_convert(y,out[0]);
00359     vidl_type_convert(u,out[1]);
00360     vidl_type_convert(v,out[2]);
00361   }
00362 
00363   template <class inT>
00364   static inline void convert(const inT in[3], vxl_byte out[3])
00365   {
00366     double r,g,b;
00367     vidl_type_convert(in[0],r);
00368     vidl_type_convert(in[1],b);
00369     vidl_type_convert(in[2],g);
00370     vidl_color_convert_rgb2yuv(r,g,b,
00371                                out[0],out[1],out[2]);
00372   }
00373 
00374   static inline void convert(const vxl_byte in[3], vxl_byte out[3])
00375   {
00376     vidl_color_convert_rgb2yuv(in[0],in[1],in[2],
00377                                out[0],out[1],out[2]);
00378   }
00379 };
00380 
00381 
00382 VCL_DEFINE_SPECIALIZATION
00383 struct vidl_color_converter<VIDL_PIXEL_COLOR_RGBA,VIDL_PIXEL_COLOR_YUV>
00384 {
00385   template <class outT>
00386   static inline void convert(const vxl_byte in[4], outT out[3])
00387   {
00388     vidl_color_convert_rgb2yuv(in[0],in[1],in[2],
00389                                out[0],out[1],out[2]);
00390   }
00391 };
00392 
00393 
00394 VCL_DEFINE_SPECIALIZATION
00395 struct vidl_color_converter<VIDL_PIXEL_COLOR_YUV,VIDL_PIXEL_COLOR_RGB>
00396 {
00397   template <class inT, class outT>
00398   static inline void convert(const inT in[3], outT out[3])
00399   {
00400     // use double as intermediate type
00401     double r,g,b, y,u,v;
00402     vidl_type_convert(in[0],y);
00403     vidl_type_convert(in[1],u);
00404     vidl_type_convert(in[2],v);
00405     vidl_color_convert_yuv2rgb(y,u,v,r,g,b);
00406     vidl_type_convert(r,out[0]);
00407     vidl_type_convert(g,out[1]);
00408     vidl_type_convert(b,out[2]);
00409   }
00410 
00411   template <class outT>
00412   static inline void convert(const vxl_byte in[3], outT out[3])
00413   {
00414     double r,g,b;
00415     vidl_color_convert_yuv2rgb(in[0],in[1],in[2],
00416                                r,g,b);
00417     vidl_type_convert(r,out[0]);
00418     vidl_type_convert(g,out[1]);
00419     vidl_type_convert(b,out[2]);
00420   }
00421 
00422   static inline void convert(const vxl_byte in[3], vxl_byte out[3])
00423   {
00424     vidl_color_convert_yuv2rgb(in[0],in[1],in[2],
00425                                out[0],out[1],out[2]);
00426   }
00427 };
00428 
00429 
00430 VCL_DEFINE_SPECIALIZATION
00431 struct vidl_color_converter<VIDL_PIXEL_COLOR_YUV,VIDL_PIXEL_COLOR_RGBA>
00432 {
00433   template <class outT>
00434   static inline void convert(const vxl_byte in[3], outT out[4])
00435   {
00436     vidl_color_convert_yuv2rgb(in[0],in[1],in[2],
00437                                out[0],out[1],out[2]);
00438     out[3] = vidl_pixel_limits<outT>::max();
00439   }
00440 };
00441 
00442 
00443 VCL_DEFINE_SPECIALIZATION
00444 struct vidl_color_converter<VIDL_PIXEL_COLOR_YUV,VIDL_PIXEL_COLOR_MONO>
00445 {
00446   template <class T>
00447   static inline void convert(const T in[3], T out[1])
00448   {
00449     // The Y channel is the greyscale value
00450     out[0] = in[0];
00451   }
00452 
00453   template <class inT, class outT>
00454   static inline void convert(const inT in[3], outT out[1])
00455   {
00456     // The Y channel is the greyscale value
00457     vidl_type_convert(*in,*out);
00458   }
00459 };
00460 
00461 
00462 VCL_DEFINE_SPECIALIZATION
00463 struct vidl_color_converter<VIDL_PIXEL_COLOR_MONO,VIDL_PIXEL_COLOR_YUV>
00464 {
00465   template <class T>
00466   static inline void convert(const T in[1], T out[3])
00467   {
00468     // The Y channel is the greyscale value
00469     out[0] = in[0];
00470     out[1] = vidl_pixel_limits<T>::chroma_zero();
00471     out[2] = vidl_pixel_limits<T>::chroma_zero();
00472   }
00473 
00474   template <class inT, class outT>
00475   static inline void convert(const inT in[1], outT out[3])
00476   {
00477     // The Y channel is the greyscale value
00478     vidl_type_convert(*in,*out);
00479     out[1] = vidl_pixel_limits<outT>::chroma_zero();
00480     out[2] = vidl_pixel_limits<outT>::chroma_zero();
00481   }
00482 };
00483 
00484 VCL_DEFINE_SPECIALIZATION
00485 struct vidl_color_converter<VIDL_PIXEL_COLOR_RGB,VIDL_PIXEL_COLOR_MONO>
00486 {
00487   template <class inT, class outT>
00488   static inline void convert(const inT in[3], outT out[1])
00489   {
00490     // use double as intermediate type
00491     double r,g,b;
00492     vidl_type_convert(in[0],r);
00493     vidl_type_convert(in[1],b);
00494     vidl_type_convert(in[2],g);
00495     double y = 0.299*r + 0.587*g + 0.114*b;
00496     vidl_type_convert(y,*out);
00497   }
00498 
00499   // fast approximation for bytes
00500   static inline void convert(const vxl_byte in[3], vxl_byte out[1])
00501   {
00502     //: FIXME verify that this works!
00503     out[0] = (306*in[0] + 601*in[1] + 117*in[2]) >> 10;
00504   }
00505 };
00506 
00507 VCL_DEFINE_SPECIALIZATION
00508 struct vidl_color_converter<VIDL_PIXEL_COLOR_RGBA,VIDL_PIXEL_COLOR_MONO>
00509 {
00510   template <class inT, class outT>
00511   static inline void convert(const inT in[4], outT out[1])
00512   {
00513     // use double as intermediate type
00514     double r,g,b;
00515     vidl_type_convert(in[0],r);
00516     vidl_type_convert(in[1],b);
00517     vidl_type_convert(in[2],g);
00518     double y = 0.299*r + 0.587*g + 0.114*b;
00519     vidl_type_convert(y,*out);
00520   }
00521 
00522   // fast approximation for bytes
00523   static inline void convert(const vxl_byte in[4], vxl_byte out[1])
00524   {
00525     //: FIXME verify that this works!
00526     out[0] = (306*in[0] + 601*in[1] + 117*in[2]) >> 10;
00527   }
00528 };
00529 
00530 VCL_DEFINE_SPECIALIZATION
00531 struct vidl_color_converter<VIDL_PIXEL_COLOR_MONO,VIDL_PIXEL_COLOR_RGB>
00532 {
00533   template <class inT, class outT>
00534   static inline void convert(const inT in[1], outT out[3])
00535   {
00536     // Set all channels to the same value
00537     vidl_type_convert(*in,*out);
00538     out[2] = out[1] = out[0];
00539   }
00540 };
00541 
00542 VCL_DEFINE_SPECIALIZATION
00543 struct vidl_color_converter<VIDL_PIXEL_COLOR_MONO,VIDL_PIXEL_COLOR_RGBA>
00544 {
00545   template <class inT, class outT>
00546   static inline void convert(const inT in[1], outT out[4])
00547   {
00548     // Set all channels to the same value
00549     vidl_type_convert(*in,*out);
00550     out[2] = out[1] = out[0];
00551     out[3] = vidl_pixel_limits<outT>::max();
00552   }
00553 };
00554 
00555 
00556 //-----------------------------------------------------------------------------
00557 // Access to color components
00558 //-----------------------------------------------------------------------------
00559 
00560 
00561 //: Component color encoding
00562 // These functions indicate how to extract a byte for each
00563 // color channel given a pointer to the pixel memory
00564 // This is only meant for non-planar non-packed formats
00565 template <vidl_pixel_format FMT>
00566 struct vidl_color_component
00567 {
00568   typedef typename vidl_pixel_traits_of<FMT>::type cmp_type;
00569   static inline
00570   cmp_type get(const cmp_type * ptr, unsigned int i)
00571   {
00572     return ptr[i];
00573   }
00574 
00575   // it may be more efficient to access all color channels at once
00576   static inline
00577   void get_all(const cmp_type * ptr, cmp_type * data)
00578   {
00579     vcl_memcpy(data, ptr, sizeof(cmp_type)*vidl_pixel_traits_of<FMT>::num_channels);
00580   }
00581 
00582   static inline
00583   void set(cmp_type * ptr, unsigned int i, cmp_type val)
00584   {
00585     ptr[i] = val;
00586   }
00587 
00588   // it may be more efficient to access all color channels at once
00589   static inline
00590   void set_all(cmp_type * ptr, const cmp_type * data)
00591   {
00592     vcl_memcpy(ptr, data, sizeof(cmp_type)*vidl_pixel_traits_of<FMT>::num_channels);
00593   }
00594 };
00595 
00596 
00597 VCL_DEFINE_SPECIALIZATION
00598 struct vidl_color_component<VIDL_PIXEL_FORMAT_BGR_24>
00599 {
00600   // 0 -> 2
00601   // 1 -> 1
00602   // 2 -> 0
00603   static inline
00604   vxl_byte get(const vxl_byte * ptr, unsigned int i)
00605   {
00606     return ptr[2-i];
00607   }
00608 
00609   static inline
00610   void get_all(const vxl_byte * ptr, vxl_byte * data)
00611   {
00612     data[0] = ptr[2];
00613     data[1] = ptr[1];
00614     data[2] = ptr[0];
00615   }
00616 
00617   static inline
00618   void set(vxl_byte * ptr, unsigned int i, vxl_byte val)
00619   {
00620     ptr[2-i] = val;
00621   }
00622 
00623   static inline
00624   void set_all(vxl_byte * ptr, const vxl_byte * data)
00625   {
00626     ptr[2] = data[0];
00627     ptr[1] = data[1];
00628     ptr[0] = data[2];
00629   }
00630 };
00631 
00632 
00633 VCL_DEFINE_SPECIALIZATION
00634 struct vidl_color_component<VIDL_PIXEL_FORMAT_RGB_555>
00635 {
00636   static inline
00637   vxl_byte get(const vxl_byte * ptr, unsigned int i)
00638   {
00639     const vxl_uint_16* p = reinterpret_cast<const vxl_uint_16*>(ptr);
00640     return static_cast<vxl_byte>((*p >> (2-i)*5)<<3);
00641   }
00642 
00643   static inline
00644   void get_all(const vxl_byte * ptr, vxl_byte * data)
00645   {
00646     const vxl_uint_16* p = reinterpret_cast<const vxl_uint_16*>(ptr);
00647     data[0] = static_cast<vxl_byte>((*p >>10)<<3);
00648     data[1] = static_cast<vxl_byte>((*p >>5)<<3);
00649     data[2] = static_cast<vxl_byte>((*p)<<3);
00650   }
00651 
00652   static inline
00653   void set(vxl_byte * ptr, unsigned int i, vxl_byte val)
00654   {
00655     vxl_uint_16* p = reinterpret_cast<vxl_uint_16*>(ptr);
00656     vxl_uint_16 v = static_cast<vxl_uint_16>((val>>3)<<(2-i)*5);
00657     vxl_uint_16 mask = static_cast<vxl_uint_16>(~(31<<(2-i)*5));
00658     *p  = (*p & mask) | v;
00659   }
00660 
00661   static inline
00662   void set_all(vxl_byte * ptr, const vxl_byte * data)
00663   {
00664     vxl_uint_16* p = reinterpret_cast<vxl_uint_16*>(ptr);
00665     *p = ((data[0]>>3) << 10) | ((data[1]>>3) << 5) | (data[2]>>3);
00666   }
00667 };
00668 
00669 
00670 VCL_DEFINE_SPECIALIZATION
00671 struct vidl_color_component<VIDL_PIXEL_FORMAT_RGB_565>
00672 {
00673   static inline
00674   vxl_byte get(const vxl_byte * ptr, unsigned int i)
00675   {
00676     const vxl_uint_16* p = reinterpret_cast<const vxl_uint_16*>(ptr);
00677     switch (i) {
00678       case 0: return vxl_byte((*p & 0xF800) >> 8); // R
00679       case 1: return vxl_byte((*p & 0x07E0) >> 3); // G
00680       case 2: return vxl_byte((*p & 0x001F) << 3); // B
00681       default: assert(!"i should be one of 0, 1, or 2");
00682     }
00683     return 0;
00684   }
00685 
00686   static inline
00687   void get_all(const vxl_byte * ptr, vxl_byte * data)
00688   {
00689     const vxl_uint_16* p = reinterpret_cast<const vxl_uint_16*>(ptr);
00690     data[0] = static_cast<vxl_byte>((*p >>11)<<3);
00691     data[1] = static_cast<vxl_byte>((*p >>5)<<2);
00692     data[2] = static_cast<vxl_byte>((*p)<<3);
00693   }
00694 
00695   static inline
00696   void set(vxl_byte * ptr, unsigned int i, vxl_byte val)
00697   {
00698     vxl_uint_16* p = reinterpret_cast<vxl_uint_16*>(ptr);
00699     vxl_uint_16 v = static_cast<vxl_uint_16>(val>>3);
00700     switch (i) {
00701       case 0: *p &= 0x07FF; *p |= static_cast<vxl_uint_16>(v<<11); break; // R
00702       case 1: *p &= 0xF81F; *p |= static_cast<vxl_uint_16>(v<<5);  break; // G
00703       case 2: *p &= 0xFFE0; *p |= v; break;                               // B
00704       default: assert(!"i should be one of 0, 1, or 2");
00705     }
00706   }
00707 
00708   static inline
00709   void set_all(vxl_byte * ptr, const vxl_byte * data)
00710   {
00711     vxl_uint_16* p = reinterpret_cast<vxl_uint_16*>(ptr);
00712     *p = ((data[0]>>3) << 11) | ((data[1]>>2) << 5) | (data[2]>>3);
00713   }
00714 };
00715 
00716 
00717 VCL_DEFINE_SPECIALIZATION
00718 struct vidl_color_component<VIDL_PIXEL_FORMAT_UYV_444>
00719 {
00720   // 0 -> 1
00721   // 1 -> 0
00722   // 2 -> 2
00723   static inline
00724   vxl_byte get(const vxl_byte * ptr, unsigned int i)
00725   {
00726     return ptr[i^((i>>1)^1)];
00727   }
00728 
00729   static inline
00730   void get_all(const vxl_byte * ptr, vxl_byte * data)
00731   {
00732     data[0] = ptr[1];
00733     data[1] = ptr[0];
00734     data[2] = ptr[2];
00735   }
00736 
00737   static inline
00738   void set(vxl_byte * ptr, unsigned int i, vxl_byte val)
00739   {
00740     ptr[i^((i>>1)^1)] = val;
00741   }
00742 
00743   static inline
00744   void set_all(vxl_byte * ptr, const vxl_byte * data)
00745   {
00746     ptr[1] = data[0];
00747     ptr[0] = data[1];
00748     ptr[2] = data[2];
00749   }
00750 };
00751 
00752 #endif // vidl_color_h_
00753