core/vidl/vidl_color.cxx
Go to the documentation of this file.
00001 // This is core/vidl/vidl_color.cxx
00002 #include "vidl_color.h"
00003 //:
00004 // \file
00005 // \author Matt Leotta
00006 //
00007 
00008 #include <vcl_iostream.h>
00009 
00010 //: The total number of pixel datatypes
00011 const unsigned int num_types = 5;
00012 
00013 namespace {
00014 
00015 //: Define the function pointer type for each pair of data types
00016 template <class T1, class T2>
00017 struct func_ptr
00018 {
00019   typedef void (*type)(const T1* in, T2* out);
00020 };
00021 
00022 
00023 // Assign an index to each of the pixel data types
00024 template <class T>
00025 struct type_index;
00026 #define vidl_type_index_mac(T,NUM)\
00027 VCL_DEFINE_SPECIALIZATION \
00028 struct type_index<T> \
00029 {\
00030 enum { index = NUM };\
00031 }
00032 
00033 vidl_type_index_mac(vxl_byte, 0);
00034 vidl_type_index_mac(bool, 1);
00035 vidl_type_index_mac(vxl_uint_16, 2);
00036 vidl_type_index_mac(vxl_ieee_32, 3);
00037 vidl_type_index_mac(vxl_ieee_64, 4);
00038 
00039 #undef vidl_type_index_mac
00040 
00041 //: Generates an entry into the table of color conversions functions
00042 // This is called for every pair of color formats and function pointers
00043 // that exist between all pairs of pixel formats
00044 template <vidl_pixel_color in_color, vidl_pixel_color out_color, class fptr_T>
00045 struct table_entry_init
00046 {
00047   static inline void set_entry(vidl_color_conv_fptr& table_entry)
00048   {
00049     if (!table_entry) {
00050       fptr_T fp = &vidl_color_converter<in_color,out_color>::convert;
00051       table_entry = reinterpret_cast<vidl_color_conv_fptr>(fp);
00052     }
00053   }
00054 };
00055 
00056 //: Recursive template metaprogram to generate table entries for each pair of pixel types
00057 template <int Fmt_Code>
00058 struct table_init
00059 {
00060   static inline void populate(vidl_color_conv_fptr table[VIDL_PIXEL_COLOR_ENUM_END][VIDL_PIXEL_COLOR_ENUM_END]
00061                                                         [num_types][num_types])
00062   {
00063     const vidl_pixel_format in_fmt = vidl_pixel_format(Fmt_Code/VIDL_PIXEL_FORMAT_ENUM_END);
00064     const vidl_pixel_format out_fmt = vidl_pixel_format(Fmt_Code%VIDL_PIXEL_FORMAT_ENUM_END);
00065     vidl_pixel_color in_color = static_cast<vidl_pixel_color>(vidl_pixel_traits_of<in_fmt>::color_idx);
00066     vidl_pixel_color out_color = static_cast<vidl_pixel_color>(vidl_pixel_traits_of<out_fmt>::color_idx);
00067     typedef typename vidl_pixel_traits_of<in_fmt>::type in_type;
00068     typedef typename vidl_pixel_traits_of<out_fmt>::type out_type;
00069     unsigned in_type_num = type_index<in_type>::index;
00070     unsigned out_type_num = type_index<out_type>::index;
00071     typedef typename func_ptr<in_type,out_type>::type fptr;
00072     table_entry_init<static_cast<vidl_pixel_color>(vidl_pixel_traits_of<in_fmt>::color_idx),
00073                      static_cast<vidl_pixel_color>(vidl_pixel_traits_of<out_fmt>::color_idx),
00074                      fptr>::set_entry(table[in_color][out_color][in_type_num][out_type_num]);
00075     table_init<Fmt_Code-1>::populate(table);
00076   }
00077 };
00078 
00079 
00080 //: The base case
00081 VCL_DEFINE_SPECIALIZATION
00082 struct table_init<0>
00083 {
00084   static inline void populate(vidl_color_conv_fptr table[VIDL_PIXEL_COLOR_ENUM_END][VIDL_PIXEL_COLOR_ENUM_END]
00085                                                         [num_types][num_types])
00086   {
00087     const vidl_pixel_format in_fmt = vidl_pixel_format(0);
00088     const vidl_pixel_format out_fmt = vidl_pixel_format(0);
00089     vidl_pixel_color in_color = static_cast<vidl_pixel_color>(vidl_pixel_traits_of<in_fmt>::color_idx);
00090     vidl_pixel_color out_color = static_cast<vidl_pixel_color>(vidl_pixel_traits_of<out_fmt>::color_idx);
00091     typedef vidl_pixel_traits_of<in_fmt>::type in_type;
00092     typedef vidl_pixel_traits_of<out_fmt>::type out_type;
00093     unsigned in_type_num = type_index<in_type>::index;
00094     unsigned out_type_num = type_index<out_type>::index;
00095     typedef func_ptr<in_type,out_type>::type fptr;
00096     table_entry_init<static_cast<vidl_pixel_color>(vidl_pixel_traits_of<in_fmt>::color_idx),
00097     static_cast<vidl_pixel_color>(vidl_pixel_traits_of<out_fmt>::color_idx),
00098     fptr>::set_entry(table[in_color][out_color][in_type_num][out_type_num]);
00099   }
00100 };
00101 
00102 
00103 //: Recursive template metaprogram to generate type table entries for each pixel data type
00104 //  All pixel formats are scanned, some data types will be initialized multiple times
00105 template <int Fmt>
00106 struct type_table_init
00107 {
00108   static inline void populate(const vcl_type_info* type_table[num_types])
00109   {
00110     typedef typename vidl_pixel_traits_of<static_cast<vidl_pixel_format>(Fmt)>::type dtype;
00111     type_table[type_index<dtype>::index] = &typeid(dtype);
00112     type_table_init<Fmt-1>::populate(type_table);
00113   }
00114 };
00115 
00116 
00117 //: The base case
00118 VCL_DEFINE_SPECIALIZATION
00119 struct type_table_init<0>
00120 {
00121   static inline void populate(const vcl_type_info* type_table[num_types])
00122   {
00123     typedef vidl_pixel_traits_of<static_cast<vidl_pixel_format>(0)>::type dtype;
00124     type_table[type_index<dtype>::index] = &typeid(dtype);
00125   }
00126 };
00127 
00128 
00129 //: A table of all conversion functions
00130 class converter
00131 {
00132  public:
00133   //: Constructor - generate the table
00134   converter()
00135   {
00136     // generate the table of function pointers
00137     table_init<VIDL_PIXEL_FORMAT_ENUM_END*VIDL_PIXEL_FORMAT_ENUM_END-1>::populate(table);
00138     type_table_init<VIDL_PIXEL_FORMAT_ENUM_END-1>::populate(type_table);
00139 #if 0
00140     for (unsigned int i=0; i<num_types; ++i){
00141       if (type_table[i])
00142         vcl_cout << "type "<<i<<" is "<<type_table[i]->name() << vcl_endl;
00143     }
00144 #endif // 0
00145   }
00146 
00147   //: Apply the conversion
00148   vidl_color_conv_fptr operator()(vidl_pixel_color in_C, const vcl_type_info& in_type,
00149                                   vidl_pixel_color out_C, const vcl_type_info& out_type) const
00150   {
00151     unsigned int in_idx = type_index(in_type);
00152     unsigned int out_idx = type_index(out_type);
00153     return table[in_C][out_C][in_idx][out_idx];
00154   }
00155 
00156   unsigned int type_index(const vcl_type_info& t) const
00157   {
00158     for (unsigned int i=0; i<num_types; ++i)
00159     {
00160       if ( type_table[i] && t == *type_table[i] )
00161         return i;
00162     }
00163     vcl_cerr << "error: unregistered pixel data type - "<<t.name()<<vcl_endl;
00164     return static_cast<unsigned int>(-1);
00165   }
00166  private:
00167   //: Table of color conversion functions
00168   vidl_color_conv_fptr table[VIDL_PIXEL_COLOR_ENUM_END][VIDL_PIXEL_COLOR_ENUM_END][num_types][num_types];
00169   const vcl_type_info* type_table[num_types];
00170 };
00171 
00172 //: Instantiate a global conversion function table
00173 converter conversion_table;
00174 
00175 } // namespace
00176 
00177 
00178 //: Returns a color conversion function based on runtime values
00179 // The function returned is always a vidl_color_conv_fptr which
00180 // converts const vxl_byte* to vxl_byte*.  Some of these function
00181 // may actually reinterpret the data as other types (i.e. bool* or
00182 // vxl_uint_16*) via reinterpret_cast
00183 vidl_color_conv_fptr
00184 vidl_color_converter_func( vidl_pixel_color in_C, const vcl_type_info& in_type,
00185                            vidl_pixel_color out_C, const vcl_type_info& out_type)
00186 {
00187   return conversion_table(in_C, in_type, out_C, out_type);
00188 }