Last active
August 29, 2015 14:15
-
-
Save duckie/8bcedd4515ff240b3c8d to your computer and use it in GitHub Desktop.
Generate an image in Microsoft BMP format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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; | |
} |
Author
duckie
commented
Feb 16, 2015
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment