png_io_private.hppGo to the documentation of this file.00001 /* 00002 Copyright 2005-2007 Adobe Systems Incorporated 00003 00004 Use, modification and distribution are subject to the Boost Software License, 00005 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at 00006 http://www.boost.org/LICENSE_1_0.txt). 00007 00008 See http://opensource.adobe.com/gil for most recent version including documentation. 00009 */ 00010 /*************************************************************************************************/ 00011 00012 #ifndef GIL_PNG_IO_PRIVATE_H 00013 #define GIL_PNG_IO_PRIVATE_H 00014 00020 00021 #include <algorithm> 00022 #include <vector> 00023 #include <boost/static_assert.hpp> 00024 #include "../../gil_all.hpp" 00025 #include "io_error.hpp" 00026 00027 namespace boost { namespace gil { 00028 00029 namespace detail { 00030 00031 static const size_t PNG_BYTES_TO_CHECK = 4; 00032 00033 // lbourdev: These can be greatly simplified, for example: 00034 template <typename Cs> struct png_color_type {BOOST_STATIC_CONSTANT(int,color_type=0);}; 00035 template<> struct png_color_type<gray_t> { BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); }; 00036 template<> struct png_color_type<rgb_t> { BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB); }; 00037 template<> struct png_color_type<rgba_t> { BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGBA); }; 00038 00039 template <typename Channel,typename ColorSpace> struct png_is_supported {BOOST_STATIC_CONSTANT(bool,value=false);}; 00040 template <> struct png_is_supported<bits8,gray_t> {BOOST_STATIC_CONSTANT(bool,value=true);}; 00041 template <> struct png_is_supported<bits8,rgb_t> {BOOST_STATIC_CONSTANT(bool,value=true);}; 00042 template <> struct png_is_supported<bits8,rgba_t> {BOOST_STATIC_CONSTANT(bool,value=true);}; 00043 template <> struct png_is_supported<bits16,gray_t> {BOOST_STATIC_CONSTANT(bool,value=true);}; 00044 template <> struct png_is_supported<bits16,rgb_t> {BOOST_STATIC_CONSTANT(bool,value=true);}; 00045 template <> struct png_is_supported<bits16,rgba_t> {BOOST_STATIC_CONSTANT(bool,value=true);}; 00046 00047 template <typename Channel> struct png_bit_depth {BOOST_STATIC_CONSTANT(int,bit_depth=sizeof(Channel)*8);}; 00048 00049 template <typename Channel,typename ColorSpace> 00050 struct png_read_support_private { 00051 BOOST_STATIC_CONSTANT(bool,is_supported=false); 00052 BOOST_STATIC_CONSTANT(int,bit_depth=0); 00053 BOOST_STATIC_CONSTANT(int,color_type=0); 00054 }; 00055 template <> 00056 struct png_read_support_private<bits8,gray_t> { 00057 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00058 BOOST_STATIC_CONSTANT(int,bit_depth=8); 00059 BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); 00060 }; 00061 template <> 00062 struct png_read_support_private<bits8,rgb_t> { 00063 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00064 BOOST_STATIC_CONSTANT(int,bit_depth=8); 00065 BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB); 00066 }; 00067 template <> 00068 struct png_read_support_private<bits8,rgba_t> { 00069 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00070 BOOST_STATIC_CONSTANT(int,bit_depth=8); 00071 BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGBA); 00072 }; 00073 template <> 00074 struct png_read_support_private<bits16,gray_t> { 00075 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00076 BOOST_STATIC_CONSTANT(int,bit_depth=16); 00077 BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); 00078 }; 00079 template <> 00080 struct png_read_support_private<bits16,rgb_t> { 00081 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00082 BOOST_STATIC_CONSTANT(int,bit_depth=16); 00083 BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB); 00084 }; 00085 template <> 00086 struct png_read_support_private<bits16,rgba_t> { 00087 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00088 BOOST_STATIC_CONSTANT(int,bit_depth=16); 00089 BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGBA); 00090 }; 00091 00092 template <typename Channel,typename ColorSpace> 00093 struct png_write_support_private { 00094 BOOST_STATIC_CONSTANT(bool,is_supported=false); 00095 BOOST_STATIC_CONSTANT(int,bit_depth=0); 00096 BOOST_STATIC_CONSTANT(int,color_type=0); 00097 }; 00098 template <> 00099 struct png_write_support_private<bits8,gray_t> { 00100 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00101 BOOST_STATIC_CONSTANT(int,bit_depth=8); 00102 BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); 00103 }; 00104 template <> 00105 struct png_write_support_private<bits8,rgb_t> { 00106 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00107 BOOST_STATIC_CONSTANT(int,bit_depth=8); 00108 BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB); 00109 }; 00110 template <> 00111 struct png_write_support_private<bits8,rgba_t> { 00112 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00113 BOOST_STATIC_CONSTANT(int,bit_depth=8); 00114 BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGBA); 00115 }; 00116 template <> 00117 struct png_write_support_private<bits16,gray_t> { 00118 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00119 BOOST_STATIC_CONSTANT(int,bit_depth=16); 00120 BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); 00121 }; 00122 template <> 00123 struct png_write_support_private<bits16,rgb_t> { 00124 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00125 BOOST_STATIC_CONSTANT(int,bit_depth=16); 00126 BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB); 00127 }; 00128 template <> 00129 struct png_write_support_private<bits16,rgba_t> { 00130 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00131 BOOST_STATIC_CONSTANT(int,bit_depth=16); 00132 BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGBA); 00133 }; 00134 00135 class png_reader : public file_mgr { 00136 protected: 00137 png_structp _png_ptr; 00138 png_infop _info_ptr; 00139 00140 void init() { 00141 char buf[PNG_BYTES_TO_CHECK]; 00142 // read in some of the signature bytes 00143 io_error_if(fread(buf, 1, PNG_BYTES_TO_CHECK, get()) != detail::PNG_BYTES_TO_CHECK, 00144 "png_check_validity: fail to read file"); 00145 // compare the first PNG_BYTES_TO_CHECK bytes of the signature. 00146 io_error_if(png_sig_cmp((png_bytep)buf, (png_size_t)0, detail::PNG_BYTES_TO_CHECK)!=0, 00147 "png_check_validity: invalid png file"); 00148 00149 _png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); 00150 io_error_if(_png_ptr==NULL,"png_get_file_size: fail to call png_create_write_struct()"); 00151 // allocate/initialize the image information data 00152 _info_ptr = png_create_info_struct(_png_ptr); 00153 if (_info_ptr == NULL) { 00154 png_destroy_read_struct(&_png_ptr,png_infopp_NULL,png_infopp_NULL); 00155 io_error("png_get_file_size: fail to call png_create_info_struct()"); 00156 } 00157 if (setjmp(png_jmpbuf(_png_ptr))) { 00158 //free all of the memory associated with the png_ptr and info_ptr 00159 png_destroy_read_struct(&_png_ptr, &_info_ptr, png_infopp_NULL); 00160 io_error("png_get_file_size: fail to call setjmp()"); 00161 } 00162 png_init_io(_png_ptr, get()); 00163 png_set_sig_bytes(_png_ptr,PNG_BYTES_TO_CHECK); 00164 png_read_info(_png_ptr, _info_ptr); 00165 if (little_endian() && png_get_bit_depth(_png_ptr,_info_ptr)>8) 00166 png_set_swap(_png_ptr); 00167 } 00168 public: 00169 png_reader(FILE* file ) : file_mgr(file) { init(); } 00170 png_reader(const char* filename) : file_mgr(filename, "rb") { init(); } 00171 00172 ~png_reader() { 00173 png_destroy_read_struct(&_png_ptr,&_info_ptr,png_infopp_NULL); 00174 } 00175 point2<std::ptrdiff_t> get_dimensions() { 00176 return point2<std::ptrdiff_t>(png_get_image_width(_png_ptr,_info_ptr), 00177 png_get_image_height(_png_ptr,_info_ptr)); 00178 } 00179 template <typename View> 00180 void apply(const View& view) { 00181 png_uint_32 width, height; 00182 int bit_depth, color_type, interlace_type; 00183 png_get_IHDR(_png_ptr, _info_ptr, 00184 &width, &height,&bit_depth,&color_type,&interlace_type, 00185 int_p_NULL, int_p_NULL); 00186 io_error_if(((png_uint_32)view.width()!=width || (png_uint_32)view.height()!= height), 00187 "png_read_view: input view size does not match PNG file size"); 00188 00189 if(png_read_support_private<typename channel_type<View>::type, 00190 typename color_space_type<View>::type>::bit_depth!=bit_depth || 00191 png_read_support_private<typename channel_type<View>::type, 00192 typename color_space_type<View>::type>::color_type!=color_type) 00193 io_error("png_read_view: input view type is incompatible with the image type"); 00194 00195 std::vector<pixel<typename channel_type<View>::type, 00196 layout<typename color_space_type<View>::type> > > row(width); 00197 for(png_uint_32 y=0;y<height;++y) { 00198 png_read_row(_png_ptr,(png_bytep)&row.front(),NULL); 00199 std::copy(row.begin(),row.end(),view.row_begin(y)); 00200 } 00201 png_read_end(_png_ptr,NULL); 00202 } 00203 00204 template <typename Image> 00205 void read_image(Image& im) { 00206 im.recreate(get_dimensions()); 00207 apply(view(im)); 00208 } 00209 }; 00210 00211 // This code will be simplified... 00212 template <typename CC> 00213 class png_reader_color_convert : public png_reader { 00214 private: 00215 CC _cc; 00216 public: 00217 png_reader_color_convert(FILE* file ,CC cc_in) : png_reader(file),_cc(cc_in) {} 00218 png_reader_color_convert(FILE* file ) : png_reader(file) {} 00219 png_reader_color_convert(const char* filename,CC cc_in) : png_reader(filename),_cc(cc_in) {} 00220 png_reader_color_convert(const char* filename) : png_reader(filename) {} 00221 template <typename View> 00222 void apply(const View& view) { 00223 png_uint_32 width, height; 00224 int bit_depth, color_type, interlace_type; 00225 png_get_IHDR(_png_ptr, _info_ptr, 00226 &width, &height,&bit_depth,&color_type,&interlace_type, 00227 int_p_NULL, int_p_NULL); 00228 io_error_if(((png_uint_32)view.width()!=width || (png_uint_32)view.height()!= height), 00229 "png_reader_color_convert::apply(): input view size does not match PNG file size"); 00230 switch (color_type) { 00231 case PNG_COLOR_TYPE_GRAY: 00232 switch (bit_depth) { 00233 case 8: { 00234 std::vector<gray8_pixel_t> row(width); 00235 for(png_uint_32 y=0;y<height;++y) { 00236 png_read_row(_png_ptr,(png_bytep)&row.front(),NULL); 00237 std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<gray8_ref_t,typename View::value_type,CC>(_cc)); 00238 } 00239 break; 00240 } 00241 case 16: { 00242 std::vector<gray16_pixel_t> row(width); 00243 for(png_uint_32 y=0;y<height;++y) { 00244 png_read_row(_png_ptr,(png_bytep)&row.front(),NULL); 00245 std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<gray16_ref_t,typename View::value_type,CC>(_cc)); 00246 } 00247 break; 00248 } 00249 default: io_error("png_reader_color_convert::apply(): unknown combination of color type and bit depth"); 00250 } 00251 break; 00252 case PNG_COLOR_TYPE_RGB: 00253 switch (bit_depth) { 00254 case 8: { 00255 std::vector<rgb8_pixel_t> row(width); 00256 for(png_uint_32 y=0;y<height;++y) { 00257 png_read_row(_png_ptr,(png_bytep)&row.front(),NULL); 00258 std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<rgb8_ref_t,typename View::value_type,CC>(_cc)); 00259 } 00260 break; 00261 } 00262 case 16: { 00263 std::vector<rgb16_pixel_t> row(width); 00264 for(png_uint_32 y=0;y<height;++y) { 00265 png_read_row(_png_ptr,(png_bytep)&row.front(),NULL); 00266 std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<rgb16_ref_t,typename View::value_type,CC>(_cc)); 00267 } 00268 break; 00269 } 00270 default: io_error("png_reader_color_convert::apply(): unknown combination of color type and bit depth"); 00271 } 00272 break; 00273 case PNG_COLOR_TYPE_RGBA: 00274 switch (bit_depth) { 00275 case 8: { 00276 std::vector<rgba8_pixel_t> row(width); 00277 for(png_uint_32 y=0;y<height;++y) { 00278 png_read_row(_png_ptr,(png_bytep)&row.front(),NULL); 00279 std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<rgba8_ref_t,typename View::value_type,CC>(_cc)); 00280 } 00281 break; 00282 } 00283 case 16: { 00284 std::vector<rgba16_pixel_t> row(width); 00285 for(png_uint_32 y=0;y<height;++y) { 00286 png_read_row(_png_ptr,(png_bytep)&row.front(),NULL); 00287 std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<rgba16_ref_t,typename View::value_type,CC>(_cc)); 00288 } 00289 break; 00290 } 00291 default: io_error("png_reader_color_convert::apply(): unknown combination of color type and bit depth"); 00292 } 00293 break; 00294 default: io_error("png_reader_color_convert::apply(): unknown color type"); 00295 } 00296 png_read_end(_png_ptr,NULL); 00297 } 00298 template <typename Image> 00299 void read_image(Image& im) { 00300 im.recreate(get_dimensions()); 00301 apply(view(im)); 00302 } 00303 }; 00304 00305 00306 class png_writer : public file_mgr { 00307 protected: 00308 png_structp _png_ptr; 00309 png_infop _info_ptr; 00310 00311 void init() { 00312 _png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL); 00313 io_error_if(!_png_ptr,"png_write_initialize: fail to call png_create_write_struct()"); 00314 _info_ptr = png_create_info_struct(_png_ptr); 00315 if (!_info_ptr) { 00316 png_destroy_write_struct(&_png_ptr,png_infopp_NULL); 00317 io_error("png_write_initialize: fail to call png_create_info_struct()"); 00318 } 00319 if (setjmp(png_jmpbuf(_png_ptr))) { 00320 png_destroy_write_struct(&_png_ptr, &_info_ptr); 00321 io_error("png_write_initialize: fail to call setjmp(png_jmpbuf())"); 00322 } 00323 png_init_io(_png_ptr,get()); 00324 } 00325 public: 00326 png_writer(FILE* file ) : file_mgr(file) { init(); } 00327 png_writer(const char* filename) : file_mgr(filename, "wb") { init(); } 00328 00329 ~png_writer() { 00330 png_destroy_write_struct(&_png_ptr,&_info_ptr); 00331 } 00332 template <typename View> 00333 void apply(const View& view) { 00334 png_set_IHDR(_png_ptr, _info_ptr, view.width(), view.height(), 00335 png_write_support_private<typename channel_type<View>::type, 00336 typename color_space_type<View>::type>::bit_depth, 00337 png_write_support_private<typename channel_type<View>::type, 00338 typename color_space_type<View>::type>::color_type, 00339 PNG_INTERLACE_NONE, 00340 PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT); 00341 png_write_info(_png_ptr,_info_ptr); 00342 if (little_endian() && 00343 png_write_support_private<typename channel_type<View>::type, 00344 typename color_space_type<View>::type>::bit_depth>8) 00345 png_set_swap(_png_ptr); 00346 std::vector<pixel<typename channel_type<View>::type, 00347 layout<typename color_space_type<View>::type> > > row(view.width()); 00348 for(int y=0;y<view.height();++y) { 00349 std::copy(view.row_begin(y),view.row_end(y),row.begin()); 00350 png_write_row(_png_ptr,(png_bytep)&row.front()); 00351 } 00352 png_write_end(_png_ptr,_info_ptr); 00353 } 00354 }; 00355 00356 } // namespace detail 00357 } } // namespace boost::gil 00358 00359 #endif Generated on Thu Nov 8 21:53:17 2007 for Generic Image Library by ![]() |