• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2013 Christian Henning
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 //
8 #include <boost/gil.hpp>
9 #include <boost/gil/extension/io/bmp.hpp>
10 
11 #include <boost/core/lightweight_test.hpp>
12 
13 #include "paths.hpp"
14 #include "scanline_read_test.hpp"
15 
16 #include <string>
17 
18 namespace gil = boost::gil;
19 namespace mp11 = boost::mp11;
20 
21 template <typename Image>
write(Image & img,std::string const & file_name)22 void write(Image& img, std::string const& file_name)
23 {
24     write_view(bmp_out + file_name, gil::view(img), gil::bmp_tag());
25 }
26 
test_read_header()27 void test_read_header()
28 {
29     using backend_t = gil::get_reader_backend<std::string const, gil::bmp_tag>::type;
30     backend_t backend = gil::read_image_info(bmp_filename, gil::bmp_tag());
31     BOOST_TEST_EQ(backend._info._offset               ,      54u);
32     BOOST_TEST_EQ(backend._info._header_size          ,      40u);
33     BOOST_TEST_EQ(backend._info._width                ,     1000);
34     BOOST_TEST_EQ(backend._info._height               ,      600);
35     BOOST_TEST_EQ(backend._info._bits_per_pixel       ,       24);
36     BOOST_TEST_EQ(backend._info._compression          ,       0u);
37     BOOST_TEST_EQ(backend._info._image_size           , 1800000u);
38     BOOST_TEST_EQ(backend._info._horizontal_resolution,        0);
39     BOOST_TEST_EQ(backend._info._vertical_resolution  ,        0);
40     BOOST_TEST_EQ(backend._info._num_colors           ,       0u);
41     BOOST_TEST_EQ(backend._info._num_important_colors ,       0u);
42     BOOST_TEST_EQ(backend._info._valid                ,     true);
43 }
44 
45 #ifdef BOOST_GIL_IO_USE_BMP_TEST_SUITE_IMAGES
test_read_reference_images_test()46 void test_read_reference_images_test()
47 {
48     // comments are taken from http://entropymine.com/jason/bmpsuite/reference/reference.html
49 
50     // g01bw.bmp - black and white palette (#000000,#FFFFFF)
51     {
52         gil::rgba8_image_t img;
53         gil::read_image(bmp_in + "g01bw.bmp", img, gil::bmp_tag());
54     }
55 
56     // g01wb.bmp - white and black palette (#FFFFFF,#000000).
57     // Should look the same as g01bw, not inverted.
58     {
59         gil::rgba8_image_t img;
60         gil::read_image(bmp_in + "g01wb.bmp", img, gil::bmp_tag());
61         BOOST_TEST_EQ(view(img).width(), 127u);
62         BOOST_TEST_EQ(view(img).height(), 64u);
63 
64         write(img, "g01wb.bmp");
65     }
66 
67     // g01bg.bmp - blue and green palette (#4040FF,#40FF40)
68     {
69         gil::rgba8_image_t img;
70         gil::read_image(bmp_in + "g01bg.bmp", img, gil::bmp_tag());
71         BOOST_TEST_EQ(view(img).width(), 127u);
72         BOOST_TEST_EQ(view(img).height(), 64u);
73 
74         write(img, "g01bg.bmp");
75     }
76 
77     // g01p1.bmp - 1-color (blue) palette (#4040FF)
78     {
79         gil::rgba8_image_t img;
80         gil::read_image(bmp_in + "g01p1.bmp", img, gil::bmp_tag());
81         BOOST_TEST_EQ(view(img).width(), 127u);
82         BOOST_TEST_EQ(view(img).height(), 64u);
83 
84         write(img, "g01p1.bmp");
85     }
86 
87     // g04.bmp - basic 4bpp (16 color) image
88     {
89         gil::rgba8_image_t img;
90         gil::read_image(bmp_in + "g04.bmp", img, gil::bmp_tag());
91         BOOST_TEST_EQ(view(img).width(), 127u);
92         BOOST_TEST_EQ(view(img).height(), 64u);
93         write(img, "g04.bmp");
94     }
95 
96     // g04rle.bmp - RLE compressed.
97     {
98         gil::rgb8_image_t img;
99         gil::read_image(bmp_in + "g04rle.bmp", img, gil::bmp_tag());
100         BOOST_TEST_EQ(view(img).width(), 127u);
101         BOOST_TEST_EQ(view(img).height(), 64u);
102 
103         write(img, "g04rle.bmp");
104     }
105 
106     // g04p4.bmp - 4-color grayscale palette
107     {
108         gil::rgba8_image_t img;
109         gil::read_image(bmp_in + "g04p4.bmp", img, gil::bmp_tag());
110         BOOST_TEST_EQ(view(img).width(), 127u);
111         BOOST_TEST_EQ(view(img).height(), 64u);
112 
113         write(img, "g04p4.bmp");
114     }
115 
116     // g08.bmp - basic 8bpp (256 color) image
117     {
118         gil::rgba8_image_t img;
119         gil::read_image(bmp_in + "g08.bmp", img, gil::bmp_tag());
120         BOOST_TEST_EQ(view(img).width(), 127u);
121         BOOST_TEST_EQ(view(img).height(), 64u);
122 
123         write(img, "g08.bmp");
124     }
125 
126     // g08p256.bmp - biClrUsed=256, biClrImportant=0 [=256]
127     {
128         gil::rgba8_image_t img;
129         gil::read_image(bmp_in + "g08p256.bmp", img, gil::bmp_tag());
130         BOOST_TEST_EQ(view(img).width(), 127u);
131         BOOST_TEST_EQ(view(img).height(), 64u);
132 
133         write(img, "g08p256.bmp");
134     }
135 
136     // g08pi256.bmp - biClrUsed=256, biClrImportant=256
137     {
138         gil::rgba8_image_t img;
139         gil::read_image(bmp_in + "g08pi256.bmp", img, gil::bmp_tag());
140         BOOST_TEST_EQ(view(img).width(), 127u);
141         BOOST_TEST_EQ(view(img).height(), 64u);
142 
143         write(img, "g08pi256.bmp");
144     }
145 
146     // g08pi64.bmp - biClrUsed=256, biClrImportant=64. It's barely possible that some
147     // sophisticated viewers may display this image in grayscale, if there are a
148     // limited number of colors available.
149     {
150         gil::rgba8_image_t img;
151         gil::read_image(bmp_in + "g08pi64.bmp", img, gil::bmp_tag());
152         BOOST_TEST_EQ(view(img).width(), 127u);
153         BOOST_TEST_EQ(view(img).height(), 64u);
154 
155         write(img, "g08pi64.bmp");
156     }
157 
158     // g08rle.bmp - RLE compressed.
159     {
160         gil::rgb8_image_t img;
161         gil::read_image(bmp_in + "g08rle.bmp", img, gil::bmp_tag());
162         BOOST_TEST_EQ(view(img).width(), 127u);
163         BOOST_TEST_EQ(view(img).height(), 64u);
164 
165         write(img, "g08rle.bmp");
166     }
167 
168     // g08os2.bmp - OS/2-style bitmap. This is an obsolete variety of BMP
169     // that is still encountered sometimes. It has 3-byte palette
170     // entries (instead of 4), and 16-bit width/height fields (instead of 32).
171     {
172         gil::rgb8_image_t img;
173         gil::read_image(bmp_in + "g08os2.bmp", img, gil::bmp_tag());
174         BOOST_TEST_EQ(view(img).width(), 127u);
175         BOOST_TEST_EQ(view(img).height(), 64u);
176 
177         write(img, "g08os2.bmp");
178     }
179 
180     // g08res22.bmp - resolution 7874x7874 pixels/meter (200x200 dpi)
181     {
182         gil::rgba8_image_t img;
183         gil::read_image(bmp_in + "g08res22.bmp", img, gil::bmp_tag());
184         BOOST_TEST_EQ(view(img).width(), 127u);
185         BOOST_TEST_EQ(view(img).height(), 64u);
186 
187         write(img, "g08res22.bmp");
188     }
189 
190     // g08res11.bmp - resolution 3937x3937 pixels/meter (100x100 dpi)
191     {
192         gil::rgba8_image_t img;
193         gil::read_image(bmp_in + "g08res11.bmp", img, gil::bmp_tag());
194         BOOST_TEST_EQ(view(img).width(), 127u);
195         BOOST_TEST_EQ(view(img).height(), 64u);
196 
197         write(img, "g08res11.bmp");
198     }
199 
200     // g08res21.bmp resolution 7874x3937 pixels/meter (200x100 dpi).
201     // Some programs (e.g. Imaging for Windows) may display this image
202     // stretched vertically, which is the optimal thing to do if the
203     // program is primarily a viewer, rather than an editor.
204     {
205         gil::rgba8_image_t img;
206         gil::read_image(bmp_in + "g08res21.bmp", img, gil::bmp_tag());
207         BOOST_TEST_EQ(view(img).width(), 127u);
208         BOOST_TEST_EQ(view(img).height(), 64u);
209 
210         write(img, "g08res21.bmp");
211     }
212 
213     // g08s0.bmp - bits size not given (set to 0). This is legal for uncompressed bitmaps.
214     {
215         gil::rgba8_image_t img;
216         gil::read_image(bmp_in + "g08s0.bmp", img, gil::bmp_tag());
217         BOOST_TEST_EQ(view(img).width(), 127u);
218         BOOST_TEST_EQ(view(img).height(), 64u);
219 
220         write(img, "g08s0.bmp");
221     }
222 
223     // g08offs.bmp - bfOffBits in header not set to the usual value.
224     // There are 100 extra unused bytes between palette and bits.
225     {
226         gil::rgba8_image_t img;
227         gil::read_image(bmp_in + "g08offs.bmp", img, gil::bmp_tag());
228         BOOST_TEST_EQ(view(img).width(), 127u);
229         BOOST_TEST_EQ(view(img).height(), 64u);
230 
231         write(img, "g08offs.bmp");
232     }
233 
234     // g08w126.bmp - size 126x63 (right and bottom slightly clipped)
235     {
236         gil::rgba8_image_t img;
237         gil::read_image(bmp_in + "g08w126.bmp", img, gil::bmp_tag());
238         BOOST_TEST_EQ(view(img).width(), 126u);
239         BOOST_TEST_EQ(view(img).height(), 63u);
240 
241         write(img, "g08w126.bmp");
242     }
243 
244     // g08w125.bmp - size 125x62
245     {
246         gil::rgba8_image_t img;
247         gil::read_image(bmp_in + "g08w125.bmp", img, gil::bmp_tag());
248         BOOST_TEST_EQ(view(img).width(), 125u);
249         BOOST_TEST_EQ(view(img).height(), 62u);
250 
251         write(img, "g08w125.bmp");
252     }
253 
254     // g08w124.bmp - size 124x61
255     {
256         gil::rgba8_image_t img;
257         gil::read_image(bmp_in + "g08w124.bmp", img, gil::bmp_tag());
258         BOOST_TEST_EQ(view(img).width(), 124u);
259         BOOST_TEST_EQ(view(img).height(), 61u);
260 
261         write(img, "g08w124.bmp");
262     }
263 
264     // g08p64.bmp - 64-color grayscale palette
265     {
266         gil::rgba8_image_t img;
267         gil::read_image(bmp_in + "g08p64.bmp", img, gil::bmp_tag());
268         BOOST_TEST_EQ(view(img).width(), 127u);
269         BOOST_TEST_EQ(view(img).height(), 64u);
270 
271         write(img, "g08p64.bmp");
272     }
273 
274     // g16def555.bmp - 15-bit color (1 bit wasted), biCompression=BI_RGB (no bitfields, defaults to 5-5-5)
275     {
276         gil::rgb8_image_t img;
277         gil::read_image(bmp_in + "g16def555.bmp", img, gil::bmp_tag());
278         BOOST_TEST_EQ(view(img).width(), 127u);
279         BOOST_TEST_EQ(view(img).height(), 64u);
280 
281         write(img, "g16def555.bmp");
282     }
283 
284     // g16bf555.bmp - 15-bit color, biCompression=BI_BITFIELDS (bitfields indicate 5-5-5)
285     {
286         gil::rgb8_image_t img;
287         gil::read_image(bmp_in + "g16bf555.bmp", img, gil::bmp_tag());
288         BOOST_TEST_EQ(view(img).width(), 127u);
289         BOOST_TEST_EQ(view(img).height(), 64u);
290 
291         write(img, "g16bf555.bmp");
292     }
293 
294     // g16bf565.bmp - 16-bit color, biCompression=BI_BITFIELDS (bitfields indicate 5-6-5)
295     {
296         gil::rgb8_image_t img;
297         gil::read_image(bmp_in + "g16bf565.bmp", img, gil::bmp_tag());
298         BOOST_TEST_EQ(view(img).width(), 127u);
299         BOOST_TEST_EQ(view(img).height(), 64u);
300 
301         write(img, "g16bf565.bmp");
302     }
303 
304     // g24.bmp - 24-bit color (BGR)
305     {
306         gil::rgb8_image_t img;
307         gil::read_image(bmp_in + "g24.bmp", img, gil::bmp_tag());
308         BOOST_TEST_EQ(view(img).width(), 127u);
309         BOOST_TEST_EQ(view(img).height(), 64u);
310 
311         write(img, "g24.bmp");
312     }
313 
314     // g32def.bmp - 24-bit color (8 bits wasted), biCompression=BI_RGB (no bitfields, defaults to BGRx)
315     {
316         gil::rgba8_image_t img;
317         gil::read_image(bmp_in + "g32def.bmp", img, gil::bmp_tag());
318         BOOST_TEST_EQ(view(img).width(), 127u);
319         BOOST_TEST_EQ(view(img).height(), 64u);
320 
321         write(img, "g32def.bmp");
322     }
323 
324     // g32bf.bmp - 24-bit color (8 bits wasted), biCompression=BI_BITFIELDS (bitfields indicate BGRx)
325     {
326         gil::rgba8_image_t img;
327         gil::read_image(bmp_in + "g32bf.bmp", img, gil::bmp_tag());
328         BOOST_TEST_EQ(view(img).width(), 127u);
329         BOOST_TEST_EQ(view(img).height(), 64u);
330 
331         write(img, "g32bf.bmp");
332     }
333 }
334 
test_read_reference_images_image_iterator()335 void test_read_reference_images_image_iterator()
336 {
337     // comments are taken from http://entropymine.com/jason/bmpsuite/reference/reference.html
338 
339     // g01bw.bmp - black and white palette (#000000,#FFFFFF)
340     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g01bw.bmp").c_str());
341 
342     // g01wb.bmp - white and black palette (#FFFFFF,#000000).
343     // Should look the same as g01bw, not inverted.
344     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g01wb.bmp").c_str());
345 
346     // g01bg.bmp - blue and green palette (#4040FF,#40FF40)
347     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g01bg.bmp").c_str());
348 
349     // g01p1.bmp - 1-color (blue) palette (#4040FF)
350     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g01p1.bmp").c_str());
351 
352     // g04.bmp - basic 4bpp (16 color) image
353     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g04.bmp").c_str());
354 
355     // not supported
356     // g04rle.bmp - RLE compressed.
357     //test_scanline_reader<gil::bgra8_image_t, gil::bmp_tag>(std::string(bmp_in + "g01bg.bmp").c_str());
358 
359     // g04p4.bmp - 4-color grayscale palette
360     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g04p4.bmp").c_str());
361 
362     // g08.bmp - basic 8bpp (256 color) image
363     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g08.bmp").c_str());
364 
365     // g08p256.bmp - biClrUsed=256, biClrImportant=0 [=256]
366     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g08p256.bmp").c_str());
367 
368     // g08pi256.bmp - biClrUsed=256, biClrImportant=256
369     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g08pi256.bmp").c_str());
370 
371     // g08pi64.bmp - biClrUsed=256, biClrImportant=64. It's barely possible that some
372     // sophisticated viewers may display this image in grayscale, if there are a
373     // limited number of colors available.
374     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g08pi64.bmp").c_str());
375 
376     // not supported
377     // g08rle.bmp - RLE compressed.
378 
379     // g08os2.bmp - OS/2-style bitmap. This is an obsolete variety of BMP
380     // that is still encountered sometimes. It has 3-byte palette
381     // entries (instead of 4), and 16-bit width/height fields (instead of 32).
382     test_scanline_reader<gil::rgb8_image_t, gil::bmp_tag>(std::string(bmp_in + "g08os2.bmp").c_str());
383 
384     // g08res22.bmp - resolution 7874x7874 pixels/meter (200x200 dpi)
385     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g08res22.bmp").c_str());
386 
387     // g08res11.bmp - resolution 3937x3937 pixels/meter (100x100 dpi)
388     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g08res11.bmp").c_str());
389 
390     // g08res21.bmp resolution 7874x3937 pixels/meter (200x100 dpi).
391     // Some programs (e.g. Imaging for Windows) may display this image
392     // stretched vertically, which is the optimal thing to do if the
393     // program is primarily a viewer, rather than an editor.
394     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g08res21.bmp").c_str());
395 
396     // g08s0.bmp - bits size not given (set to 0). This is legal for uncompressed bitmaps.
397     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g08s0.bmp").c_str());
398 
399     // g08offs.bmp - bfOffBits in header not set to the usual value.
400     // There are 100 extra unused bytes between palette and bits.
401     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g08offs.bmp").c_str());
402 
403     // g08w126.bmp - size 126x63 (right and bottom slightly clipped)
404     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g08w126.bmp").c_str());
405 
406     // g08w125.bmp - size 125x62
407     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g08w125.bmp").c_str());
408 
409     // g08w124.bmp - size 124x61
410     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g08w124.bmp").c_str());
411 
412     // g08p64.bmp - 64-color grayscale palette
413     test_scanline_reader<gil::rgba8_image_t, gil::bmp_tag>(std::string(bmp_in + "g08p64.bmp").c_str());
414 
415     // g16def555.bmp - 15-bit color (1 bit wasted), biCompression=BI_RGB (no bitfields, defaults to 5-5-5)
416     test_scanline_reader<gil::rgb8_image_t, gil::bmp_tag>(std::string(bmp_in + "g16def555.bmp").c_str());
417 
418     // g16bf555.bmp - 15-bit color, biCompression=BI_BITFIELDS (bitfields indicate 5-5-5)
419     test_scanline_reader<gil::rgb8_image_t, gil::bmp_tag>(std::string(bmp_in + "g16bf555.bmp").c_str());
420 
421     // g16bf565.bmp - 16-bit color, biCompression=BI_BITFIELDS (bitfields indicate 5-6-5)
422     test_scanline_reader<gil::rgb8_image_t, gil::bmp_tag>(std::string(bmp_in + "g16bf565.bmp").c_str());
423 
424     // g24.bmp - 24-bit color (BGR)
425     test_scanline_reader<gil::bgr8_image_t, gil::bmp_tag>(std::string(bmp_in + "g24.bmp").c_str());
426 
427     // g32def.bmp - 24-bit color (8 bits wasted), biCompression=BI_RGB (no bitfields, defaults to BGRx)
428     test_scanline_reader<gil::bgra8_image_t, gil::bmp_tag>(std::string(bmp_in + "g32def.bmp").c_str());
429 
430     // g32bf.bmp - 24-bit color (8 bits wasted), biCompression=BI_BITFIELDS (bitfields indicate BGRx)
431     test_scanline_reader<gil::bgra8_image_t, gil::bmp_tag>(std::string(bmp_in + "g32bf.bmp").c_str());
432 }
433 
test_partial_image()434 void test_partial_image()
435 {
436     std::string const filename(bmp_in + "g24.bmp");
437 
438     gil::rgb8_image_t img;
439     gil::read_image(filename, img, gil::image_read_settings<gil::bmp_tag>(
440         gil::point_t(0, 0), gil::point_t(50, 50)));
441 
442     write_view(bmp_out + "rgb_partial.bmp", gil::view(img), gil::bmp_tag());
443 }
444 #endif // BOOST_GIL_IO_USE_BMP_TEST_SUITE_IMAGES
445 
main(int argc,char * argv[])446 int main(int argc, char *argv[])
447 {
448     try
449     {
450         test_read_header();
451 
452 #ifdef BOOST_GIL_IO_USE_BMP_TEST_SUITE_IMAGES
453         test_read_reference_images_test();
454         test_read_reference_images_image_iterator();
455         test_partial_image();
456 #endif
457     }
458      catch (std::exception const& e)
459     {
460         BOOST_ERROR(e.what());
461     }
462     return boost::report_errors();
463 }
464