1// PPM image format -  https://netpbm.sourceforge.net/doc/ppm.html
 2
 3const std = @import("std");
 4
 5const ImageSize = 600;
 6
 7const Color = struct {
 8    r: u8,
 9    g: u8,
10    b: u8,
11
12    pub fn initRandom() Color {
13        const rand = std.crypto.random;
14        return Color{
15            .r = rand.int(u8),
16            .g = rand.int(u8),
17            .b = rand.int(u8),
18        };
19    }
20
21    pub fn toString(self: Color) []const u8 {
22        return std.fmt.allocPrint(std.heap.page_allocator, "{d} {d} {d} ", .{ self.r, self.g, self.b }) catch unreachable;
23    }
24};
25
26pub fn main() !void {
27    const image_file = try std.fs.cwd().createFile("image.ppm", .{});
28    defer image_file.close();
29
30    // NOTE: This should be done at compile time instead since the data is
31    //       known in advance. I am leaving this here as a reference.
32    // const header: []const u8 = std.fmt.allocPrint(std.heap.page_allocator, "P3\n{d} {d}\n255\n", .{ ImageSize, ImageSize }) catch unreachable;
33
34    // NOTE: This is done at compile time instead. It does look a bit ugly
35    //       and there must be a better way of doing this. Good enough!
36    const header = "P3\n" ++ std.fmt.comptimePrint("{d}", .{ImageSize}) ++ " " ++ std.fmt.comptimePrint("{d}", .{ImageSize}) ++ "\n255\n";
37
38    _ = try image_file.write(header);
39
40    for (0..(ImageSize * ImageSize)) |_| {
41        const color = Color.initRandom();
42        _ = try image_file.write(color.toString());
43    }
44}