read.hpp 7.4 KB

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