1 /*
2     Copyright 2005-2007 Adobe Systems Incorporated
3 
4     Use, modification and distribution are subject to the Boost Software License,
5     Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6     http://www.boost.org/LICENSE_1_0.txt).
7 
8     See http://opensource.adobe.com/gil for most recent version including documentation.
9 */
10 
11 /*************************************************************************************************/
12 
13 #ifndef GIL_TIFF_IO_H
14 #define GIL_TIFF_IO_H
15 
16 /// \file
17 /// \brief  Support for reading and writing TIFF files
18 ///         Requires libtiff!
19 /// \author Hailin Jin and Lubomir Bourdev \n
20 ///         Adobe Systems Incorporated
21 /// \date   2005-2007 \n Last updated September 24, 2006
22 
23 #include <vector>
24 #include <string>
25 #include <algorithm>
26 #include <boost/static_assert.hpp>
27 #include <tiffio.h>
28 #include "../../gil_all.hpp"
29 #include "io_error.hpp"
30 
31 namespace boost { namespace gil {
32 
33 namespace detail {
34 
35 template <typename Channel,typename ColorSpace>
36 struct tiff_read_support_private {
37     BOOST_STATIC_CONSTANT(bool,is_supported=false);
38     BOOST_STATIC_CONSTANT(int,bit_depth=0);
39     BOOST_STATIC_CONSTANT(int,color_type=0);
40 };
41 template <>
42 struct tiff_read_support_private<bits8,gray_t> {
43     BOOST_STATIC_CONSTANT(bool,is_supported=true);
44     BOOST_STATIC_CONSTANT(int,bit_depth=8);
45     BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK);
46 };
47 template <>
48 struct tiff_read_support_private<bits8,rgb_t> {
49     BOOST_STATIC_CONSTANT(bool,is_supported=true);
50     BOOST_STATIC_CONSTANT(int,bit_depth=8);
51     BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB);
52 };
53 template <>
54 struct tiff_read_support_private<bits16,gray_t> {
55     BOOST_STATIC_CONSTANT(bool,is_supported=true);
56     BOOST_STATIC_CONSTANT(int,bit_depth=16);
57     BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK);
58 };
59 template <>
60 struct tiff_read_support_private<bits16,rgb_t> {
61     BOOST_STATIC_CONSTANT(bool,is_supported=true);
62     BOOST_STATIC_CONSTANT(int,bit_depth=16);
63     BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB);
64 };
65 template <>
66 struct tiff_read_support_private<bits32f,gray_t> {
67     BOOST_STATIC_CONSTANT(bool,is_supported=true);
68     BOOST_STATIC_CONSTANT(int,bit_depth=32);
69     BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK);
70 };
71 template <>
72 struct tiff_read_support_private<bits32f,rgb_t> {
73     BOOST_STATIC_CONSTANT(bool,is_supported=true);
74     BOOST_STATIC_CONSTANT(int,bit_depth=32);
75     BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB);
76 };
77 
78 template <typename Channel,typename ColorSpace>
79 struct tiff_write_support_private {
80     BOOST_STATIC_CONSTANT(bool,is_supported=false);
81     BOOST_STATIC_CONSTANT(int,bit_depth=0);
82     BOOST_STATIC_CONSTANT(int,color_type=0);
83 };
84 template <>
85 struct tiff_write_support_private<bits8,gray_t> {
86     BOOST_STATIC_CONSTANT(bool,is_supported=true);
87     BOOST_STATIC_CONSTANT(int,bit_depth=8);
88     BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK);
89 };
90 template <>
91 struct tiff_write_support_private<bits8,rgb_t> {
92     BOOST_STATIC_CONSTANT(bool,is_supported=true);
93     BOOST_STATIC_CONSTANT(int,bit_depth=8);
94     BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB);
95 };
96 template <>
97 struct tiff_write_support_private<bits16,gray_t> {
98     BOOST_STATIC_CONSTANT(bool,is_supported=true);
99     BOOST_STATIC_CONSTANT(int,bit_depth=16);
100     BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK);
101 };
102 template <>
103 struct tiff_write_support_private<bits16,rgb_t> {
104     BOOST_STATIC_CONSTANT(bool,is_supported=true);
105     BOOST_STATIC_CONSTANT(int,bit_depth=16);
106     BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB);
107 };
108 template <>
109 struct tiff_write_support_private<bits32f,gray_t> {
110     BOOST_STATIC_CONSTANT(bool,is_supported=true);
111     BOOST_STATIC_CONSTANT(int,bit_depth=32);
112     BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK);
113 };
114 template <>
115 struct tiff_write_support_private<bits32f,rgb_t> {
116     BOOST_STATIC_CONSTANT(bool,is_supported=true);
117     BOOST_STATIC_CONSTANT(int,bit_depth=32);
118     BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB);
119 };
120 
121 class tiff_reader {
122 protected:
123     TIFF *_tp;
124 public:
tiff_reader(const char * filename,tdir_t dirnum=0)125     tiff_reader(const char* filename,tdir_t dirnum=0) {
126         io_error_if((_tp=TIFFOpen(filename,"r"))==NULL,
127                     "tiff_reader: fail to open file");
128         if(dirnum>0) {
129             io_error_if(TIFFSetDirectory(_tp,dirnum)!=1,
130                         "tiff_reader: fail to set directory");
131         }
132     }
~tiff_reader()133     ~tiff_reader() { TIFFClose(_tp); }
134     template <typename View>
apply(const View & view)135     void apply(const View& view) {
136         unsigned short bps,photometric;
137         point2<std::ptrdiff_t> dims=get_dimensions();
138         io_error_if(TIFFGetField(_tp,TIFFTAG_BITSPERSAMPLE,&bps)!=1);
139         io_error_if(TIFFGetField(_tp,TIFFTAG_PHOTOMETRIC,&photometric)!=1);
140         io_error_if(dims!=view.dimensions(),
141                     "tiff_read_view: input view size does not match TIFF file size");
142         io_error_if(tiff_read_support_private<typename channel_type<View>::type,
143                                               typename color_space_type<View>::type>::bit_depth!=bps ||
144                     tiff_read_support_private<typename channel_type<View>::type,
145                                               typename color_space_type<View>::type>::color_type!=photometric,
146                     "tiff_read_view: input view type is incompatible with the image type");
147         std::size_t element_size=sizeof(pixel<typename channel_type<View>::type,
148                                               layout<typename color_space_type<View>::type> >);
149         std::size_t size_to_allocate = (std::max)((std::size_t)view.width(),
150                                                  (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size);
151         std::vector<pixel<typename channel_type<View>::type,
152                           layout<typename color_space_type<View>::type> > > row(size_to_allocate);
153         for (int y=0;y<view.height();++y) {
154             io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
155             std::copy(row.begin(),row.begin()+view.width(),view.row_begin(y));
156         }
157     }
get_dimensions()158     point2<std::ptrdiff_t> get_dimensions() {
159         int w,h;
160         io_error_if(TIFFGetField(_tp,TIFFTAG_IMAGEWIDTH, &w)!=1);
161         io_error_if(TIFFGetField(_tp,TIFFTAG_IMAGELENGTH,&h)!=1);
162         return point2<std::ptrdiff_t>(w,h);
163     }
164 
165     template <typename Image>
read_image(Image & im)166     void read_image(Image& im) {
167         im.recreate(get_dimensions());
168         apply(view(im));
169     }
170 };
171 
172 // This code will be simplified...
173 template <typename CC>
174 class tiff_reader_color_convert : public tiff_reader {
175 private:
176     CC _cc;
177 public:
tiff_reader_color_convert(const char * filename,tdir_t dirnum=0)178     tiff_reader_color_convert(const char* filename,tdir_t dirnum=0) :
179         tiff_reader(filename,dirnum) {}
tiff_reader_color_convert(const char * filename,CC cc_in,tdir_t dirnum=0)180     tiff_reader_color_convert(const char* filename,CC cc_in,tdir_t dirnum=0) :
181         tiff_reader(filename,dirnum),_cc(cc_in) {}
182     template <typename View>
apply(const View & view)183     void apply(const View& view) {
184         point2<std::ptrdiff_t> dims=get_dimensions();
185         unsigned short bps,photometric;
186         io_error_if(TIFFGetField(_tp,TIFFTAG_BITSPERSAMPLE,&bps)!=1);
187         io_error_if(TIFFGetField(_tp,TIFFTAG_PHOTOMETRIC,&photometric)!=1);
188         io_error_if(dims!=view.dimensions(),
189                     "tiff_reader_color_convert::apply(): input view size does not match TIFF file size");
190         switch (photometric) {
191         case PHOTOMETRIC_MINISBLACK: {
192             switch (bps) {
193             case 8: {
194                 std::size_t element_size=sizeof(gray8_pixel_t);
195                 std::size_t size_to_allocate = (std::max)((std::size_t)view.width(),
196                                                           (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size);
197                 std::vector<gray8_pixel_t> row(size_to_allocate);
198                 for (int y=0;y<view.height();++y) {
199                     io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
200                     std::transform(row.begin(),row.begin()+view.width(),view.row_begin(y),
201                                    color_convert_deref_fn<gray8_ref_t,typename View::value_type,CC>(_cc));
202                 }
203                 break;
204             }
205             case 16: {
206                 std::size_t element_size=sizeof(gray16_pixel_t);
207                 std::size_t size_to_allocate = (std::max)((std::size_t)view.width(),
208                                                           (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size);
209                 std::vector<gray16_pixel_t> row(size_to_allocate);
210                 for (int y=0;y<view.height();++y) {
211                     io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
212                     std::transform(row.begin(),row.begin()+view.width(),view.row_begin(y),
213                                    color_convert_deref_fn<gray16_ref_t,typename View::value_type,CC>(_cc));
214                 }
215                 break;
216             }
217             case 32: {
218                 std::size_t element_size=sizeof(gray32f_pixel_t);
219                 std::size_t size_to_allocate = (std::max)((std::size_t)view.width(),
220                                                           (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size);
221                 std::vector<gray32f_pixel_t> row(size_to_allocate);
222                 for (int y=0;y<view.height();++y) {
223                     io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
224                     std::transform(row.begin(),row.begin()+view.width(),view.row_begin(y),
225                                    color_convert_deref_fn<gray32f_ref_t,typename View::value_type,CC>(_cc));
226                 }
227                 break;
228             }
229             default:
230                 io_error("tiff_reader_color_convert::apply(): unknown combination of color type and bit depth");
231             }
232             break;
233         }
234         case PHOTOMETRIC_RGB: {
235             switch (bps) {
236             case 8: {
237                 std::size_t element_size=sizeof(rgb8_pixel_t);
238                 std::size_t size_to_allocate = (std::max)((std::size_t)view.width(),
239                                                           (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size);
240                 std::vector<rgb8_pixel_t> row(size_to_allocate);
241                 for (int y=0;y<view.height();++y) {
242                     io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
243                     std::transform(row.begin(),row.begin()+view.width(),view.row_begin(y),
244                                    color_convert_deref_fn<rgb8_ref_t,typename View::value_type,CC>(_cc));
245                 }
246                 break;
247             }
248             case 16: {
249                 std::size_t element_size=sizeof(rgb16_pixel_t);
250                 std::size_t size_to_allocate = (std::max)((std::size_t)view.width(),
251                                                           (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size);
252                 std::vector<rgb16_pixel_t> row(size_to_allocate);
253                 for (int y=0;y<view.height();++y) {
254                     io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
255                     std::transform(row.begin(),row.begin()+view.width(),view.row_begin(y),
256                                    color_convert_deref_fn<rgb16_ref_t,typename View::value_type,CC>(_cc));
257                 }
258                 break;
259             }
260             case 32: {
261                 std::size_t element_size=sizeof(rgb32f_pixel_t);
262                 std::size_t size_to_allocate = (std::max)((std::size_t)view.width(),
263                                                           (std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size);
264                 std::vector<rgb32f_pixel_t> row(size_to_allocate);
265                 for (int y=0;y<view.height();++y) {
266                     io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
267                     std::transform(row.begin(),row.begin()+view.width(),view.row_begin(y),
268                                    color_convert_deref_fn<rgb32f_ref_t,typename View::value_type,CC>(_cc));
269                 }
270                 break;
271             }
272             default:
273                 io_error("tiff_reader_color_convert::apply(): unknown combination of color type and bit depth");
274             }
275             break;
276         }
277         default: {
278             // reads an image in incompatible format via TIFFReadRGBAImage
279             rgba8_image_t rgbaImg(dims);
280             io_error_if(!TIFFReadRGBAImage(_tp, dims.x, dims.y, (uint32*)&gil::view(rgbaImg)(0,0), 0),
281                 "tiff_reader_color_convert::unsupported image format");
282             copy_and_convert_pixels(flipped_up_down_view(const_view(rgbaImg)), view, _cc);
283         }
284         }
285     }
286     template <typename Image>
read_image(Image & im)287     void read_image(Image& im) {
288         im.recreate(get_dimensions());
289         apply(view(im));
290     }
291 };
292 
293 class tiff_writer {
294 protected:
295     TIFF* _tp;
296 public:
tiff_writer(const char * filename)297     tiff_writer(const char *filename) {
298         io_error_if((_tp=TIFFOpen(filename,"w"))==NULL,
299                     "tiff_writer: fail to open file");
300     }
~tiff_writer()301     ~tiff_writer() {TIFFClose(_tp);}
302     template <typename View>
apply(const View & view)303     void apply(const View& view) {
304         io_error_if(TIFFSetField(_tp,TIFFTAG_IMAGELENGTH, view.height())!=1);
305         io_error_if(TIFFSetField(_tp,TIFFTAG_IMAGEWIDTH, view.width())!=1);
306         io_error_if(TIFFSetField(_tp,TIFFTAG_PHOTOMETRIC, tiff_write_support_private<typename channel_type<View>::type,
307                                                                      typename color_space_type<View>::type>::color_type)!=1);
308         io_error_if(TIFFSetField(_tp,TIFFTAG_RESOLUTIONUNIT, RESUNIT_NONE)!=1);
309         io_error_if(TIFFSetField(_tp,TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)!=1);
310         io_error_if(TIFFSetField(_tp,TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT)!=1);
311         io_error_if(TIFFSetField(_tp,TIFFTAG_SAMPLESPERPIXEL,num_channels<View>::value)!=1);
312         io_error_if(TIFFSetField(_tp,TIFFTAG_BITSPERSAMPLE, tiff_write_support_private<typename channel_type<View>::type,
313                                                                      typename color_space_type<View>::type>::bit_depth)!=1);
314         io_error_if(TIFFSetField(_tp,TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(_tp, 0))!=1);
315         std::vector<pixel<typename channel_type<View>::type,
316                           layout<typename color_space_type<View>::type> > > row(view.width());
317         for (int y=0;y<view.height();++y) {
318             std::copy(view.row_begin(y),view.row_end(y),row.begin());
319             io_error_if(TIFFWriteScanline(_tp,&row.front(),y,0)!=1,
320                         "tiff_write_view: fail to write file");
321         }
322     }
323 };
324 
325 } // namespace detail
326 
327 /// \ingroup TIFF_IO
328 /// \brief Determines whether the given view type is supported for reading
329 template <typename View>
330 struct tiff_read_support {
331     BOOST_STATIC_CONSTANT(bool,is_supported=
332                           (detail::tiff_read_support_private<typename channel_type<View>::type,
333                                                              typename color_space_type<View>::type>::is_supported));
334     BOOST_STATIC_CONSTANT(int,bit_depth=
335                           (detail::tiff_read_support_private<typename channel_type<View>::type,
336                                                              typename color_space_type<View>::type>::bit_depth));
337     BOOST_STATIC_CONSTANT(int,color_type=
338                           (detail::tiff_read_support_private<typename channel_type<View>::type,
339                                                              typename color_space_type<View>::type>::color_type));
340 };
341 
342 /// \ingroup TIFF_IO
343 /// \brief Returns the number of directories in the TIFF file
tiff_get_directory_count(const char * filename)344 inline int tiff_get_directory_count(const char* filename) {
345     TIFF *tif;
346     io_error_if((tif=TIFFOpen(filename,"r"))==NULL,
347                     "tiff_get_count: fail to open file");
348 
349     int dircount = 0;
350     do {
351         dircount++;
352     } while (TIFFReadDirectory(tif));
353 
354     TIFFClose(tif);
355     return dircount;
356 }
357 
358 /// \ingroup TIFF_IO
359 /// \brief Returns the width and height of the TIFF file at the specified location.
360 /// Throws std::ios_base::failure if the location does not correspond to a valid TIFF file
tiff_read_dimensions(const char * filename,tdir_t dirnum=0)361 inline point2<std::ptrdiff_t> tiff_read_dimensions(const char* filename,tdir_t dirnum=0) {
362     detail::tiff_reader m(filename,dirnum);
363     return m.get_dimensions();
364 }
365 
366 /// \ingroup TIFF_IO
367 /// \brief Returns the width and height of the TIFF file at the specified location.
368 /// Throws std::ios_base::failure if the location does not correspond to a valid TIFF file
tiff_read_dimensions(const std::string & filename,tdir_t dirnum=0)369 inline point2<std::ptrdiff_t> tiff_read_dimensions(const std::string& filename,tdir_t dirnum=0) {
370     return tiff_read_dimensions(filename.c_str(),dirnum);
371 }
372 
373 /// \ingroup TIFF_IO
374 /// \brief Loads the image specified by the given tiff image file name into the given view.
375 /// Triggers a compile assert if the view color space and channel depth are not supported by the TIFF library or by the I/O extension.
376 /// Throws std::ios_base::failure if the file is not a valid TIFF file, or if its color space or channel depth are not
377 /// compatible with the ones specified by View, or if its dimensions don't match the ones of the view.
378 template <typename View>
tiff_read_view(const char * filename,const View & view,tdir_t dirnum=0)379 inline void tiff_read_view(const char* filename,const View& view,tdir_t dirnum=0) {
380     BOOST_STATIC_ASSERT(tiff_read_support<View>::is_supported);
381     detail::tiff_reader m(filename,dirnum);
382     m.apply(view);
383 }
384 
385 /// \ingroup TIFF_IO
386 /// \brief Loads the image specified by the given tiff image file name into the given view.
387 template <typename View>
tiff_read_view(const std::string & filename,const View & view,tdir_t dirnum=0)388 inline void tiff_read_view(const std::string& filename,const View& view,tdir_t dirnum=0) {
389     tiff_read_view(filename.c_str(),view,dirnum);
390 }
391 
392 /// \ingroup TIFF_IO
393 /// \brief Allocates a new image whose dimensions are determined by the given tiff image file, and loads the pixels into it.
394 /// Triggers a compile assert if the image color space or channel depth are not supported by the TIFF library or by the I/O extension.
395 /// Throws std::ios_base::failure if the file is not a valid TIFF file, or if its color space or channel depth are not
396 /// compatible with the ones specified by Image
397 template <typename Image>
tiff_read_image(const char * filename,Image & im,tdir_t dirnum=0)398 void tiff_read_image(const char* filename,Image& im,tdir_t dirnum=0) {
399     BOOST_STATIC_ASSERT(tiff_read_support<typename Image::view_t>::is_supported);
400     detail::tiff_reader m(filename,dirnum);
401     m.read_image(im);
402 }
403 
404 /// \ingroup TIFF_IO
405 /// \brief Allocates a new image whose dimensions are determined by the given tiff image file, and loads the pixels into it.
406 template <typename Image>
tiff_read_image(const std::string & filename,Image & im,tdir_t dirnum=0)407 inline void tiff_read_image(const std::string& filename,Image& im,tdir_t dirnum=0) {
408     tiff_read_image(filename.c_str(),im,dirnum);
409 }
410 
411 /// \ingroup TIFF_IO
412 /// \brief Loads and color-converts the image specified by the given tiff image file name into the given view.
413 /// Throws std::ios_base::failure if the file is not a valid TIFF file, or if its dimensions don't match the ones of the view.
414 template <typename View,typename CC>
tiff_read_and_convert_view(const char * filename,const View & view,CC cc,tdir_t dirnum=0)415 inline void tiff_read_and_convert_view(const char* filename,const View& view,CC cc,tdir_t dirnum=0) {
416     detail::tiff_reader_color_convert<CC> m(filename,cc,dirnum);
417     m.apply(view);
418 }
419 
420 /// \ingroup TIFF_IO
421 /// \brief Loads and color-converts the image specified by the given tiff image file name into the given view.
422 /// Throws std::ios_base::failure if the file is not a valid TIFF file, or if its dimensions don't match the ones of the view.
423 template <typename View>
tiff_read_and_convert_view(const char * filename,const View & view,tdir_t dirnum=0)424 inline void tiff_read_and_convert_view(const char* filename,const View& view,tdir_t dirnum=0) {
425     detail::tiff_reader_color_convert<default_color_converter> m(filename,default_color_converter(),dirnum);
426     m.apply(view);
427 }
428 
429 /// \ingroup TIFF_IO
430 /// \brief Loads and color-converts the image specified by the given tiff image file name into the given view.
431 template <typename View,typename CC>
tiff_read_and_convert_view(const std::string & filename,const View & view,CC cc,tdir_t dirnum=0)432 inline void tiff_read_and_convert_view(const std::string& filename,const View& view,CC cc,tdir_t dirnum=0) {
433     tiff_read_and_convert_view(filename.c_str(),view,cc,dirnum);
434 }
435 
436 /// \ingroup TIFF_IO
437 /// \brief Loads and color-converts the image specified by the given tiff image file name into the given view.
438 template <typename View>
tiff_read_and_convert_view(const std::string & filename,const View & view,tdir_t dirnum=0)439 inline void tiff_read_and_convert_view(const std::string& filename,const View& view,tdir_t dirnum=0) {
440     tiff_read_and_convert_view(filename.c_str(),view,dirnum);
441 }
442 
443 /// \ingroup TIFF_IO
444 /// \brief Allocates a new image whose dimensions are determined by the given tiff image file, loads and color-converts the pixels into it.
445 /// Throws std::ios_base::failure if the file is not a valid TIFF file
446 template <typename Image,typename CC>
tiff_read_and_convert_image(const char * filename,Image & im,CC cc,tdir_t dirnum=0)447 void tiff_read_and_convert_image(const char* filename,Image& im,CC cc,tdir_t dirnum=0) {
448     detail::tiff_reader_color_convert<CC> m(filename,cc,dirnum);
449     m.read_image(im);
450 }
451 
452 /// \ingroup TIFF_IO
453 /// \brief Allocates a new image whose dimensions are determined by the given tiff image file, loads and color-converts the pixels into it.
454 /// Throws std::ios_base::failure if the file is not a valid TIFF file
455 template <typename Image>
tiff_read_and_convert_image(const char * filename,Image & im,tdir_t dirnum=0)456 void tiff_read_and_convert_image(const char* filename,Image& im,tdir_t dirnum=0) {
457     detail::tiff_reader_color_convert<default_color_converter> m(filename,default_color_converter(),dirnum);
458     m.read_image(im);
459 }
460 
461 /// \ingroup TIFF_IO
462 /// \brief Allocates a new image whose dimensions are determined by the given tiff image file, loads and color-converts the pixels into it.
463 template <typename Image,typename CC>
tiff_read_and_convert_image(const std::string & filename,Image & im,CC cc,tdir_t dirnum=0)464 inline void tiff_read_and_convert_image(const std::string& filename,Image& im,CC cc,tdir_t dirnum=0) {
465     tiff_read_and_convert_image(filename.c_str(),im,cc,dirnum);
466 }
467 
468 /// \ingroup TIFF_IO
469 /// \brief Allocates a new image whose dimensions are determined by the given tiff image file, loads and color-converts the pixels into it.
470 template <typename Image>
tiff_read_and_convert_image(const std::string & filename,Image & im,tdir_t dirnum=0)471 inline void tiff_read_and_convert_image(const std::string& filename,Image& im,tdir_t dirnum=0) {
472     tiff_read_and_convert_image(filename.c_str(),im,dirnum);
473 }
474 
475 /// \ingroup TIFF_IO
476 /// \brief Determines whether the given view type is supported for writing
477 template <typename View>
478 struct tiff_write_support {
479     BOOST_STATIC_CONSTANT(bool,is_supported=
480                           (detail::tiff_write_support_private<typename channel_type<View>::type,
481                                                               typename color_space_type<View>::type>::is_supported));
482     BOOST_STATIC_CONSTANT(int,bit_depth=
483                           (detail::tiff_write_support_private<typename channel_type<View>::type,
484                                                               typename color_space_type<View>::type>::bit_depth));
485     BOOST_STATIC_CONSTANT(int,color_type=
486                           (detail::tiff_write_support_private<typename channel_type<View>::type,
487                                                               typename color_space_type<View>::type>::color_type));
488     BOOST_STATIC_CONSTANT(bool, value=is_supported);
489 };
490 
491 /// \ingroup TIFF_IO
492 /// \brief Saves the view to a tiff file specified by the given tiff image file name.
493 /// Triggers a compile assert if the view color space and channel depth are not supported by the TIFF library or by the I/O extension.
494 /// Throws std::ios_base::failure if it fails to create the file.
495 template <typename View>
tiff_write_view(const char * filename,const View & view)496 inline void tiff_write_view(const char* filename,const View& view) {
497     BOOST_STATIC_ASSERT(tiff_write_support<View>::is_supported);
498     detail::tiff_writer m(filename);
499     m.apply(view);
500 }
501 
502 /// \ingroup TIFF_IO
503 /// \brief Saves the view to a tiff file specified by the given tiff image file name.
504 template <typename View>
tiff_write_view(const std::string & filename,const View & view)505 inline void tiff_write_view(const std::string& filename,const View& view) {
506     tiff_write_view(filename.c_str(),view);
507 }
508 
509 } }  // namespace boost::gil
510 
511 #endif
512