read.hpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. //
  2. // Copyright 2012 Olivier Tournaire, Christian Henning
  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_RAW_DETAIL_READ_HPP
  9. #define BOOST_GIL_EXTENSION_IO_RAW_DETAIL_READ_HPP
  10. #include <boost/gil/extension/io/raw/tags.hpp>
  11. #include <boost/gil/extension/io/raw/detail/device.hpp>
  12. #include <boost/gil/extension/io/raw/detail/is_allowed.hpp>
  13. #include <boost/gil/extension/io/raw/detail/reader_backend.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/dynamic_io_new.hpp>
  19. #include <boost/gil/io/reader_base.hpp>
  20. #include <boost/gil/io/row_buffer_helper.hpp>
  21. #include <boost/gil/io/typedefs.hpp>
  22. #include <cstdio>
  23. #include <sstream>
  24. #include <vector>
  25. namespace boost { namespace gil {
  26. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  27. #pragma warning(push)
  28. #pragma warning(disable:4512) //assignment operator could not be generated
  29. #endif
  30. #define BUILD_INTERLEAVED_VIEW(color_layout, bits_per_pixel) \
  31. { \
  32. color_layout##bits_per_pixel##_view_t build = boost::gil::interleaved_view(processed_image->width, \
  33. processed_image->height, \
  34. (color_layout##bits_per_pixel##_pixel_t*)processed_image->data, \
  35. processed_image->colors*processed_image->width*processed_image->bits/8); \
  36. this->_cc_policy.read( build.begin(), build.end(), dst_view.begin() ); \
  37. } \
  38. template< typename Device
  39. , typename ConversionPolicy
  40. >
  41. class reader< Device
  42. , raw_tag
  43. , ConversionPolicy
  44. >
  45. : public reader_base< raw_tag
  46. , ConversionPolicy
  47. >
  48. , public reader_backend< Device
  49. , raw_tag
  50. >
  51. {
  52. private:
  53. using this_t = reader<Device, raw_tag, ConversionPolicy>;
  54. using cc_t = typename ConversionPolicy::color_converter_type;
  55. public:
  56. using backend_t = reader_backend<Device, raw_tag>;
  57. //
  58. // Constructor
  59. //
  60. reader( const Device& io_dev
  61. , const image_read_settings< raw_tag >& settings
  62. )
  63. : backend_t( io_dev
  64. , settings
  65. )
  66. {}
  67. //
  68. // Constructor
  69. //
  70. reader( const Device& io_dev
  71. , const cc_t& cc
  72. , const image_read_settings< raw_tag >& settings
  73. )
  74. : reader_base< raw_tag
  75. , ConversionPolicy
  76. >( cc )
  77. , backend_t( io_dev
  78. , settings
  79. )
  80. {}
  81. template< typename View >
  82. void apply( const View& dst_view )
  83. {
  84. if( this->_info._valid == false )
  85. {
  86. io_error( "Image header was not read." );
  87. }
  88. using is_read_and_convert_t = typename is_same
  89. <
  90. ConversionPolicy,
  91. detail::read_and_no_convert
  92. >::type;
  93. io_error_if( !detail::is_allowed< View >( this->_info
  94. , is_read_and_convert_t()
  95. )
  96. , "Image types aren't compatible."
  97. );
  98. // TODO: better error handling based on return code
  99. int return_code = this->_io_dev.unpack();
  100. io_error_if( return_code != LIBRAW_SUCCESS, "Unable to unpack image" );
  101. this->_info._unpack_function_name = this->_io_dev.get_unpack_function_name();
  102. return_code = this->_io_dev.dcraw_process();
  103. io_error_if( return_code != LIBRAW_SUCCESS, "Unable to emulate dcraw behavior to process image" );
  104. libraw_processed_image_t* processed_image = this->_io_dev.dcraw_make_mem_image(&return_code);
  105. io_error_if( return_code != LIBRAW_SUCCESS, "Unable to dcraw_make_mem_image" );
  106. if(processed_image->colors!=1 && processed_image->colors!=3)
  107. io_error( "Image is neither gray nor RGB" );
  108. if(processed_image->bits!=8 && processed_image->bits!=16)
  109. io_error( "Image is neither 8bit nor 16bit" );
  110. // TODO Olivier Tournaire
  111. // Here, we should use a metafunction to reduce code size and avoid a (compile time) macro
  112. if(processed_image->bits==8)
  113. {
  114. if(processed_image->colors==1){ BUILD_INTERLEAVED_VIEW(gray, 8); }
  115. else { BUILD_INTERLEAVED_VIEW(rgb, 8); }
  116. }
  117. else if(processed_image->bits==16)
  118. {
  119. if(processed_image->colors==1){ BUILD_INTERLEAVED_VIEW(gray, 16); }
  120. else { BUILD_INTERLEAVED_VIEW(rgb, 16); }
  121. }
  122. }
  123. };
  124. namespace detail {
  125. struct raw_read_is_supported
  126. {
  127. template< typename View >
  128. struct apply : public is_read_supported< typename get_pixel_type< View >::type
  129. , raw_tag
  130. >
  131. {};
  132. };
  133. struct raw_type_format_checker
  134. {
  135. raw_type_format_checker( const image_read_info< raw_tag >& info )
  136. : _info( info )
  137. {}
  138. template< typename Image >
  139. bool apply()
  140. {
  141. using view_t = typename Image::view_t;
  142. return is_allowed< view_t >( _info
  143. , mpl::true_()
  144. );
  145. }
  146. private:
  147. ///todo: do we need this here. Should be part of reader_backend
  148. const image_read_info< raw_tag >& _info;
  149. };
  150. } // namespace detail
  151. ///
  152. /// RAW Dynamic Reader
  153. ///
  154. template< typename Device >
  155. class dynamic_image_reader< Device
  156. , raw_tag
  157. >
  158. : public reader< Device
  159. , raw_tag
  160. , detail::read_and_no_convert
  161. >
  162. {
  163. using parent_t = reader<Device, raw_tag, detail::read_and_no_convert>;
  164. public:
  165. dynamic_image_reader( const Device& io_dev
  166. , const image_read_settings< raw_tag >& settings
  167. )
  168. : parent_t( io_dev
  169. , settings
  170. )
  171. {}
  172. template< typename Images >
  173. void apply( any_image< Images >& images )
  174. {
  175. detail::raw_type_format_checker format_checker( this->_info );
  176. if( !construct_matched( images
  177. , format_checker
  178. ))
  179. {
  180. std::ostringstream error_message;
  181. error_message << "No matching image type between those of the given any_image and that of the file.\n";
  182. error_message << "Image type must be {gray||rgb}{8||16} unsigned for RAW image files.";
  183. io_error( error_message.str().c_str() );
  184. }
  185. else
  186. {
  187. if( !this->_info._valid )
  188. this->read_header();
  189. this->init_image(images, this->_settings);
  190. detail::dynamic_io_fnobj< detail::raw_read_is_supported
  191. , parent_t
  192. > op( this );
  193. apply_operation( view( images )
  194. , op
  195. );
  196. }
  197. }
  198. };
  199. #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
  200. #pragma warning(pop)
  201. #endif
  202. } // gil
  203. } // boost
  204. #endif