My omnium-gatherom of scripts and source code.
1#include <array>
2#include <cmath>
3#include <expected>
4#include <fstream>
5#include "prelude.hpp"
6
7enum class Error {
8 file_error
9};
10
11struct RGB {
12 U8 Red;
13 U8 Green;
14 U8 Blue;
15
16 RGB(U8 r, U8 g, U8 b);
17};
18
19struct Color {
20 F32 hue;
21 F32 saturation;
22 F32 value;
23 Color();
24 Color(U32 val);
25 Color(F32 hue, F32 saturation, F32 value);
26
27 fn to_rgb() const noexcept -> RGB;
28 fn lerp(ref<const Color>, F64) const noexcept -> Color;
29};
30
31struct Point {
32 F64 x;
33 F64 y;
34
35 Point(F64 x, F64 y);
36};
37
38template<Size width, Size height>
39class Canvas {
40 F64 x_max;
41 F64 y_max;
42 F64 x_min;
43 F64 y_min;
44 std::array<Color, width * height> pixels;
45
46 public:
47 Canvas(F64 min_x, F64 min_y, F64 max_x, F64 max_y)
48 : x_max(max_x)
49 , y_max(max_y)
50 , x_min(min_x)
51 , y_min(min_y)
52 { }
53
54 Canvas(Point p, Size size)
55 {
56 let delta = size / 2.0;
57 x_max = p.x + delta;
58 x_min = p.x - delta;
59 y_max = p.y + delta;
60 y_min = p.y - delta;
61 }
62
63 fn save_to_ppm(const char* file_path) const noexcept -> std::expected<Unit, Error>
64 {
65 var f =
66 std::fstream(file_path, std::ios::binary | std::ios::out);
67 if (not f.is_open())
68 return std::unexpected(Error::file_error);
69
70 f << "P6\n" << width << " " << height << " 255\n";
71 for (let &color : pixels) {
72 var c = color.to_rgb();
73 let rgb = std::make_tuple(c.Red, c.Green, c.Blue);
74 f << fst(rgb) << snd(rgb) << thr(rgb) ;
75 }
76 f.close();
77 return Unit();
78 }
79
80 fn coordinate(Size index) const noexcept -> Point
81 {
82 return Point(
83 std::lerp(x_min, x_max,
84 (index % width) / (F64)width),
85 std::lerp(y_min, y_max,
86 ((F64)index / height) / height));
87 }
88
89 fn construct(auto op) noexcept -> Unit
90 {
91 #pragma omp parallel for
92 for (Size idx = 0; idx < width * height; idx++)
93 pixels[idx] = op(coordinate(idx));
94
95 return Unit();
96 }
97
98 fn operator[](Size index) noexcept -> ref<Color>
99 {
100 return pixels[index];
101 }
102
103 fn operator()(Size row, Size col) noexcept -> ref<Color>
104 {
105 return pixels[row * width + col];
106 }
107};