]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/gil/extension/io/tiff/detail/scanline_read.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / gil / extension / io / tiff / detail / scanline_read.hpp
1 //
2 // Copyright 2007-2012 Christian Henning, Lubomir Bourdev
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_SCANLINE_READ_HPP
9 #define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_SCANLINE_READ_HPP
10
11 #include <boost/gil/extension/io/tiff/detail/device.hpp>
12 #include <boost/gil/extension/io/tiff/detail/is_allowed.hpp>
13 #include <boost/gil/extension/io/tiff/detail/reader_backend.hpp>
14
15 #include <boost/gil/io/base.hpp>
16 #include <boost/gil/io/bit_operations.hpp>
17 #include <boost/gil/io/conversion_policies.hpp>
18 #include <boost/gil/io/device.hpp>
19 #include <boost/gil/io/reader_base.hpp>
20 #include <boost/gil/io/row_buffer_helper.hpp>
21 #include <boost/gil/io/scanline_read_iterator.hpp>
22
23 #include <algorithm>
24 #include <functional>
25 #include <string>
26 #include <type_traits>
27 #include <vector>
28
29 // taken from jpegxx - https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/ijg_headers.hpp
30 #ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
31 extern "C" {
32 #endif
33
34 #include <tiff.h>
35 #include <tiffio.h>
36
37 #ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
38 }
39 #endif
40
41 namespace boost { namespace gil {
42
43 ///
44 /// TIFF scanline reader
45 ///
46 template< typename Device >
47 class scanline_reader< Device
48 , tiff_tag
49 >
50 : public reader_backend< Device
51 , tiff_tag
52 >
53 {
54 public:
55
56 using tag_t = tiff_tag;
57 using backend_t = reader_backend<Device, tag_t>;
58 using this_t = scanline_reader<Device, tag_t>;
59 using iterator_t = scanline_read_iterator<this_t>;
60
61 scanline_reader( Device& device
62 , const image_read_settings< tiff_tag >& settings
63 )
64 : backend_t( device
65 , settings
66 )
67 {
68 initialize();
69 }
70
71 /// Read part of image defined by View and return the data.
72 void read( byte_t* dst, int pos )
73 {
74 _read_function( this, dst, pos );
75 }
76
77 /// Skip over a scanline.
78 void skip( byte_t* dst, int pos )
79 {
80 this->_read_function( this, dst, pos );
81 }
82
83 iterator_t begin() { return iterator_t( *this ); }
84 iterator_t end() { return iterator_t( *this, this->_info._height ); }
85
86 private:
87
88 void initialize()
89 {
90 io_error_if( this->_info._is_tiled
91 , "scanline_reader doesn't support tiled tiff images."
92 );
93
94 if( this->_info._photometric_interpretation == PHOTOMETRIC_PALETTE )
95 {
96
97 this->_scanline_length = this->_info._width
98 * num_channels< rgb16_view_t >::value
99 * sizeof( channel_type<rgb16_view_t>::type );
100
101 this->_io_dev.get_field_defaulted( this->_red
102 , this->_green
103 , this->_blue
104 );
105
106 _buffer = std::vector< byte_t >( this->_io_dev.get_scanline_size() );
107
108 switch( this->_info._bits_per_sample )
109 {
110 case 1:
111 {
112 using channel_t = channel_type<get_pixel_type<gray1_image_t::view_t>::type>::type;
113
114 int num_colors = channel_traits< channel_t >::max_value() + 1;
115
116 this->_palette = planar_rgb_view( num_colors
117 , 1
118 , this->_red
119 , this->_green
120 , this->_blue
121 , sizeof(uint16_t) * num_colors
122 );
123
124 _read_function = std::mem_fn(&this_t::read_1_bit_index_image);
125
126 break;
127 }
128
129 case 2:
130 {
131 using channel_t = channel_type<get_pixel_type<gray2_image_t::view_t>::type>::type;
132
133 int num_colors = channel_traits< channel_t >::max_value() + 1;
134
135 this->_palette = planar_rgb_view( num_colors
136 , 1
137 , this->_red
138 , this->_green
139 , this->_blue
140 , sizeof(uint16_t) * num_colors
141 );
142
143 _read_function = std::mem_fn(&this_t::read_2_bits_index_image);
144
145 break;
146 }
147 case 4:
148 {
149 using channel_t = channel_type<get_pixel_type<gray4_image_t::view_t>::type>::type;
150
151 int num_colors = channel_traits< channel_t >::max_value() + 1;
152
153 this->_palette = planar_rgb_view( num_colors
154 , 1
155 , this->_red
156 , this->_green
157 , this->_blue
158 , sizeof(uint16_t) * num_colors
159 );
160
161 _read_function = std::mem_fn(&this_t::read_4_bits_index_image);
162
163 break;
164 }
165
166 case 8:
167 {
168 using channel_t = channel_type<get_pixel_type<gray8_image_t::view_t>::type>::type;
169
170 int num_colors = channel_traits< channel_t >::max_value() + 1;
171
172 this->_palette = planar_rgb_view( num_colors
173 , 1
174 , this->_red
175 , this->_green
176 , this->_blue
177 , sizeof(uint16_t) * num_colors
178 );
179
180 _read_function = std::mem_fn(&this_t::read_8_bits_index_image);
181
182 break;
183 }
184
185 case 16:
186 {
187 using channel_t = channel_type<get_pixel_type<gray16_image_t::view_t>::type>::type;
188
189 int num_colors = channel_traits< channel_t >::max_value() + 1;
190
191 this->_palette = planar_rgb_view( num_colors
192 , 1
193 , this->_red
194 , this->_green
195 , this->_blue
196 , sizeof(uint16_t) * num_colors
197 );
198
199 _read_function = std::mem_fn(&this_t::read_16_bits_index_image);
200
201 break;
202 }
203
204 case 24:
205 {
206 using channel_t = channel_type<get_pixel_type<gray24_image_t::view_t>::type>::type;
207
208 int num_colors = channel_traits< channel_t >::max_value() + 1;
209
210 this->_palette = planar_rgb_view( num_colors
211 , 1
212 , this->_red
213 , this->_green
214 , this->_blue
215 , sizeof(uint16_t) * num_colors
216 );
217
218 _read_function = std::mem_fn(&this_t::read_24_bits_index_image);
219
220 break;
221 }
222
223 case 32:
224 {
225 using channel_t = channel_type<get_pixel_type<gray32_image_t::view_t>::type>::type;
226
227 int num_colors = channel_traits< channel_t >::max_value() + 1;
228
229 this->_palette = planar_rgb_view( num_colors
230 , 1
231 , this->_red
232 , this->_green
233 , this->_blue
234 , sizeof(uint16_t) * num_colors
235 );
236
237 _read_function = std::mem_fn(&this_t::read_32_bits_index_image);
238
239 break;
240 }
241 default: { io_error( "Not supported palette " ); }
242 }
243 }
244 else
245 {
246 this->_scanline_length = this->_io_dev.get_scanline_size();
247
248 if( this->_info._planar_configuration == PLANARCONFIG_SEPARATE )
249 {
250 io_error( "scanline_reader doesn't support planar tiff images." );
251 }
252 else if( this->_info._planar_configuration == PLANARCONFIG_CONTIG )
253 {
254
255 // the read_data function needs to know what gil type the source image is
256 // to have the default color converter function correctly
257
258 switch( this->_info._photometric_interpretation )
259 {
260 case PHOTOMETRIC_MINISWHITE:
261 case PHOTOMETRIC_MINISBLACK:
262 {
263 switch( this->_info._bits_per_sample )
264 {
265 case 1:
266 case 2:
267 case 4:
268 case 6:
269 case 8:
270 case 10:
271 case 12:
272 case 14:
273 case 16:
274 case 24:
275 case 32: { _read_function = std::mem_fn(&this_t::read_row); break; }
276 default: { io_error( "Image type is not supported." ); }
277 }
278
279 break;
280 }
281
282 case PHOTOMETRIC_RGB:
283 {
284 switch( this->_info._samples_per_pixel )
285 {
286 case 3:
287 {
288 switch( this->_info._bits_per_sample )
289 {
290 case 2:
291 case 4:
292 case 8:
293 case 10:
294 case 12:
295 case 14:
296 case 16:
297 case 24:
298 case 32: { _read_function = std::mem_fn(&this_t::read_row); break; }
299 default: { io_error( "Image type is not supported." ); }
300 }
301
302 break;
303 }
304
305 case 4:
306 {
307 switch( this->_info._bits_per_sample )
308 {
309 case 2:
310 case 4:
311 case 8:
312 case 10:
313 case 12:
314 case 14:
315 case 16:
316 case 24:
317 case 32: { _read_function = std::mem_fn(&this_t::read_row); break; }
318 default: { io_error( "Image type is not supported." ); }
319 }
320
321 break;
322 }
323
324 default: { io_error( "Image type is not supported." ); }
325 }
326
327 break;
328 }
329 case PHOTOMETRIC_SEPARATED: // CYMK
330 {
331 switch( this->_info._bits_per_sample )
332 {
333 case 2:
334 case 4:
335 case 8:
336 case 10:
337 case 12:
338 case 14:
339 case 16:
340 case 24:
341 case 32: { _read_function = std::mem_fn(&this_t::read_row); break; }
342 default: { io_error( "Image type is not supported." ); }
343 }
344
345 break;
346 }
347
348 default: { io_error( "Image type is not supported." ); }
349 }
350 }
351 else
352 {
353 io_error( "Wrong planar configuration setting." );
354 }
355 }
356 }
357
358 template< typename Src_View >
359 void read_n_bits_row( byte_t* dst, int pos )
360 {
361 using dst_view_t = rgb16_view_t;
362
363 this->_io_dev.read_scanline( _buffer
364 , pos
365 , 0
366 );
367
368 Src_View src_view = interleaved_view( this->_info._width
369 , 1
370 , (typename Src_View::x_iterator) &_buffer.front()
371 , this->_scanline_length
372 );
373
374 dst_view_t dst_view = interleaved_view( this->_info._width
375 , 1
376 , (typename dst_view_t::value_type*) dst
377 , num_channels< dst_view_t >::value * 2 * this->_info._width
378 );
379
380
381 typename Src_View::x_iterator src_it = src_view.row_begin( 0 );
382 typename dst_view_t::x_iterator dst_it = dst_view.row_begin( 0 );
383
384 for( dst_view_t::x_coord_t i = 0
385 ; i < this->_info._width
386 ; ++i, src_it++, dst_it++
387 )
388 {
389 auto const c = static_cast<std::uint16_t>(get_color(*src_it, gray_color_t()));
390 *dst_it = this->_palette[c];
391 }
392 }
393
394 void read_1_bit_index_image( byte_t* dst, int pos )
395 {
396 read_n_bits_row< gray1_image_t::view_t >( dst, pos );
397 }
398
399 void read_2_bits_index_image( byte_t* dst, int pos )
400 {
401 read_n_bits_row< gray2_image_t::view_t >( dst, pos );
402 }
403
404 void read_4_bits_index_image( byte_t* dst, int pos )
405 {
406 read_n_bits_row< gray4_image_t::view_t >( dst, pos );
407 }
408
409 void read_8_bits_index_image( byte_t* dst, int pos )
410 {
411 read_n_bits_row< gray8_image_t::view_t >( dst, pos );
412 }
413
414 void read_16_bits_index_image( byte_t* dst, int pos )
415 {
416 read_n_bits_row< gray16_image_t::view_t >( dst, pos );
417 }
418
419 void read_24_bits_index_image( byte_t* dst, int pos )
420 {
421 read_n_bits_row< gray24_image_t::view_t >( dst, pos );
422 }
423
424 void read_32_bits_index_image( byte_t* dst, int pos )
425 {
426 read_n_bits_row< gray32_image_t::view_t >( dst, pos );
427 }
428
429 void read_row(byte_t* dst, int pos )
430 {
431 this->_io_dev.read_scanline( dst
432 , pos
433 , 0
434 );
435 }
436
437 private:
438
439 std::vector< byte_t> _buffer;
440 detail::mirror_bits<std::vector<byte_t>, std::true_type> _mirror_bites;
441 std::function<void(this_t*, byte_t*, int)> _read_function;
442 };
443
444 } // namespace gil
445 } // namespace boost
446
447 #endif