read.hpp 23 KB

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