diff --git a/src/Image.zig b/src/Image.zig index 063833a..93ab63b 100644 --- a/src/Image.zig +++ b/src/Image.zig @@ -15,6 +15,12 @@ pub const Source = union(enum) { mem: []const u8, }; +pub const TransmitFormat = enum { + rgb, + rgba, + png, +}; + pub const Placement = struct { img_id: u32, options: Image.DrawOptions, diff --git a/src/Vaxis.zig b/src/Vaxis.zig index 63d3c75..175ac48 100644 --- a/src/Vaxis.zig +++ b/src/Vaxis.zig @@ -717,33 +717,51 @@ pub fn translateMouse(self: Vaxis, mouse: Mouse) Mouse { return result; } -pub fn loadImage( +pub fn transmitImage( self: *Vaxis, alloc: std.mem.Allocator, tty: AnyWriter, - src: Image.Source, + img: *zigimg.Image, + format: Image.TransmitFormat, ) !Image { if (!self.caps.kitty_graphics) return error.NoGraphicsCapability; defer self.next_img_id += 1; - var img = switch (src) { - .path => |path| try zigimg.Image.fromFilePath(alloc, path), - .mem => |bytes| try zigimg.Image.fromMemory(alloc, bytes), + var arena = std.heap.ArenaAllocator.init(alloc); + defer arena.deinit(); + + const buf = switch (format) { + .png => png: { + const png_buf = try arena.allocator().alloc(u8, img.imageByteSize()); + const png = try img.writeToMemory(png_buf, .{ .png = .{} }); + break :png png; + }, + .rgb => rgb: { + try img.convert(.rgb24); + break :rgb img.rawBytes(); + }, + .rgba => rgba: { + try img.convert(.rgba32); + break :rgba img.rawBytes(); + }, }; - defer img.deinit(); - const png_buf = try alloc.alloc(u8, img.imageByteSize()); - defer alloc.free(png_buf); - const png = try img.writeToMemory(png_buf, .{ .png = .{} }); - const b64_buf = try alloc.alloc(u8, base64Encoder.calcSize(png.len)); - const encoded = base64Encoder.encode(b64_buf, png); - defer alloc.free(b64_buf); + + const b64_buf = try arena.allocator().alloc(u8, base64Encoder.calcSize(buf.len)); + const encoded = base64Encoder.encode(b64_buf, buf); const id = self.next_img_id; + const fmt: u8 = switch (format) { + .rgb => 24, + .rgba => 32, + .png => 100, + }; + if (encoded.len < 4096) { try tty.print( - "\x1b_Gf=100,i={d};{s}\x1b\\", + "\x1b_Gf={d},i={d};{s}\x1b\\", .{ + fmt, id, encoded, }, @@ -752,8 +770,8 @@ pub fn loadImage( var n: usize = 4096; try tty.print( - "\x1b_Gf=100,i={d},m=1;{s}\x1b\\", - .{ id, encoded[0..n] }, + "\x1b_Gf={d},i={d},m=1;{s}\x1b\\", + .{ fmt, id, encoded[0..n] }, ); while (n < encoded.len) : (n += 4096) { const end: usize = @min(n + 4096, encoded.len); @@ -774,6 +792,22 @@ pub fn loadImage( }; } +pub fn loadImage( + self: *Vaxis, + alloc: std.mem.Allocator, + tty: AnyWriter, + src: Image.Source, +) !Image { + if (!self.caps.kitty_graphics) return error.NoGraphicsCapability; + + var img = switch (src) { + .path => |path| try zigimg.Image.fromFilePath(alloc, path), + .mem => |bytes| try zigimg.Image.fromMemory(alloc, bytes), + }; + defer img.deinit(); + return self.transmitImage(alloc, tty, &img, .png); +} + /// deletes an image from the terminal's memory pub fn freeImage(_: Vaxis, tty: AnyWriter, id: u32) void { tty.print("\x1b_Ga=d,d=I,i={d};\x1b\\", .{id}) catch |err| {