scanline_read.hpp 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  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_JPEG_DETAIL_SCANLINE_READ_HPP
  9. #define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_SCANLINE_READ_HPP
  10. #include <boost/gil/extension/io/jpeg/detail/base.hpp>
  11. #include <boost/gil/extension/io/jpeg/detail/is_allowed.hpp>
  12. #include <boost/gil/extension/io/jpeg/detail/reader_backend.hpp>
  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/scanline_read_iterator.hpp>
  18. #include <boost/gil/io/typedefs.hpp>
  19. #include <csetjmp>
  20. #include <vector>
  21. namespace boost { namespace gil {
  22. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  23. #pragma warning(push)
  24. #pragma warning(disable:4611) //interaction between '_setjmp' and C++ object destruction is non-portable
  25. #endif
  26. ///
  27. /// JPEG Scanline Reader
  28. ///
  29. template< typename Device >
  30. class scanline_reader< Device
  31. , jpeg_tag
  32. >
  33. : public reader_backend< Device
  34. , jpeg_tag
  35. >
  36. {
  37. public:
  38. using tag_t = jpeg_tag;
  39. using backend_t = reader_backend<Device, tag_t>;
  40. using this_t = scanline_reader<Device, tag_t>;
  41. using iterator_t = scanline_read_iterator<this_t>;
  42. public:
  43. scanline_reader( Device& device
  44. , const image_read_settings< jpeg_tag >& settings
  45. )
  46. : reader_backend< Device
  47. , jpeg_tag
  48. >( device
  49. , settings
  50. )
  51. {
  52. initialize();
  53. }
  54. void read( byte_t* dst
  55. , int
  56. )
  57. {
  58. // Fire exception in case of error.
  59. if( setjmp( this->_mark )) { this->raise_error(); }
  60. // read data
  61. read_scanline( dst );
  62. }
  63. /// Skip over a scanline.
  64. void skip( byte_t* dst, int )
  65. {
  66. // Fire exception in case of error.
  67. if( setjmp( this->_mark )) { this->raise_error(); }
  68. // read data
  69. read_scanline( dst );
  70. }
  71. iterator_t begin() { return iterator_t( *this ); }
  72. iterator_t end() { return iterator_t( *this, this->_info._height ); }
  73. private:
  74. void initialize()
  75. {
  76. this->get()->dct_method = this->_settings._dct_method;
  77. io_error_if( jpeg_start_decompress( this->get() ) == false
  78. , "Cannot start decompression." );
  79. switch( this->_info._color_space )
  80. {
  81. case JCS_GRAYSCALE:
  82. {
  83. this->_scanline_length = this->_info._width;
  84. break;
  85. }
  86. case JCS_RGB:
  87. //!\todo add Y'CbCr? We loose image quality when reading JCS_YCbCr as JCS_RGB
  88. case JCS_YCbCr:
  89. {
  90. this->_scanline_length = this->_info._width * num_channels< rgb8_view_t >::value;
  91. break;
  92. }
  93. case JCS_CMYK:
  94. //!\todo add Y'CbCrK? We loose image quality when reading JCS_YCCK as JCS_CMYK
  95. case JCS_YCCK:
  96. {
  97. this->get()->out_color_space = JCS_CMYK;
  98. this->_scanline_length = this->_info._width * num_channels< cmyk8_view_t >::value;
  99. break;
  100. }
  101. default: { io_error( "Unsupported jpeg color space." ); }
  102. }
  103. }
  104. void read_scanline( byte_t* dst )
  105. {
  106. JSAMPLE *row_adr = reinterpret_cast< JSAMPLE* >( dst );
  107. // Read data.
  108. io_error_if( jpeg_read_scanlines( this->get()
  109. , &row_adr
  110. , 1
  111. ) != 1
  112. , "jpeg_read_scanlines: fail to read JPEG file"
  113. );
  114. }
  115. };
  116. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  117. #pragma warning(pop)
  118. #endif
  119. } // namespace gil
  120. } // namespace boost
  121. #endif