diff --git a/build.zig.zon b/build.zig.zon index b19b16c..cf4b97a 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -1,5 +1,5 @@ .{ - .name = "salmon", + .name = "vaxis", // This is a [Semantic Version](https://semver.org/). // In a future version of Zig it will be used for package deduplication. .version = "0.0.0", diff --git a/src/Image.zig b/src/Image.zig index 638641b..0e34875 100644 --- a/src/Image.zig +++ b/src/Image.zig @@ -76,8 +76,9 @@ test "image" { .y_pixel = 1, }, .{ .path = "vaxis.png" }, + 1, ); defer img.deinit(); - try testing.expectEqual(1, img.cell_width); - try testing.expectEqual(1, img.cell_height); + try testing.expectEqual(200, img.cell_width); + try testing.expectEqual(197, img.cell_height); } diff --git a/src/image/Kitty.zig b/src/image/Kitty.zig new file mode 100644 index 0000000..7bf15c8 --- /dev/null +++ b/src/image/Kitty.zig @@ -0,0 +1,74 @@ +const std = @import("std"); +const math = std.math; +const testing = std.testing; +const zigimg = @import("zigimg"); +const png = zigimg.png; + +const Window = @import("../Window.zig"); +const Winsize = @import("../Tty.zig").Winsize; + +const Kitty = @This(); + +/// the decoded image +img: zigimg.Image, + +/// unique identifier for this image +id: u32, + +/// width of the image, in cells +cell_width: usize, +/// height of the image, in cells +cell_height: usize, + +/// initialize a new image +pub fn init( + alloc: std.mem.Allocator, + winsize: Winsize, + src: []const u8, + id: u32, +) !Kitty { + const img = switch (src) { + .path => |path| try zigimg.Image.fromFilePath(alloc, path), + .mem => |bytes| try zigimg.Image.fromMemory(alloc, bytes), + }; + // cell geometry + const pix_per_col = try math.divCeil(usize, winsize.x_pixel, winsize.cols); + const pix_per_row = try math.divCeil(usize, winsize.y_pixel, winsize.rows); + + const cell_width = math.divCeil(usize, img.width, pix_per_col) catch 0; + const cell_height = math.divCeil(usize, img.height, pix_per_row) catch 0; + + return Image{ + .img = img, + .cell_width = cell_width, + .cell_height = cell_height, + .id = id, + }; +} + +pub fn deinit(self: *Image) void { + self.img.deinit(); +} + +pub fn draw(self: *Image, win: Window, placement_id: u32) !void { + try win.writeImage(win.x_off, win.y_off, self, placement_id); +} + +test "image" { + const alloc = testing.allocator; + var img = try init( + alloc, + .{ + .rows = 1, + .cols = 1, + .x_pixel = 1, + .y_pixel = 1, + }, + .{ .path = "vaxis.png" }, + 0, + .kitty, + ); + defer img.deinit(); + try testing.expectEqual(200, img.cell_width); + try testing.expectEqual(197, img.cell_height); +} diff --git a/src/image/image.zig b/src/image/image.zig new file mode 100644 index 0000000..8c5c8db --- /dev/null +++ b/src/image/image.zig @@ -0,0 +1,42 @@ +const std = @import("std"); +const math = std.math; +const testing = std.testing; +const zigimg = @import("zigimg"); + +const Winsize = @import("../Tty.zig").Winsize; +const Window = @import("../Window.zig"); + +const Kitty = @import("Kitty.zig"); + +pub const Image = union(enum) { + kitty: Kitty, + + pub const Protocol = enum { + kitty, + // TODO: sixel, full block, half block, quad block + }; + + /// initialize a new image + pub fn init( + alloc: std.mem.Allocator, + winsize: Winsize, + src: []const u8, + id: u32, + protocol: Protocol, + ) !Image { + switch (protocol) { + .kitty => { + const img = try Kitty.init(alloc, winsize, src, id); + return .{ .kitty = img }; + }, + } + } + + pub fn deinit(self: *Image) void { + self.img.deinit(); + } + + pub fn draw(self: *Image, win: Window, placement_id: u32) !void { + try win.writeImage(win.x_off, win.y_off, self, placement_id); + } +};