1 // This is core/vil/tests/test_convert.cxx
2 #define VXL_LEGACY_ERROR_REPORTING // REQUIRED FOR PASSING TESTS 2018-11-02
3 #include <iostream>
4 #include "vxl_config.h" // for vxl_byte
5 #ifdef _MSC_VER
6 # include "vcl_msvc_warnings.h"
7 #endif
8 #include "vul/vul_file.h"
9 #include "vil/vil_convert.h"
10 #include "vil/vil_image_view.h"
11 #include "vil/vil_print.h"
12 #include "vil/vil_load.h"
13 #include "vil/vil_math.h"
14 #include "vil/vil_exception.h"
15 #include "testlib/testlib_test.h"
16 #include "testlib/testlib_root_dir.h"
17 static void
test_convert1(const char * golden_data_dir)18 test_convert1(const char * golden_data_dir)
19 {
20 std::cout << "*******************************************\n"
21 << " Testing vil_convert*(vil_image_view<T>..)\n"
22 << "*******************************************\n";
23
24 std::string datadir = golden_data_dir;
25 if (*golden_data_dir)
26 datadir += "/";
27 vil_image_view<vxl_byte> image1 =
28 vil_convert_to_grey_using_rgb_weighting(vil_load((datadir + "ff_grey8bit_raw.pgm").c_str()));
29 TEST("vil_convert_to_grey_using_rgb_weighting(vil_load(grey_image))", image1 ? true : false, true);
30
31 vil_print_all(std::cout, image1);
32
33 vil_image_view<vxl_byte> image2 =
34 vil_convert_to_grey_using_average(vil_load((datadir + "ff_rgb8bit_ascii.ppm").c_str()));
35 TEST("vil_convert_to_grey_using_average(vil_load(rgb_image))", image2 ? true : false, true);
36
37 vil_print_all(std::cout, image2);
38 }
39
40 static void
test_convert_diff_types(const char * golden_data_dir)41 test_convert_diff_types(const char * golden_data_dir)
42 {
43 std::cout << "******************************************************\n"
44 << " Testing vil_convert_cast(T,vil_image_view_base_sptr)\n"
45 << "******************************************************\n";
46
47 std::string datadir = golden_data_dir;
48 if (*golden_data_dir)
49 datadir += "/";
50
51 vil_image_view<vxl_byte> image1 = vil_load((datadir + "ff_grey8bit_raw.pgm").c_str());
52 vil_image_view_base_sptr image_base1 = vil_load((datadir + "ff_grey8bit_raw.pgm").c_str());
53 vil_image_view_base_sptr image2 = vil_load((datadir + "ff_grey16bit_raw.pgm").c_str());
54 vil_image_view_base_sptr image3 = vil_load((datadir + "ff_rgb8bit_raw.ppm").c_str());
55 vil_image_view_base_sptr image4 = vil_load((datadir + "ff_rgb16bit_raw.ppm").c_str());
56 TEST("Loading images", image1 && image_base1, true);
57
58 vil_image_view<vxl_uint_16> image_16_1;
59 vil_convert_cast(image1, image_16_1);
60 TEST("Converting explicitly 8bit grey to 16bit grey", image_16_1(3, 0), vxl_uint_16(image1(3, 0)));
61
62 vil_print_all(std::cout, image1);
63 if (image_16_1)
64 vil_print_all(std::cout, image_16_1);
65 else
66 std::cout << "(no dump)\n";
67
68 vil_image_view<vxl_uint_16> image_16_2 = vil_convert_cast(vxl_uint_16(), image_base1);
69 TEST("Converting implicitly 8bit grey to 16bit grey", image_16_2(4, 2), vxl_uint_16(image1(4, 2)));
70
71 vil_print_all(std::cout, image_base1);
72 if (image_16_2)
73 vil_print_all(std::cout, image_16_2);
74 else
75 std::cout << "(no dump)\n";
76
77 vil_image_view<vxl_byte> image_8_2 = vil_convert_cast(vxl_byte(), image2);
78 vil_image_view<vxl_uint_16> image_2 = image2;
79 TEST("Converting implicitly 16bit grey to 8bit grey", image_8_2(4, 2), vxl_byte(image_2(4, 2)));
80
81 vil_print_all(std::cout, image2);
82 if (image_8_2)
83 vil_print_all(std::cout, image_8_2);
84 else
85 std::cout << "(no dump)\n";
86
87 vil_image_view<vxl_byte> image_3 = image3;
88 vil_image_view<vxl_byte> image_8_3;
89 vil_convert_planes_to_grey(image_3, image_8_3);
90 TEST(
91 "Converting explicitly 8bit RGB to 8bit grey", image_8_3(1, 0), image_3(1, 0, 1)); // accidentally a grey pixel ...
92
93 vil_print_all(std::cout, image3);
94 if (image_8_3)
95 vil_print_all(std::cout, image_8_3);
96 else
97 std::cout << "(no dump)\n";
98
99 vil_image_view<vxl_byte> image_8_4 = vil_convert_cast(vxl_byte(), image4);
100 vil_image_view<vxl_uint_16> image_4 = image4;
101 TEST("Converting implicitly 16bit RGB to 8bit grey", image_8_4(1, 0), vxl_byte(image_4(1, 0, 1)));
102
103 vil_print_all(std::cout, image4);
104 if (image_8_4)
105 vil_print_all(std::cout, image_8_4);
106 else
107 std::cout << "(no dump)\n";
108 }
109
110 static void
test_convert_stretch_range()111 test_convert_stretch_range()
112 {
113 std::cout << "testing vil_convert_stretch_range(src,dest):\n";
114 vil_image_view<float> f_image(10, 10);
115 for (unsigned j = 0; j < f_image.nj(); ++j)
116 for (unsigned i = 0; i < f_image.ni(); ++i)
117 f_image(i, j) = 0.1f * i + 0.01f * j + 5.f;
118
119 // vil_print_all(std::cout, f_image) ;
120
121 vil_image_view<vxl_byte> b_image;
122 vil_convert_stretch_range(f_image, b_image);
123 TEST("Width", b_image.ni(), f_image.ni());
124 TEST("Height", b_image.nj(), f_image.nj());
125 vxl_byte min_b, max_b;
126 vil_math_value_range(b_image, min_b, max_b);
127 TEST("Min. value", min_b, 0);
128 TEST("Max. value", max_b, 255);
129 TEST("b_image(5,5)", b_image(5, 5), vxl_byte((5.55 - 5.0) * 255 / 0.99));
130 }
131
132 static void
test_convert_stretch_range_limited()133 test_convert_stretch_range_limited()
134 {
135 std::cout << "testing test_convert_stretch_range_limited(src,dest):\n";
136 vil_image_view<float> f_image(10, 10);
137 for (unsigned j = 0; j < f_image.nj(); ++j)
138 for (unsigned i = 0; i < f_image.ni(); ++i)
139 f_image(i, j) = 0.1f * i + 0.01f * j + 5.f;
140 #if 0
141 float min_f, max_f;
142 vil_math_value_range(f_image, min_f, max_f );
143 std::cout << "Min f value: " << min_f << '\n'
144 << "Max f value: " << max_f << '\n';
145 vil_print_all(std::cout, f_image) ;
146 #endif // 0
147
148 float slo = 5.2f, shi = 5.8f;
149 vxl_byte dlo = 50, dhi = 200;
150 vil_image_view<vxl_byte> b_image;
151 vil_convert_stretch_range_limited(f_image, b_image, slo, shi, dlo, dhi);
152 TEST("Width", b_image.ni(), f_image.ni());
153 TEST("Height", b_image.nj(), f_image.nj());
154 vxl_byte min_b, max_b;
155 vil_math_value_range(b_image, min_b, max_b);
156 TEST("Min. value", min_b, dlo);
157 TEST("Max. value", max_b, dhi);
158 #ifdef DEBUG
159 vil_print_all(std::cout, b_image);
160 #endif // DEBUG
161
162 float f55 = f_image(5, 5);
163 auto b55 = vxl_byte(dlo + (f55 - slo) * (dhi - dlo) / (shi - slo) + 0.5);
164 #if 0
165 std::cout << "f55= " << f55 << '\n'
166 << "b55= " << (int)b55 << '\n'
167 << "b_image(5,5)" << (int)b_image(5,5) << '\n';
168 #endif // 0
169 TEST("b_image(5,5)", b_image(5, 5), b55);
170 }
171
172 static void
test_convert_to_n_planes()173 test_convert_to_n_planes()
174 {
175 constexpr unsigned n = 10;
176 std::cout << "testing test_convert_to_n_planes(src,dest):\n";
177 vil_image_view<float> f_image(n, n, 2);
178 vil_image_view<float> f_image_expected(n, n, 3);
179 vil_image_view<vxl_uint_16> u16_image_expected(n, n, 3);
180 for (unsigned j = 0; j < f_image.nj(); ++j)
181 for (unsigned i = 0; i < f_image.ni(); ++i)
182 {
183 f_image(i, j, 0) = 1.0f * i + 10.0f * j + 5.0f;
184 f_image(i, j, 1) = 1.0f * i + 10.0f * j;
185 f_image_expected(i, j, 0) = i + 10.0f * j + 5.0f;
186 f_image_expected(i, j, 1) = i + 10.0f * j;
187 f_image_expected(i, j, 2) = i + 10.0f * j + 5.0f;
188 u16_image_expected(i, j, 0) = static_cast<vxl_uint_16>(i + 10 * j + 5);
189 u16_image_expected(i, j, 1) = static_cast<vxl_uint_16>(i + 10 * j);
190 u16_image_expected(i, j, 2) = static_cast<vxl_uint_16>(i + 10 * j + 5);
191 }
192
193 #ifdef DEBUG
194 vil_print_all(std::cout, f_image);
195 #endif // DEBUG
196
197 vil_image_view_base_sptr f_image_ref = new vil_image_view<float>(f_image);
198
199 vil_image_view<float> f_image_dest = vil_convert_to_n_planes(3, f_image_ref);
200
201 TEST("Image as expected", vil_image_view_deep_equality(f_image_dest, f_image_expected), true);
202
203 vil_math_scale_and_offset_values(f_image, 1.0f, 0.499f);
204
205 vil_image_view_base_sptr f_image_dest_sptr(new vil_image_view<float>(f_image_dest));
206 vil_image_view<vxl_uint_16> image_16_3 = vil_convert_round(vxl_uint_16(), f_image_dest_sptr);
207 TEST("implicit vil_convert_round float to 16bit with rounding",
208 vil_image_view_deep_equality(image_16_3, u16_image_expected),
209 true);
210
211 vil_image_view<vxl_uint_16> image_16_3_stretched = vil_convert_stretch_range(vxl_uint_16(), f_image_ref);
212 vxl_uint_16 minp, maxp;
213 vil_math_value_range(image_16_3_stretched, minp, maxp);
214 TEST("implicit vil_convert_stretch_range float to 16bit with rounding", minp == 0 && maxp == 65535, true);
215
216 #if !defined VXL_LEGACY_ERROR_REPORTING
217 bool caught_exception = false;
218 try
219 {
220 vil_image_view<vil_rgb<float>>(f_image_dest_sptr) ? true : false;
221 }
222 catch (const vil_exception_pixel_formats_incompatible & e)
223 {
224 caught_exception = true;
225 std::cout << "Exception: " << e.what() << std::endl;
226 }
227 TEST("Plane image cannot be directly converted to components", caught_exception, true);
228 caught_exception = false;
229 vil_image_view<vil_rgb<float>> rgb_image;
230 try
231 {
232 rgb_image = vil_convert_to_component_order(f_image_dest_sptr);
233 }
234 catch (const vil_exception_pixel_formats_incompatible & e)
235 {
236 caught_exception = true;
237 std::cout << "Exception: " << e.what() << std::endl;
238 }
239 TEST("implict vil_convert_to_component_order API", caught_exception, false);
240 #else
241 TEST("Plane image cannot be directly converted to components",
242 vil_image_view<vil_rgb<float>>(f_image_dest_sptr) ? true : false,
243 false);
244 vil_image_view<vil_rgb<float>> rgb_image = vil_convert_to_component_order(f_image_dest_sptr);
245 TEST("implict vil_convert_to_component_order API", rgb_image ? true : false, true);
246 #endif
247
248 TEST("implict vil_convert_to_component_order correct",
249 vil_image_view_deep_equality(vil_image_view<float>(rgb_image), f_image_dest),
250 true);
251 #ifdef DEBUG
252 vil_print_all(std::cout, image_16_3_stretched);
253 vil_print_all(std::cout, image_16_3);
254 vil_print_all(std::cout, u16_image_expected);
255 #endif // DEBUG
256 }
257
258 static void
test_simple_pixel_conversions()259 test_simple_pixel_conversions()
260 {
261 {
262 vil_convert_round_pixel<float, int> op;
263 int out;
264 op(5.5f, out);
265 std::cout << out << std::endl;
266 TEST("round_pixel float->int", out, 6);
267 op(5.4f, out);
268 std::cout << out << std::endl;
269 TEST("round_pixel float->int", out, 5);
270 }
271 {
272 vil_convert_round_pixel<double, unsigned short> op;
273 unsigned short out;
274 op(5.5f, out);
275 std::cout << out << std::endl;
276 TEST("round_pixel double->ushort", out, 6);
277 op(5.4f, out);
278 std::cout << out << std::endl;
279 TEST("round_pixel double->ushort", out, 5);
280 }
281 }
282
283
284 static void
test_convert(int argc,char * argv[])285 test_convert(int argc, char * argv[])
286 {
287 std::string path;
288 if (argc > 1)
289 {
290 path = argv[1];
291 }
292 else
293 {
294 std::string root = testlib_root_dir();
295 path = root + "/core/vil/tests/file_read_data";
296 }
297 bool exists = vul_file::is_directory(path);
298 if (exists)
299 {
300 path += "/";
301 test_convert1(path.c_str());
302 test_convert_diff_types(path.c_str());
303 }
304 else
305 {
306 TEST("test data exists", false, true);
307 std::cout << "Failed path: " << path << '\n';
308 }
309 test_convert_to_n_planes();
310 // test data path is not passed into argv - JLM
311 // test_convert1(argc>1 ? argv[1] : "file_read_data");
312 test_convert_stretch_range();
313 test_convert_stretch_range_limited();
314 // test data path is not passed into argv - JLM
315 // test_convert_diff_types(argc>1 ? argv[1] : "file_read_data");
316 test_simple_pixel_conversions();
317 }
318
319 TESTMAIN_ARGS(test_convert);
320