core/vidl/vidl_pixel_format.cxx
Go to the documentation of this file.
00001 // This is core/vidl/vidl_pixel_format.cxx
00002 #include "vidl_pixel_format.h"
00003 //:
00004 // \file
00005 // \author Matt Leotta
00006 //
00007 #include <vcl_iostream.h>
00008 
00009 #define vidl_ppi_mac(FMT)\
00010 const vcl_ptrdiff_t vidl_pixel_pack_of<VIDL_PIXEL_FORMAT_##FMT>::offset[macro_pix_size][num_channels]
00011 
00012 // Define the packing order for each packed vidl_pixel_format
00013 // The main purpose of this struct is to define a static
00014 // array of pointer offsets to describe the packing.
00015 //
00016 // The array vidl_pixel_pack_of<format>::offset is a 2D array
00017 // of pointer offsets from the start of the macro pixel.  The
00018 // size of the array is macro-pixel-size by number-of-channels.
00019 // The value offset[i][j] gives the offset to the jth channel
00020 // of the ith pixel in the current macro-pixel.  For example,
00021 // offset[1][0] gives the 'Y' channel (if YUV) or 'R' channel
00022 // (if RGB) of the second pixel in the macro pixel
00023 
00024 vidl_ppi_mac(YUYV_422) = {{0,1,3},{2,1,3}};
00025 vidl_ppi_mac(UYVY_422) = {{1,0,2},{3,0,2}};
00026 vidl_ppi_mac(UYVY_411) = {{1,0,3},{2,0,3},{4,0,3},{5,0,3}};
00027 
00028 #undef vidl_ppi_mac
00029 
00030 
00031 //=============================================================================
00032 
00033 //: Recursive template metaprogram to generate conditionals for checking the traits of each defined pixel type
00034 template <vidl_pixel_format pix_type>
00035 struct check_types
00036 {
00037   static inline
00038   void traits(vidl_pixel_format f, vidl_pixel_traits& t)
00039   {
00040     if (f == pix_type){
00041       t.name           = vidl_pixel_traits_of<pix_type>::name();
00042       t.type           = &typeid(typename vidl_pixel_traits_of<pix_type>::type);
00043       t.bits_per_pixel = vidl_pixel_traits_of<pix_type>::bits_per_pixel;
00044       t.num_channels   = vidl_pixel_traits_of<pix_type>::num_channels;
00045       t.color          = vidl_pixel_traits_of<pix_type>::color();
00046       t.arrangement    = vidl_pixel_traits_of<pix_type>::arrangement();
00047       t.chroma_shift_x = vidl_pixel_traits_of<pix_type>::chroma_shift_x;
00048       t.chroma_shift_y = vidl_pixel_traits_of<pix_type>::chroma_shift_y;
00049     }
00050     else
00051       check_types<vidl_pixel_format(pix_type-1)>::traits(f,t);
00052   }
00053 
00054   static inline vidl_pixel_format from_string(const vcl_string& s)
00055   {
00056     if (s == vidl_pixel_traits_of<pix_type>::name())
00057       return pix_type;
00058     return check_types<vidl_pixel_format(pix_type-1)>::from_string(s);
00059   }
00060 
00061 };
00062 
00063 
00064 //: The base case: unknown pixel type
00065 VCL_DEFINE_SPECIALIZATION
00066 struct check_types<VIDL_PIXEL_FORMAT_UNKNOWN>
00067 {
00068   static inline
00069   void traits(vidl_pixel_format f, vidl_pixel_traits& t)
00070   {
00071     t.name           = vidl_pixel_traits_of<VIDL_PIXEL_FORMAT_UNKNOWN>::name();
00072     t.type           = &typeid(vidl_pixel_traits_of<VIDL_PIXEL_FORMAT_UNKNOWN>::type);
00073     t.bits_per_pixel = vidl_pixel_traits_of<VIDL_PIXEL_FORMAT_UNKNOWN>::bits_per_pixel;
00074     t.num_channels   = vidl_pixel_traits_of<VIDL_PIXEL_FORMAT_UNKNOWN>::num_channels;
00075     t.color          = vidl_pixel_traits_of<VIDL_PIXEL_FORMAT_UNKNOWN>::color();
00076     t.arrangement    = vidl_pixel_traits_of<VIDL_PIXEL_FORMAT_UNKNOWN>::arrangement();
00077     t.chroma_shift_x = vidl_pixel_traits_of<VIDL_PIXEL_FORMAT_UNKNOWN>::chroma_shift_x;
00078     t.chroma_shift_y = vidl_pixel_traits_of<VIDL_PIXEL_FORMAT_UNKNOWN>::chroma_shift_y;
00079   }
00080 
00081   static inline vidl_pixel_format from_string(const vcl_string& s)
00082   {
00083     return VIDL_PIXEL_FORMAT_UNKNOWN;
00084   }
00085 
00086 };
00087 
00088 
00089 //=============================================================================
00090 
00091 //: Return the number of channels needed in a color mode
00092 unsigned
00093     vidl_pixel_color_num_channels(vidl_pixel_color c)
00094 {
00095   switch(c){
00096     case VIDL_PIXEL_COLOR_MONO:
00097       return vidl_color_traits_of<VIDL_PIXEL_COLOR_MONO>::num_channels;
00098     case VIDL_PIXEL_COLOR_RGB:
00099       return vidl_color_traits_of<VIDL_PIXEL_COLOR_RGB>::num_channels;
00100     case VIDL_PIXEL_COLOR_YUV:
00101       return vidl_color_traits_of<VIDL_PIXEL_COLOR_YUV>::num_channels;
00102     case VIDL_PIXEL_COLOR_RGBA:
00103       return vidl_color_traits_of<VIDL_PIXEL_COLOR_RGBA>::num_channels;
00104     default:
00105       break;
00106   }
00107   return vidl_color_traits_of<VIDL_PIXEL_COLOR_UNKNOWN>::num_channels;
00108 }
00109 
00110 
00111 //: Return the set of traits for pixel format f
00112 vidl_pixel_traits
00113 vidl_pixel_format_traits(vidl_pixel_format f)
00114 {
00115   // Template metaprogramming automatically generates the conditions
00116   // to check each enum value from VIDL_PIXEL_FORMAT_UNKNOWN
00117   // to VIDL_PIXEL_FORMAT_ENUM_END-1
00118   vidl_pixel_traits t;
00119   check_types<vidl_pixel_format(VIDL_PIXEL_FORMAT_ENUM_END-1)>::traits(f,t);
00120   return t;
00121 }
00122 
00123 
00124 //: Output a pretty string representing the pixel format.
00125 vcl_ostream & operator << (vcl_ostream &os, vidl_pixel_format f)
00126 {
00127   // Template metaprogramming automatically generates the conditions
00128   // to check each enum value from VIDL_PIXEL_FORMAT_UNKNOWN
00129   // to VIDL_PIXEL_FORMAT_ENUM_END-1
00130   os << vidl_pixel_format_traits(f).name;
00131   return os;
00132 }
00133 
00134 
00135 //: Convert a string into a pixel format.
00136 // This uses the same encoding as operator<<.
00137 vidl_pixel_format vidl_pixel_format_from_string(const vcl_string& s)
00138 {
00139   // Template metaprogramming automatically generates the conditions
00140   // to check each enum value from VIDL_PIXEL_FORMAT_UNKNOWN
00141   // to VIDL_PIXEL_FORMAT_ENUM_END-1
00142   return check_types<vidl_pixel_format(VIDL_PIXEL_FORMAT_ENUM_END-1)>::from_string(s);
00143 }
00144 
00145 
00146 //: Compute the size (in bytes) of a \a ni x \a nj image buffer of pixel format \a f
00147 unsigned
00148 vidl_pixel_format_buffer_size(unsigned ni, unsigned nj, vidl_pixel_format f)
00149 {
00150   // FIXME This may be incorrect for some formats that require blocks
00151   // of macro pixels when the size of the image is not evenly divisible
00152   // by the size of the block.
00153   unsigned long bits = ((unsigned long)ni)*nj*vidl_pixel_format_bpp(f);
00154   return (bits + 7)/8;
00155 }