Guest User

Untitled

a guest
Jun 7th, 2020
450
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.98 KB | None | 0 0
  1. // This C++/C99 program writes file "out.bmp" with the picture
  2. // The version in QR code sacrifices readability to fit better in QR code. This version is more versatile.
  3. // https://www.deviantart.com/xbi/art/Sweetie-Bot-qr-code-fractal-program-art-844689437
  4.  
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8.  
  9.  
  10. int bmp_bytes_per_line(int w) {
  11.     return ((((w * 3) + 3) & ~3));
  12. }
  13.  
  14. #define FWRITE(data, size, file) do { if (size != fwrite((data), 1, (size), (file))) { fprintf(stderr, "write error\n"); exit(1); }  } while (0)
  15.  
  16. void write_bmp_header(FILE *f, int w, int h) {
  17.     #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 ;
  18.     unsigned char H[54] =  { 0 };
  19.  
  20.     H[0] = 66; // 'B' Magic header "BM"
  21.     H[1] = 77; // 'M'
  22.     H[10] = sizeof(H); // offset to pixel data
  23.     H[14] = 40; // size of BITMAPINFOHEADER, pixel data sub-header of full file header
  24.     H[26] = 1;  // number of planes, always 1
  25.     H[28] = 24; // 24 bits per pixel
  26.  
  27.     SetDword(2,  bmp_bytes_per_line(w) * h + sizeof(H)); // full file size
  28.     SetDword(18, w);
  29.     SetDword(22, h);
  30.     SetDword(34, bmp_bytes_per_line(w) * h); // pixel plane size
  31.  
  32.     FWRITE(H, sizeof(H), f);
  33.     #undef SetDword
  34. }
  35.  
  36. double get_fractal_value(double x, double y) {
  37.     int k = 0;
  38.     double steps = 256;
  39.     double prev_distance = 0;
  40.     for (; k < 256; ++k) {
  41.         // complex number multiplication. See Julia fractal definition.
  42.         double tx = x;
  43.         x = x*x - y*y - 0.755;
  44.         y = 2*tx*y + 0.15;
  45.  
  46.         double distance = x*x + y*y;
  47.         double max_dist = 30;
  48.         if (distance > max_dist) {
  49.             // convert integer number of steps to something smoother
  50.             double extra_smooth = (max_dist - prev_distance) / (distance - prev_distance);
  51.             steps = k + extra_smooth;
  52.             break;
  53.         }
  54.         prev_distance = distance;
  55.     }
  56.     return steps;
  57. }
  58.  
  59. void get_pixel(int i, int j, int w, int h, unsigned char col[3]) {
  60.     double fr = 0, fg = 0, fb = 0;
  61.     int aa = 3; // antialiasing multisampling, sample and average multiple values in pixel
  62.     for (int dj = 0; dj < aa; ++dj) {
  63.         for (int di = 0; di < aa; ++di) {
  64.             //shift/rotate/scale image:
  65.             double jj = (j + 308 + 1.0*dj/aa - w/2);
  66.             double ii = (i - 420 + 1.0*di/aa - h/2);
  67.             double scale = 1.92 / w;
  68.             double cos = 0.855;
  69.             double sin = 0.516;
  70.             double x = (jj * cos - ii * sin) * scale;
  71.             double y = (jj * sin + ii * cos) * scale;
  72.  
  73.  
  74.             double c = get_fractal_value(x, y);
  75.             // changing gradient steepness
  76.             c = 256 - c;
  77.             c = c * c / 256 / 256;
  78.  
  79.             // mix two colors to get gradient
  80.             fr += 255 - 205 * c;
  81.             fg += 173 - 151 * c;
  82.             fb += 408 - 348 * c;
  83.         }
  84.     }
  85.     int aaa = aa * aa;
  86.     fr /= aaa; // average by antialiasing sample count
  87.     fg /= aaa;
  88.     fb /= aaa;
  89.     fr = fr > 255 ? 255 : fr;
  90.     fg = fg > 255 ? 255 : fg;
  91.     fb = fb > 255 ? 255 : fb;
  92.     col[0] = fb;
  93.     col[1] = fg;
  94.     col[2] = fr;
  95. }
  96.  
  97. int main() {
  98.     FILE *f = fopen("out.bmp", "wb");
  99.     if (!f) {
  100.         fprintf(stderr, "can't create output file\n");
  101.         return 1;
  102.     }
  103.  
  104.     int w = 1600, h = 900;
  105.     write_bmp_header(f, w, h);
  106.  
  107.     for (int i = 0; i < h;  ++i) {
  108.         for (int j = 0; j < w; ++j) {
  109.             unsigned char col[3];
  110.             get_pixel(i, j, w, h, col);
  111.             FWRITE(col, 3, f);
  112.         }
  113.         int extra_bytes = bmp_bytes_per_line(w) - 3*w;
  114.         if (extra_bytes) {
  115.             // write BMP align on 4 bytes boundary
  116.             char padding[4] = { 0 };
  117.             FWRITE(padding, extra_bytes, f);
  118.         }
  119.     }
  120.  
  121.     if (0 != fclose(f)) {
  122.         // fclose reports mistakes if there are problems with flushing buffers
  123.         fprintf(stderr, "write file error\n");
  124.         return 1;
  125.     }
  126.     return 0;
  127. }
Add Comment
Please, Sign In to add comment