Check out the Pastebin Gadgets Shop. We have thousands of fun, geeky & affordable gadgets on sale :-)Want more features on Pastebin? Sign Up, it's FREE!

# Hypnagogic imagery

By: a guest on Jul 17th, 2012  |  syntax: C++  |  size: 6.88 KB  |  views: 99  |  expires: Never
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
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. }
clone this paste RAW Paste Data
Top