read.hpp 27 KB

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