Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // This C++/C99 program writes file "out.bmp" with the picture
- // The version in QR code sacrifices readability to fit better in QR code. This version is more versatile.
- // https://www.deviantart.com/xbi/art/Sweetie-Bot-qr-code-fractal-program-art-844689437
- #include <stdio.h>
- #include <stdlib.h>
- int bmp_bytes_per_line(int w) {
- return ((((w * 3) + 3) & ~3));
- }
- #define FWRITE(data, size, file) do { if (size != fwrite((data), 1, (size), (file))) { fprintf(stderr, "write error\n"); exit(1); } } while (0)
- void write_bmp_header(FILE *f, int w, int h) {
- #define SetDword(i, x) H[i] = (x) & 0xff ; H[i+1] = ((x) >> 8) & 0xff ; H[i+2] = ((x) >> 16) & 0xff ; H[i+3] = ((x) >> 24) & 0xff ;
- unsigned char H[54] = { 0 };
- H[0] = 66; // 'B' Magic header "BM"
- H[1] = 77; // 'M'
- H[10] = sizeof(H); // offset to pixel data
- H[14] = 40; // size of BITMAPINFOHEADER, pixel data sub-header of full file header
- H[26] = 1; // number of planes, always 1
- H[28] = 24; // 24 bits per pixel
- SetDword(2, bmp_bytes_per_line(w) * h + sizeof(H)); // full file size
- SetDword(18, w);
- SetDword(22, h);
- SetDword(34, bmp_bytes_per_line(w) * h); // pixel plane size
- FWRITE(H, sizeof(H), f);
- #undef SetDword
- }
- double get_fractal_value(double x, double y) {
- int k = 0;
- double steps = 256;
- double prev_distance = 0;
- for (; k < 256; ++k) {
- // complex number multiplication. See Julia fractal definition.
- double tx = x;
- x = x*x - y*y - 0.755;
- y = 2*tx*y + 0.15;
- double distance = x*x + y*y;
- double max_dist = 30;
- if (distance > max_dist) {
- // convert integer number of steps to something smoother
- double extra_smooth = (max_dist - prev_distance) / (distance - prev_distance);
- steps = k + extra_smooth;
- break;
- }
- prev_distance = distance;
- }
- return steps;
- }
- void get_pixel(int i, int j, int w, int h, unsigned char col[3]) {
- double fr = 0, fg = 0, fb = 0;
- int aa = 3; // antialiasing multisampling, sample and average multiple values in pixel
- for (int dj = 0; dj < aa; ++dj) {
- for (int di = 0; di < aa; ++di) {
- //shift/rotate/scale image:
- double jj = (j + 308 + 1.0*dj/aa - w/2);
- double ii = (i - 420 + 1.0*di/aa - h/2);
- double scale = 1.92 / w;
- double cos = 0.855;
- double sin = 0.516;
- double x = (jj * cos - ii * sin) * scale;
- double y = (jj * sin + ii * cos) * scale;
- double c = get_fractal_value(x, y);
- // changing gradient steepness
- c = 256 - c;
- c = c * c / 256 / 256;
- // mix two colors to get gradient
- fr += 255 - 205 * c;
- fg += 173 - 151 * c;
- fb += 408 - 348 * c;
- }
- }
- int aaa = aa * aa;
- fr /= aaa; // average by antialiasing sample count
- fg /= aaa;
- fb /= aaa;
- fr = fr > 255 ? 255 : fr;
- fg = fg > 255 ? 255 : fg;
- fb = fb > 255 ? 255 : fb;
- col[0] = fb;
- col[1] = fg;
- col[2] = fr;
- }
- int main() {
- FILE *f = fopen("out.bmp", "wb");
- if (!f) {
- fprintf(stderr, "can't create output file\n");
- return 1;
- }
- int w = 1600, h = 900;
- write_bmp_header(f, w, h);
- for (int i = 0; i < h; ++i) {
- for (int j = 0; j < w; ++j) {
- unsigned char col[3];
- get_pixel(i, j, w, h, col);
- FWRITE(col, 3, f);
- }
- int extra_bytes = bmp_bytes_per_line(w) - 3*w;
- if (extra_bytes) {
- // write BMP align on 4 bytes boundary
- char padding[4] = { 0 };
- FWRITE(padding, extra_bytes, f);
- }
- }
- if (0 != fclose(f)) {
- // fclose reports mistakes if there are problems with flushing buffers
- fprintf(stderr, "write file error\n");
- return 1;
- }
- return 0;
- }
Add Comment
Please, Sign In to add comment