]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/gil/extension/io/bmp/detail/reader_backend.hpp
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / boost / boost / gil / extension / io / bmp / detail / reader_backend.hpp
1 //
2 // Copyright 2012 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_BMP_DETAIL_READER_BACKEND_HPP
9 #define BOOST_GIL_EXTENSION_IO_BMP_DETAIL_READER_BACKEND_HPP
10
11 #include <boost/gil/extension/io/bmp/tags.hpp>
12
13 namespace boost { namespace gil {
14
15 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
16 #pragma warning(push)
17 #pragma warning(disable:4512) //assignment operator could not be generated
18 #endif
19
20 /// Color channel mask
21 struct bit_field
22 {
23 unsigned int mask; // Bit mask at corresponding position
24 unsigned int width; // Bit width of the mask
25 unsigned int shift; // Bit position from right to left
26 };
27
28 /// BMP color masks
29 struct color_mask
30 {
31 bit_field red; // Red bits
32 bit_field green; // Green bits
33 bit_field blue; // Blue bits
34 };
35
36
37 ///
38 /// BMP Backend
39 ///
40 template< typename Device >
41 struct reader_backend< Device
42 , bmp_tag
43 >
44 {
45 public:
46
47 using format_tag_t = bmp_tag;
48
49 public:
50
51 reader_backend( const Device& io_dev
52 , const image_read_settings< bmp_tag >& settings
53 )
54 : _io_dev ( io_dev )
55 , _settings( settings )
56 , _info()
57 , _scanline_length( 0 )
58 , _palette()
59 {
60 read_header();
61
62 if( _settings._dim.x == 0 )
63 {
64 _settings._dim.x = _info._width;
65 }
66
67 if( _settings._dim.y == 0 )
68 {
69 _settings._dim.y = _info._height;
70 }
71 }
72
73 void read_header()
74 {
75 // the magic number used to identify the BMP file:
76 // 0x42 0x4D (ASCII code points for B and M)
77 if( _io_dev.read_uint16() == 0x424D )
78 {
79 io_error( "Wrong magic number for bmp file." );
80 }
81
82 // the size of the BMP file in bytes
83 _io_dev.read_uint32();
84
85 // reserved; actual value depends on the application that creates the image
86 _io_dev.read_uint16();
87 // reserved; actual value depends on the application that creates the image
88 _io_dev.read_uint16();
89
90 _info._offset = _io_dev.read_uint32();
91
92
93 // bitmap information
94
95 // the size of this header ( 40 bytes )
96 _info._header_size = _io_dev.read_uint32();
97
98 if( _info._header_size == bmp_header_size::_win32_info_size )
99 {
100 _info._width = _io_dev.read_uint32();
101 _info._height = _io_dev.read_uint32();
102
103 if (_info._height < 0)
104 {
105 _info._height = -_info._height;
106 _info._top_down = true;
107 }
108
109 // the number of color planes being used. Must be set to 1.
110 _io_dev.read_uint16();
111
112 _info._bits_per_pixel = _io_dev.read_uint16();
113
114 _info._compression = _io_dev.read_uint32();
115
116 _info._image_size = _io_dev.read_uint32();
117
118 _info._horizontal_resolution = _io_dev.read_uint32();
119 _info._vertical_resolution = _io_dev.read_uint32();
120
121 _info._num_colors = _io_dev.read_uint32();
122 _info._num_important_colors = _io_dev.read_uint32();
123
124 }
125 else if( _info._header_size == bmp_header_size::_os2_info_size )
126 {
127 _info._width = static_cast< bmp_image_width::type >( _io_dev.read_uint16() );
128 _info._height = static_cast< bmp_image_height::type >( _io_dev.read_uint16() );
129
130 // the number of color planes being used. Must be set to 1.
131 _io_dev.read_uint16();
132
133 _info._bits_per_pixel = _io_dev.read_uint16();
134
135 _info._compression = bmp_compression::_rgb;
136
137 // not used
138 _info._image_size = 0;
139 _info._horizontal_resolution = 0;
140 _info._vertical_resolution = 0;
141 _info._num_colors = 0;
142 _info._num_important_colors = 0;
143 }
144 else if (_info._header_size > bmp_header_size::_win32_info_size)
145 {
146 // could be v4 or v5
147 // see MSDN: Bitmap Header Types ( BITMAPV4HEADER or BITMAPV5HEADER )
148
149 _info._width = _io_dev.read_uint32();
150 _info._height = _io_dev.read_uint32();
151
152 // the number of color planes being used. Must be set to 1.
153 _io_dev.read_uint16();
154
155 _info._bits_per_pixel = _io_dev.read_uint16();
156
157 _info._compression = _io_dev.read_uint32();
158
159 _info._image_size = _io_dev.read_uint32();
160
161 _info._horizontal_resolution = _io_dev.read_uint32();
162 _info._vertical_resolution = _io_dev.read_uint32();
163
164 _info._num_colors = _io_dev.read_uint32();
165 _info._num_important_colors = _io_dev.read_uint32();
166 }
167 else
168 {
169 io_error( "Invalid BMP info header." );
170 }
171
172 _info._valid = true;
173 }
174
175 void read_palette()
176 {
177 int entries = this->_info._num_colors;
178
179 if( entries == 0 )
180 {
181 entries = 1u << this->_info._bits_per_pixel;
182 }
183
184 _palette.resize( entries, rgba8_pixel_t(0, 0, 0, 0));
185
186 for( int i = 0; i < entries; ++i )
187 {
188 get_color( _palette[i], blue_t() ) = _io_dev.read_uint8();
189 get_color( _palette[i], green_t() ) = _io_dev.read_uint8();
190 get_color( _palette[i], red_t() ) = _io_dev.read_uint8();
191
192 // there are 4 entries when windows header
193 // but 3 for os2 header
194 if( _info._header_size == bmp_header_size::_win32_info_size )
195 {
196 _io_dev.read_uint8();
197 }
198
199 } // for
200 }
201
202 /// Check if image is large enough.
203 void check_image_size( const point_t& img_dim )
204 {
205 if( _settings._dim.x > 0 )
206 {
207 if( img_dim.x < _settings._dim.x ) { io_error( "Supplied image is too small" ); }
208 }
209 else
210 {
211 if( img_dim.x < _info._width ) { io_error( "Supplied image is too small" ); }
212 }
213
214
215 if( _settings._dim.y > 0 )
216 {
217 if( img_dim.y < _settings._dim.y ) { io_error( "Supplied image is too small" ); }
218 }
219 else
220 {
221 if( img_dim.y < _info._height ) { io_error( "Supplied image is too small" ); }
222 }
223 }
224
225 public:
226
227 Device _io_dev;
228
229 image_read_settings< bmp_tag > _settings;
230 image_read_info< bmp_tag > _info;
231
232 std::size_t _scanline_length;
233
234 ///@todo make it an image.
235 std::vector< rgba8_pixel_t > _palette;
236
237 color_mask _mask;
238 };
239
240 #if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
241 #pragma warning(pop)
242 #endif
243
244 } // namespace gil
245 } // namespace boost
246
247 #endif