55 std::shared_ptr<utils::BaseOutputTarget> target
57 auto& outstream = target->ostream();
60 auto const width = image.
cols();
64 size_t const row_pad = (4 - (( width * 3 ) % 4 )) % 4;
67 size_t const line_len = width * 3 + row_pad;
68 assert(( row_pad < 4 ) && ( line_len % 4 == 0 ));
71 size_t const data_size = line_len *
height;
75 height >
static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) ||
76 width >
static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) ||
77 14 + 40 + data_size >
static_cast<size_t>( std::numeric_limits<uint32_t>::max() )
79 throw std::runtime_error(
80 "Cannot save Bitmap larger than " +
85 assert( data_size <=
static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) );
86 assert(
height <=
static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) );
87 assert( width <=
static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) );
91 file_header.
bfSize = 14 + 40 +
static_cast<uint32_t
>( data_size );
96 info_header.
biWidth =
static_cast<uint32_t
>( width );
101 write_file_header_( file_header, outstream );
102 write_info_header_( info_header, outstream );
105 for(
size_t yr = 0; yr <
height; ++yr ) {
109 for(
size_t x = 0; x < width; ++x ) {
112 auto const& color = image( y, x );
113 outstream.put( color.b_byte() );
114 outstream.put( color.g_byte() );
115 outstream.put( color.r_byte() );
119 for(
size_t x = 0; x < row_pad; ++x ) {
131 std::shared_ptr<utils::BaseOutputTarget> target
134 auto palette = std::vector<Color>( 256 );
135 for(
size_t i = 0; i < 256; ++i ) {
136 palette[i].r_byte( i );
137 palette[i].g_byte( i );
138 palette[i].b_byte( i );
140 write( image, palette, target );
149 std::vector<Color>
const& palette,
150 std::shared_ptr<utils::BaseOutputTarget> target
152 auto& outstream = target->ostream();
155 auto const width = image.
cols();
159 size_t const row_pad = (4 - ( width % 4 )) % 4;
162 size_t const line_len = width + row_pad;
163 assert(( row_pad < 4 ) && ( line_len % 4 == 0 ));
166 size_t const data_size = line_len *
height;
170 height >
static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) ||
171 width >
static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) ||
172 14 + 40 + 256 * 4 + data_size >
static_cast<size_t>( std::numeric_limits<uint32_t>::max() )
174 throw std::runtime_error(
175 "Cannot save Bitmap larger than " +
180 assert( data_size <=
static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) );
181 assert(
height <=
static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) );
182 assert( width <=
static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) );
186 file_header.
bfSize = 14 + 40 + 256 * 4 +
static_cast<uint32_t
>( data_size );
187 file_header.
bfOffBits = 14 + 40 + 256 * 4;
196 if( palette.size() != 256 ) {
197 throw std::invalid_argument(
"Bitmap color palette needs to have 256 entries." );
201 info.
bmiColors = std::vector<RgbQuad>( 256 );
202 for(
size_t i = 0; i < 256; ++i ) {
203 info.
bmiColors[i].rgbBlue = palette[i].b_byte();
204 info.
bmiColors[i].rgbGreen = palette[i].g_byte();
205 info.
bmiColors[i].rgbRed = palette[i].r_byte();
209 write_file_header_( file_header, outstream );
210 write_info_( info, outstream );
213 for(
size_t yr = 0; yr <
height; ++yr ) {
217 for(
size_t x = 0; x < width; ++x ) {
218 outstream.put( image( y, x ));
222 for(
size_t x = 0; x < row_pad; ++x ) {
232 void BmpWriter::write_uint16_( uint16_t data, std::ostream& target )
const
234 auto const bytes =
reinterpret_cast< uint8_t const*
>( &data );
237 if( is_little_endian ) {
238 target.put( bytes[0] );
239 target.put( bytes[1] );
241 target.put( bytes[1] );
242 target.put( bytes[0] );
246 void BmpWriter::write_uint32_( uint32_t data, std::ostream& target )
const
248 auto const bytes =
reinterpret_cast< uint8_t const*
>( &data );
251 if( is_little_endian ) {
252 target.put( bytes[0] );
253 target.put( bytes[1] );
254 target.put( bytes[2] );
255 target.put( bytes[3] );
257 target.put( bytes[3] );
258 target.put( bytes[2] );
259 target.put( bytes[1] );
260 target.put( bytes[0] );
264 void BmpWriter::write_file_header_( BitmapFileheader
const& header, std::ostream& target )
const
266 write_uint16_( header.bfType, target );
267 write_uint32_( header.bfSize, target );
268 write_uint16_( header.bfReserved1, target );
269 write_uint16_( header.bfReserved2, target );
270 write_uint32_( header.bfOffBits, target );
273 void BmpWriter::write_info_header_( BitmapInfoheader
const& header, std::ostream& target )
const
275 write_uint32_( header.biSize, target );
276 write_uint32_( header.biWidth, target );
277 write_uint32_( header.biHeight, target );
278 write_uint16_( header.biPlanes, target );
279 write_uint16_( header.biBitCount, target );
280 write_uint32_( header.biCompression, target );
281 write_uint32_( header.biSizeImage, target );
282 write_uint32_( header.biXPelsPerMeter, target );
283 write_uint32_( header.biYPelsPerMeter, target );
284 write_uint32_( header.biClrUsed, target );
285 write_uint32_( header.biClrImportant, target );
288 void BmpWriter::write_info_( BitmapInfo
const& info, std::ostream& target )
const
290 write_info_header_( info.bmiHeader, target );
291 for(
auto const& c : info.bmiColors ) {
292 target.put( c.rgbBlue );
293 target.put( c.rgbGreen );
294 target.put( c.rgbRed );
295 target.put( c.rgbReserved );