Advertisement
Guest User

Hypnagogic imagery

a guest
Jul 17th, 2012
225
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.88 KB | None | 0 0
  1. #include <cassert>
  2. #include <cmath>
  3. #include <cerrno>
  4. #include <cstdio>
  5. #include <cstring>
  6. #include <random>
  7. #include <stdexcept>
  8. #include <tuple>
  9. #include <vector>
  10.  
  11. extern "C" {
  12. #include <png.h>
  13. }
  14.  
  15. template<typename T>
  16. T clamp(const T &x, const T &min, const T &max)
  17. {
  18.     if (x < min)
  19.         return min;
  20.     if (x > max)
  21.         return max;
  22.  
  23.     return x;
  24. }
  25.  
  26. struct vector {
  27.     double x, y;
  28.  
  29.     explicit vector(double x, double y):
  30.         x(x), y(y)
  31.     {
  32.     }
  33.  
  34.     double normsq() const
  35.     {
  36.         return x * x + y * y;
  37.     }
  38.  
  39.     double norm() const
  40.     {
  41.         return sqrt(normsq());
  42.     }
  43.  
  44.     double angle() const
  45.     {
  46.         return atan2(y, x);
  47.     }
  48.  
  49.     void operator+=(const vector &other)
  50.     {
  51.         x += other.x;
  52.         y += other.y;
  53.     }
  54. };
  55.  
  56. bool operator==(const vector &a, const vector &b)
  57. {
  58.     return a.x == b.x && a.y == b.y;
  59. }
  60.  
  61. vector operator-(const vector &a, const vector &b)
  62. {
  63.     return vector(a.x - b.x, a.y - b.y);
  64. }
  65.  
  66. static double bezier_interpolate(double p0, double p1, double t)
  67. {
  68.     return (1 - t) * p0 + t * p1;
  69. }
  70.  
  71. static double bezier_interpolate(double p0, double p1, double p2, double t)
  72. {
  73.     double tp = (1 - t);
  74.     return tp * tp * p0 + 2 * tp * t * p1 + t * t * p2;
  75. }
  76.  
  77. static double bezier_interpolate(double p0, double p1, double p2, double p3, double t)
  78. {
  79.     double tp = 1 - t;
  80.     return tp * tp * tp * p0
  81.         + 3 * tp * tp * t * p1
  82.         + 3 * tp * t * t * p2
  83.         + t * t * t * p3;
  84. }
  85.  
  86. static const unsigned int width = 320;
  87. static const unsigned int height = 240;
  88.  
  89. static std::tuple<double, double, double> hsl_to_rgb(double H, double S, double L)
  90. {
  91.     double C = (1 - fabs(2 * L - 1)) * S;
  92.     double X = C * (1 - fabs(fmod(H, 2) - 1));
  93.  
  94.     double r, g, b;
  95.     if (H >= 0 && H < 1) {
  96.         r = C; g = X; b = 0;
  97.     } else if (H >= 1 && H < 2) {
  98.         r = X; g = C; b = 0;
  99.     } else if (H >= 2 && H < 3) {
  100.         r = 0; g = C; b = X;
  101.     } else if (H >= 3 && H < 4) {
  102.         r = 0; g = X; b = C;
  103.     } else if (H >= 4 && H < 5) {
  104.         r = X; g = 0; b = C;
  105.     } else if (H >= 5 && H <= 6) {
  106.         r = C; g = 0; b = X;
  107.     }
  108.  
  109.     double m = L - C / 2;
  110.  
  111.     return std::make_tuple(r + m, g + m, b + m);
  112. }
  113.  
  114. template<unsigned int nr_corners>
  115. struct blob {
  116.     unsigned int x;
  117.     unsigned int y;
  118.     double size;
  119.  
  120.     double corners[nr_corners];
  121.     double between[nr_corners];
  122. };
  123.  
  124. template<typename Random, unsigned int nr_corners>
  125. static void output_frame(Random &rand, const char *filename, const blob<nr_corners> &blue)
  126. {
  127.     png_byte data[width * height * 4];
  128.     for (unsigned int y = 0; y < height; ++y) {
  129.         for (unsigned int x = 0; x < width; ++x) {
  130.             png_bytep rgb = &data[4 * (y * width + x)];
  131.             rgb[0] = 0;
  132.             rgb[1] = 0;
  133.             rgb[2] = 0;
  134.             rgb[3] = 255;
  135.         }
  136.     }
  137.  
  138. #define LESS
  139.  
  140.     for (unsigned int y = 0; y < height; ++y) {
  141.         for (unsigned int x = 0; x < width; ++x) {
  142. #ifdef LESS
  143.             if (std::uniform_int_distribution<>(0, 100)(rand) < 50)
  144.                 continue;
  145. #endif
  146.  
  147.             double H = 2 * std::uniform_int_distribution<>(0, 2)(rand);
  148.             double S = std::uniform_real_distribution<>(0, 1)(rand);
  149. #ifdef LESS
  150.             double L = clamp(fabs(std::normal_distribution<>(0, 0.05)(rand)), 0., 1.);
  151. #else
  152.             double L = clamp(0.1 * std::exponential_distribution<>()(rand), 0., 1.);
  153. #endif
  154.  
  155.             double r, g, b;
  156.             std::tie(r, g, b) = hsl_to_rgb(H, S, L);
  157.  
  158.             png_bytep rgb = &data[4 * (y * width + x)];
  159.             rgb[0] = 255 * r;
  160.             rgb[1] = 255 * g;
  161.             rgb[2] = 255 * b;
  162.             rgb[3] = 255;
  163.         }
  164.     }
  165.  
  166.     unsigned int cx = blue.x;
  167.     unsigned int cy = blue.y;
  168.     unsigned int size = blue.size;
  169.  
  170.     for (unsigned int y = 0; y < 2 * size; ++y) {
  171.         if (cy + y < size)
  172.             continue;
  173.         if (cy + y >= height + size)
  174.             continue;
  175.  
  176.         for (unsigned int x = 0; x < 2 * size; ++x) {
  177.             if (cx + x < size)
  178.                 continue;
  179.             if (cx + x >= width + size)
  180.                 continue;
  181.  
  182.             vector p((double) y - size, (double) x - size);
  183.  
  184.             double corner = fmod(nr_corners * (M_PI + p.angle()) / 2 / M_PI, nr_corners);
  185.             unsigned int corner_i = floor(corner);
  186.  
  187.             double t = corner - corner_i;
  188.             assert(t >= 0 && t < 1);
  189.  
  190.             double norm = size * bezier_interpolate(
  191.                 blue.corners[corner_i],
  192.                 blue.corners[corner_i] + blue.between[corner_i],
  193.                 blue.corners[(corner_i + 1) % nr_corners] - blue.between[(corner_i + 1) % nr_corners],
  194.                 blue.corners[(corner_i + 1) % nr_corners],
  195.                 t);
  196.  
  197.             if (p.norm() > norm)
  198.                 continue;
  199.  
  200.             if (size > 100) {
  201.                 if (std::uniform_real_distribution<>(0, (p.norm() / norm))(rand) < (size - 100) / 500.)
  202.                     continue;
  203.             }
  204.  
  205.             double H = fmod(std::normal_distribution<>(4.4, .15)(rand), 6);
  206.             double S = clamp(1., 0., 1.);
  207.             double L;
  208.             if (p.norm() > 0.98 * norm)
  209.                 L = clamp(std::normal_distribution<>(.5, .1)(rand), 0., 1.);
  210.             else
  211.                 L = clamp(std::normal_distribution<>(.3, .1)(rand), 0., 1.);
  212.  
  213.             double r, g, b;
  214.             std::tie(r, g, b) = hsl_to_rgb(H, S, L);
  215.  
  216.             png_bytep rgb = &data[4 * ((cy + y - size) * width + (cx + x - size))];
  217.             rgb[0] = 255 * r;
  218.             rgb[1] = 255 * g;
  219.             rgb[2] = 255 * b;
  220.             rgb[3] = 255;
  221.         }
  222.     }
  223.  
  224.     FILE *fp = fopen(filename, "wb");
  225.     if (!fp)
  226.         throw std::runtime_error(strerror(errno));
  227.  
  228.     png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
  229.     if (!png_ptr)
  230.         throw std::runtime_error("png_create_write_struct");
  231.  
  232.     png_infop info_ptr = png_create_info_struct(png_ptr);
  233.     if (!info_ptr)
  234.         throw std::runtime_error("png_create_info_struct");
  235.  
  236.     png_init_io(png_ptr, fp);
  237.     png_set_filter(png_ptr, 0, PNG_FILTER_NONE);
  238.     png_set_IHDR(png_ptr, info_ptr, width, height, 8, PNG_COLOR_TYPE_RGBA,
  239.         PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
  240.         PNG_FILTER_TYPE_DEFAULT);
  241.  
  242.     png_bytep rows[height];
  243.     for (unsigned int i = 0; i < height; ++i)
  244.         rows[i] = &data[i * width * 4];
  245.  
  246.     png_set_rows(png_ptr, info_ptr, rows);
  247.     png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
  248.     fclose(fp);
  249. }
  250.  
  251. int main(int argc, char *argv[])
  252. {
  253.     std::random_device rd;
  254.     std::mt19937 rand(rd());
  255.  
  256.     unsigned int frame_i = 0;
  257.  
  258.     for (unsigned int i = 0; i < 3; ++i) {
  259.         static const unsigned int nr_corners = 6;
  260.         blob<nr_corners> blue;
  261.         blue.x = std::normal_distribution<>(width / 2, width / 8)(rand);
  262.         blue.y = std::normal_distribution<>(height / 2, height / 8)(rand);
  263.         blue.size = 0;
  264.  
  265.         for (unsigned int i = 0; i < nr_corners; ++i)
  266.             blue.corners[i] = std::uniform_real_distribution<>(.6, 1)(rand);
  267.         for (unsigned int i = 0; i < nr_corners; ++i)
  268.             blue.between[i] = std::uniform_real_distribution<>(.1, .3)(rand);
  269.  
  270.         double size_inc = 1;
  271.         for (unsigned int j = 0; blue.size < width; ++j) {
  272.             printf("Frame %u (size %.2f)\n", frame_i, blue.size);
  273.  
  274.             char png_filename[100];
  275.             sprintf(png_filename, "output/frame-%03u.png", frame_i);
  276.  
  277.             char gif_filename[100];
  278.             sprintf(gif_filename, "output/frame-%03u.gif", frame_i);
  279.  
  280.             output_frame(rand, png_filename, blue);
  281.             ++frame_i;
  282.  
  283.             char command[100];
  284.             sprintf(command, "convert %s %s && rm %s", png_filename, gif_filename, png_filename);
  285.             system(command);
  286.  
  287.             size_inc *= 1.08;
  288.             blue.size += size_inc;
  289.         }
  290.     }
  291.  
  292.     return 0;
  293. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement