bmp_read_test.cpp 17 KB

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