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