From 81a6b373a00f8401cdb6d50829d41c831bee6a38 Mon Sep 17 00:00:00 2001 From: Tim Culverhouse Date: Sat, 20 Jul 2024 15:51:03 -0500 Subject: [PATCH] image: add transmitPreEncodedImage method Add a method that allows users of the library to pre-encode an image using whichever base64 encoder they want (ie a simd encoder). --- src/Vaxis.zig | 88 +++++++++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 38 deletions(-) diff --git a/src/Vaxis.zig b/src/Vaxis.zig index a123270c..878bb61c 100644 --- a/src/Vaxis.zig +++ b/src/Vaxis.zig @@ -717,38 +717,16 @@ pub fn translateMouse(self: Vaxis, mouse: Mouse) Mouse { return result; } -pub fn transmitImage( +/// Transmit an image which has been pre-base64 encoded +pub fn transmitPreEncodedImage( self: *Vaxis, - alloc: std.mem.Allocator, tty: AnyWriter, - img: *zigimg.Image, + bytes: []const u8, + width: usize, + height: usize, format: Image.TransmitFormat, ) !Image { - if (!self.caps.kitty_graphics) return error.NoGraphicsCapability; defer self.next_img_id += 1; - - 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(); - }, - }; - - 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) { @@ -757,15 +735,15 @@ pub fn transmitImage( .png => 100, }; - if (encoded.len < 4096) { + if (bytes.len < 4096) { try tty.print( "\x1b_Gf={d},s={d},v={d},i={d};{s}\x1b\\", .{ fmt, - img.width, - img.height, + width, + height, id, - encoded, + bytes, }, ); } else { @@ -773,25 +751,59 @@ pub fn transmitImage( try tty.print( "\x1b_Gf={d},s={d},v={d},i={d},m=1;{s}\x1b\\", - .{ fmt, img.width, img.height, id, encoded[0..n] }, + .{ fmt, width, height, id, bytes[0..n] }, ); - while (n < encoded.len) : (n += 4096) { - const end: usize = @min(n + 4096, encoded.len); - const m: u2 = if (end == encoded.len) 0 else 1; + while (n < bytes.len) : (n += 4096) { + const end: usize = @min(n + 4096, bytes.len); + const m: u2 = if (end == bytes.len) 0 else 1; try tty.print( "\x1b_Gm={d};{s}\x1b\\", .{ m, - encoded[n..end], + bytes[n..end], }, ); } } return .{ .id = id, - .width = img.width, - .height = img.height, + .width = width, + .height = height, + }; +} + +pub fn transmitImage( + self: *Vaxis, + alloc: std.mem.Allocator, + tty: AnyWriter, + img: *zigimg.Image, + format: Image.TransmitFormat, +) !Image { + if (!self.caps.kitty_graphics) return error.NoGraphicsCapability; + + 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(); + }, }; + + const b64_buf = try arena.allocator().alloc(u8, base64Encoder.calcSize(buf.len)); + const encoded = base64Encoder.encode(b64_buf, buf); + + return self.transmitPreEncodedImage(tty, encoded, img.width, img.height, format); } pub fn loadImage(