tiff_io.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 00013 #ifndef GIL_TIFF_IO_H 00014 #define GIL_TIFF_IO_H 00015 00022 00023 #include <vector> 00024 #include <string> 00025 #include <algorithm> 00026 #include <boost/static_assert.hpp> 00027 #include <tiffio.h> 00028 #include "../../gil_all.hpp" 00029 #include "io_error.hpp" 00030 00031 namespace boost { namespace gil { 00032 00033 namespace detail { 00034 00035 template <typename Channel,typename ColorSpace> 00036 struct tiff_read_support_private { 00037 BOOST_STATIC_CONSTANT(bool,is_supported=false); 00038 BOOST_STATIC_CONSTANT(int,bit_depth=0); 00039 BOOST_STATIC_CONSTANT(int,color_type=0); 00040 }; 00041 template <> 00042 struct tiff_read_support_private<bits8,gray_t> { 00043 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00044 BOOST_STATIC_CONSTANT(int,bit_depth=8); 00045 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK); 00046 }; 00047 template <> 00048 struct tiff_read_support_private<bits8,rgb_t> { 00049 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00050 BOOST_STATIC_CONSTANT(int,bit_depth=8); 00051 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB); 00052 }; 00053 template <> 00054 struct tiff_read_support_private<bits16,gray_t> { 00055 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00056 BOOST_STATIC_CONSTANT(int,bit_depth=16); 00057 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK); 00058 }; 00059 template <> 00060 struct tiff_read_support_private<bits16,rgb_t> { 00061 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00062 BOOST_STATIC_CONSTANT(int,bit_depth=16); 00063 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB); 00064 }; 00065 template <> 00066 struct tiff_read_support_private<bits32f,gray_t> { 00067 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00068 BOOST_STATIC_CONSTANT(int,bit_depth=32); 00069 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK); 00070 }; 00071 template <> 00072 struct tiff_read_support_private<bits32f,rgb_t> { 00073 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00074 BOOST_STATIC_CONSTANT(int,bit_depth=32); 00075 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB); 00076 }; 00077 00078 template <typename Channel,typename ColorSpace> 00079 struct tiff_write_support_private { 00080 BOOST_STATIC_CONSTANT(bool,is_supported=false); 00081 BOOST_STATIC_CONSTANT(int,bit_depth=0); 00082 BOOST_STATIC_CONSTANT(int,color_type=0); 00083 }; 00084 template <> 00085 struct tiff_write_support_private<bits8,gray_t> { 00086 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00087 BOOST_STATIC_CONSTANT(int,bit_depth=8); 00088 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK); 00089 }; 00090 template <> 00091 struct tiff_write_support_private<bits8,rgb_t> { 00092 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00093 BOOST_STATIC_CONSTANT(int,bit_depth=8); 00094 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB); 00095 }; 00096 template <> 00097 struct tiff_write_support_private<bits16,gray_t> { 00098 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00099 BOOST_STATIC_CONSTANT(int,bit_depth=16); 00100 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK); 00101 }; 00102 template <> 00103 struct tiff_write_support_private<bits16,rgb_t> { 00104 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00105 BOOST_STATIC_CONSTANT(int,bit_depth=16); 00106 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB); 00107 }; 00108 template <> 00109 struct tiff_write_support_private<bits32f,gray_t> { 00110 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00111 BOOST_STATIC_CONSTANT(int,bit_depth=32); 00112 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK); 00113 }; 00114 template <> 00115 struct tiff_write_support_private<bits32f,rgb_t> { 00116 BOOST_STATIC_CONSTANT(bool,is_supported=true); 00117 BOOST_STATIC_CONSTANT(int,bit_depth=32); 00118 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB); 00119 }; 00120 00121 class tiff_reader { 00122 protected: 00123 TIFF *_tp; 00124 public: 00125 tiff_reader(const char* filename) { 00126 io_error_if((_tp=TIFFOpen(filename,"r"))==NULL, 00127 "tiff_reader: fail to open file"); 00128 } 00129 ~tiff_reader() { TIFFClose(_tp); } 00130 template <typename View> 00131 void apply(const View& view) { 00132 unsigned short bps,photometric; 00133 point2<std::ptrdiff_t> dims=get_dimensions(); 00134 io_error_if(TIFFGetField(_tp,TIFFTAG_BITSPERSAMPLE,&bps)!=1); 00135 io_error_if(TIFFGetField(_tp,TIFFTAG_PHOTOMETRIC,&photometric)!=1); 00136 io_error_if(dims!=view.dimensions(), 00137 "tiff_read_view: input view size does not match TIFF file size"); 00138 io_error_if(tiff_read_support_private<typename channel_type<View>::type, 00139 typename color_space_type<View>::type>::bit_depth!=bps || 00140 tiff_read_support_private<typename channel_type<View>::type, 00141 typename color_space_type<View>::type>::color_type!=photometric, 00142 "tiff_read_view: input view type is incompatible with the image type"); 00143 std::size_t element_size=sizeof(pixel<typename channel_type<View>::type, 00144 layout<typename color_space_type<View>::type> >); 00145 std::size_t size_to_allocate = (std::max)((std::size_t)view.width(), 00146 (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size); 00147 std::vector<pixel<typename channel_type<View>::type, 00148 layout<typename color_space_type<View>::type> > > row(size_to_allocate); 00149 for (int y=0;y<view.height();++y) { 00150 io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1); 00151 std::copy(row.begin(),row.begin()+view.width(),view.row_begin(y)); 00152 } 00153 } 00154 point2<std::ptrdiff_t> get_dimensions() { 00155 int w,h; 00156 io_error_if(TIFFGetField(_tp,TIFFTAG_IMAGEWIDTH, &w)!=1); 00157 io_error_if(TIFFGetField(_tp,TIFFTAG_IMAGELENGTH,&h)!=1); 00158 return point2<std::ptrdiff_t>(w,h); 00159 } 00160 00161 template <typename Image> 00162 void read_image(Image& im) { 00163 im.recreate(get_dimensions()); 00164 apply(view(im)); 00165 } 00166 }; 00167 00168 // This code will be simplified... 00169 template <typename CC> 00170 class tiff_reader_color_convert : public tiff_reader { 00171 private: 00172 CC _cc; 00173 public: 00174 tiff_reader_color_convert(const char* filename) : 00175 tiff_reader(filename) {} 00176 tiff_reader_color_convert(const char* filename,CC cc_in) : 00177 tiff_reader(filename),_cc(cc_in) {} 00178 template <typename View> 00179 void apply(const View& view) { 00180 point2<std::ptrdiff_t> dims=get_dimensions(); 00181 unsigned short bps,photometric; 00182 io_error_if(TIFFGetField(_tp,TIFFTAG_BITSPERSAMPLE,&bps)!=1); 00183 io_error_if(TIFFGetField(_tp,TIFFTAG_PHOTOMETRIC,&photometric)!=1); 00184 io_error_if(dims!=view.dimensions(), 00185 "tiff_reader_color_convert::apply(): input view size does not match TIFF file size"); 00186 switch (photometric) { 00187 case PHOTOMETRIC_MINISBLACK: { 00188 switch (bps) { 00189 case 8: { 00190 std::size_t element_size=sizeof(gray8_pixel_t); 00191 std::size_t size_to_allocate = (std::max)((std::size_t)view.width(), 00192 (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size); 00193 std::vector<gray8_pixel_t> row(size_to_allocate); 00194 for (int y=0;y<view.height();++y) { 00195 io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1); 00196 std::transform(row.begin(),row.begin()+view.width(),view.row_begin(y), 00197 color_convert_deref_fn<gray8_ref_t,typename View::value_type,CC>(_cc)); 00198 } 00199 break; 00200 } 00201 case 16: { 00202 std::size_t element_size=sizeof(gray16_pixel_t); 00203 std::size_t size_to_allocate = (std::max)((std::size_t)view.width(), 00204 (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size); 00205 std::vector<gray16_pixel_t> row(size_to_allocate); 00206 for (int y=0;y<view.height();++y) { 00207 io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1); 00208 std::transform(row.begin(),row.begin()+view.width(),view.row_begin(y), 00209 color_convert_deref_fn<gray16_ref_t,typename View::value_type,CC>(_cc)); 00210 } 00211 break; 00212 } 00213 case 32: { 00214 std::size_t element_size=sizeof(gray32f_pixel_t); 00215 std::size_t size_to_allocate = (std::max)((std::size_t)view.width(), 00216 (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size); 00217 std::vector<gray32f_pixel_t> row(size_to_allocate); 00218 for (int y=0;y<view.height();++y) { 00219 io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1); 00220 std::transform(row.begin(),row.begin()+view.width(),view.row_begin(y), 00221 color_convert_deref_fn<gray32f_ref_t,typename View::value_type,CC>(_cc)); 00222 } 00223 break; 00224 } 00225 default: 00226 io_error("tiff_reader_color_convert::apply(): unknown combination of color type and bit depth"); 00227 } 00228 break; 00229 } 00230 case PHOTOMETRIC_RGB: { 00231 switch (bps) { 00232 case 8: { 00233 std::size_t element_size=sizeof(rgb8_pixel_t); 00234 std::size_t size_to_allocate = (std::max)((std::size_t)view.width(), 00235 (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size); 00236 std::vector<rgb8_pixel_t> row(size_to_allocate); 00237 for (int y=0;y<view.height();++y) { 00238 io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1); 00239 std::transform(row.begin(),row.begin()+view.width(),view.row_begin(y), 00240 color_convert_deref_fn<rgb8_ref_t,typename View::value_type,CC>(_cc)); 00241 } 00242 break; 00243 } 00244 case 16: { 00245 std::size_t element_size=sizeof(rgb16_pixel_t); 00246 std::size_t size_to_allocate = (std::max)((std::size_t)view.width(), 00247 (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size); 00248 std::vector<rgb16_pixel_t> row(size_to_allocate); 00249 for (int y=0;y<view.height();++y) { 00250 io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1); 00251 std::transform(row.begin(),row.begin()+view.width(),view.row_begin(y), 00252 color_convert_deref_fn<rgb16_ref_t,typename View::value_type,CC>(_cc)); 00253 } 00254 break; 00255 } 00256 case 32: { 00257 std::size_t element_size=sizeof(rgb32f_pixel_t); 00258 std::size_t size_to_allocate = (std::max)((std::size_t)view.width(), 00259 (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size); 00260 std::vector<rgb32f_pixel_t> row(size_to_allocate); 00261 for (int y=0;y<view.height();++y) { 00262 io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1); 00263 std::transform(row.begin(),row.begin()+view.width(),view.row_begin(y), 00264 color_convert_deref_fn<rgb32f_ref_t,typename View::value_type,CC>(_cc)); 00265 } 00266 break; 00267 } 00268 default: 00269 io_error("tiff_reader_color_convert::apply(): unknown combination of color type and bit depth"); 00270 } 00271 break; 00272 } 00273 default: { 00274 // reads an image in incompatible format via TIFFReadRGBAImage 00275 rgba8_image_t rgbaImg(dims); 00276 io_error_if(!TIFFReadRGBAImage(_tp, dims.x, dims.y, (uint32*)&gil::view(rgbaImg)(0,0), 0), 00277 "tiff_reader_color_convert::unsupported image format"); 00278 copy_and_convert_pixels(flipped_up_down_view(const_view(rgbaImg)), view, _cc); 00279 } 00280 } 00281 } 00282 template <typename Image> 00283 void read_image(Image& im) { 00284 im.recreate(get_dimensions()); 00285 apply(view(im)); 00286 } 00287 }; 00288 00289 class tiff_writer { 00290 protected: 00291 TIFF* _tp; 00292 public: 00293 tiff_writer(const char *filename) { 00294 io_error_if((_tp=TIFFOpen(filename,"w"))==NULL, 00295 "tiff_writer: fail to open file"); 00296 } 00297 ~tiff_writer() {TIFFClose(_tp);} 00298 template <typename View> 00299 void apply(const View& view) { 00300 io_error_if(TIFFSetField(_tp,TIFFTAG_IMAGELENGTH, view.height())!=1); 00301 io_error_if(TIFFSetField(_tp,TIFFTAG_IMAGEWIDTH, view.width())!=1); 00302 io_error_if(TIFFSetField(_tp,TIFFTAG_PHOTOMETRIC, tiff_write_support_private<typename channel_type<View>::type, 00303 typename color_space_type<View>::type>::color_type)!=1); 00304 io_error_if(TIFFSetField(_tp,TIFFTAG_RESOLUTIONUNIT, RESUNIT_NONE)!=1); 00305 io_error_if(TIFFSetField(_tp,TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)!=1); 00306 io_error_if(TIFFSetField(_tp,TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT)!=1); 00307 io_error_if(TIFFSetField(_tp,TIFFTAG_SAMPLESPERPIXEL,num_channels<View>::value)!=1); 00308 io_error_if(TIFFSetField(_tp,TIFFTAG_BITSPERSAMPLE, tiff_write_support_private<typename channel_type<View>::type, 00309 typename color_space_type<View>::type>::bit_depth)!=1); 00310 io_error_if(TIFFSetField(_tp,TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(_tp, 0))!=1); 00311 std::vector<pixel<typename channel_type<View>::type, 00312 layout<typename color_space_type<View>::type> > > row(view.width()); 00313 for (int y=0;y<view.height();++y) { 00314 std::copy(view.row_begin(y),view.row_end(y),row.begin()); 00315 io_error_if(TIFFWriteScanline(_tp,&row.front(),y,0)!=1, 00316 "tiff_write_view: fail to write file"); 00317 } 00318 } 00319 }; 00320 00321 } // namespace detail 00322 00325 template <typename View> 00326 struct tiff_read_support { 00327 BOOST_STATIC_CONSTANT(bool,is_supported= 00328 (detail::tiff_read_support_private<typename channel_type<View>::type, 00329 typename color_space_type<View>::type>::is_supported)); 00330 BOOST_STATIC_CONSTANT(int,bit_depth= 00331 (detail::tiff_read_support_private<typename channel_type<View>::type, 00332 typename color_space_type<View>::type>::bit_depth)); 00333 BOOST_STATIC_CONSTANT(int,color_type= 00334 (detail::tiff_read_support_private<typename channel_type<View>::type, 00335 typename color_space_type<View>::type>::color_type)); 00336 }; 00337 00341 inline point2<std::ptrdiff_t> tiff_read_dimensions(const char* filename) { 00342 detail::tiff_reader m(filename); 00343 return m.get_dimensions(); 00344 } 00345 00349 inline point2<std::ptrdiff_t> tiff_read_dimensions(const std::string& filename) { 00350 return tiff_read_dimensions(filename.c_str()); 00351 } 00352 00358 template <typename View> 00359 inline void tiff_read_view(const char* filename,const View& view) { 00360 BOOST_STATIC_ASSERT(tiff_read_support<View>::is_supported); 00361 detail::tiff_reader m(filename); 00362 m.apply(view); 00363 } 00364 00367 template <typename View> 00368 inline void tiff_read_view(const std::string& filename,const View& view) { 00369 tiff_read_view(filename.c_str(),view); 00370 } 00371 00377 template <typename Image> 00378 void tiff_read_image(const char* filename,Image& im) { 00379 BOOST_STATIC_ASSERT(tiff_read_support<typename Image::view_t>::is_supported); 00380 detail::tiff_reader m(filename); 00381 m.read_image(im); 00382 } 00383 00386 template <typename Image> 00387 inline void tiff_read_image(const std::string& filename,Image& im) { 00388 tiff_read_image(filename.c_str(),im); 00389 } 00390 00394 template <typename View,typename CC> 00395 inline void tiff_read_and_convert_view(const char* filename,const View& view,CC cc) { 00396 detail::tiff_reader_color_convert<CC> m(filename,cc); 00397 m.apply(view); 00398 } 00399 00403 template <typename View> 00404 inline void tiff_read_and_convert_view(const char* filename,const View& view) { 00405 detail::tiff_reader_color_convert<default_color_converter> m(filename,default_color_converter()); 00406 m.apply(view); 00407 } 00408 00411 template <typename View,typename CC> 00412 inline void tiff_read_and_convert_view(const std::string& filename,const View& view,CC cc) { 00413 tiff_read_and_convert_view(filename.c_str(),view,cc); 00414 } 00415 00418 template <typename View> 00419 inline void tiff_read_and_convert_view(const std::string& filename,const View& view) { 00420 tiff_read_and_convert_view(filename.c_str(),view); 00421 } 00422 00426 template <typename Image,typename CC> 00427 void tiff_read_and_convert_image(const char* filename,Image& im,CC cc) { 00428 detail::tiff_reader_color_convert<CC> m(filename,cc); 00429 m.read_image(im); 00430 } 00431 00435 template <typename Image> 00436 void tiff_read_and_convert_image(const char* filename,Image& im) { 00437 detail::tiff_reader_color_convert<default_color_converter> m(filename,default_color_converter()); 00438 m.read_image(im); 00439 } 00440 00443 template <typename Image,typename CC> 00444 inline void tiff_read_and_convert_image(const std::string& filename,Image& im,CC cc) { 00445 tiff_read_and_convert_image(filename.c_str(),im,cc); 00446 } 00447 00450 template <typename Image> 00451 inline void tiff_read_and_convert_image(const std::string& filename,Image& im) { 00452 tiff_read_and_convert_image(filename.c_str(),im); 00453 } 00454 00457 template <typename View> 00458 struct tiff_write_support { 00459 BOOST_STATIC_CONSTANT(bool,is_supported= 00460 (detail::tiff_write_support_private<typename channel_type<View>::type, 00461 typename color_space_type<View>::type>::is_supported)); 00462 BOOST_STATIC_CONSTANT(int,bit_depth= 00463 (detail::tiff_write_support_private<typename channel_type<View>::type, 00464 typename color_space_type<View>::type>::bit_depth)); 00465 BOOST_STATIC_CONSTANT(int,color_type= 00466 (detail::tiff_write_support_private<typename channel_type<View>::type, 00467 typename color_space_type<View>::type>::color_type)); 00468 BOOST_STATIC_CONSTANT(bool, value=is_supported); 00469 }; 00470 00475 template <typename View> 00476 inline void tiff_write_view(const char* filename,const View& view) { 00477 BOOST_STATIC_ASSERT(tiff_write_support<View>::is_supported); 00478 detail::tiff_writer m(filename); 00479 m.apply(view); 00480 } 00481 00484 template <typename View> 00485 inline void tiff_write_view(const std::string& filename,const View& view) { 00486 tiff_write_view(filename.c_str(),view); 00487 } 00488 00489 } } // namespace boost::gil 00490 00491 #endif Generated on Sat May 2 13:50:15 2009 for Generic Image Library by 1.5.6 |