]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/gil/extension/io/tiff/detail/device.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / gil / extension / io / tiff / detail / device.hpp
1 //
2 // Copyright 2007-2008 Andreas Pokorny, Christian Henning
3 //
4 // Distributed under the Boost Software License, Version 1.0
5 // See accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt
7 //
8 #ifndef BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_DEVICE_HPP
9 #define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_DEVICE_HPP
10
11 #include <boost/gil/extension/io/tiff/tags.hpp>
12 #include <boost/gil/extension/io/tiff/detail/log.hpp>
13 #include <boost/gil/detail/mp11.hpp>
14 #include <boost/gil/io/base.hpp>
15 #include <boost/gil/io/device.hpp>
16
17 #include <algorithm>
18 #include <memory>
19 #include <sstream>
20 #include <type_traits>
21
22 // taken from jpegxx - https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/ijg_headers.hpp
23 #ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
24 extern "C" {
25 #endif
26
27 #include <tiff.h>
28 #include <tiffio.h>
29
30 #ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
31 }
32 #endif
33
34 #include <tiffio.hxx>
35
36 namespace boost { namespace gil { namespace detail {
37
38 template <int n_args>
39 struct get_property_f {
40 template <typename Property>
41 bool call_me(typename Property:: type& value, std::shared_ptr<TIFF>& file);
42 };
43
44 template <int n_args>
45 struct set_property_f {
46 template <typename Property>
47 bool call_me(const typename Property:: type& value, std::shared_ptr<TIFF>& file) const;
48 };
49
50 template <> struct get_property_f <1>
51 {
52 // For single-valued properties
53 template <typename Property>
54 bool call_me(typename Property::type & value, std::shared_ptr<TIFF>& file) const
55 {
56 // @todo: defaulted, really?
57 return (1 == TIFFGetFieldDefaulted( file.get()
58 , Property:: tag
59 , & value));
60 }
61 };
62
63 template <> struct get_property_f <2>
64 {
65 // Specialisation for multi-valued properties. @todo: add one of
66 // these for the three-parameter fields too.
67 template <typename Property>
68 bool call_me(typename Property::type& vs, std::shared_ptr<TIFF>& file) const
69 {
70 mp11::mp_at<typename Property::arg_types, std::integral_constant<int, 0>> length;
71 mp11::mp_at<typename Property::arg_types, std::integral_constant<int, 1>> pointer;
72 if (1 == TIFFGetFieldDefaulted(file.get(), Property:: tag, & length, & pointer))
73 {
74 std:: copy_n(static_cast<typename Property::type::const_pointer>(pointer), length, std:: back_inserter(vs));
75 return true;
76 } else
77 return false;
78 }
79 };
80
81 template <> struct set_property_f <1>
82 {
83 // For single-valued properties
84 template <typename Property>
85 inline
86 bool call_me(typename Property:: type const & value, std::shared_ptr<TIFF>& file) const
87 {
88 return (1 == TIFFSetField( file.get()
89 , Property:: tag
90 , value));
91 }
92 };
93
94 template <> struct set_property_f <2>
95 {
96 // Specialisation for multi-valued properties. @todo: add one
97 // of these for the three-parameter fields too. Actually we
98 // will need further templation / specialisation for the
99 // two-element fields which aren't a length and a data buffer
100 // (e.g. http://www.awaresystems.be/imaging/tiff/tifftags/dotrange.html
101 // )
102 template <typename Property>
103 inline
104 bool call_me(typename Property:: type const & values, std::shared_ptr<TIFF>& file) const
105 {
106 using length_t = mp11::mp_at_c<typename Property::arg_types, 0>;
107 auto const length = static_cast<length_t>(values.size());
108
109 using pointer_t = mp11::mp_at_c<typename Property::arg_types, 1>;
110 auto const pointer = static_cast<pointer_t>(&(values.front()));
111 return (1 == TIFFSetField( file.get(), Property:: tag, length, pointer));
112 }
113 };
114
115 template< typename Log >
116 class tiff_device_base
117 {
118 public:
119 using tiff_file_t = std::shared_ptr<TIFF>;
120
121 tiff_device_base()
122 {}
123
124 tiff_device_base( TIFF* tiff_file )
125 : _tiff_file( tiff_file
126 , TIFFClose )
127 {}
128
129 template <typename Property>
130 bool get_property( typename Property::type& value )
131 {
132 return get_property_f<mp11::mp_size<typename Property::arg_types>::value>().template call_me<Property>(value, _tiff_file);
133 }
134
135 template <typename Property>
136 inline
137 bool set_property( const typename Property::type& value )
138 {
139 // http://www.remotesensing.org/libtiff/man/TIFFSetField.3tiff.html
140 return set_property_f<mp11::mp_size<typename Property::arg_types>::value>().template call_me<Property>(value, _tiff_file);
141 }
142
143 // TIFFIsByteSwapped returns a non-zero value if the image data was in a different
144 // byte-order than the host machine. Zero is returned if the TIFF file and local
145 // host byte-orders are the same. Note that TIFFReadTile(), TIFFReadStrip() and TIFFReadScanline()
146 // functions already normally perform byte swapping to local host order if needed.
147 bool are_bytes_swapped()
148 {
149 return ( TIFFIsByteSwapped( _tiff_file.get() )) ? true : false;
150 }
151
152 bool is_tiled() const
153 {
154 return ( TIFFIsTiled( _tiff_file.get() )) ? true : false;
155 }
156
157 unsigned int get_default_strip_size()
158 {
159 return TIFFDefaultStripSize( _tiff_file.get()
160 , 0 );
161 }
162
163 std::size_t get_scanline_size()
164 {
165 return TIFFScanlineSize( _tiff_file.get() );
166 }
167
168 std::size_t get_tile_size()
169 {
170 return TIFFTileSize( _tiff_file.get() );
171 }
172
173
174 int get_field_defaulted( uint16_t*& red
175 , uint16_t*& green
176 , uint16_t*& blue
177 )
178 {
179 return TIFFGetFieldDefaulted( _tiff_file.get()
180 , TIFFTAG_COLORMAP
181 , &red
182 , &green
183 , &blue
184 );
185 }
186
187 template< typename Buffer >
188 void read_scanline( Buffer& buffer
189 , std::ptrdiff_t row
190 , tsample_t plane
191 )
192 {
193 io_error_if( TIFFReadScanline( _tiff_file.get()
194 , reinterpret_cast< tdata_t >( &buffer.front() )
195 , (uint32) row
196 , plane ) == -1
197 , "Read error."
198 );
199 }
200
201 void read_scanline( byte_t* buffer
202 , std::ptrdiff_t row
203 , tsample_t plane
204 )
205 {
206 io_error_if( TIFFReadScanline( _tiff_file.get()
207 , reinterpret_cast< tdata_t >( buffer )
208 , (uint32) row
209 , plane ) == -1
210 , "Read error."
211 );
212 }
213
214 template< typename Buffer >
215 void read_tile( Buffer& buffer
216 , std::ptrdiff_t x
217 , std::ptrdiff_t y
218 , std::ptrdiff_t z
219 , tsample_t plane
220 )
221 {
222 if( TIFFReadTile( _tiff_file.get()
223 , reinterpret_cast< tdata_t >( &buffer.front() )
224 , (uint32) x
225 , (uint32) y
226 , (uint32) z
227 , plane
228 ) == -1 )
229 {
230 std::ostringstream oss;
231 oss << "Read tile error (" << x << "," << y << "," << z << "," << plane << ").";
232 io_error(oss.str().c_str());
233 }
234 }
235
236 template< typename Buffer >
237 void write_scaline( Buffer& buffer
238 , uint32 row
239 , tsample_t plane
240 )
241 {
242 io_error_if( TIFFWriteScanline( _tiff_file.get()
243 , &buffer.front()
244 , row
245 , plane
246 ) == -1
247 , "Write error"
248 );
249 }
250
251 void write_scaline( byte_t* buffer
252 , uint32 row
253 , tsample_t plane
254 )
255 {
256 io_error_if( TIFFWriteScanline( _tiff_file.get()
257 , buffer
258 , row
259 , plane
260 ) == -1
261 , "Write error"
262 );
263 }
264
265 template< typename Buffer >
266 void write_tile( Buffer& buffer
267 , uint32 x
268 , uint32 y
269 , uint32 z
270 , tsample_t plane
271 )
272 {
273 if( TIFFWriteTile( _tiff_file.get()
274 , &buffer.front()
275 , x
276 , y
277 , z
278 , plane
279 ) == -1 )
280 {
281 std::ostringstream oss;
282 oss << "Write tile error (" << x << "," << y << "," << z << "," << plane << ").";
283 io_error(oss.str().c_str());
284 }
285 }
286
287 void set_directory( tdir_t directory )
288 {
289 io_error_if( TIFFSetDirectory( _tiff_file.get()
290 , directory
291 ) != 1
292 , "Failing to set directory"
293 );
294 }
295
296 // return false if the given tile width or height is not TIFF compliant (multiple of 16) or larger than image size, true otherwise
297 bool check_tile_size( tiff_tile_width::type& width
298 , tiff_tile_length::type& height
299
300 )
301 {
302 bool result = true;
303 uint32 tw = static_cast< uint32 >( width );
304 uint32 th = static_cast< uint32 >( height );
305
306 TIFFDefaultTileSize( _tiff_file.get()
307 , &tw
308 , &th
309 );
310
311 if(width==0 || width%16!=0)
312 {
313 width = tw;
314 result = false;
315 }
316 if(height==0 || height%16!=0)
317 {
318 height = th;
319 result = false;
320 }
321 return result;
322 }
323
324 protected:
325
326 tiff_file_t _tiff_file;
327
328 Log _log;
329 };
330
331 /*!
332 *
333 * file_stream_device specialization for tiff images, which are based on TIFF*.
334 */
335 template<>
336 class file_stream_device< tiff_tag > : public tiff_device_base< tiff_no_log >
337 {
338 public:
339
340 struct read_tag {};
341 struct write_tag {};
342
343 file_stream_device( std::string const& file_name, read_tag )
344 {
345 TIFF* tiff;
346
347 io_error_if( ( tiff = TIFFOpen( file_name.c_str(), "r" )) == nullptr
348 , "file_stream_device: failed to open file" );
349
350 _tiff_file = tiff_file_t( tiff, TIFFClose );
351 }
352
353 file_stream_device( std::string const& file_name, write_tag )
354 {
355 TIFF* tiff;
356
357 io_error_if( ( tiff = TIFFOpen( file_name.c_str(), "w" )) == nullptr
358 , "file_stream_device: failed to open file" );
359
360 _tiff_file = tiff_file_t( tiff, TIFFClose );
361 }
362
363 file_stream_device( TIFF* tiff_file )
364 : tiff_device_base( tiff_file )
365 {}
366 };
367
368 /*!
369 *
370 * ostream_device specialization for tiff images.
371 */
372 template<>
373 class ostream_device< tiff_tag > : public tiff_device_base< tiff_no_log >
374 {
375 public:
376 ostream_device( std::ostream & out )
377 : _out( out )
378 {
379 TIFF* tiff;
380
381 io_error_if( ( tiff = TIFFStreamOpen( ""
382 , &_out
383 )
384 ) == nullptr
385 , "ostream_device: failed to stream"
386 );
387
388 _tiff_file = tiff_file_t( tiff, TIFFClose );
389 }
390
391 private:
392 ostream_device& operator=( const ostream_device& ) { return *this; }
393
394 private:
395
396 std::ostream& _out;
397 };
398
399 /*!
400 *
401 * ostream_device specialization for tiff images.
402 */
403 template<>
404 class istream_device< tiff_tag > : public tiff_device_base< tiff_no_log >
405 {
406 public:
407 istream_device( std::istream & in )
408 : _in( in )
409 {
410 TIFF* tiff;
411
412 io_error_if( ( tiff = TIFFStreamOpen( ""
413 , &_in
414 )
415 ) == nullptr
416 , "istream_device: failed to stream"
417 );
418
419 _tiff_file = tiff_file_t( tiff, TIFFClose );
420 }
421
422 private:
423 istream_device& operator=( const istream_device& ) { return *this; }
424
425 private:
426
427 std::istream& _in;
428 };
429
430 /*
431 template< typename T, typename D >
432 struct is_adaptable_input_device< tiff_tag, T, D > : std::false_type {};
433 */
434
435 template<typename FormatTag>
436 struct is_adaptable_input_device<FormatTag, TIFF*, void> : std::true_type
437 {
438 using device_type = file_stream_device<FormatTag>;
439 };
440
441 template<typename FormatTag>
442 struct is_adaptable_output_device<FormatTag, TIFF*, void> : std::true_type
443 {
444 using device_type = file_stream_device<FormatTag>;
445 };
446
447
448 template <typename Channel>
449 struct sample_format : std::integral_constant<int, SAMPLEFORMAT_UINT> {};
450 template<>
451 struct sample_format<uint8_t> : std::integral_constant<int, SAMPLEFORMAT_UINT> {};
452 template<>
453 struct sample_format<uint16_t> : std::integral_constant<int, SAMPLEFORMAT_UINT> {};
454 template<>
455 struct sample_format<uint32_t> : std::integral_constant<int, SAMPLEFORMAT_UINT> {};
456 template<>
457 struct sample_format<float32_t> : std::integral_constant<int, SAMPLEFORMAT_IEEEFP> {};
458 template<>
459 struct sample_format<double> : std::integral_constant<int, SAMPLEFORMAT_IEEEFP> {};
460 template<>
461 struct sample_format<int8_t> : std::integral_constant<int, SAMPLEFORMAT_INT> {};
462 template<>
463 struct sample_format<int16_t> : std::integral_constant<int, SAMPLEFORMAT_INT> {};
464 template<>
465 struct sample_format<int32_t> : std::integral_constant<int, SAMPLEFORMAT_INT> {};
466
467 template <typename Channel>
468 struct photometric_interpretation {};
469 template<>
470 struct photometric_interpretation<gray_t>
471 : std::integral_constant<int, PHOTOMETRIC_MINISBLACK> {};
472 template<>
473 struct photometric_interpretation<rgb_t>
474 : std::integral_constant<int, PHOTOMETRIC_RGB> {};
475 template<>
476 struct photometric_interpretation<rgba_t>
477 : std::integral_constant<int, PHOTOMETRIC_RGB> {};
478 template<>
479 struct photometric_interpretation<cmyk_t>
480 : std::integral_constant<int, PHOTOMETRIC_SEPARATED> {};
481
482 } // namespace detail
483 } // namespace gil
484 } // namespace boost
485
486 #endif