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