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