Skip to content

Instantly share code, notes, and snippets.

@duckie duckie/write_bmp_image.cc
Last active Aug 29, 2015

Embed
What would you like to do?
Generate an image in Microsoft BMP format
#include <sstream>
#include <string>
#include <vector>
#include <fstream>
#include <cstdint>
#include <array>
using UChar = uint8_t;
using Color = std::array<UChar, 3>;
using Image = std::vector<Color>;
Color constexpr bottom_left = Color {{0,0,0}};
Color constexpr top_left = Color {{255,0,0}};
Color constexpr top_right = Color {{0,255,0}};
Color constexpr bottom_right = Color {{0,0,255}};
size_t constexpr sqr_max_dist = 255*255;
size_t computeColorWeight(size_t distance_to_target) {
distance_to_target = (sqr_max_dist < distance_to_target) ? sqr_max_dist : distance_to_target;
return sqr_max_dist - distance_to_target;
}
template <typename F, typename T> void binaryWrite(F& stream, T const & data) {
stream.write(reinterpret_cast<char const *>(&data), sizeof(T));
}
int main(int argc, char* argv[]) {
size_t width = 800u;
size_t height = 600u;
std::string filename = "file.bmp";
if (1 < argc)
filename = argv[1];
if (3 < argc) {
std::istringstream(std::string(argv[2])) >> width;
std::istringstream(std::string(argv[3])) >> height;
}
// Generating an image in BGR (instead of RGB)
size_t size = width*height;
Image img(size, {{0, 0, 0}});
for (size_t line=0; line < height; ++line) {
for (size_t column=0; column < width; ++column) {
UChar color_line = static_cast<UChar>(255u*line/(height-1));
UChar color_column = static_cast<UChar>(255u*column/(width-1));
size_t local_bottom_left = computeColorWeight(color_line*color_line + color_column*color_column);
size_t local_top_left = computeColorWeight((255u - color_line)*(255u-color_line) + color_column*color_column);
size_t local_top_right = computeColorWeight((255u - color_line)*(255u-color_line) + (255u-color_column)*(255u-color_column));
size_t local_bottom_right = computeColorWeight(color_line*color_line + (255u-color_column)*(255u-color_column));
Color & target = img[line*width + column];
for(size_t index=0; index < 3u; ++index)
target[index] = static_cast<uint8_t>((local_bottom_left*bottom_left[index] + local_top_left*top_left[index] + local_top_right*top_right[index] + local_bottom_right*bottom_right[index])/(sqr_max_dist));
}
}
// Writing a BMP file
uint32_t offset =
2u // File type
+ 4u // File size
+ 4u // Reserved field
+ 4u // Image offset
+ 40u // Image header
;
size_t nb_padding_octets = width%4;
size_t image_data_size = 3u*size + height*nb_padding_octets;
uint32_t file_size = offset + image_data_size;
std::ofstream file(filename.c_str(), std::ios::binary | std::ios::out);
if (file) {
// Write the header
binaryWrite(file, uint16_t(0x4d42)); // File type
binaryWrite(file, file_size);
binaryWrite(file, uint32_t(0));
binaryWrite(file, offset);
// Image header
binaryWrite(file, uint32_t(0x0028)); // Img header size
binaryWrite(file, uint32_t(width));
binaryWrite(file, uint32_t(height));
binaryWrite(file, uint16_t(1)); // Nb layers
binaryWrite(file, uint16_t(24u)); // Color depht
binaryWrite(file, uint32_t(0)); // Compression method
binaryWrite(file, uint32_t(image_data_size)); // Image size
binaryWrite(file, uint32_t(0)); // Resolution
binaryWrite(file, uint32_t(0)); // Resolution
binaryWrite(file, uint32_t(0u)); // Palette
binaryWrite(file, uint32_t(0u)); // Important colors of palette
// Write the image
for (size_t line=0; line < height; ++line) {
for (size_t column=0; column < width; ++column) {
Color & color = img[line*width + column];
binaryWrite(file, uint8_t(color[0]));
binaryWrite(file, uint8_t(color[1]));
binaryWrite(file, uint8_t(color[2]));
}
// Add padding
for (size_t index=0; index < nb_padding_octets; ++index)
binaryWrite(file,uint8_t(0u));
}
}
return 0;
}
@duckie

This comment has been minimized.

Copy link
Owner Author

duckie commented Feb 16, 2015

generated_image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.