56 auto const width = image.
cols();
60 size_t const row_pad = (4 - (( width * 3 ) % 4 )) % 4;
63 size_t const line_len = width * 3 + row_pad;
64 assert(( row_pad < 4 ) && ( line_len % 4 == 0 ));
67 size_t const data_size = line_len *
height;
71 height > static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) ||
72 width > static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) ||
73 14 + 40 + data_size > static_cast<size_t>( std::numeric_limits<uint32_t>::max() )
75 throw std::runtime_error(
76 "Cannot save Bitmap larger than " +
81 assert( data_size <= static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) );
82 assert( height <= static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) );
83 assert( width <= static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) );
87 file_header.
bfSize = 14 + 40 +
static_cast<uint32_t
>( data_size );
92 info_header.
biWidth =
static_cast<uint32_t
>( width );
97 write_file_header_( file_header, outstream );
98 write_info_header_( info_header, outstream );
101 for(
size_t yr = 0; yr <
height; ++yr ) {
103 auto y = height - 1 - yr;
105 for(
size_t x = 0; x < width; ++x ) {
108 auto const& color = image( y, x );
109 outstream.put( color.b_byte() );
110 outstream.put( color.g_byte() );
111 outstream.put( color.r_byte() );
115 for(
size_t x = 0; x < row_pad; ++x ) {
135 auto palette = std::vector<Color>( 256 );
136 for(
size_t i = 0; i < 256; ++i ) {
137 palette[i].r_byte( i );
138 palette[i].g_byte( i );
139 palette[i].b_byte( i );
159 auto const width = image.
cols();
163 size_t const row_pad = (4 - ( width % 4 )) % 4;
166 size_t const line_len = width + row_pad;
167 assert(( row_pad < 4 ) && ( line_len % 4 == 0 ));
170 size_t const data_size = line_len *
height;
174 height > static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) ||
175 width > static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) ||
176 14 + 40 + 256 * 4 + data_size > static_cast<size_t>( std::numeric_limits<uint32_t>::max() )
178 throw std::runtime_error(
179 "Cannot save Bitmap larger than " +
184 assert( data_size <= static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) );
185 assert( height <= static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) );
186 assert( width <= static_cast<size_t>( std::numeric_limits<uint32_t>::max() ) );
190 file_header.
bfSize = 14 + 40 + 256 * 4 +
static_cast<uint32_t
>( data_size );
191 file_header.
bfOffBits = 14 + 40 + 256 * 4;
200 if( palette.size() != 256 ) {
201 throw std::invalid_argument(
"Bitmap color palette needs to have 256 entries." );
205 info.
bmiColors = std::vector<RgbQuad>( 256 );
206 for(
size_t i = 0; i < 256; ++i ) {
207 info.
bmiColors[i].rgbBlue = palette[i].b_byte();
208 info.
bmiColors[i].rgbGreen = palette[i].g_byte();
209 info.
bmiColors[i].rgbRed = palette[i].r_byte();
213 write_file_header_( file_header, outstream );
214 write_info_( info, outstream );
217 for(
size_t yr = 0; yr <
height; ++yr ) {
219 auto y = height - 1 - yr;
221 for(
size_t x = 0; x < width; ++x ) {
222 outstream.put( image( y, x ));
226 for(
size_t x = 0; x < row_pad; ++x ) {
244 void BmpWriter::write_uint16_( uint16_t data, std::ostream& target )
const 246 auto const bytes =
reinterpret_cast< uint8_t const*
>( &data );
249 target.put( bytes[0] );
250 target.put( bytes[1] );
252 target.put( bytes[1] );
253 target.put( bytes[0] );
257 void BmpWriter::write_uint32_( uint32_t data, std::ostream& target )
const 259 auto const bytes =
reinterpret_cast< uint8_t const*
>( &data );
262 target.put( bytes[0] );
263 target.put( bytes[1] );
264 target.put( bytes[2] );
265 target.put( bytes[3] );
267 target.put( bytes[3] );
268 target.put( bytes[2] );
269 target.put( bytes[1] );
270 target.put( bytes[0] );
274 void BmpWriter::write_file_header_(
BitmapFileheader const& header, std::ostream& target )
const 276 write_uint16_( header.
bfType, target );
277 write_uint32_( header.
bfSize, target );
280 write_uint32_( header.
bfOffBits, target );
283 void BmpWriter::write_info_header_(
BitmapInfoheader const& header, std::ostream& target )
const 285 write_uint32_( header.
biSize, target );
286 write_uint32_( header.
biWidth, target );
287 write_uint32_( header.
biHeight, target );
288 write_uint16_( header.
biPlanes, target );
294 write_uint32_( header.
biClrUsed, target );
298 void BmpWriter::write_info_(
BitmapInfo const& info, std::ostream& target )
const 300 write_info_header_( info.
bmiHeader, target );
302 target.put( c.rgbBlue );
303 target.put( c.rgbGreen );
304 target.put( c.rgbRed );
305 target.put( c.rgbReserved );
Bitmap info that describes dimensions and color information.
void file_output_stream(std::string const &filename, std::ofstream &out_stream, std::ios_base::openmode mode=std::ios_base::out)
Helper function to obtain an output stream to a file.
Container namespace for all symbols of genesis in order to keep them separate when used as a library...
void to_stream(Matrix< Color > const &image, std::ostream &outstream) const
Write a full 24bit RGB Color image to a stream.
BitmapInfoheader bmiHeader
double height(Tree const &tree)
Get the height of the tree, i.e., the longest distance from the root to a leaf, measured using the br...
Provides functions for accessing the file system.
void to_file(Matrix< Color > const &image, std::string const &filename) const
Write a full 24bit RGB Color image to a file.
std::vector< RgbQuad > bmiColors
std::shared_ptr< BaseOutputTarget > to_string(std::string &target_string)
Obtain an output target for writing to a string.
static bool is_little_endian()
Return whether the system uses little endian memory.