read.hpp 27 KB

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