Adobe Systems, Inc.

tiff_io.hpp

Go to the documentation of this file.
00001 /*
00002   Copyright 2005-2006 Adobe Systems Incorporated
00003   Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
00004   or a copy at http://opensource.adobe.com/licenses.html)
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 // This code will be simplified...
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 } // namespace detail
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

Copyright © 2006 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google