]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/gil/test/legacy/image.cpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / libs / gil / test / legacy / image.cpp
CommitLineData
7c673cae 1//
92f5a8d4
TL
2// Copyright 2005-2007 Adobe Systems Incorporated
3//
4// Distributed under the Boost Software License, Version 1.0
5// See accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt
7//
7c673cae 8#ifdef _MSC_VER
92f5a8d4 9#pragma warning(disable : 4244) // conversion from 'gil::image<V,Alloc>::coord_t' to 'int', possible loss of data (visual studio compiler doesn't realize that the two types are the same)
7c673cae 10#pragma warning(disable : 4503) // decorated name length exceeded, name was truncated
92f5a8d4 11#pragma warning(disable : 4701) // potentially uninitialized local variable 'result' used in boost/crc.hpp
7c673cae
FG
12#endif
13
92f5a8d4
TL
14#include <boost/gil.hpp>
15#include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
16
17#include <boost/core/ignore_unused.hpp>
18#include <boost/crc.hpp>
19#include <boost/mp11.hpp>
20
7c673cae
FG
21#include <ios>
22#include <iostream>
23#include <fstream>
24#include <map>
92f5a8d4
TL
25#include <stdexcept>
26#include <string>
27#include <type_traits>
28#include <vector>
7c673cae
FG
29
30using namespace boost::gil;
31using namespace std;
32using namespace boost;
33
34extern rgb8c_planar_view_t sample_view;
35void error_if(bool condition);
36
92f5a8d4
TL
37#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
38#pragma warning(push)
39#pragma warning(disable:4127) //conditional expression is constant
40#endif
7c673cae
FG
41
42// When BOOST_GIL_GENERATE_REFERENCE_DATA is defined, the reference data is generated and saved.
43// When it is undefined, regression tests are checked against it
44//#define BOOST_GIL_GENERATE_REFERENCE_DATA
45
46////////////////////////////////////////////////////
47///
48/// Some algorithms to use in testing
49///
50////////////////////////////////////////////////////
51
52template <typename GrayView, typename R>
92f5a8d4
TL
53void gray_image_hist(GrayView const& img_view, R& hist)
54{
55 for (auto it = img_view.begin(); it != img_view.end(); ++it)
7c673cae 56 ++hist[*it];
92f5a8d4
TL
57
58 // Alternatively, prefer the algorithm with lambda
59 // for_each_pixel(img_view, [&hist](gray8_pixel_t const& pixel) {
60 // ++hist[pixel];
61 // });
7c673cae
FG
62}
63
64template <typename V, typename R>
65void get_hist(const V& img_view, R& hist) {
66 gray_image_hist(color_converted_view<gray8_pixel_t>(img_view), hist);
67}
68
69// testing custom color conversion
70template <typename C1, typename C2>
71struct my_color_converter_impl : public default_color_converter_impl<C1,C2> {};
72template <typename C1>
73struct my_color_converter_impl<C1,gray_t> {
74 template <typename P1, typename P2>
75 void operator()(const P1& src, P2& dst) const {
76 default_color_converter_impl<C1,gray_t>()(src,dst);
77 get_color(dst,gray_color_t())=channel_invert(get_color(dst,gray_color_t()));
78 }
79};
80
81struct my_color_converter {
82 template <typename SrcP,typename DstP>
92f5a8d4
TL
83 void operator()(const SrcP& src,DstP& dst) const {
84 using src_cs_t = typename color_space_type<SrcP>::type;
85 using dst_cs_t = typename color_space_type<DstP>::type;
7c673cae
FG
86 my_color_converter_impl<src_cs_t,dst_cs_t>()(src,dst);
87 }
88};
89
92f5a8d4
TL
90/// Models a Unary Function
91/// \tparam P models PixelValueConcept
92template <typename P>
93struct mandelbrot_fn
94{
95 using point_t = boost::gil::point_t;
96 using const_t = mandelbrot_fn<P>;
97 using value_type = P;
98 using reference = value_type;
99 using const_reference = value_type;
100 using argument_type = point_t;
101 using result_type = reference;
102 static constexpr bool is_mutable = false;
7c673cae
FG
103
104 value_type _in_color,_out_color;
105 point_t _img_size;
106 static const int MAX_ITER=100; // max number of iterations
107
108 mandelbrot_fn() {}
109 mandelbrot_fn(const point_t& sz, const value_type& in_color, const value_type& out_color) : _in_color(in_color), _out_color(out_color), _img_size(sz) {}
110
111 result_type operator()(const point_t& p) const {
112 // normalize the coords to (-2..1, -1.5..1.5)
113 // (actually make y -1.0..2 so it is asymmetric, so we can verify some view factory methods)
92f5a8d4 114 double t=get_num_iter(point<double>(p.x/(double)_img_size.x*3-2, p.y/(double)_img_size.y*3-1.0f));//1.5f));
7c673cae
FG
115 t=pow(t,0.2);
116
117 value_type ret;
f67539c2 118 for (std::size_t k=0; k<num_channels<P>::value; ++k)
7c673cae
FG
119 ret[k]=(typename channel_type<value_type>::type)(_in_color[k]*t + _out_color[k]*(1-t));
120 return ret;
121 }
122
123private:
92f5a8d4
TL
124 double get_num_iter(const point<double>& p) const {
125 point<double> Z(0,0);
7c673cae 126 for (int i=0; i<MAX_ITER; ++i) {
92f5a8d4 127 Z = point<double>(Z.x*Z.x - Z.y*Z.y + p.x, 2*Z.x*Z.y + p.y);
7c673cae
FG
128 if (Z.x*Z.x + Z.y*Z.y > 4)
129 return i/(double)MAX_ITER;
130 }
131 return 0;
132 }
133};
134
135template <typename T>
136void x_gradient(const T& src, const gray8s_view_t& dst) {
137 for (int y=0; y<src.height(); ++y) {
138 typename T::x_iterator src_it = src.row_begin(y);
139 gray8s_view_t::x_iterator dst_it = dst.row_begin(y);
140
141 for (int x=1; x<src.width()-1; ++x)
142 dst_it[x] = (src_it[x+1] - src_it[x-1]) / 2;
143 }
144}
145
146// A quick test whether a view is homogeneous
147
148template <typename Pixel>
92f5a8d4 149struct pixel_is_homogeneous : public std::true_type {};
7c673cae
FG
150
151template <typename P, typename C, typename L>
92f5a8d4 152struct pixel_is_homogeneous<packed_pixel<P,C,L> > : public std::false_type {};
7c673cae
FG
153
154template <typename View>
155struct view_is_homogeneous : public pixel_is_homogeneous<typename View::value_type> {};
156
7c673cae
FG
157////////////////////////////////////////////////////
158///
159/// Tests image view transformations and algorithms
160///
161////////////////////////////////////////////////////
162class image_test {
163public:
164 virtual void initialize() {}
165 virtual void finalize() {}
166 virtual ~image_test() {}
167
168 void run();
169protected:
170 virtual void check_view_impl(const rgb8c_view_t& view, const string& name)=0;
171 template <typename View>
172 void check_view(const View& img_view, const string& name) {
173 rgb8_image_t rgb_img(img_view.dimensions());
174 copy_and_convert_pixels(img_view,view(rgb_img));
175 check_view_impl(const_view(rgb_img), name);
176 }
177private:
178 template <typename Img> void basic_test(const string& prefix);
179 template <typename View> void view_transformations_test(const View& img_view, const string& prefix);
92f5a8d4
TL
180 template <typename View> void homogeneous_view_transformations_test(const View& img_view, const string& prefix, std::true_type);
181 template <typename View> void homogeneous_view_transformations_test(const View& img_view, const string& prefix, std::false_type)
182 {
183 boost::ignore_unused(img_view);
184 boost::ignore_unused(prefix);
185 }
7c673cae
FG
186 template <typename View> void histogram_test(const View& img_view, const string& prefix);
187 void virtual_view_test();
188 void packed_image_test();
189 void dynamic_image_test();
190 template <typename Img> void image_all_test(const string& prefix);
191};
192
7c673cae
FG
193// testing image iterators, clone, fill, locators, color convert
194template <typename Img>
195void image_test::basic_test(const string& prefix) {
92f5a8d4 196 using View = typename Img::view_t;
7c673cae
FG
197
198 // make a 20x20 image
199 Img img(typename View::point_t(20,20));
200 const View& img_view=view(img);
201
202 // fill it with red
203 rgb8_pixel_t red8(255,0,0), green8(0,255,0), blue8(0,0,255), white8(255,255,255);
204 typename View::value_type red,green,blue,white;
205 color_convert(red8,red);
206 default_color_converter()(red8,red);
207 red=color_convert_deref_fn<rgb8_ref_t,typename Img::view_t::value_type>()(red8);
208
209 color_convert(green8,green);
210 color_convert(blue8,blue);
211 color_convert(white8,white);
212 fill(img_view.begin(),img_view.end(),red);
213
214 color_convert(red8,img_view[0]);
215
216 // pointer to first pixel of second row
217 typename View::reference rt=img_view.at(0,0)[img_view.width()];
218 typename View::x_iterator ptr=&rt;
219 typename View::reference rt2=*(img_view.at(0,0)+img_view.width());
220 typename View::x_iterator ptr2=&rt2;
221 error_if(ptr!=ptr2);
222 error_if(img_view.x_at(0,0)+10!=10+img_view.x_at(0,0));
223
224 // draw a blue line along the diagonal
225 typename View::xy_locator loc=img_view.xy_at(0,img_view.height()-1);
226 for (int y=0; y<img_view.height(); ++y) {
227 *loc=blue;
228 ++loc.x();
229 loc.y()--;
230 }
231
232 // draw a green dotted line along the main diagonal with step of 3
233 loc=img_view.xy_at(img_view.width()-1,img_view.height()-1);
234 while (loc.x()>=img_view.x_at(0,0)) {
235 *loc=green;
236 loc-=typename View::point_t(3,3);
237 }
238
239 // Clone and make every red pixel white
240 Img imgWhite(img);
241 for (typename View::iterator it=view(imgWhite).end(); (it-1)!=view(imgWhite).begin(); --it) {
242 if (*(it-1)==red)
243 *(it-1)=white;
244 }
245
246 check_view(img_view,prefix+"red_x");
247 check_view(view(imgWhite),prefix+"white_x");
248}
249
250template <typename View>
251void image_test::histogram_test(const View& img_view, const string& prefix) {
252// vector<int> histogram(255,0);
253// get_hist(cropped,histogram.begin());
254 unsigned char histogram[256];
255 fill(histogram,histogram+256,0);
256 get_hist(img_view,histogram);
257 gray8c_view_t hist_view=interleaved_view(256,1,(const gray8_pixel_t*)histogram,256);
258 check_view(hist_view,prefix+"histogram");
259}
260
7c673cae
FG
261template <typename View>
262void image_test::view_transformations_test(const View& img_view, const string& prefix) {
263 check_view(img_view,prefix+"original");
264
265 check_view(subimage_view(img_view, iround(img_view.dimensions()/4), iround(img_view.dimensions()/2)),prefix+"cropped");
266 check_view(color_converted_view<gray8_pixel_t>(img_view),prefix+"gray8");
267 check_view(color_converted_view<gray8_pixel_t>(img_view,my_color_converter()),prefix+"my_gray8");
268 check_view(transposed_view(img_view),prefix+"transpose");
269 check_view(rotated180_view(img_view),prefix+"rot180");
270 check_view(rotated90cw_view(img_view),prefix+"90cw");
271 check_view(rotated90ccw_view(img_view),prefix+"90ccw");
272 check_view(flipped_up_down_view(img_view),prefix+"flipped_ud");
273 check_view(flipped_left_right_view(img_view),prefix+"flipped_lr");
92f5a8d4 274 check_view(subsampled_view(img_view,typename View::point_t(2,1)),prefix+"subsampled");
7c673cae
FG
275 check_view(kth_channel_view<0>(img_view),prefix+"0th_k_channel");
276 homogeneous_view_transformations_test(img_view, prefix, view_is_homogeneous<View>());
277}
278
279template <typename View>
92f5a8d4 280void image_test::homogeneous_view_transformations_test(const View& img_view, const string& prefix, std::true_type) {
7c673cae
FG
281 check_view(nth_channel_view(img_view,0),prefix+"0th_n_channel");
282}
283
92f5a8d4
TL
284void image_test::virtual_view_test()
285{
286 using deref_t = mandelbrot_fn<rgb8_pixel_t>;
287 using point_t = deref_t::point_t;
288 using locator_t = virtual_2d_locator<deref_t, false>;
289 using my_virt_view_t = image_view<locator_t>;
7c673cae
FG
290
291 boost::function_requires<PixelLocatorConcept<locator_t> >();
292 gil_function_requires<StepIteratorConcept<locator_t::x_iterator> >();
293
294 point_t dims(200,200);
295 my_virt_view_t mandel(dims, locator_t(point_t(0,0), point_t(1,1), deref_t(dims, rgb8_pixel_t(255,0,255), rgb8_pixel_t(0,255,0))));
296
297 gray8s_image_t img(dims);
298 fill_pixels(view(img),0); // our x_gradient algorithm doesn't change the first & last column, so make sure they are 0
299 x_gradient(color_converted_view<gray8_pixel_t>(mandel), view(img));
300 check_view(color_converted_view<gray8_pixel_t>(const_view(img)), "mandelLuminosityGradient");
301
302 view_transformations_test(mandel,"virtual_");
303 histogram_test(mandel,"virtual_");
304}
305
306// Test alignment and packed images
92f5a8d4
TL
307void image_test::packed_image_test()
308{
309 using bgr131_image_t = bit_aligned_image3_type<1,3,1, bgr_layout_t>::type;
310 using bgr131_pixel_t = bgr131_image_t::value_type;
7c673cae
FG
311 bgr131_pixel_t fill_val(1,3,1);
312
313 bgr131_image_t bgr131_img(3,10);
314 fill_pixels(view(bgr131_img), fill_val);
315
316 bgr131_image_t bgr131a_img(3,10,1);
317 copy_pixels(const_view(bgr131_img), view(bgr131a_img));
318
319 bgr131_image_t bgr131b_img(3,10,4);
320 copy_pixels(const_view(bgr131_img), view(bgr131b_img));
321
322 error_if(bgr131_img!=bgr131a_img || bgr131a_img!=bgr131b_img);
323}
324
92f5a8d4
TL
325void image_test::dynamic_image_test()
326{
327 using any_image_t = any_image
328 <
20effc67
TL
329 gray8_image_t,
330 bgr8_image_t,
331 argb8_image_t,
332 rgb8_image_t,
333 rgb8_planar_image_t
92f5a8d4 334 >;
7c673cae
FG
335 rgb8_planar_image_t img(sample_view.dimensions());
336 copy_pixels(sample_view, view(img));
337 any_image_t any_img=any_image_t(img);
338
339 check_view(view(any_img), "dynamic_");
340 check_view(flipped_left_right_view(view(any_img)), "dynamic_fliplr");
341 check_view(flipped_up_down_view(view(any_img)), "dynamic_flipud");
92f5a8d4 342
7c673cae
FG
343 any_image_t::view_t subimageView=subimage_view(view(any_img),0,0,10,15);
344
345 check_view(subimageView, "dynamic_subimage");
346 check_view(subsampled_view(rotated180_view(view(any_img)), 2,1), "dynamic_subimage_subsampled180rot");
347}
348
349template <typename Img>
350void image_test::image_all_test(const string& prefix) {
351 basic_test<Img>(prefix+"basic_");
352
353 Img img;
354 img.recreate(sample_view.dimensions());
355 copy_and_convert_pixels(sample_view,view(img));
356
357 view_transformations_test(view(img), prefix+"views_");
358
359 histogram_test(const_view(img),prefix+"histogram_");
360}
361
362void image_test::run() {
363 initialize();
364
365 image_all_test<bgr8_image_t>("bgr8_");
366 image_all_test<rgb8_image_t>("rgb8_");
367 image_all_test<rgb8_planar_image_t>("planarrgb8_");
368 image_all_test<gray8_image_t>("gray8_");
369
f67539c2
TL
370// FIXME: https://github.com/boostorg/gil/issues/447
371// Disable bgc121_image_t drawing as work around for a mysterious bug
372// revealing itself when using MSVC 64-bit optimized build.
373#if !(defined(NDEBUG) && defined (_MSC_VER) && defined(_WIN64))
92f5a8d4
TL
374 using bgr121_ref_t = bit_aligned_pixel_reference
375 <
376 boost::uint8_t,
377 mp11::mp_list_c<int, 1, 2, 1>,
378 bgr_layout_t,
379 true
380 > const;
381 using bgr121_image_t = image<bgr121_ref_t, false>;
7c673cae 382 image_all_test<bgr121_image_t>("bgr121_");
f67539c2 383#endif
7c673cae
FG
384
385 // TODO: Remove?
92f5a8d4 386 view_transformations_test(subsampled_view(sample_view, point_t(1,2)), "subsampled_");
7c673cae
FG
387 view_transformations_test(color_converted_view<gray8_pixel_t>(sample_view),"color_converted_");
388
389 virtual_view_test();
390 packed_image_test();
391 dynamic_image_test();
392
393 finalize();
394}
395
7c673cae
FG
396////////////////////////////////////////////////////
397///
398/// Performs or generates image tests using checksums
399///
400////////////////////////////////////////////////////
401
92f5a8d4
TL
402class checksum_image_mgr : public image_test
403{
7c673cae 404protected:
92f5a8d4 405 using crc_map_t = map<string, boost::crc_32_type::value_type>;
7c673cae
FG
406 crc_map_t _crc_map;
407};
408
409////////////////////////////////////////////////////
410///
411/// Performs image tests by comparing image pixel checksums against a reference
412///
413////////////////////////////////////////////////////
414
415class checksum_image_test : public checksum_image_mgr {
416public:
417 checksum_image_test(const char* filename) : _filename(filename) {}
418private:
419 const char* _filename;
92f5a8d4
TL
420 void initialize() override;
421 void check_view_impl(const rgb8c_view_t& v, const string& name) override;
7c673cae
FG
422};
423
424// Load the checksums from the reference file and create the start image
425void checksum_image_test::initialize() {
7c673cae
FG
426 boost::crc_32_type::value_type crc_result;
427 fstream checksum_ref(_filename,ios::in);
428 while (true) {
92f5a8d4 429 string crc_name;
7c673cae
FG
430 checksum_ref >> crc_name >> std::hex >> crc_result;
431 if(checksum_ref.fail()) break;
92f5a8d4
TL
432 if (!crc_name.empty() && crc_name[0] == '#')
433 {
434 crc_result = 0; // skip test case
435 crc_name = crc_name.substr(1);
436 }
7c673cae
FG
437 _crc_map[crc_name]=crc_result;
438 }
439 checksum_ref.close();
440}
441
442// Create a checksum for the given view and compare it with the reference checksum. Throw exception if different
443void checksum_image_test::check_view_impl(const rgb8c_view_t& img_view, const string& name) {
444 boost::crc_32_type checksum_acumulator;
445 checksum_acumulator.process_bytes(img_view.row_begin(0),img_view.size()*3);
92f5a8d4
TL
446 unsigned int const crc_expect = _crc_map[name];
447 if (crc_expect == 0)
448 {
449 cerr << "Skipping checksum check for " << name << " (crc=0)" << endl;
450 return;
451 }
7c673cae 452
92f5a8d4
TL
453 boost::crc_32_type::value_type const crc = checksum_acumulator.checksum();
454 if (crc==crc_expect) {
455 cerr << "Checking checksum for " << name << " (crc=" << std::hex << crc << ")" << endl;
456 }
457 else {
458 cerr << "Checksum error in " << name
459 << " (crc=" << std::hex << crc << " != " << std::hex << crc_expect << ")" << endl;
7c673cae
FG
460 error_if(true);
461 }
462}
463
464////////////////////////////////////////////////////
465///
466/// Generates a set of reference checksums to compare against
467///
468////////////////////////////////////////////////////
469
470class checksum_image_generate : public checksum_image_mgr {
471public:
472 checksum_image_generate(const char* filename) : _filename(filename) {}
473private:
474 const char* _filename;
92f5a8d4
TL
475 void check_view_impl(const rgb8c_view_t& img_view, const string& name) override;
476 void finalize() override;
7c673cae
FG
477};
478
479// Add the checksum of the given view to the map of checksums
480void checksum_image_generate::check_view_impl(const rgb8c_view_t& img_view, const string& name) {
481 boost::crc_32_type result;
482 result.process_bytes(img_view.row_begin(0),img_view.size()*3);
483 cerr << "Generating checksum for " << name << endl;
484 _crc_map[name] = result.checksum();
485}
486
487// Save the checksums into the reference file
488void checksum_image_generate::finalize() {
489 fstream checksum_ref(_filename,ios::out);
490 for (crc_map_t::const_iterator it=_crc_map.begin(); it!=_crc_map.end(); ++it) {
491 checksum_ref << it->first << " " << std::hex << it->second << "\r\n";
492 }
493 checksum_ref.close();
494}
495
7c673cae
FG
496////////////////////////////////////////////////////
497///
498/// Performs or generates image tests using image I/O
499///
500////////////////////////////////////////////////////
501
502extern const string in_dir;
503extern const string out_dir;
504extern const string ref_dir;
505
506const string in_dir=""; // directory of source images
507const string out_dir=in_dir+"image-out/"; // directory where to write output
508const string ref_dir=in_dir+"image-ref/"; // reference directory to compare written with actual output
509
7c673cae
FG
510void static_checks() {
511 gil_function_requires<ImageConcept<rgb8_image_t> >();
512
92f5a8d4
TL
513 static_assert(view_is_basic<rgb8_step_view_t>::value, "");
514 static_assert(view_is_basic<cmyk8c_planar_step_view_t>::value, "");
515 static_assert(view_is_basic<rgb8_planar_view_t>::value, "");
516
517 static_assert(view_is_step_in_x<rgb8_step_view_t>::value, "");
518 static_assert(view_is_step_in_x<cmyk8c_planar_step_view_t>::value, "");
519 static_assert(!view_is_step_in_x<rgb8_planar_view_t>::value, "");
520
521 static_assert(!is_planar<rgb8_step_view_t>::value, "");
522 static_assert(is_planar<cmyk8c_planar_step_view_t>::value, "");
523 static_assert(is_planar<rgb8_planar_view_t>::value, "");
524
525 static_assert(view_is_mutable<rgb8_step_view_t>::value, "");
526 static_assert(!view_is_mutable<cmyk8c_planar_step_view_t>::value, "");
527 static_assert(view_is_mutable<rgb8_planar_view_t>::value, "");
528
529 static_assert(std::is_same
530 <
531 derived_view_type<cmyk8c_planar_step_view_t>::type,
532 cmyk8c_planar_step_view_t
533 >::value, "");
534 static_assert(std::is_same
535 <
536 derived_view_type
537 <
538 cmyk8c_planar_step_view_t, std::uint16_t, rgb_layout_t
539 >::type,
540 rgb16c_planar_step_view_t
541 >::value, "");
542 static_assert(std::is_same
543 <
544 derived_view_type
545 <
546 cmyk8c_planar_step_view_t, use_default, rgb_layout_t, std::false_type, use_default, std::false_type
547 >::type,
548 rgb8c_step_view_t
549 >::value, "");
7c673cae
FG
550
551 // test view get raw data (mostly compile-time test)
552 {
553 rgb8_image_t rgb8(100,100);
554 unsigned char* data=interleaved_view_get_raw_data(view(rgb8));
555 const unsigned char* cdata=interleaved_view_get_raw_data(const_view(rgb8));
556 error_if(data!=cdata);
557 }
558
559 {
560 rgb16s_planar_image_t rgb8(100,100);
561 short* data=planar_view_get_raw_data(view(rgb8),1);
562 const short* cdata=planar_view_get_raw_data(const_view(rgb8),1);
563 error_if(data!=cdata);
564 }
565}
566
92f5a8d4
TL
567using image_test_t = checksum_image_test;
568using image_generate_t = checksum_image_generate;
7c673cae
FG
569
570#ifdef BOOST_GIL_GENERATE_REFERENCE_DATA
92f5a8d4 571using image_mgr_t = image_generate_t;
7c673cae 572#else
92f5a8d4 573using image_mgr_t = image_test_t;
7c673cae
FG
574#endif
575
7c673cae
FG
576void test_image(const char* ref_checksum) {
577 image_mgr_t mgr(ref_checksum);
578
92f5a8d4 579 cerr << "Reading checksums from " << ref_checksum << endl;
7c673cae
FG
580 mgr.run();
581 static_checks();
582}
583
92f5a8d4
TL
584int main(int argc, char* argv[])
585{
586 try
587 {
588 if (argc != 2)
589 throw std::runtime_error("No file with reference checksums specified");
7c673cae 590
92f5a8d4
TL
591 std::string local_name = argv[1];
592 std::ifstream file_is_there(local_name.c_str());
593 if (!file_is_there)
594 throw std::runtime_error("Unable to open gil_reference_checksums.txt");
595
596 test_image(local_name.c_str());
7c673cae 597
92f5a8d4
TL
598 return EXIT_SUCCESS;
599 }
600 catch (std::exception const& e)
601 {
602 std::cerr << e.what() << std::endl;
603 return EXIT_FAILURE;
604 }
605 catch (...)
606 {
607 return EXIT_FAILURE;
608 }
609}