00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef GIL_TIFF_IO_H
00010 #define GIL_TIFF_IO_H
00011
00015
00019
00020 #include <vector>
00021 #include <string>
00022 #include <boost/static_assert.hpp>
00023 #include <tiffio.h>
00024 #include "../../core/gil_all.hpp"
00025 #include "io_error.hpp"
00026
00027 ADOBE_GIL_NAMESPACE_BEGIN
00028
00029 namespace detail {
00030
00031 template <typename CHANNEL,typename COLORSPACE>
00032 struct tiff_read_support_private {
00033 BOOST_STATIC_CONSTANT(bool,is_supported=false);
00034 BOOST_STATIC_CONSTANT(int,bit_depth=0);
00035 BOOST_STATIC_CONSTANT(int,color_type=0);
00036 };
00037 template <>
00038 struct tiff_read_support_private<bits8,gray_t> {
00039 BOOST_STATIC_CONSTANT(bool,is_supported=true);
00040 BOOST_STATIC_CONSTANT(int,bit_depth=8);
00041 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK);
00042 };
00043 template <>
00044 struct tiff_read_support_private<bits8,rgb_t> {
00045 BOOST_STATIC_CONSTANT(bool,is_supported=true);
00046 BOOST_STATIC_CONSTANT(int,bit_depth=8);
00047 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB);
00048 };
00049 template <>
00050 struct tiff_read_support_private<bits8,lab_t> {
00051 BOOST_STATIC_CONSTANT(bool,is_supported=true);
00052 BOOST_STATIC_CONSTANT(int,bit_depth=8);
00053 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_CIELAB);
00054 };
00055 template <>
00056 struct tiff_read_support_private<bits16,gray_t> {
00057 BOOST_STATIC_CONSTANT(bool,is_supported=true);
00058 BOOST_STATIC_CONSTANT(int,bit_depth=16);
00059 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK);
00060 };
00061 template <>
00062 struct tiff_read_support_private<bits16,rgb_t> {
00063 BOOST_STATIC_CONSTANT(bool,is_supported=true);
00064 BOOST_STATIC_CONSTANT(int,bit_depth=16);
00065 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB);
00066 };
00067 template <>
00068 struct tiff_read_support_private<bits16,lab_t> {
00069 BOOST_STATIC_CONSTANT(bool,is_supported=true);
00070 BOOST_STATIC_CONSTANT(int,bit_depth=16);
00071 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_CIELAB);
00072 };
00073 template <>
00074 struct tiff_read_support_private<bits32f,gray_t> {
00075 BOOST_STATIC_CONSTANT(bool,is_supported=true);
00076 BOOST_STATIC_CONSTANT(int,bit_depth=32);
00077 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK);
00078 };
00079 template <>
00080 struct tiff_read_support_private<bits32f,rgb_t> {
00081 BOOST_STATIC_CONSTANT(bool,is_supported=true);
00082 BOOST_STATIC_CONSTANT(int,bit_depth=32);
00083 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB);
00084 };
00085 template <>
00086 struct tiff_read_support_private<bits32f,lab_t> {
00087 BOOST_STATIC_CONSTANT(bool,is_supported=true);
00088 BOOST_STATIC_CONSTANT(int,bit_depth=32);
00089 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_CIELAB);
00090 };
00091
00092 template <typename CHANNEL,typename COLORSPACE>
00093 struct tiff_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 tiff_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=PHOTOMETRIC_MINISBLACK);
00103 };
00104 template <>
00105 struct tiff_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=PHOTOMETRIC_RGB);
00109 };
00110 template <>
00111 struct tiff_write_support_private<bits8,lab_t> {
00112 BOOST_STATIC_CONSTANT(bool,is_supported=true);
00113 BOOST_STATIC_CONSTANT(int,bit_depth=8);
00114 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_CIELAB);
00115 };
00116 template <>
00117 struct tiff_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=PHOTOMETRIC_MINISBLACK);
00121 };
00122 template <>
00123 struct tiff_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=PHOTOMETRIC_RGB);
00127 };
00128 template <>
00129 struct tiff_write_support_private<bits16,lab_t> {
00130 BOOST_STATIC_CONSTANT(bool,is_supported=true);
00131 BOOST_STATIC_CONSTANT(int,bit_depth=16);
00132 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_CIELAB);
00133 };
00134 template <>
00135 struct tiff_write_support_private<bits32f,gray_t> {
00136 BOOST_STATIC_CONSTANT(bool,is_supported=true);
00137 BOOST_STATIC_CONSTANT(int,bit_depth=32);
00138 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK);
00139 };
00140 template <>
00141 struct tiff_write_support_private<bits32f,rgb_t> {
00142 BOOST_STATIC_CONSTANT(bool,is_supported=true);
00143 BOOST_STATIC_CONSTANT(int,bit_depth=32);
00144 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB);
00145 };
00146 template <>
00147 struct tiff_write_support_private<bits32f,lab_t> {
00148 BOOST_STATIC_CONSTANT(bool,is_supported=true);
00149 BOOST_STATIC_CONSTANT(int,bit_depth=32);
00150 BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_CIELAB);
00151 };
00152
00153 class tiff_reader {
00154 protected:
00155 TIFF *_tp;
00156 public:
00157 tiff_reader(const char* filename) {
00158 io_error_if((_tp=TIFFOpen(filename,"r"))==NULL,
00159 "tiff_reader: fail to open file");
00160 }
00161 ~tiff_reader() { TIFFClose(_tp); }
00162 template <typename VIEW>
00163 void apply(const VIEW& view) {
00164 int width,height;
00165 unsigned short bps,photometric;
00166 io_error_if(TIFFGetField(_tp,TIFFTAG_IMAGEWIDTH,&width)!=1);
00167 io_error_if(TIFFGetField(_tp,TIFFTAG_IMAGELENGTH,&height)!=1);
00168 io_error_if(TIFFGetField(_tp,TIFFTAG_BITSPERSAMPLE,&bps)!=1);
00169 io_error_if(TIFFGetField(_tp,TIFFTAG_PHOTOMETRIC,&photometric)!=1);
00170 io_error_if(width!=view.width() || height!=view.height(),
00171 "tiff_read_view: input view size does not match TIFF file size");
00172 io_error_if(tiff_read_support_private<typename VIEW::channel_t,
00173 typename VIEW::color_space_t::base>::bit_depth!=bps ||
00174 tiff_read_support_private<typename VIEW::channel_t,
00175 typename VIEW::color_space_t::base>::color_type!=photometric,
00176 "tiff_read_view: input view type is incompatible with the image type");
00177
00178 std::vector<pixel<typename VIEW::channel_t,
00179 typename VIEW::color_space_t::base> > row(view.width());
00180 for (int y=0;y<view.height();++y) {
00181 io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
00182 std::copy(row.begin(),row.end(),view.row_begin(y));
00183 }
00184 }
00185 point2<int> get_dimensions() {
00186 point2<int> file_size;
00187 io_error_if(TIFFGetField(_tp,TIFFTAG_IMAGEWIDTH, &file_size.x)!=1);
00188 io_error_if(TIFFGetField(_tp,TIFFTAG_IMAGELENGTH,&file_size.y)!=1);
00189 return file_size;
00190 }
00191
00192 template <typename IMAGE>
00193 void read_image(IMAGE& im) {
00194 resize_clobber_image(im,get_dimensions());
00195 apply(view(im));
00196 }
00197 };
00198
00199
00200 class tiff_reader_color_convert : public tiff_reader {
00201 public:
00202 tiff_reader_color_convert(const char* filename) : tiff_reader(filename) {}
00203 template <typename VIEW>
00204 void apply(const VIEW& view) {
00205 int width,height;
00206 unsigned short bps,photometric;
00207 io_error_if(TIFFGetField(_tp,TIFFTAG_IMAGEWIDTH,&width)!=1);
00208 io_error_if(TIFFGetField(_tp,TIFFTAG_IMAGELENGTH,&height)!=1);
00209 io_error_if(TIFFGetField(_tp,TIFFTAG_BITSPERSAMPLE,&bps)!=1);
00210 io_error_if(TIFFGetField(_tp,TIFFTAG_PHOTOMETRIC,&photometric)!=1);
00211 io_error_if(width!=view.width() || height!=view.height(),
00212 "tiff_reader_color_convert::apply(): input view size does not match TIFF file size");
00213 switch (photometric) {
00214 case PHOTOMETRIC_MINISBLACK: {
00215 switch (bps) {
00216 case 8: {
00217 std::vector<pixel<bits8,gray_t> > row(view.width());
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.end(),view.row_begin(y),
00221 color_converter<typename VIEW::pixel_t>());
00222 }
00223 break;
00224 }
00225 case 16: {
00226 std::vector<pixel<bits16,gray_t> > row(view.width());
00227 for (int y=0;y<view.height();++y) {
00228 io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
00229 std::transform(row.begin(),row.end(),view.row_begin(y),
00230 color_converter<typename VIEW::pixel_t>());
00231 }
00232 break;
00233 }
00234 case 32: {
00235 std::vector<pixel<bits32f,gray_t> > row(view.width());
00236 for (int y=0;y<view.height();++y) {
00237 io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
00238 std::transform(row.begin(),row.end(),view.row_begin(y),
00239 color_converter<typename VIEW::pixel_t>());
00240 }
00241 break;
00242 }
00243 default:
00244 io_error("tiff_reader_color_convert::apply(): unknown combination of color type and bit depth");
00245 }
00246 break;
00247 }
00248 case PHOTOMETRIC_RGB: {
00249 switch (bps) {
00250 case 8: {
00251 std::vector<pixel<bits8,rgb_t> > row(view.width());
00252 for (int y=0;y<view.height();++y) {
00253 io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
00254 std::transform(row.begin(),row.end(),view.row_begin(y),
00255 color_converter<typename VIEW::pixel_t>());
00256 }
00257 break;
00258 }
00259 case 16: {
00260 std::vector<pixel<bits16,rgb_t> > row(view.width());
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.end(),view.row_begin(y),
00264 color_converter<typename VIEW::pixel_t>());
00265 }
00266 break;
00267 }
00268 case 32: {
00269 std::vector<pixel<bits32f,rgb_t> > row(view.width());
00270 for (int y=0;y<view.height();++y) {
00271 io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
00272 std::transform(row.begin(),row.end(),view.row_begin(y),
00273 color_converter<typename VIEW::pixel_t>());
00274 }
00275 break;
00276 }
00277 default:
00278 io_error("tiff_reader_color_convert::apply(): unknown combination of color type and bit depth");
00279 }
00280 break;
00281 }
00282 case PHOTOMETRIC_CIELAB:
00283 io_error("tiff_reader_color_convert::apply(): current implementation does not support reading and converting CIE-LAB files");
00284 default:
00285 io_error("tiff_reader_color_convert::apply(): unknown color type");
00286 }
00287 }
00288 template <typename IMAGE>
00289 void read_image(IMAGE& im) {
00290 resize_clobber_image(im,get_dimensions());
00291 apply(view(im));
00292 }
00293 };
00294
00295 class tiff_writer {
00296 protected:
00297 TIFF* _tp;
00298 public:
00299 tiff_writer(const char *filename) {
00300 io_error_if((_tp=TIFFOpen(filename,"w"))==NULL,
00301 "tiff_writer: fail to open file");
00302 }
00303 ~tiff_writer() {TIFFClose(_tp);}
00304 template <typename VIEW>
00305 void apply(const VIEW& view) {
00306 io_error_if(TIFFSetField(_tp,TIFFTAG_IMAGELENGTH, view.height())!=1);
00307 io_error_if(TIFFSetField(_tp,TIFFTAG_IMAGEWIDTH, view.width())!=1);
00308 io_error_if(TIFFSetField(_tp,TIFFTAG_PHOTOMETRIC, tiff_write_support_private<typename VIEW::channel_t,
00309 typename VIEW::color_space_t::base>::color_type)!=1);
00310 io_error_if(TIFFSetField(_tp,TIFFTAG_RESOLUTIONUNIT, RESUNIT_NONE)!=1);
00311 io_error_if(TIFFSetField(_tp,TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)!=1);
00312 io_error_if(TIFFSetField(_tp,TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT)!=1);
00313 io_error_if(TIFFSetField(_tp,TIFFTAG_SAMPLESPERPIXEL,VIEW::num_channels)!=1);
00314 io_error_if(TIFFSetField(_tp,TIFFTAG_BITSPERSAMPLE, tiff_write_support_private<typename VIEW::channel_t,
00315 typename VIEW::color_space_t::base>::bit_depth)!=1);
00316 io_error_if(TIFFSetField(_tp,TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(_tp, 0))!=1);
00317 std::vector<pixel<typename VIEW::channel_t,
00318 typename VIEW::color_space_t::base> > row(view.width());
00319 for (int y=0;y<view.height();++y) {
00320 std::copy(view.row_begin(y),view.row_end(y),row.begin());
00321 io_error_if(TIFFWriteScanline(_tp,&row.front(),y,0)!=1,
00322 "tiff_write_view: fail to write file");
00323 }
00324 }
00325 };
00326
00327 }
00328
00331 template <typename VIEW>
00332 struct tiff_read_support {
00333 BOOST_STATIC_CONSTANT(bool,is_supported=
00334 (detail::tiff_read_support_private<typename VIEW::channel_t,
00335 typename VIEW::color_space_t::base>::is_supported));
00336 BOOST_STATIC_CONSTANT(int,bit_depth=
00337 (detail::tiff_read_support_private<typename VIEW::channel_t,
00338 typename VIEW::color_space_t::base>::bit_depth));
00339 BOOST_STATIC_CONSTANT(int,color_type=
00340 (detail::tiff_read_support_private<typename VIEW::channel_t,
00341 typename VIEW::color_space_t::base>::color_type));
00342 };
00343
00347 inline point2<int> tiff_read_dimensions(const char* filename) {
00348 detail::tiff_reader m(filename);
00349 return m.get_dimensions();
00350 }
00351
00355 inline point2<int> tiff_read_dimensions(const std::string& filename) {
00356 return tiff_read_dimensions(filename.c_str());
00357 }
00358
00364 template <typename VIEW>
00365 inline void tiff_read_view(const char* filename,const VIEW& view) {
00366 BOOST_STATIC_ASSERT(tiff_read_support<VIEW>::is_supported);
00367 detail::tiff_reader m(filename);
00368 m.apply(view);
00369 }
00370
00373 template <typename VIEW>
00374 inline void tiff_read_view(const std::string& filename,const VIEW& view) {
00375 tiff_read_view(filename.c_str(),view);
00376 }
00377
00383 template <typename IMAGE>
00384 void tiff_read_image(const char* filename,IMAGE& im) {
00385 BOOST_STATIC_ASSERT(tiff_read_support<typename IMAGE::view_t>::is_supported);
00386 detail::tiff_reader m(filename);
00387 m.read_image(im);
00388 }
00389
00392 template <typename IMAGE>
00393 inline void tiff_read_image(const std::string& filename,IMAGE& im) {
00394 tiff_read_image(filename.c_str(),im);
00395 }
00396
00400 template <typename VIEW>
00401 inline void tiff_read_and_convert_view(const char* filename,const VIEW& view) {
00402 detail::tiff_reader_color_convert m(filename);
00403 m.apply(view);
00404 }
00405
00408 template <typename VIEW>
00409 inline void tiff_read_and_convert_view(const std::string& filename,const VIEW& view) {
00410 tiff_read_view(filename.c_str(),view);
00411 }
00412
00416 template <typename IMAGE>
00417 void tiff_read_and_convert_image(const char* filename,IMAGE& im) {
00418 detail::tiff_reader_color_convert m(filename);
00419 m.read_image(im);
00420 }
00421
00424 template <typename IMAGE>
00425 inline void tiff_read_and_convert_image(const std::string& filename,IMAGE& im) {
00426 tiff_read_and_convert_image(filename.c_str(),im);
00427 }
00428
00431 template <typename VIEW>
00432 struct tiff_write_support {
00433 BOOST_STATIC_CONSTANT(bool,is_supported=
00434 (detail::tiff_write_support_private<typename VIEW::channel_t,
00435 typename VIEW::color_space_t::base>::is_supported));
00436 BOOST_STATIC_CONSTANT(int,bit_depth=
00437 (detail::tiff_write_support_private<typename VIEW::channel_t,
00438 typename VIEW::color_space_t::base>::bit_depth));
00439 BOOST_STATIC_CONSTANT(int,color_type=
00440 (detail::tiff_write_support_private<typename VIEW::channel_t,
00441 typename VIEW::color_space_t::base>::color_type));
00442 BOOST_STATIC_CONSTANT(bool, value=is_supported);
00443 };
00444
00449 template <typename VIEW>
00450 inline void tiff_write_view(const char* filename,const VIEW& view) {
00451 BOOST_STATIC_ASSERT(tiff_write_support<VIEW>::is_supported);
00452 detail::tiff_writer m(filename);
00453 m.apply(view);
00454 }
00455
00458 template <typename VIEW>
00459 inline void tiff_write_view(const std::string& filename,const VIEW& view) {
00460 tiff_write_view(filename.c_str(),view);
00461 }
00462
00463 ADOBE_GIL_NAMESPACE_END
00464
00465 #endif