Created
July 19, 2018 00:46
-
-
Save dragon0/72bfe548d29a92b04a6a58372d1c0f16 to your computer and use it in GitHub Desktop.
Create BMP in C++
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 <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"); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
https://jeremykun.com/2012/01/01/random-psychedelic-art/