read.hpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802
  1. /*
  2. Copyright 2007-2012 Christian Henning, Lubomir Bourdev
  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_TIFF_DETAIL_READER_HPP
  9. #define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_READER_HPP
  10. ////////////////////////////////////////////////////////////////////////////////////////
  11. /// \file
  12. /// \brief
  13. /// \author Christian Henning, Lubomir Bourdev \n
  14. ///
  15. /// \date 2007-2012 \n
  16. ///
  17. ////////////////////////////////////////////////////////////////////////////////////////
  18. // taken from jpegxx - https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/ijg_headers.hpp
  19. #ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
  20. extern "C" {
  21. #endif
  22. #include <tiff.h>
  23. #include <tiffio.h>
  24. #ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
  25. }
  26. #endif
  27. #include <algorithm>
  28. #include <string>
  29. #include <vector>
  30. #include <boost/static_assert.hpp>
  31. #include <boost/gil/io/base.hpp>
  32. #include <boost/gil/io/conversion_policies.hpp>
  33. #include <boost/gil/io/bit_operations.hpp>
  34. #include <boost/gil/io/row_buffer_helper.hpp>
  35. #include <boost/gil/io/device.hpp>
  36. #include <boost/gil/io/reader_base.hpp>
  37. #include <boost/gil/extension/io/tiff/detail/reader_backend.hpp>
  38. #include <boost/gil/extension/io/tiff/detail/device.hpp>
  39. #include <boost/gil/extension/io/tiff/detail/is_allowed.hpp>
  40. namespace boost { namespace gil {
  41. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  42. #pragma warning(push)
  43. #pragma warning(disable:4512) //assignment operator could not be generated
  44. #endif
  45. template < int K >
  46. struct plane_recursion
  47. {
  48. template< typename View
  49. , typename Device
  50. , typename ConversionPolicy
  51. >
  52. static
  53. void read_plane( const View& dst_view
  54. , reader< Device
  55. , tiff_tag
  56. , ConversionPolicy >* p
  57. )
  58. {
  59. typedef typename kth_channel_view_type< K, View >::type plane_t;
  60. plane_t plane = kth_channel_view<K>( dst_view );
  61. p->template read_data< detail::row_buffer_helper_view< plane_t > >( plane, K );
  62. plane_recursion< K - 1 >::read_plane( dst_view, p );
  63. }
  64. };
  65. template <>
  66. struct plane_recursion< -1 >
  67. {
  68. template< typename View
  69. , typename Device
  70. , typename ConversionPolicy
  71. >
  72. static
  73. void read_plane( const View& /* dst_view */
  74. , reader< Device
  75. , tiff_tag
  76. , ConversionPolicy
  77. >* /* p */
  78. )
  79. {}
  80. };
  81. ///
  82. /// Tiff Reader
  83. ///
  84. template< typename Device
  85. , typename ConversionPolicy
  86. >
  87. class reader< Device
  88. , tiff_tag
  89. , ConversionPolicy
  90. >
  91. : public reader_base< tiff_tag
  92. , ConversionPolicy >
  93. , public reader_backend< Device
  94. , tiff_tag
  95. >
  96. {
  97. private:
  98. typedef reader< Device
  99. , tiff_tag
  100. , ConversionPolicy
  101. > this_t;
  102. typedef typename ConversionPolicy::color_converter_type cc_t;
  103. public:
  104. typedef reader_backend< Device, tiff_tag > backend_t;
  105. public:
  106. reader( const Device& io_dev
  107. , const image_read_settings< tiff_tag >& settings
  108. )
  109. : reader_base< tiff_tag
  110. , ConversionPolicy
  111. >()
  112. , backend_t( io_dev
  113. , settings
  114. )
  115. {}
  116. reader( const Device& io_dev
  117. , const typename ConversionPolicy::color_converter_type& cc
  118. , const image_read_settings< tiff_tag >& settings
  119. )
  120. : reader_base< tiff_tag
  121. , ConversionPolicy
  122. >( cc )
  123. , backend_t( io_dev
  124. , settings
  125. )
  126. {}
  127. // only works for homogeneous image types
  128. template< typename View >
  129. void apply( View& dst_view )
  130. {
  131. if( this->_info._photometric_interpretation == PHOTOMETRIC_PALETTE )
  132. {
  133. this->_scanline_length = this->_info._width
  134. * num_channels< rgb16_view_t >::value
  135. * sizeof( channel_type<rgb16_view_t>::type );
  136. // Steps:
  137. // 1. Read indices. It's an array of grayX_pixel_t.
  138. // 2. Read palette. It's an array of rgb16_pixel_t.
  139. // 3. ??? Create virtual image or transform the two arrays
  140. // into a rgb16_image_t object. The latter might
  141. // be a good first solution.
  142. switch( this->_info._bits_per_sample )
  143. {
  144. case 1: { read_palette_image< gray1_image_t >( dst_view ); break; }
  145. case 2: { read_palette_image< gray2_image_t >( dst_view ); break; }
  146. case 4: { read_palette_image< gray4_image_t >( dst_view ); break; }
  147. case 8: { read_palette_image< gray8_image_t >( dst_view ); break; }
  148. case 16: { read_palette_image< gray16_image_t >( dst_view ); break; }
  149. default: { io_error( "Not supported palette " ); }
  150. }
  151. return;
  152. }
  153. else
  154. {
  155. this->_scanline_length = this->_io_dev.get_scanline_size();
  156. // In case we only read the image the user's type and
  157. // the tiff type need to compatible. Which means:
  158. // color_spaces_are_compatible && channels_are_pairwise_compatible
  159. typedef typename is_same< ConversionPolicy
  160. , detail::read_and_no_convert
  161. >::type is_read_only;
  162. io_error_if( !detail::is_allowed< View >( this->_info
  163. , is_read_only()
  164. )
  165. , "Image types aren't compatible."
  166. );
  167. if( this->_info._planar_configuration == PLANARCONFIG_SEPARATE )
  168. {
  169. plane_recursion< num_channels< View >::value - 1 >::read_plane( dst_view
  170. , this
  171. );
  172. }
  173. else if( this->_info._planar_configuration == PLANARCONFIG_CONTIG )
  174. {
  175. read( dst_view
  176. , typename is_read_only::type()
  177. );
  178. }
  179. else
  180. {
  181. io_error( "Wrong planar configuration setting." );
  182. }
  183. }
  184. }
  185. private:
  186. template< typename View >
  187. void read( View v
  188. , mpl::true_ // is_read_only
  189. )
  190. {
  191. read_data< detail::row_buffer_helper_view< View > >( v, 0 );
  192. }
  193. template< typename View >
  194. void read( View v
  195. , mpl::false_ // is_read_only
  196. )
  197. {
  198. // the read_data function needs to know what gil type the source image is
  199. // to have the default color converter function correctly
  200. switch( this->_info._photometric_interpretation )
  201. {
  202. case PHOTOMETRIC_MINISWHITE:
  203. case PHOTOMETRIC_MINISBLACK:
  204. {
  205. switch( this->_info._bits_per_sample )
  206. {
  207. case 1: { read_data< detail::row_buffer_helper_view< gray1_image_t::view_t > >( v, 0 ); break; }
  208. case 2: { read_data< detail::row_buffer_helper_view< gray2_image_t::view_t > >( v, 0 ); break; }
  209. case 4: { read_data< detail::row_buffer_helper_view< gray4_image_t::view_t > >( v, 0 ); break; }
  210. case 8: { read_data< detail::row_buffer_helper_view< gray8_view_t > >( v, 0 ); break; }
  211. case 16: { read_data< detail::row_buffer_helper_view< gray16_view_t > >( v, 0 ); break; }
  212. case 32: { read_data< detail::row_buffer_helper_view< gray32_view_t > >( v, 0 ); break; }
  213. default: { io_error( "Image type is not supported." ); }
  214. }
  215. break;
  216. }
  217. case PHOTOMETRIC_RGB:
  218. {
  219. switch( this->_info._samples_per_pixel )
  220. {
  221. case 3:
  222. {
  223. switch( this->_info._bits_per_sample )
  224. {
  225. case 8: { read_data< detail::row_buffer_helper_view< rgb8_view_t > >( v, 0 ); break; }
  226. case 16: { read_data< detail::row_buffer_helper_view< rgb16_view_t > >( v, 0 ); break; }
  227. case 32: { read_data< detail::row_buffer_helper_view< rgb32_view_t > >( v, 0 ); break; }
  228. default: { io_error( "Image type is not supported." ); }
  229. }
  230. break;
  231. }
  232. case 4:
  233. {
  234. switch( this->_info._bits_per_sample )
  235. {
  236. case 8: { read_data< detail::row_buffer_helper_view< rgba8_view_t > >( v, 0 ); break; }
  237. case 16: { read_data< detail::row_buffer_helper_view< rgba16_view_t > >( v, 0 ); break; }
  238. case 32: { read_data< detail::row_buffer_helper_view< rgba32_view_t > >( v, 0 ); break; }
  239. default: { io_error( "Image type is not supported." ); }
  240. }
  241. break;
  242. }
  243. default: { io_error( "Image type is not supported." ); }
  244. }
  245. break;
  246. }
  247. case PHOTOMETRIC_SEPARATED: // CYMK
  248. {
  249. switch( this->_info._bits_per_sample )
  250. {
  251. case 8: { read_data< detail::row_buffer_helper_view< cmyk8_view_t > >( v, 0 ); break; }
  252. case 16: { read_data< detail::row_buffer_helper_view< cmyk16_view_t > >( v, 0 ); break; }
  253. case 32: { read_data< detail::row_buffer_helper_view< cmyk32_view_t > >( v, 0 ); break; }
  254. default: { io_error( "Image type is not supported." ); }
  255. }
  256. break;
  257. }
  258. default: { io_error( "Image type is not supported." ); }
  259. }
  260. }
  261. template< typename PaletteImage
  262. , typename View
  263. >
  264. void read_palette_image( const View& dst_view )
  265. {
  266. PaletteImage indices( this->_info._width - this->_settings._top_left.x
  267. , this->_info._height - this->_settings._top_left.y );
  268. // read the palette first
  269. read_data< detail::row_buffer_helper_view< typename PaletteImage::view_t > >( view( indices ), 0 );
  270. read_palette_image( dst_view
  271. , view( indices )
  272. , typename is_same< View, rgb16_view_t >::type() );
  273. }
  274. template< typename View
  275. , typename Indices_View
  276. >
  277. void read_palette_image( const View& dst_view
  278. , const Indices_View& indices_view
  279. , mpl::true_ // is View rgb16_view_t
  280. )
  281. {
  282. tiff_color_map::red_t red = NULL;
  283. tiff_color_map::green_t green = NULL;
  284. tiff_color_map::blue_t blue = NULL;
  285. this->_io_dev.get_field_defaulted( red, green, blue );
  286. typedef typename channel_traits<
  287. typename element_type<
  288. typename Indices_View::value_type >::type >::value_type channel_t;
  289. int num_colors = channel_traits< channel_t >::max_value();
  290. rgb16_planar_view_t palette = planar_rgb_view( num_colors
  291. , 1
  292. , red
  293. , green
  294. , blue
  295. , sizeof(uint16_t) * num_colors );
  296. for( typename rgb16_view_t::y_coord_t y = 0; y < dst_view.height(); ++y )
  297. {
  298. typename rgb16_view_t::x_iterator it = dst_view.row_begin( y );
  299. typename rgb16_view_t::x_iterator end = dst_view.row_end( y );
  300. typename Indices_View::x_iterator indices_it = indices_view.row_begin( y );
  301. for( ; it != end; ++it, ++indices_it )
  302. {
  303. uint16_t i = gil::at_c<0>( *indices_it );
  304. *it = palette[i];
  305. }
  306. }
  307. }
  308. template< typename View
  309. , typename Indices_View
  310. >
  311. inline
  312. void read_palette_image( const View& /* dst_view */
  313. , const Indices_View& /* indices_view */
  314. , mpl::false_ // is View rgb16_view_t
  315. )
  316. {
  317. io_error( "User supplied image type must be rgb16_image_t." );
  318. }
  319. template< typename Buffer >
  320. void skip_over_rows( Buffer& buffer
  321. , int plane
  322. )
  323. {
  324. if( this->_info._compression != COMPRESSION_NONE )
  325. {
  326. // Skipping over rows is not possible for compressed images( no random access ). See man
  327. // page ( diagnostics section ) for more information.
  328. for( std::ptrdiff_t row = 0; row < this->_settings._top_left.y; ++row )
  329. {
  330. this->_io_dev.read_scanline( buffer
  331. , row
  332. , static_cast< tsample_t >( plane ));
  333. }
  334. }
  335. }
  336. template< typename Buffer
  337. , typename View
  338. >
  339. void read_data( const View& dst_view
  340. , int /* plane */ )
  341. {
  342. if( this->_io_dev.is_tiled() )
  343. {
  344. read_tiled_data< Buffer >( dst_view, 0 );
  345. }
  346. else
  347. {
  348. read_stripped_data< Buffer >( dst_view, 0 );
  349. }
  350. }
  351. template< typename Buffer
  352. , typename View
  353. >
  354. void read_tiled_data( const View& dst_view
  355. , int plane
  356. )
  357. {
  358. if( dst_view.width() != this->_info._width
  359. || dst_view.height() != this->_info._height
  360. )
  361. {
  362. // read a subimage
  363. read_tiled_data_subimage< Buffer >( dst_view, plane );
  364. }
  365. else
  366. {
  367. // read full image
  368. read_tiled_data_full< Buffer >( dst_view, plane );
  369. }
  370. }
  371. template< typename Buffer
  372. , typename View
  373. >
  374. void read_tiled_data_subimage( const View& dst_view
  375. , int plane
  376. )
  377. {
  378. ///@todo: why is
  379. /// typedef Buffer row_buffer_helper_t;
  380. /// not working? I get compiler error with MSVC10.
  381. /// read_stripped_data IS working.
  382. typedef detail::row_buffer_helper_view< View > row_buffer_helper_t;
  383. typedef typename row_buffer_helper_t::iterator_t it_t;
  384. tiff_image_width::type image_width = this->_info._width;
  385. tiff_image_height::type image_height = this->_info._height;
  386. tiff_tile_width::type tile_width = this->_info._tile_width;
  387. tiff_tile_length::type tile_height = this->_info._tile_length;
  388. std::ptrdiff_t subimage_x = this->_settings._top_left.x;
  389. std::ptrdiff_t subimage_y = this->_settings._top_left.y;
  390. std::ptrdiff_t subimage_width = this->_settings._dim.x;
  391. std::ptrdiff_t subimage_height = this->_settings._dim.y;
  392. row_buffer_helper_t row_buffer_helper(this->_io_dev.get_tile_size(), true );
  393. for( unsigned int y = 0; y < image_height; y += tile_height )
  394. {
  395. for( unsigned int x = 0; x < image_width; x += tile_width )
  396. {
  397. uint32_t current_tile_width = ( x + tile_width < image_width ) ? tile_width : image_width - x;
  398. uint32_t current_tile_length = ( y + tile_height < image_height ) ? tile_height : image_height - y;
  399. this->_io_dev.read_tile( row_buffer_helper.buffer()
  400. , x
  401. , y
  402. , 0
  403. , static_cast< tsample_t >( plane )
  404. );
  405. // these are all whole image coordinates
  406. point_t tile_top_left ( x, y );
  407. point_t tile_lower_right( x + current_tile_width - 1, y + current_tile_length - 1 );
  408. point_t view_top_left ( subimage_x, subimage_y );
  409. point_t view_lower_right( subimage_x + subimage_width - 1
  410. , subimage_y + subimage_height - 1 );
  411. if( tile_top_left.x > view_lower_right.x
  412. || tile_top_left.y > view_lower_right.y
  413. || tile_lower_right.x < view_top_left.x
  414. || tile_lower_right.y < view_top_left.y
  415. )
  416. {
  417. // current tile and dst_view do not overlap
  418. continue;
  419. }
  420. else
  421. {
  422. // dst_view is overlapping the current tile
  423. // next is to define the portion in the tile that needs to be copied
  424. // get the whole image coordinates
  425. std::ptrdiff_t img_x0 = ( tile_top_left.x >= view_top_left.x ) ? tile_top_left.x : view_top_left.x;
  426. std::ptrdiff_t img_y0 = ( tile_top_left.y >= view_top_left.y ) ? tile_top_left.y : view_top_left.y;
  427. std::ptrdiff_t img_x1 = ( tile_lower_right.x <= view_lower_right.x ) ? tile_lower_right.x : view_lower_right.x;
  428. std::ptrdiff_t img_y1 = ( tile_lower_right.y <= view_lower_right.y ) ? tile_lower_right.y : view_lower_right.y;
  429. // convert to tile coordinates
  430. std::ptrdiff_t tile_x0 = img_x0 - x;
  431. std::ptrdiff_t tile_y0 = img_y0 - y;
  432. std::ptrdiff_t tile_x1 = img_x1 - x;
  433. std::ptrdiff_t tile_y1 = img_y1 - y;
  434. assert( tile_x0 >= 0 && tile_y0 >= 0 && tile_x1 >= 0 && tile_y1 >= 0 );
  435. assert( tile_x0 <= img_x1 && tile_y0 <= img_y1 );
  436. assert( tile_x0 < tile_width && tile_y0 < tile_height && tile_x1 < tile_width && tile_y1 < tile_height );
  437. std::ptrdiff_t tile_subimage_view_width = tile_x1 - tile_x0 + 1;
  438. std::ptrdiff_t tile_subimage_view_height = tile_y1 - tile_y0 + 1;
  439. // convert to dst_view coordinates
  440. std::ptrdiff_t dst_x0 = img_x0 - subimage_x;
  441. std::ptrdiff_t dst_y0 = img_y0 - subimage_y;
  442. assert( dst_x0 >= 0 && dst_y0 >= 0 );
  443. View dst_subimage_view = subimage_view( dst_view
  444. , (int) dst_x0
  445. , (int) dst_y0
  446. , (int) tile_subimage_view_width
  447. , (int) tile_subimage_view_height
  448. );
  449. // the row_buffer is a 1D array which represents a 2D image. We cannot
  450. // use interleaved_view here, since row_buffer could be bit_aligned.
  451. // Interleaved_view's fourth parameter "rowsize_in_bytes" doesn't work
  452. // for bit_aligned pixels.
  453. for( std::ptrdiff_t dst_row = 0; dst_row < dst_subimage_view.height(); ++dst_row )
  454. {
  455. std::ptrdiff_t tile_row = dst_row + tile_y0;
  456. // jump to the beginning of the current tile row
  457. it_t begin = row_buffer_helper.begin() + tile_row * tile_width;
  458. begin += tile_x0;
  459. it_t end = begin + dst_subimage_view.width();
  460. this->_cc_policy.read( begin
  461. , end
  462. , dst_subimage_view.row_begin( dst_row )
  463. );
  464. } //for
  465. }
  466. } // for
  467. } // for
  468. }
  469. template< typename Buffer
  470. , typename View
  471. >
  472. void read_tiled_data_full( const View& dst_view
  473. , int plane
  474. )
  475. {
  476. ///@todo: why is
  477. /// typedef Buffer row_buffer_helper_t;
  478. /// not working? I get compiler error with MSVC10.
  479. /// read_stripped_data IS working.
  480. typedef detail::row_buffer_helper_view< View > row_buffer_helper_t;
  481. typedef typename row_buffer_helper_t::iterator_t it_t;
  482. tiff_image_width::type image_width = this->_info._width;
  483. tiff_image_height::type image_height = this->_info._height;
  484. tiff_tile_width::type tile_width = this->_info._tile_width;
  485. tiff_tile_length::type tile_height = this->_info._tile_length;
  486. row_buffer_helper_t row_buffer_helper(this->_io_dev.get_tile_size(), true );
  487. for( unsigned int y = 0; y < image_height; y += tile_height )
  488. {
  489. for( unsigned int x = 0; x < image_width; x += tile_width )
  490. {
  491. uint32_t current_tile_width = ( x + tile_width < image_width ) ? tile_width : image_width - x;
  492. uint32_t current_tile_length = ( y + tile_height < image_height ) ? tile_height : image_height - y;
  493. this->_io_dev.read_tile( row_buffer_helper.buffer()
  494. , x
  495. , y
  496. , 0
  497. , static_cast< tsample_t >( plane )
  498. );
  499. View dst_subimage_view = subimage_view( dst_view
  500. , x
  501. , y
  502. , current_tile_width
  503. , current_tile_length
  504. );
  505. // the row_buffer is a 1D array which represents a 2D image. We cannot
  506. // use interleaved_view here, since row_buffer could be bit_aligned.
  507. // Interleaved_view's fourth parameter "rowsize_in_bytes" doesn't work
  508. // for bit_aligned pixels.
  509. for( int row = 0; row < dst_subimage_view.height(); ++row )
  510. {
  511. it_t begin = row_buffer_helper.begin() + row * tile_width;
  512. it_t end = begin + dst_subimage_view.width();
  513. this->_cc_policy.read( begin
  514. , end
  515. , dst_subimage_view.row_begin( row )
  516. );
  517. } //for
  518. } // for
  519. } // for
  520. }
  521. template< typename Buffer
  522. , typename View
  523. >
  524. void read_stripped_data( const View& dst_view
  525. , int plane )
  526. {
  527. typedef typename is_bit_aligned< typename View::value_type >::type is_view_bit_aligned_t;
  528. //typedef detail::row_buffer_helper_view< View > row_buffer_helper_t;
  529. typedef Buffer row_buffer_helper_t;
  530. typedef typename row_buffer_helper_t::iterator_t it_t;
  531. std::size_t size_to_allocate = buffer_size< typename View::value_type >( dst_view.width()
  532. , is_view_bit_aligned_t() );
  533. row_buffer_helper_t row_buffer_helper( size_to_allocate, true );
  534. it_t begin = row_buffer_helper.begin();
  535. it_t first = begin + this->_settings._top_left.x;
  536. it_t last = first + this->_settings._dim.x; // one after last element
  537. // I don't think tiff allows for random access of row, that's why we need
  538. // to read and discard rows when reading subimages.
  539. skip_over_rows( row_buffer_helper.buffer()
  540. , plane
  541. );
  542. std::ptrdiff_t row = this->_settings._top_left.y;
  543. std::ptrdiff_t row_end = row + this->_settings._dim.y;
  544. std::ptrdiff_t dst_row = 0;
  545. for(
  546. ; row < row_end
  547. ; ++row, ++dst_row
  548. )
  549. {
  550. this->_io_dev.read_scanline( row_buffer_helper.buffer()
  551. , row
  552. , static_cast< tsample_t >( plane )
  553. );
  554. this->_cc_policy.read( first
  555. , last
  556. , dst_view.row_begin( dst_row ));
  557. }
  558. }
  559. template< typename Pixel >
  560. std::size_t buffer_size( std::size_t width
  561. , mpl::false_ // is_bit_aligned
  562. )
  563. {
  564. std::size_t scanline_size_in_bytes = this->_io_dev.get_scanline_size();
  565. std::size_t element_size = sizeof( Pixel );
  566. std::size_t ret = std::max( width
  567. , (( scanline_size_in_bytes + element_size - 1 ) / element_size )
  568. );
  569. return ret;
  570. }
  571. template< typename Pixel >
  572. std::size_t buffer_size( std::size_t /* width */
  573. , mpl::true_ // is_bit_aligned
  574. )
  575. {
  576. return this->_io_dev.get_scanline_size();
  577. }
  578. private:
  579. template < int K > friend struct plane_recursion;
  580. };
  581. namespace detail {
  582. struct tiff_type_format_checker
  583. {
  584. tiff_type_format_checker( const image_read_info< tiff_tag >& info )
  585. : _info( info )
  586. {}
  587. template< typename Image >
  588. bool apply()
  589. {
  590. typedef typename Image::view_t view_t;
  591. return is_allowed< view_t >( _info
  592. , mpl::true_()
  593. );
  594. }
  595. private:
  596. tiff_type_format_checker& operator=( const tiff_type_format_checker& ) { return *this; }
  597. private:
  598. const image_read_info< tiff_tag > _info;
  599. };
  600. struct tiff_read_is_supported
  601. {
  602. template< typename View >
  603. struct apply : public is_read_supported< typename get_pixel_type< View >::type
  604. , tiff_tag
  605. >
  606. {};
  607. };
  608. } // namespace detail
  609. ///
  610. /// Tiff Dynamic Image Reader
  611. ///
  612. template< typename Device >
  613. class dynamic_image_reader< Device
  614. , tiff_tag
  615. >
  616. : public reader< Device
  617. , tiff_tag
  618. , detail::read_and_no_convert
  619. >
  620. {
  621. typedef reader< Device
  622. , tiff_tag
  623. , detail::read_and_no_convert
  624. > parent_t;
  625. public:
  626. dynamic_image_reader( const Device& io_dev
  627. , const image_read_settings< tiff_tag >& settings
  628. )
  629. : parent_t( io_dev
  630. , settings
  631. )
  632. {}
  633. template< typename Images >
  634. void apply( any_image< Images >& images )
  635. {
  636. detail::tiff_type_format_checker format_checker( this->_info );
  637. if( !construct_matched( images
  638. , format_checker
  639. ))
  640. {
  641. io_error( "No matching image type between those of the given any_image and that of the file" );
  642. }
  643. else
  644. {
  645. this->init_image( images
  646. , this->_settings
  647. );
  648. detail::dynamic_io_fnobj< detail::tiff_read_is_supported
  649. , parent_t
  650. > op( this );
  651. apply_operation( view( images )
  652. , op
  653. );
  654. }
  655. }
  656. };
  657. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  658. #pragma warning(pop)
  659. #endif
  660. } // namespace gil
  661. } // namespace boost
  662. #endif