diff --git a/src/image.zig b/src/image.zig index c18ae6a..3921e05 100644 --- a/src/image.zig +++ b/src/image.zig @@ -1,6 +1,7 @@ const std = @import("std"); const assert = std.debug.assert; -const expectEqual = std.testing.expectEqual; +const expectEqual = std.testing.expectEqualDeep; +const expectEqualDeep = std.testing.expectEqualDeep; const Allocator = std.mem.Allocator; const as = @import("meta.zig").as; @@ -56,6 +57,7 @@ pub fn Image(comptime T: type) type { pub fn deinit(self: *Self, allocator: Allocator) void { self.rows = 0; self.cols = 0; + self.stride = 0; allocator.free(self.data); } @@ -98,6 +100,12 @@ pub fn Image(comptime T: type) type { }; } + /// Returns true if, and only if, self is not a view of another image. This is computed + /// by comparing the `rows` and `stride` fields. + pub fn isView(self: Self) bool { + return self.cols != self.stride; + } + /// Returns the value at position row, col. It assumes the coordinates are in bounds and /// triggers safety-checked undefined behavior when they aren't. pub inline fn at(self: Self, row: usize, col: usize) *T { @@ -593,3 +601,13 @@ test "getRectangle" { try expectEqual(rect.width(), image.cols); try expectEqual(rect.height(), image.rows); } + +test "view" { + var image = try Image(Rgba).initAlloc(std.testing.allocator, 21, 13); + defer image.deinit(std.testing.allocator); + const rect: Rectangle(usize) = .{ .l = 0, .t = 0, .r = 8, .b = 10 }; + const view = image.view(rect); + try expectEqual(view.isView(), true); + try expectEqual(image.isView(), false); + try expectEqualDeep(rect, view.getRectangle()); +}