1 // This is core/vidl/vidl_color.cxx
2 #include <iostream>
3 #include "vidl_color.h"
4 //:
5 // \file
6 // \author Matt Leotta
7 //
8 
9 #ifdef _MSC_VER
10 #  include "vcl_msvc_warnings.h"
11 #endif
12 
13 //: The total number of pixel datatypes
14 constexpr unsigned int num_types = 5;
15 
16 namespace
17 {
18 
19 //: Define the function pointer type for each pair of data types
20 template <class T1, class T2>
21 struct func_ptr
22 {
23   typedef void (*type)(const T1 * in, T2 * out);
24 };
25 
26 
27 // Assign an index to each of the pixel data types
28 template <class T>
29 struct type_index;
30 #define vidl_type_index_mac(T, NUM)                                                                                    \
31   template <>                                                                                                          \
32   struct type_index<T>                                                                                                 \
33   {                                                                                                                    \
34     enum                                                                                                               \
35     {                                                                                                                  \
36       index = (NUM)                                                                                                    \
37     };                                                                                                                 \
38   }
39 
40 vidl_type_index_mac(vxl_byte, 0);
41 vidl_type_index_mac(bool, 1);
42 vidl_type_index_mac(vxl_uint_16, 2);
43 vidl_type_index_mac(vxl_ieee_32, 3);
44 vidl_type_index_mac(vxl_ieee_64, 4);
45 
46 #undef vidl_type_index_mac
47 
48 //: Generates an entry into the table of color conversions functions
49 // This is called for every pair of color formats and function pointers
50 // that exist between all pairs of pixel formats
51 template <vidl_pixel_color in_color, vidl_pixel_color out_color, class fptr_T>
52 struct table_entry_init
53 {
54   static inline void
set_entry__anon00bcd3bc0111::table_entry_init55   set_entry(vidl_color_conv_fptr & table_entry)
56   {
57     if (!table_entry)
58     {
59       fptr_T fp = &vidl_color_converter<in_color, out_color>::convert;
60       table_entry = reinterpret_cast<vidl_color_conv_fptr>(fp);
61     }
62   }
63 };
64 
65 //: Recursive template metaprogram to generate table entries for each pair of pixel types
66 template <int Fmt_Code>
67 struct table_init
68 {
69   static inline void
populate__anon00bcd3bc0111::table_init70   populate(vidl_color_conv_fptr table[VIDL_PIXEL_COLOR_ENUM_END][VIDL_PIXEL_COLOR_ENUM_END][num_types][num_types])
71   {
72     const auto in_fmt = vidl_pixel_format(Fmt_Code / VIDL_PIXEL_FORMAT_ENUM_END);
73     const auto out_fmt = vidl_pixel_format(Fmt_Code % VIDL_PIXEL_FORMAT_ENUM_END);
74     auto in_color = static_cast<vidl_pixel_color>(vidl_pixel_traits_of<in_fmt>::color_idx);
75     auto out_color = static_cast<vidl_pixel_color>(vidl_pixel_traits_of<out_fmt>::color_idx);
76     typedef typename vidl_pixel_traits_of<in_fmt>::type in_type;
77     typedef typename vidl_pixel_traits_of<out_fmt>::type out_type;
78     unsigned in_type_num = type_index<in_type>::index;
79     unsigned out_type_num = type_index<out_type>::index;
80     typedef typename func_ptr<in_type, out_type>::type fptr;
81     table_entry_init<static_cast<vidl_pixel_color>(vidl_pixel_traits_of<in_fmt>::color_idx),
82                      static_cast<vidl_pixel_color>(vidl_pixel_traits_of<out_fmt>::color_idx),
83                      fptr>::set_entry(table[in_color][out_color][in_type_num][out_type_num]);
84     table_init<Fmt_Code - 1>::populate(table);
85   }
86 };
87 
88 
89 //: The base case
90 template <>
91 struct table_init<0>
92 {
93   static inline void
populate__anon00bcd3bc0111::table_init94   populate(vidl_color_conv_fptr table[VIDL_PIXEL_COLOR_ENUM_END][VIDL_PIXEL_COLOR_ENUM_END][num_types][num_types])
95   {
96     const auto in_fmt = vidl_pixel_format(0);
97     const auto out_fmt = vidl_pixel_format(0);
98     auto in_color = static_cast<vidl_pixel_color>(vidl_pixel_traits_of<in_fmt>::color_idx);
99     auto out_color = static_cast<vidl_pixel_color>(vidl_pixel_traits_of<out_fmt>::color_idx);
100     typedef vidl_pixel_traits_of<in_fmt>::type in_type;
101     typedef vidl_pixel_traits_of<out_fmt>::type out_type;
102     unsigned in_type_num = type_index<in_type>::index;
103     unsigned out_type_num = type_index<out_type>::index;
104     typedef func_ptr<in_type, out_type>::type fptr;
105     table_entry_init<static_cast<vidl_pixel_color>(vidl_pixel_traits_of<in_fmt>::color_idx),
106                      static_cast<vidl_pixel_color>(vidl_pixel_traits_of<out_fmt>::color_idx),
107                      fptr>::set_entry(table[in_color][out_color][in_type_num][out_type_num]);
108   }
109 };
110 
111 
112 //: Recursive template metaprogram to generate type table entries for each pixel data type
113 //  All pixel formats are scanned, some data types will be initialized multiple times
114 template <int Fmt>
115 struct type_table_init
116 {
117   static inline void
populate__anon00bcd3bc0111::type_table_init118   populate(const std::type_info * type_table[num_types])
119   {
120     typedef typename vidl_pixel_traits_of<static_cast<vidl_pixel_format>(Fmt)>::type dtype;
121     type_table[type_index<dtype>::index] = &typeid(dtype);
122     type_table_init<Fmt - 1>::populate(type_table);
123   }
124 };
125 
126 
127 //: The base case
128 template <>
129 struct type_table_init<0>
130 {
131   static inline void
populate__anon00bcd3bc0111::type_table_init132   populate(const std::type_info * type_table[num_types])
133   {
134     typedef vidl_pixel_traits_of<static_cast<vidl_pixel_format>(0)>::type dtype;
135     type_table[type_index<dtype>::index] = &typeid(dtype);
136   }
137 };
138 
139 
140 //: A table of all conversion functions
141 class converter
142 {
143 public:
144   //: Constructor - generate the table
converter()145   converter()
146   {
147     // generate the table of function pointers
148     table_init<VIDL_PIXEL_FORMAT_ENUM_END * VIDL_PIXEL_FORMAT_ENUM_END - 1>::populate(table);
149     type_table_init<VIDL_PIXEL_FORMAT_ENUM_END - 1>::populate(type_table);
150 #if 0
151     for (unsigned int i=0; i<num_types; ++i){
152       if (type_table[i])
153         std::cout << "type "<<i<<" is "<<type_table[i]->name() << std::endl;
154     }
155 #endif // 0
156   }
157 
158   //: Apply the conversion
159   vidl_color_conv_fptr
operator ()(vidl_pixel_color in_C,const std::type_info & in_type,vidl_pixel_color out_C,const std::type_info & out_type) const160   operator()(vidl_pixel_color in_C,
161              const std::type_info & in_type,
162              vidl_pixel_color out_C,
163              const std::type_info & out_type) const
164   {
165     unsigned int in_idx = type_index(in_type);
166     unsigned int out_idx = type_index(out_type);
167     return table[in_C][out_C][in_idx][out_idx];
168   }
169 
170   unsigned int
type_index(const std::type_info & t) const171   type_index(const std::type_info & t) const
172   {
173     for (unsigned int i = 0; i < num_types; ++i)
174     {
175       if (type_table[i] && t == *type_table[i])
176         return i;
177     }
178     std::cerr << "error: unregistered pixel data type - " << t.name() << std::endl;
179     return static_cast<unsigned int>(-1);
180   }
181 
182 private:
183   //: Table of color conversion functions
184   vidl_color_conv_fptr table[VIDL_PIXEL_COLOR_ENUM_END][VIDL_PIXEL_COLOR_ENUM_END][num_types][num_types];
185   const std::type_info * type_table[num_types];
186 };
187 
188 //: Instantiate a global conversion function table
189 converter conversion_table;
190 
191 } // namespace
192 
193 
194 //: Returns a color conversion function based on runtime values
195 // The function returned is always a vidl_color_conv_fptr which
196 // converts const vxl_byte* to vxl_byte*.  Some of these function
197 // may actually reinterpret the data as other types (i.e. bool* or
198 // vxl_uint_16*) via reinterpret_cast
199 vidl_color_conv_fptr
vidl_color_converter_func(vidl_pixel_color in_C,const std::type_info & in_type,vidl_pixel_color out_C,const std::type_info & out_type)200 vidl_color_converter_func(vidl_pixel_color in_C,
201                           const std::type_info & in_type,
202                           vidl_pixel_color out_C,
203                           const std::type_info & out_type)
204 {
205   return conversion_table(in_C, in_type, out_C, out_type);
206 }
207