1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
// float2bmp2.hpp
//
// Copyright 2010 Michael Thomas Greer
// Distributed under the Boost Software License, Version 1.0.
// (See http://www.boost.org/LICENSE_1_0.txt )
//
#pragma once
#ifndef FLOAT2BMP2_HPP
#define FLOAT2BMP2_HPP
#include <fstream>
#include <iostream>
namespace float2bmp2
{
//--------------------------------------------------------------------------
// This little helper is to write little-endian values to file.
//
struct lwrite
{
unsigned long value;
unsigned size;
lwrite( unsigned long value, unsigned size ):
value( value ), size( size )
{ }
};
//--------------------------------------------------------------------------
inline std::ostream& operator << ( std::ostream& outs, const lwrite& v )
{
unsigned long value = v.value;
for (unsigned cntr = 0; cntr < v.size; cntr++, value >>= 8)
outs.put( static_cast <char> (value & 0xFF) );
return outs;
}
//--------------------------------------------------------------------------
template <typename Iterator>
bool
floats_to_bitmap_file(
const char* filename,
Iterator begin,
Iterator end,
size_t rows,
size_t columns,
unsigned char default_value = 0
) {
std::ofstream f( filename, std::ios::out | std::ios::trunc | std::ios::binary );
if (!f) return false;
// Some basic
unsigned long headers_size = 14 // sizeof( BITMAPFILEHEADER )
+ 40; // sizeof( BITMAPINFOHEADER )
unsigned long padding_size = (4 - ((columns * 3) % 4)) % 4;
unsigned long pixel_data_size = rows * ((columns * 3) + padding_size);
// Write the BITMAPFILEHEADER
f.put( 'B' ).put( 'M' ); // bfType
f << lwrite( headers_size + pixel_data_size, 4 ); // bfSize
f << lwrite( 0, 2 ); // bfReserved1
f << lwrite( 0, 2 ); // bfReserved2
f << lwrite( headers_size, 4 ); // bfOffBits
// Write the BITMAPINFOHEADER
f << lwrite( 40, 4 ); // biSize
f << lwrite( columns, 4 ); // biWidth
f << lwrite( rows, 4 ); // biHeight
f << lwrite( 1, 2 ); // biPlanes
f << lwrite( 24, 2 ); // biBitCount
f << lwrite( 0, 4 ); // biCompression=BI_RGB
f << lwrite( pixel_data_size, 4 ); // biSizeImage
f << lwrite( 0, 4 ); // biXPelsPerMeter
f << lwrite( 0, 4 ); // biYPelsPerMeter
f << lwrite( 0, 4 ); // biClrUsed
f << lwrite( 0, 4 ); // biClrImportant
// Write the pixel data
for (unsigned row = rows; row; row--) // bottom-to-top
{
for (unsigned col = 0; col < columns; col++) // left-to-right
{
unsigned char value;
double d = 0.0;
// If we haven't overrun the end of our input, convert it to a grayscale value.
// Input is clamped to the range [0, 1], where 0 --> black and 1 --> white.
if (begin != end)
{
d = *begin++;
if (d < 0.0) d = 0.0;
else if (d > 1.0) d = 1.0;
value = 255 * d;
}
// Otherwise we just use the default grayscale value
else value = default_value;
f.put( static_cast <char> (value) )
.put( static_cast <char> (value) )
.put( static_cast <char> (value) );
}
if (padding_size) f << lwrite( 0, padding_size );
}
// All done!
return f.good();
}
} // namespace float2bmp2
#endif
// end float2bmp2.hpp
|