read.hpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. //
  2. // Copyright 2012 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. #ifndef BOOST_GIL_EXTENSION_IO_BMP_DETAIL_READ_HPP
  9. #define BOOST_GIL_EXTENSION_IO_BMP_DETAIL_READ_HPP
  10. #include <boost/gil/extension/io/bmp/detail/is_allowed.hpp>
  11. #include <boost/gil/extension/io/bmp/detail/reader_backend.hpp>
  12. #include <boost/gil/io/base.hpp>
  13. #include <boost/gil/io/bit_operations.hpp>
  14. #include <boost/gil/io/conversion_policies.hpp>
  15. #include <boost/gil/io/device.hpp>
  16. #include <boost/gil/io/dynamic_io_new.hpp>
  17. #include <boost/gil/io/reader_base.hpp>
  18. #include <boost/gil/io/row_buffer_helper.hpp>
  19. #include <boost/gil/io/typedefs.hpp>
  20. #include <boost/assert.hpp>
  21. #include <boost/type_traits/is_same.hpp>
  22. #include <type_traits>
  23. #include <vector>
  24. namespace boost { namespace gil {
  25. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  26. #pragma warning(push)
  27. #pragma warning(disable:4512) //assignment operator could not be generated
  28. #endif
  29. ///
  30. /// BMP Reader
  31. ///
  32. template< typename Device
  33. , typename ConversionPolicy
  34. >
  35. class reader< Device
  36. , bmp_tag
  37. , ConversionPolicy
  38. >
  39. : public reader_base< bmp_tag
  40. , ConversionPolicy
  41. >
  42. , public reader_backend< Device
  43. , bmp_tag
  44. >
  45. {
  46. private:
  47. using this_t = reader<Device, bmp_tag, ConversionPolicy>;
  48. using cc_t = typename ConversionPolicy::color_converter_type;
  49. public:
  50. using backend_t = reader_backend< Device, bmp_tag>;
  51. public:
  52. //
  53. // Constructor
  54. //
  55. reader( const Device& io_dev
  56. , const image_read_settings< bmp_tag >& settings
  57. )
  58. : backend_t( io_dev
  59. , settings
  60. )
  61. , _pitch( 0 )
  62. {}
  63. //
  64. // Constructor
  65. //
  66. reader( const Device& io_dev
  67. , const ConversionPolicy& cc
  68. , const image_read_settings< bmp_tag >& settings
  69. )
  70. : reader_base< bmp_tag
  71. , ConversionPolicy
  72. >( cc )
  73. , backend_t( io_dev
  74. , settings
  75. )
  76. , _pitch( 0 )
  77. {}
  78. /// Read image.
  79. template< typename View >
  80. void apply( const View& dst_view )
  81. {
  82. if( this->_info._valid == false )
  83. {
  84. io_error( "Image header was not read." );
  85. }
  86. using is_read_and_convert_t = typename is_same
  87. <
  88. ConversionPolicy,
  89. detail::read_and_no_convert
  90. >::type;
  91. io_error_if( !detail::is_allowed< View >( this->_info
  92. , is_read_and_convert_t()
  93. )
  94. , "Image types aren't compatible."
  95. );
  96. // the row pitch must be multiple 4 bytes
  97. if( this->_info._bits_per_pixel < 8 )
  98. {
  99. _pitch = static_cast<long>((( this->_info._width * this->_info._bits_per_pixel ) + 7 ) >> 3 );
  100. }
  101. else
  102. {
  103. _pitch = static_cast<long>( this->_info._width * (( this->_info._bits_per_pixel + 7 ) >> 3 ));
  104. }
  105. _pitch = (_pitch + 3) & ~3;
  106. switch( this->_info._bits_per_pixel )
  107. {
  108. case 1:
  109. {
  110. this->_scanline_length = ( this->_info._width * num_channels< rgba8_view_t >::value + 3 ) & ~3;
  111. read_palette_image
  112. <
  113. gray1_image_t::view_t,
  114. detail::mirror_bits<byte_vector_t, std::true_type>
  115. >(dst_view);
  116. break;
  117. }
  118. case 4:
  119. {
  120. switch ( this->_info._compression )
  121. {
  122. case bmp_compression::_rle4:
  123. {
  124. ///@todo How can we determine that?
  125. this->_scanline_length = 0;
  126. read_palette_image_rle( dst_view );
  127. break;
  128. }
  129. case bmp_compression::_rgb:
  130. {
  131. this->_scanline_length = ( this->_info._width * num_channels< rgba8_view_t >::value + 3 ) & ~3;
  132. read_palette_image
  133. <
  134. gray4_image_t::view_t,
  135. detail::swap_half_bytes<byte_vector_t, std::true_type>
  136. >(dst_view);
  137. break;
  138. }
  139. default:
  140. {
  141. io_error( "Unsupported compression mode in BMP file." );
  142. break;
  143. }
  144. }
  145. break;
  146. }
  147. case 8:
  148. {
  149. switch ( this->_info._compression )
  150. {
  151. case bmp_compression::_rle8:
  152. {
  153. ///@todo How can we determine that?
  154. this->_scanline_length = 0;
  155. read_palette_image_rle( dst_view );
  156. break;
  157. }
  158. case bmp_compression::_rgb:
  159. {
  160. this->_scanline_length = ( this->_info._width * num_channels< rgba8_view_t >::value + 3 ) & ~3;
  161. read_palette_image< gray8_image_t::view_t
  162. , detail::do_nothing< std::vector< gray8_pixel_t > >
  163. > ( dst_view );
  164. break;
  165. }
  166. default:
  167. {
  168. io_error( "Unsupported compression mode in BMP file." );
  169. break;
  170. }
  171. }
  172. break;
  173. }
  174. case 15: case 16:
  175. {
  176. this->_scanline_length = ( this->_info._width * num_channels< rgb8_view_t >::value + 3 ) & ~3;
  177. read_data_15( dst_view );
  178. break;
  179. }
  180. case 24:
  181. {
  182. this->_scanline_length = ( this->_info._width * num_channels< rgb8_view_t >::value + 3 ) & ~3;
  183. read_data< bgr8_view_t >( dst_view );
  184. break;
  185. }
  186. case 32:
  187. {
  188. this->_scanline_length = ( this->_info._width * num_channels< rgba8_view_t >::value + 3 ) & ~3;
  189. read_data< bgra8_view_t >( dst_view );
  190. break;
  191. }
  192. }
  193. }
  194. private:
  195. long get_offset( std::ptrdiff_t pos )
  196. {
  197. if( this->_info._height > 0 )
  198. {
  199. // the image is upside down
  200. return static_cast<long>( ( this->_info._offset
  201. + ( this->_info._height - 1 - pos ) * _pitch
  202. ));
  203. }
  204. else
  205. {
  206. return static_cast<long>( ( this->_info._offset
  207. + pos * _pitch
  208. ));
  209. }
  210. }
  211. template< typename View_Src
  212. , typename Byte_Manipulator
  213. , typename View_Dst
  214. >
  215. void read_palette_image( const View_Dst& view )
  216. {
  217. this->read_palette();
  218. using rh_t = detail::row_buffer_helper_view<View_Src>;
  219. using it_t = typename rh_t::iterator_t;
  220. rh_t rh( _pitch, true );
  221. // we have to swap bits
  222. Byte_Manipulator byte_manipulator;
  223. for( std::ptrdiff_t y = 0
  224. ; y < this->_settings._dim.y
  225. ; ++y
  226. )
  227. {
  228. this->_io_dev.seek( get_offset( y + this->_settings._top_left.y ));
  229. this->_io_dev.read( reinterpret_cast< byte_t* >( rh.data() )
  230. , _pitch
  231. );
  232. byte_manipulator( rh.buffer() );
  233. typename View_Dst::x_iterator dst_it = view.row_begin( y );
  234. it_t it = rh.begin() + this->_settings._top_left.x;
  235. it_t end = it + this->_settings._dim.x;
  236. for( ; it != end; ++it, ++dst_it )
  237. {
  238. unsigned char c = get_color( *it, gray_color_t() );
  239. *dst_it = this->_palette[ c ];
  240. }
  241. }
  242. }
  243. template< typename View >
  244. void read_data_15( const View& view )
  245. {
  246. byte_vector_t row( _pitch );
  247. // read the color masks
  248. if( this->_info._compression == bmp_compression::_bitfield )
  249. {
  250. this->_mask.red.mask = this->_io_dev.read_uint32();
  251. this->_mask.green.mask = this->_io_dev.read_uint32();
  252. this->_mask.blue.mask = this->_io_dev.read_uint32();
  253. this->_mask.red.width = detail::count_ones( this->_mask.red.mask );
  254. this->_mask.green.width = detail::count_ones( this->_mask.green.mask );
  255. this->_mask.blue.width = detail::count_ones( this->_mask.blue.mask );
  256. this->_mask.red.shift = detail::trailing_zeros( this->_mask.red.mask );
  257. this->_mask.green.shift = detail::trailing_zeros( this->_mask.green.mask );
  258. this->_mask.blue.shift = detail::trailing_zeros( this->_mask.blue.mask );
  259. }
  260. else if( this->_info._compression == bmp_compression::_rgb )
  261. {
  262. switch( this->_info._bits_per_pixel )
  263. {
  264. case 15:
  265. case 16:
  266. {
  267. this->_mask.red.mask = 0x007C00; this->_mask.red.width = 5; this->_mask.red.shift = 10;
  268. this->_mask.green.mask = 0x0003E0; this->_mask.green.width = 5; this->_mask.green.shift = 5;
  269. this->_mask.blue.mask = 0x00001F; this->_mask.blue.width = 5; this->_mask.blue.shift = 0;
  270. break;
  271. }
  272. case 24:
  273. case 32:
  274. {
  275. this->_mask.red.mask = 0xFF0000; this->_mask.red.width = 8; this->_mask.red.shift = 16;
  276. this->_mask.green.mask = 0x00FF00; this->_mask.green.width = 8; this->_mask.green.shift = 8;
  277. this->_mask.blue.mask = 0x0000FF; this->_mask.blue.width = 8; this->_mask.blue.shift = 0;
  278. break;
  279. }
  280. }
  281. }
  282. else
  283. {
  284. io_error( "bmp_reader::apply(): unsupported BMP compression" );
  285. }
  286. using image_t = rgb8_image_t;
  287. using it_t = typename image_t::view_t::x_iterator;
  288. for( std::ptrdiff_t y = 0
  289. ; y < this->_settings._dim.y
  290. ; ++y
  291. )
  292. {
  293. this->_io_dev.seek( get_offset( y + this->_settings._top_left.y ));
  294. this->_io_dev.read( &row.front()
  295. , row.size()
  296. );
  297. image_t img_row( this->_info._width, 1 );
  298. image_t::view_t v = gil::view( img_row );
  299. it_t it = v.row_begin( 0 );
  300. it_t beg = v.row_begin( 0 ) + this->_settings._top_left.x;
  301. it_t end = beg + this->_settings._dim.x;
  302. byte_t* src = &row.front();
  303. for( int32_t i = 0 ; i < this->_info._width; ++i, src += 2 )
  304. {
  305. int p = ( src[1] << 8 ) | src[0];
  306. int r = ((p & this->_mask.red.mask) >> this->_mask.red.shift) << (8 - this->_mask.red.width);
  307. int g = ((p & this->_mask.green.mask) >> this->_mask.green.shift) << (8 - this->_mask.green.width);
  308. int b = ((p & this->_mask.blue.mask) >> this->_mask.blue.shift) << (8 - this->_mask.blue.width);
  309. get_color( it[i], red_t() ) = static_cast< byte_t >( r );
  310. get_color( it[i], green_t() ) = static_cast< byte_t >( g );
  311. get_color( it[i], blue_t() ) = static_cast< byte_t >( b );
  312. }
  313. this->_cc_policy.read( beg
  314. , end
  315. , view.row_begin( y )
  316. );
  317. }
  318. }
  319. // 8-8-8 BGR
  320. // 8-8-8-8 BGRA
  321. template< typename View_Src
  322. , typename View_Dst
  323. >
  324. void read_data( const View_Dst& view )
  325. {
  326. byte_vector_t row( _pitch );
  327. View_Src v = interleaved_view( this->_info._width
  328. , 1
  329. , (typename View_Src::value_type*) &row.front()
  330. , this->_info._width * num_channels< View_Src >::value
  331. );
  332. typename View_Src::x_iterator beg = v.row_begin( 0 ) + this->_settings._top_left.x;
  333. typename View_Src::x_iterator end = beg + this->_settings._dim.x;
  334. for( std::ptrdiff_t y = 0
  335. ; y < this->_settings._dim.y
  336. ; ++y
  337. )
  338. {
  339. this->_io_dev.seek( get_offset( y + this->_settings._top_left.y ));
  340. this->_io_dev.read( &row.front()
  341. , row.size()
  342. );
  343. this->_cc_policy.read( beg
  344. , end
  345. , view.row_begin( y )
  346. );
  347. }
  348. }
  349. template< typename Buffer
  350. , typename View
  351. >
  352. void copy_row_if_needed( const Buffer& buf
  353. , const View& view
  354. , std::ptrdiff_t y
  355. )
  356. {
  357. if( y >= this->_settings._top_left.y
  358. && y < this->_settings._dim.y
  359. )
  360. {
  361. typename Buffer::const_iterator beg = buf.begin() + this->_settings._top_left.x;
  362. typename Buffer::const_iterator end = beg + this->_settings._dim.x;
  363. std::copy( beg
  364. , end
  365. , view.row_begin( y )
  366. );
  367. }
  368. }
  369. template< typename View_Dst >
  370. void read_palette_image_rle( const View_Dst& view )
  371. {
  372. BOOST_ASSERT(
  373. this->_info._compression == bmp_compression::_rle4 ||
  374. this->_info._compression == bmp_compression::_rle8);
  375. this->read_palette();
  376. // jump to start of rle4 data
  377. this->_io_dev.seek( this->_info._offset );
  378. // we need to know the stream position for padding purposes
  379. std::size_t stream_pos = this->_info._offset;
  380. using Buf_type = std::vector<rgba8_pixel_t>;
  381. Buf_type buf( this->_settings._dim.x );
  382. Buf_type::iterator dst_it = buf.begin();
  383. Buf_type::iterator dst_end = buf.end();
  384. // If height is positive, the bitmap is a bottom-up DIB.
  385. // If height is negative, the bitmap is a top-down DIB.
  386. // The origin of a bottom-up DIB is the bottom left corner of the bitmap image,
  387. // which is the first pixel of the first row of bitmap data.
  388. // The origin of a top-down DIB is also the bottom left corner of the bitmap image,
  389. // but in this case the bottom left corner is the first pixel of the last row of bitmap data.
  390. // - "Programming Windows", 5th Ed. by Charles Petzold explains Windows docs ambiguities.
  391. std::ptrdiff_t ybeg = 0;
  392. std::ptrdiff_t yend = this->_settings._dim.y;
  393. std::ptrdiff_t yinc = 1;
  394. if( this->_info._height > 0 )
  395. {
  396. ybeg = this->_settings._dim.y - 1;
  397. yend = -1;
  398. yinc = -1;
  399. }
  400. std::ptrdiff_t y = ybeg;
  401. bool finished = false;
  402. while ( !finished )
  403. {
  404. std::ptrdiff_t count = this->_io_dev.read_uint8();
  405. std::ptrdiff_t second = this->_io_dev.read_uint8();
  406. stream_pos += 2;
  407. if ( count )
  408. {
  409. // encoded mode
  410. // clamp to boundary
  411. if( count > dst_end - dst_it )
  412. {
  413. count = dst_end - dst_it;
  414. }
  415. if( this->_info._compression == bmp_compression::_rle4 )
  416. {
  417. std::ptrdiff_t cs[2] = { second >> 4, second & 0x0f };
  418. for( int i = 0; i < count; ++i )
  419. {
  420. *dst_it++ = this->_palette[ cs[i & 1] ];
  421. }
  422. }
  423. else
  424. {
  425. for( int i = 0; i < count; ++i )
  426. {
  427. *dst_it++ = this->_palette[ second ];
  428. }
  429. }
  430. }
  431. else
  432. {
  433. switch( second )
  434. {
  435. case 0: // end of row
  436. {
  437. copy_row_if_needed( buf, view, y );
  438. y += yinc;
  439. if( y == yend )
  440. {
  441. finished = true;
  442. }
  443. else
  444. {
  445. dst_it = buf.begin();
  446. dst_end = buf.end();
  447. }
  448. break;
  449. }
  450. case 1: // end of bitmap
  451. {
  452. copy_row_if_needed( buf, view, y );
  453. finished = true;
  454. break;
  455. }
  456. case 2: // offset coordinates
  457. {
  458. std::ptrdiff_t dx = this->_io_dev.read_uint8();
  459. std::ptrdiff_t dy = this->_io_dev.read_uint8() * yinc;
  460. stream_pos += 2;
  461. if( dy )
  462. {
  463. copy_row_if_needed( buf, view, y );
  464. }
  465. std::ptrdiff_t x = dst_it - buf.begin();
  466. x += dx;
  467. if( x > this->_info._width )
  468. {
  469. io_error( "Mangled BMP file." );
  470. }
  471. y += dy;
  472. if( yinc > 0 ? y > yend : y < yend )
  473. {
  474. io_error( "Mangled BMP file." );
  475. }
  476. dst_it = buf.begin() + x;
  477. dst_end = buf.end();
  478. break;
  479. }
  480. default: // absolute mode
  481. {
  482. count = second;
  483. // clamp to boundary
  484. if( count > dst_end - dst_it )
  485. {
  486. count = dst_end - dst_it;
  487. }
  488. if ( this->_info._compression == bmp_compression::_rle4 )
  489. {
  490. for( int i = 0; i < count; ++i )
  491. {
  492. uint8_t packed_indices = this->_io_dev.read_uint8();
  493. ++stream_pos;
  494. *dst_it++ = this->_palette[ packed_indices >> 4 ];
  495. if( ++i == second )
  496. break;
  497. *dst_it++ = this->_palette[ packed_indices & 0x0f ];
  498. }
  499. }
  500. else
  501. {
  502. for( int i = 0; i < count; ++i )
  503. {
  504. uint8_t c = this->_io_dev.read_uint8();
  505. ++stream_pos;
  506. *dst_it++ = this->_palette[ c ];
  507. }
  508. }
  509. // pad to word boundary
  510. if( ( stream_pos - get_offset( 0 )) & 1 )
  511. {
  512. this->_io_dev.seek( 1, SEEK_CUR );
  513. ++stream_pos;
  514. }
  515. break;
  516. }
  517. }
  518. }
  519. }
  520. }
  521. private:
  522. std::size_t _pitch;
  523. };
  524. namespace detail {
  525. class bmp_type_format_checker
  526. {
  527. public:
  528. bmp_type_format_checker( const bmp_bits_per_pixel::type& bpp )
  529. : _bpp( bpp )
  530. {}
  531. template< typename Image >
  532. bool apply()
  533. {
  534. if( _bpp < 32 )
  535. {
  536. return pixels_are_compatible< typename Image::value_type, rgb8_pixel_t >::value
  537. ? true
  538. : false;
  539. }
  540. else
  541. {
  542. return pixels_are_compatible< typename Image::value_type, rgba8_pixel_t >::value
  543. ? true
  544. : false;
  545. }
  546. }
  547. private:
  548. // to avoid C4512
  549. bmp_type_format_checker& operator=( const bmp_type_format_checker& ) { return *this; }
  550. private:
  551. const bmp_bits_per_pixel::type _bpp;
  552. };
  553. struct bmp_read_is_supported
  554. {
  555. template< typename View >
  556. struct apply : public is_read_supported< typename get_pixel_type< View >::type
  557. , bmp_tag
  558. >
  559. {};
  560. };
  561. } // namespace detail
  562. ///
  563. /// BMP Dynamic Reader
  564. ///
  565. template< typename Device >
  566. class dynamic_image_reader< Device
  567. , bmp_tag
  568. >
  569. : public reader< Device
  570. , bmp_tag
  571. , detail::read_and_no_convert
  572. >
  573. {
  574. using parent_t = reader<Device, bmp_tag, detail::read_and_no_convert>;
  575. public:
  576. dynamic_image_reader( const Device& io_dev
  577. , const image_read_settings< bmp_tag >& settings
  578. )
  579. : parent_t( io_dev
  580. , settings
  581. )
  582. {}
  583. template< typename Images >
  584. void apply( any_image< Images >& images )
  585. {
  586. detail::bmp_type_format_checker format_checker( this->_info._bits_per_pixel );
  587. if( !construct_matched( images
  588. , format_checker
  589. ))
  590. {
  591. io_error( "No matching image type between those of the given any_image and that of the file" );
  592. }
  593. else
  594. {
  595. this->init_image( images
  596. , this->_settings
  597. );
  598. detail::dynamic_io_fnobj< detail::bmp_read_is_supported
  599. , parent_t
  600. > op( this );
  601. apply_operation( view( images )
  602. , op
  603. );
  604. }
  605. }
  606. };
  607. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  608. #pragma warning(pop)
  609. #endif
  610. } // gil
  611. } // boost
  612. #endif