scanline_read.hpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. //
  2. // Copyright 2007-2012 Christian Henning, Andreas Pokorny, 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_PNG_DETAIL_SCANLINE_READ_HPP
  9. #define BOOST_GIL_EXTENSION_IO_PNG_DETAIL_SCANLINE_READ_HPP
  10. #include <boost/gil/extension/io/png/detail/is_allowed.hpp>
  11. #include <boost/gil/extension/io/png/detail/reader_backend.hpp>
  12. #include <boost/gil.hpp> // FIXME: Include what you use!
  13. #include <boost/gil/io/base.hpp>
  14. #include <boost/gil/io/conversion_policies.hpp>
  15. #include <boost/gil/io/device.hpp>
  16. #include <boost/gil/io/reader_base.hpp>
  17. #include <boost/gil/io/row_buffer_helper.hpp>
  18. #include <boost/gil/io/scanline_read_iterator.hpp>
  19. #include <boost/gil/io/typedefs.hpp>
  20. namespace boost { namespace gil {
  21. ///
  22. /// PNG Reader
  23. ///
  24. template< typename Device >
  25. class scanline_reader< Device
  26. , png_tag
  27. >
  28. : public reader_backend< Device
  29. , png_tag
  30. >
  31. {
  32. public:
  33. using tag_t = png_tag;
  34. using backend_t = reader_backend<Device, tag_t>;
  35. using this_t = scanline_reader<Device, tag_t>;
  36. using iterator_t = scanline_read_iterator<this_t>;
  37. //
  38. // Constructor
  39. //
  40. scanline_reader( const Device& io_dev
  41. , const image_read_settings< png_tag >& settings
  42. )
  43. : reader_backend< Device
  44. , png_tag
  45. >( io_dev
  46. , settings
  47. )
  48. {
  49. initialize();
  50. }
  51. void read( byte_t* dst
  52. , int
  53. )
  54. {
  55. read_scanline( dst );
  56. }
  57. /// Skip over a scanline.
  58. void skip( byte_t* dst, int )
  59. {
  60. read_scanline( dst );
  61. }
  62. iterator_t begin() { return iterator_t( *this ); }
  63. iterator_t end() { return iterator_t( *this, this->_info._height ); }
  64. private:
  65. void initialize()
  66. {
  67. // Now it's time for some transformations.
  68. if( little_endian() )
  69. {
  70. if( this->_info._bit_depth == 16 )
  71. {
  72. // Swap bytes of 16 bit files to least significant byte first.
  73. png_set_swap( this->get()->_struct );
  74. }
  75. if( this->_info._bit_depth < 8 )
  76. {
  77. // swap bits of 1, 2, 4 bit packed pixel formats
  78. png_set_packswap( this->get()->_struct );
  79. }
  80. }
  81. if( this->_info._color_type == PNG_COLOR_TYPE_PALETTE )
  82. {
  83. png_set_palette_to_rgb( this->get()->_struct );
  84. }
  85. if( this->_info._num_trans > 0 )
  86. {
  87. png_set_tRNS_to_alpha( this->get()->_struct );
  88. }
  89. // Tell libpng to handle the gamma conversion for you. The final call
  90. // is a good guess for PC generated images, but it should be configurable
  91. // by the user at run time by the user. It is strongly suggested that
  92. // your application support gamma correction.
  93. if( this->_settings._apply_screen_gamma )
  94. {
  95. // png_set_gamma will change the image data!
  96. #ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
  97. png_set_gamma( this->get()->_struct
  98. , this->_settings._screen_gamma
  99. , this->_info._file_gamma
  100. );
  101. #else
  102. png_set_gamma( this->get()->_struct
  103. , this->_settings._screen_gamma
  104. , this->_info._file_gamma
  105. );
  106. #endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
  107. }
  108. // Interlaced images are not supported.
  109. this->_number_passes = png_set_interlace_handling( this->get()->_struct );
  110. io_error_if( this->_number_passes != 1
  111. , "scanline_read_iterator cannot read interlaced png images."
  112. );
  113. // The above transformation might have changed the bit_depth and color type.
  114. png_read_update_info( this->get()->_struct
  115. , this->get()->_info
  116. );
  117. this->_info._bit_depth = png_get_bit_depth( this->get()->_struct
  118. , this->get()->_info
  119. );
  120. this->_info._num_channels = png_get_channels( this->get()->_struct
  121. , this->get()->_info
  122. );
  123. this->_info._color_type = png_get_color_type( this->get()->_struct
  124. , this->get()->_info
  125. );
  126. this->_scanline_length = png_get_rowbytes( this->get()->_struct
  127. , this->get()->_info
  128. );
  129. }
  130. void read_scanline( byte_t* dst )
  131. {
  132. png_read_row( this->get()->_struct
  133. , dst
  134. , NULL
  135. );
  136. }
  137. };
  138. } // namespace gil
  139. } // namespace boost
  140. #endif