Skip to content

Instantly share code, notes, and snippets.

@dragon0
Created July 19, 2018 00:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dragon0/72bfe548d29a92b04a6a58372d1c0f16 to your computer and use it in GitHub Desktop.
Save dragon0/72bfe548d29a92b04a6a58372d1c0f16 to your computer and use it in GitHub Desktop.
Create BMP in C++
#include <fstream>
#include <iostream>
#include <cmath>
const int WIDTH = 300;
const int HEIGHT = 300;
void save_img(int *red[], int *green[], int *blue[]);
void create_img(float *red[], float *green[], float *blue[], int pixelsPerUnit);
void print_img(float *red[], float *green[], float *blue[]);
void print_img(int *red[], int *green[], int *blue[]);
void transform_img(float *red[], float *green[], float *blue[], int *r[], int *g[], int *b[]);
template <typename T>
inline T** make_channel();
int main(){
float **red = make_channel<float>();
float **green = make_channel<float>();
float **blue = make_channel<float>();
int **r = make_channel<int>();
int **g = make_channel<int>();
int **b = make_channel<int>();
create_img(red, green, blue, 150);
print_img(red, green, blue);
transform_img(red, green, blue, r, g, b);
print_img(r, g, b);
save_img(r, g, b);
return 0;
}
template <typename T>
inline T** make_channel(){
T** a = new T*[WIDTH];
for(int i = 0; i < WIDTH; ++i)
a[i] = new T[HEIGHT];
return a;
}
// generate arrays with values in range [-1, 1]
void create_img(float *red[], float *green[], float *blue[], int pixelsPerUnit){
for(int i=0; i<WIDTH; i++)
{
for(int j=0; j<HEIGHT; j++)
{
// sin(pi*x), cos(pi*x*y), sin(pi*y)
float x = float(i - pixelsPerUnit) / pixelsPerUnit;
float y = -float(j - pixelsPerUnit) / pixelsPerUnit;
red[i][j] = sin(M_PI * x);
green[i][j] = cos(M_PI * x * y);
blue[i][j] = sin(M_PI * y);
}
}
}
// convert 2D arrays in range [-1, 1] to arrays in range [0, 255]
void transform_img(float *red[], float *green[], float *blue[], int *r[], int *g[], int *b[]){
for(int i=0; i<WIDTH; i++)
{
for(int j=0; j<HEIGHT; j++)
{
r[i][j] = (red[i][j] + 1)*127;
g[i][j] = (green[i][j] + 1)*127;
b[i][j] = (blue[i][j] + 1)*127;
if (r[i][j] > 255) r[i][j]=255;
if (g[i][j] > 255) g[i][j]=255;
if (b[i][j] > 255) b[i][j]=255;
}
}
}
// Write BMP image
void save_img(int *red[], int *green[], int *blue[]){
int filesize =
54 // BPM header
+ 3*WIDTH*HEIGHT; // RGB data
unsigned char *img = new unsigned char[3*WIDTH*HEIGHT];
// Flatten 2D arrays into 1D array
for(int i=0; i<WIDTH; i++)
{
for(int j=0; j<HEIGHT; j++)
{
int x=i;
int y=(HEIGHT-1)-j;
img[(x+y*WIDTH)*3+0] = (unsigned char)(blue[i][j]);
img[(x+y*WIDTH)*3+1] = (unsigned char)(green[i][j]);
img[(x+y*WIDTH)*3+2] = (unsigned char)(red[i][j]);
}
}
// BMP header
unsigned char bmpfileheader[14] = {'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0};
unsigned char bmpinfoheader[40] = {40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0};
unsigned char bmppad[3] = {0,0,0};
// File size in little-endian
bmpfileheader[ 2] = (unsigned char)(filesize );
bmpfileheader[ 3] = (unsigned char)(filesize>> 8);
bmpfileheader[ 4] = (unsigned char)(filesize>>16);
bmpfileheader[ 5] = (unsigned char)(filesize>>24);
// Image dimensions in little-endian
bmpinfoheader[ 4] = (unsigned char)( WIDTH );
bmpinfoheader[ 5] = (unsigned char)( WIDTH>> 8);
bmpinfoheader[ 6] = (unsigned char)( WIDTH>>16);
bmpinfoheader[ 7] = (unsigned char)( WIDTH>>24);
bmpinfoheader[ 8] = (unsigned char)( HEIGHT );
bmpinfoheader[ 9] = (unsigned char)( HEIGHT>> 8);
bmpinfoheader[10] = (unsigned char)( HEIGHT>>16);
bmpinfoheader[11] = (unsigned char)( HEIGHT>>24);
std::ofstream f( "img.bmp", std::ios::binary );
f.write((const char*)bmpfileheader, 14);
f.write((const char*)bmpinfoheader, 40);
for(int i=0; i<HEIGHT; i++)
{
f.write((const char*)img+(WIDTH*(HEIGHT-i-1)*3), 3*WIDTH);
f.write((const char*)bmppad, (4-(WIDTH*3)%4)%4);
}
delete img;
}
void print_img(float *red[], float *green[], float *blue[]){
for(int i=0; i<WIDTH; i++)
{
for(int j=0; j<HEIGHT; j++)
{
printf(
"%.02f, %.02f, %.02f ",
red[i][j],
green[i][j],
blue[i][j]);
}
printf("\n");
}
}
void print_img(int *red[], int *green[], int *blue[]){
for(int i=0; i<WIDTH; i++)
{
for(int j=0; j<HEIGHT; j++)
{
printf(
"%.03d, %.03d, %.03d ",
red[i][j],
green[i][j],
blue[i][j]);
}
printf("\n");
}
}
@dragon0
Copy link
Author

dragon0 commented Jul 19, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment