summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannes Stoelp <johannes.stoelp@gmail.com>2024-12-17 20:56:01 +0100
committerJohannes Stoelp <johannes.stoelp@gmail.com>2025-02-07 21:54:55 +0100
commit9225c3bf291061a25dadbdfc5ec6eab72e86bb5e (patch)
treefdf7ef2d917258485ab2d4b4bb70a4f845d95525
parent177aad9d77cb94cc19a52860c2f3c9add018868e (diff)
downloadzig-playground-9225c3bf291061a25dadbdfc5ec6eab72e86bb5e.tar.gz
zig-playground-9225c3bf291061a25dadbdfc5ec6eab72e86bb5e.zip
ppm: simple example to generate a ppm image
-rw-r--r--ppm/Makefile8
-rw-r--r--ppm/main.zig22
-rw-r--r--ppm/ppm.zig51
3 files changed, 81 insertions, 0 deletions
diff --git a/ppm/Makefile b/ppm/Makefile
new file mode 100644
index 0000000..031bfc6
--- /dev/null
+++ b/ppm/Makefile
@@ -0,0 +1,8 @@
+main: main.zig ppm.zig
+ zig run main.zig
+
+show:
+ nsxiv test.ppm
+
+clean:
+ $(RM) test.ppm
diff --git a/ppm/main.zig b/ppm/main.zig
new file mode 100644
index 0000000..6e1bb1b
--- /dev/null
+++ b/ppm/main.zig
@@ -0,0 +1,22 @@
+const std = @import("std");
+const ppm = @import("ppm.zig");
+
+pub fn main() !void {
+ var img = ppm.ppm(200, 200).init;
+ defer img.dump("test.ppm") catch unreachable;
+
+ for (img.row(10)) |*px| {
+ px.*.r = 255;
+ }
+ for (img.row(20)) |*px| {
+ px.*.g = 255;
+ }
+ for (img.row(30)) |*px| {
+ px.*.b = 255;
+ }
+
+ const white = ppm.Pixel{ .r = 255, .g = 255, .b = 255 };
+
+ img.set(100, 100, white);
+ img.set(199, 199, white);
+}
diff --git a/ppm/ppm.zig b/ppm/ppm.zig
new file mode 100644
index 0000000..0606a8b
--- /dev/null
+++ b/ppm/ppm.zig
@@ -0,0 +1,51 @@
+const std = @import("std");
+const assert = std.debug.assert;
+
+pub const Pixel = extern struct {
+ r: u8,
+ g: u8,
+ b: u8,
+};
+
+pub fn ppm(comptime xdim: u32, comptime ydim: u32) type {
+ return struct {
+ const Self = @This();
+
+ /// Pixel data of the ppm image.
+ px: [ydim][xdim]Pixel,
+
+ /// Initial value of the `ppm` type.
+ pub const init: Self = .{
+ .px = undefined,
+ };
+
+ /// Set pixel data at `(x, y)`.
+ pub fn set(self: *Self, x: u32, y: u32, px: Pixel) void {
+ assert(x < xdim and y < ydim);
+ self.px[y][x] = px;
+ }
+
+ /// Get slice of pixels for row `y`.
+ pub fn row(self: *Self, y: u32) []Pixel {
+ assert(y < ydim);
+ return self.px[y][0..];
+ }
+
+ /// Write out image file with `name`.
+ pub fn dump(self: *const Self, name: []const u8) !void {
+ const f = try std.fs.cwd().createFile(name, .{ .truncate = true });
+ defer f.close();
+
+ const w = f.writer();
+ // Write ppm header (in ascii):
+ // MAGIC XDIM YDIM MAX_COLOR_VALUE
+ try w.print("P6 {} {} 255\n", .{ xdim, ydim });
+
+ for (self.px) |curr_row| {
+ for (curr_row) |px| {
+ try w.writeStruct(px);
+ }
+ }
+ }
+ };
+}