read.hpp 7.9 KB

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