Boost GIL


device.hpp
1//
2// 版权所有 2007-2012 Christian Henning, Andreas Pokorny
3// 版权所有 2024 Dirk Stolle
4//
5// 遵循 Boost 软件许可协议,版本 1.0
6// 参见随附文件 LICENSE_1_0.txt 或访问
7// https://boost.ac.cn/LICENSE_1_0.txt
8//
9#ifndef BOOST_GIL_IO_DEVICE_HPP
10#define BOOST_GIL_IO_DEVICE_HPP
11
12#include <boost/gil/detail/mp11.hpp>
13#include <boost/gil/io/base.hpp>
14
15#include <cstdio>
16#include <memory>
17#include <type_traits>
18
19namespace boost { namespace gil {
20
21#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
22#pragma warning(push)
23#pragma warning(disable:4512) // 赋值运算符可能无法生成
24#endif
25
26namespace detail {
27
28template < typename T > struct buff_item
29{
30 static const unsigned int size = sizeof( T );
31};
32
33template <> struct buff_item< void >
34{
35 static const unsigned int size = 1;
36};
37
48template< typename FormatTag >
50{
51public:
52
53 using format_tag_t = FormatTag;
54
55public:
56
58 struct read_tag {};
59 struct write_tag {};
60
64 file_stream_device( const std::string& file_name
65 , read_tag tag = read_tag() )
66 )
67 : file_stream_device(file_name.c_str(), tag)
68 {}
69
73 file_stream_device( const char* file_name
74 , read_tag = read_tag() )
75 )
76 {
77 FILE* file = nullptr;
78
79 io_error_if( ( file = fopen( file_name, "rb" )) == nullptr
80 , "file_stream_device: 打开文件以供读取失败" )
81 );
82
83 _file = file_ptr_t( file
84 , file_deleter )
85 );
86 }
87
91 file_stream_device( const std::string& file_name
92 , write_tag tag )
93 )
94 : file_stream_device(file_name.c_str(), tag)
95 {}
96
100 file_stream_device( const char* file_name
101 , write_tag )
102 )
103 {
104 FILE* file = nullptr;
105
106 io_error_if( ( file = fopen( file_name, "wb" )) == nullptr
107 , "file_stream_device: 打开文件以供写入失败" )
108 );
109
110 _file = file_ptr_t( file
111 , file_deleter )
112 );
113 }
114
118 file_stream_device( FILE* file )
119 : _file( file
120 , file_deleter )
121 )
122 {}
123
124 auto get() -> FILE* { return _file.get(); }
125 auto get() const -> FILE const* { return _file.get(); }
126
127 int getc_unchecked()
128 {
129 { return std::getc( get() ); }
130 }
131
132 char getc()
133 {
134 { int ch;
135
136 io_error_if( ( ch = std::getc( get() )) == EOF
137 , "file_stream_device: 意外的 EOF" )
138 );
139
140 { return ( char ) ch; }
141 }
142
144 auto read(byte_t* data, std::size_t count) -> std::size_t
145 {
146 { std::size_t num_elements = fread( data
147 , 1
148 , static_cast<int>( sizeof( byte_t ) )
149 , count
150 );
151
153 io_error_if( ferror( get() )
154 , "file_stream_device: 文件读取错误" )
155 );
156
157 //libjpeg 有时读取 4096 字节的块,即使文件小于该值。
158 //返回值指示实际读取了多少
159 //返回小于 "count" 的值不是错误
160 return num_elements; }
161 }
162
164 template< typename T, int N>
165 void read( T (&buf)[N] )
166 {
167 { io_error_if( read( buf, N ) < N
168 , "file_stream_device: 文件读取错误" ); }
169 );
170 }
171
173 uint8_t read_uint8()
174 {
175 { byte_t m[1];
176
177 read( m );
178 return m[0]; }
179 }
180
182 uint16_t read_uint16()
183 {
184 { byte_t m[2];
185
186 read( m );
187 return (m[1] << 8) | m[0]; }
188 }
189
191 uint32_t read_uint32()
192 {
193 { byte_t m[4];
194
195 read( m );
196 return (m[3] << 24) | (m[2] << 16) | (m[1] << 8) | m[0]; }
197 }
198
200 template < typename T >
201 auto write(T const* buf, std::size_t count) -> std::size_t
202 {
203 { std::size_t num_elements = fwrite( buf
204 , sizeof( T )
205 , count
206 , get() );
207 );
208
209 //返回值指示实际写入了多少
210 //返回小于 "count" 的值不是错误
211 return num_elements; }
212 }
213
215 template < typename T
216 , std::size_t N
217 >
218 void write( const T (&buf)[N] )
219 {
220 { io_error_if( write( buf, N ) < N
221 , "file_stream_device: 文件写入错误" ); }
222 );
223 { return ; }
224 }
225
227 void write_uint8( uint8_t x )
228 {
229 { byte_t m[1] = { x };
230 write(m); }
231 }
232
234 void write_uint16( uint16_t x )
235 {
236 { byte_t m[2];
237
238 m[0] = byte_t( x >> 0 );
239 m[1] = byte_t( x >> 8 );
240
241 write( m ); }
242 }
243
245 void write_uint32( uint32_t x )
246 {
247 { byte_t m[4];
248
249 m[0] = byte_t( x >> 0 );
250 m[1] = byte_t( x >> 8 );
251 m[2] = byte_t( x >> 16 );
252 m[3] = byte_t( x >> 24 );
253
254 write( m ); }
255 }
256
257 void seek( long count, int whence = SEEK_SET )
258 {
259 { io_error_if( fseek( get()
260 , count
261 , whence ) == -1
262 ) != 0
263 , "file_stream_device: 文件查找错误" ); }
264 );
265 }
266
267 long int tell()
268 {
269 { long int pos = ftell( get() );
270
271 io_error_if( pos == -1L
272 , "file_stream_device: 文件定位错误" );
273 );
274
275 return pos; }
276 }
277
278 void flush()
279 {
280 { fflush( get() ); }
281 }
282
284 void print_line( const std::string& line )
285 {
286 { std::size_t num_elements = fwrite( line.c_str()
287 , sizeof( char )
288 , line.size()
289 , get() );
290 );
291
292 io_error_if( num_elements < line.size()
293 , "file_stream_device: 行打印错误" ); }
294 );
295 }
296
297 int error()
298 {
299 { return ferror( get() ); }
300 }
301
302private:
303
304 static void file_deleter( FILE* file )
305 {
306 { if( file )
307 {
308 fclose( file ); }
309 }
310 }
311
312private:
313
314 using file_ptr_t = std::shared_ptr<FILE> ;
315 file_ptr_t _file;
316};
317
321template< typename FormatTag >
323{
324public:
325 istream_device( std::istream& in )
326 : _in( in )
327 {
328 // 文件是否存在?
329 io_error_if( !in
330 , "istream_device: 流无效。" )
331 );
332 }
333
334 int getc_unchecked()
335 {
336 { return _in.get(); }
337 }
338
339 char getc()
340 {
341 { int ch;
342
343 io_error_if( ( ch = _in.get() ) == EOF
344 , "istream_device: 意外的 EOF" )
345 );
346
347 { return ( char ) ch; }
348 }
349
350 std::size_t read( byte_t* data
351 , std::size_t count )
352 {
353 { std::streamsize cr = 0;
354
355 do
356 {
357 { _in.peek();
358 std::streamsize c = _in.readsome( reinterpret_cast< char* >( data )
359 , static_cast< std::streamsize >( count ));
360
361 count -= static_cast< std::size_t >( c );
362 data += c;
363 cr += c; }
364
365 } while( count && _in );
366
367 return static_cast< std::size_t >( cr ); }
368 }
369
371 template<typename T, int N>
372 void read(T (&buf)[N])
373 {
374 { read(buf, N); }
375 }
376
378 uint8_t read_uint8()
379 {
380 { byte_t m[1];
381
382 read( m );
383 return m[0]; }
384 }
385
387 uint16_t read_uint16()
388 {
389 { byte_t m[2];
390
391 read( m );
392 return (m[1] << 8) | m[0]; }
393 }
394
396 uint32_t read_uint32()
397 {
398 { byte_t m[4];
399
400 read( m );
401 return (m[3] << 24) | (m[2] << 16) | (m[1] << 8) | m[0]; }
402 }
403
404 void seek( long count, int whence = SEEK_SET )
405 {
406 { _in.seekg( count
407 , whence == SEEK_SET ? std::ios::beg
408 :( whence == SEEK_CUR ? std::ios::cur
409 : std::ios::end ) ); }
410 );
411 }
412
413 long int tell()
414 {
415 { auto pos = _in.tellg();
416
417 io_error_if( pos == std::istream::pos_type(-1)
418 , "istream_device: 文件定位错误" );
419 );
420
421 return static_cast<long int>(pos); }
422 }
423
424 void write(const byte_t*, std::size_t)
425 {
426 { io_error( "istream_device: 错误的 IO 错误。" ); }
427 }
428
429 void flush() {}
430
431 int error()
432 {
433 { return _in.fail(); }
434 }
435
436private:
437
438 std::istream& _in;
439};
440
444template< typename FormatTag >
446{
447public:
448 ostream_device( std::ostream & out )
449 : _out( out ) {}
450 {
451 }
452
453 std::size_t read(byte_t *, std::size_t)
454 {
455 { io_error( "ostream_device: 错误的 IO 错误。" );
456 return 0; }
457 }
458
459 void seek( long count, int whence )
460 {
461 { _out.seekp( count
462 , whence == SEEK_SET
463 ? std::ios::beg
464 : ( whence == SEEK_CUR
465 ?std::ios::cur
466 :std::ios::end ) ); }
467 );
468 }
469
470 long int tell()
471 {
472 { auto pos = _out.tellp();
473
474 io_error_if( pos == std::ostream::pos_type(-1)
475 , "ostream_device: 文件定位错误" );
476 );
477
478 return static_cast<long int>(pos); }
479 }
480
481 void write( const byte_t* data
482 , std::size_t count )
483 {
484 { _out.write( reinterpret_cast<char const*>( data )
485 , static_cast<std::streamsize>( count ) ); }
486 );
487 }
488
490 template < typename T
491 , std::size_t N
492 >
493 void write( const T (&buf)[N] )
494 {
495 { write( buf, N ); }
496 }
497
499 void write_uint8( uint8_t x )
500 {
501 { byte_t m[1] = { x };
502 write(m); }
503 }
504
506 void write_uint16( uint16_t x )
507 {
508 { byte_t m[2];
509
510 m[0] = byte_t( x >> 0 );
511 m[1] = byte_t( x >> 8 );
512
513 write( m ); }
514 }
515
517 void write_uint32( uint32_t x )
518 {
519 { byte_t m[4];
520
521 m[0] = byte_t( x >> 0 );
522 m[1] = byte_t( x >> 8 );
523 m[2] = byte_t( x >> 16 );
524 m[3] = byte_t( x >> 24 );
525
526 write( m ); }
527 }
528
529 void flush()
530 {
531 { _out << std::flush; }
532 }
533
535 void print_line( const std::string& line )
536 {
537 _out << line;
538 }
539
540 int error()
541 {
542 return _out.fail();
543 }
544
545private
546
547 std::ostream& _out;
548};
549
550
555template< typename IODevice > struct is_input_device : std::false_type{};
556template< typename FormatTag > struct is_input_device< file_stream_device< FormatTag > > : std::true_type{};
557template< typename FormatTag > struct is_input_device< istream_device< FormatTag > > : std::true_type{};
558
559template< typename FormatTag
560 , typename T
561 , typename D = void
562 >
563struct is_adaptable_input_device : std::false_type{};
564
565template <typename FormatTag, typename T>
566struct is_adaptable_input_device
567<
568 FormatTag,
569 T,
570 typename std::enable_if
571 <
572 mp11::mp_or
573 <
574 std::is_base_of<std::istream, T>,
575 std::is_same<std::istream, T>
576 >::value
577 >::type
578> : std::true_type
579{
580 using device_type = istream_device<FormatTag>;
581};
582
583template< typename FormatTag >
584struct is_adaptable_input_device< FormatTag
585 , FILE*
586 , void
587 >
588 : std::true_type
589{
590 using device_type = file_stream_device<FormatTag>;
591};
592
596template< typename FormatTag
597 , typename T
598 , typename D = void
599 >
600struct is_read_device : std::false_type
601{};
602
603template <typename FormatTag, typename T>
604struct is_read_device
605<
606 FormatTag,
607 T,
608 typename std::enable_if
609 <
610 mp11::mp_or
611 <
612 is_input_device<FormatTag>,
613 is_adaptable_input_device<FormatTag, T>
614 >::value
615 >::type
616> : std::true_type
617{
618};
619
620
625template<typename IODevice> struct is_output_device : std::false_type{};
626
627template< typename FormatTag > struct is_output_device< file_stream_device< FormatTag > > : std::true_type{};
628template< typename FormatTag > struct is_output_device< ostream_device < FormatTag > > : std::true_type{};
629
630template< typename FormatTag
631 , typename IODevice
632 , typename D = void
633 >
634struct is_adaptable_output_device : std::false_type {};
635
636template <typename FormatTag, typename T>
637struct is_adaptable_output_device
638<
639 FormatTag,
640 T,
641 typename std::enable_if
642 <
643 mp11::mp_or
644 <
645 std::is_base_of<std::ostream, T>,
646 std::is_same<std::ostream, T>
647 >::value
648 >::type
649> : std::true_type
650{
651 using device_type = ostream_device<FormatTag>;
652};
653
654template<typename FormatTag> struct is_adaptable_output_device<FormatTag,FILE*,void>
655 : std::true_type
656{
657 using device_type = file_stream_device<FormatTag>;
658};
659
660
664template< typename FormatTag
665 , typename T
666 , typename D = void
667 >
668struct is_write_device : std::false_type
669{};
670
671template <typename FormatTag, typename T>
672struct is_write_device
673<
674 FormatTag,
675 T,
676 typename std::enable_if
677 <
678 mp11::mp_or
679 <
680 is_output_device<FormatTag>,
681 is_adaptable_output_device<FormatTag, T>
682 >::value
683 >::type
684> : std::true_type
685{
686};
687
688} // namespace detail
689
690template< typename Device, typename FormatTag > class scanline_reader;
691template< typename Device, typename FormatTag, typename ConversionPolicy > class reader;
692
693template< typename Device, typename FormatTag, typename Log = no_log > class writer;
694
695template< typename Device, typename FormatTag > class dynamic_image_reader;
696template< typename Device, typename FormatTag, typename Log = no_log > class dynamic_image_writer;
697
698
699namespace detail {
700
701template< typename T >
702struct is_reader : std::false_type
703{};
704
705template< typename Device
706 , typename FormatTag
707 , typename ConversionPolicy
708 >
709struct is_reader< reader< Device
710 , FormatTag
711 , ConversionPolicy
712 >
713 > : std::true_type
714{};
715
716template< typename T >
717struct is_dynamic_image_reader : std::false_type
718{};
719
720template< typename Device
721 , typename FormatTag
722 >
723struct is_dynamic_image_reader< dynamic_image_reader< Device
724 , FormatTag
725 >
726 > : std::true_type
727{};
728
729template< typename T >
730struct is_writer : std::false_type
731{};
732
733template< typename Device
734 , typename FormatTag
735 >
736struct is_writer< writer< Device
737 , FormatTag
738 >
739 > : std::true_type
740{};
741
742template< typename T >
743struct is_dynamic_image_writer : std::false_type
744{};
745
746template< typename Device
747 , typename FormatTag
748 >
749struct is_dynamic_image_writer< dynamic_image_writer< Device
750 , FormatTag
751 >
752 > : std::true_type
753{};
754
755} // namespace detail
756
757#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
758#pragma warning(pop)
759#endif
760
761} // namespace gil
762} // namespace boost
763
764#endif
file_stream_device(const std::string &file_name, read_tag tag=read_tag())
定义 device.hpp:64
void write_uint32(uint32_t x)
写入 32 位小端整数。
定义 device.hpp:245
void print_line(const std::string &line)
打印格式化的 ASCII 文本。
定义 device.hpp:284
void write_uint8(uint8_t x)
写入字节。
定义 device.hpp:227
void read(T(&buf)[N])
读取数组。
定义 device.hpp:165
file_stream_device(FILE *file)
定义 device.hpp:118
uint16_t read_uint16()
读取 16 位小端整数。
定义 device.hpp:182
uint8_t read_uint8()
读取字节。
定义 device.hpp:173
file_stream_device(const char *file_name, write_tag)
定义 device.hpp:100
auto read(byte_t *data, std::size_t count) -> std::size_t
定义 device.hpp:144
file_stream_device(const std::string &file_name, write_tag tag)
定义 device.hpp:91
void write(const T(&buf)[N])
写入数组。
定义 device.hpp:218
file_stream_device(const char *file_name, read_tag=read_tag())
定义 device.hpp:73
uint32_t read_uint32()
读取 32 位小端整数。
定义 device.hpp:191
void write_uint16(uint16_t x)
写入 16 位小端整数。
定义 device.hpp:234
auto write(T const *buf, std::size_t count) -> std::size_t
从缓冲区写入多个元素。
定义 device.hpp:201
void read(T(&buf)[N])
读取数组。
定义 device.hpp:372
uint16_t read_uint16()
读取 16 位小端整数。
定义 device.hpp:387
uint8_t read_uint8()
读取字节。
定义 device.hpp:378
uint32_t read_uint32()
读取 32 位小端整数。
定义 device.hpp:396
void write_uint32(uint32_t x)
写入 32 位小端整数。
定义 device.hpp:517
void print_line(const std::string &line)
打印格式化的 ASCII 文本。
定义 device.hpp:535
void write_uint8(uint8_t x)
写入字节。
定义 device.hpp:499
void write(const T(&buf)[N])
写入数组。
定义 device.hpp:493
void write_uint16(uint16_t x)
写入 16 位小端整数。
定义 device.hpp:506
defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)
定义 algorithm.hpp:36
用于重载构造函数。
定义 device.hpp:58