summaryrefslogtreecommitdiff
path: root/image.zig
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-07-02 21:41:13 -0300
committerGabriel Schneider <[email protected]>2026-08-01 15:02:07 -0300
commit81992cc92743a98066ee1a9025bc74f91cf0e967 (patch)
tree12c07f68f8ad030f6c6f8a2b3415998d0a87eee7 /image.zig
parentbead9f0b78380d1428f40fdab339c1c8f88fa626 (diff)
downloadpardes-81992cc92743a98066ee1a9025bc74f91cf0e967.tar.gz
pardes-81992cc92743a98066ee1a9025bc74f91cf0e967.zip
storage and replay
Diffstat (limited to 'image.zig')
-rw-r--r--image.zig39
1 files changed, 26 insertions, 13 deletions
diff --git a/image.zig b/image.zig
index 4c83f8ad..79e7775f 100644
--- a/image.zig
+++ b/image.zig
@@ -78,7 +78,8 @@ pub fn deinitView(view: *View, gpa: std.mem.Allocator) void {
pub fn isImagePath(path: []const u8) bool {
const exts = [_][]const u8{
".png", ".jpg", ".jpeg", ".jpe", ".bmp", ".tga",
- ".gif", ".psd", ".hdr", ".pic", ".pnm", ".ppm", ".pgm",
+ ".gif", ".psd", ".hdr", ".pic", ".pnm", ".ppm",
+ ".pgm",
};
for (exts) |ext| {
if (path.len >= ext.len and std.ascii.eqlIgnoreCase(path[path.len - ext.len ..], ext)) return true;
@@ -86,17 +87,7 @@ pub fn isImagePath(path: []const u8) bool {
return false;
}
-// Decode (RGBA), downscale to MAX_DIM, keep the pixels for PETSCII, and — when the
-// terminal supports kitty graphics — transmit them once. Runs from the render loop,
-// which owns the tty writer. On failure `handle` stays null (PETSCII still works).
-pub fn ensureLoaded(view: *View, vx: *vaxis.Vaxis, gpa: std.mem.Allocator, writer: *std.Io.Writer) void {
- if (view.tried) return;
- view.tried = true;
- var pathbuf: [4096]u8 = undefined;
- const pz = std.fmt.bufPrintZ(&pathbuf, "{s}", .{view.path}) catch return;
- var img = zstbi.Image.loadFromFile(pz, 4) catch return; // force 4 components = RGBA
- defer img.deinit();
-
+fn keepDecodedImage(view: *View, vx: *vaxis.Vaxis, gpa: std.mem.Allocator, writer: *std.Io.Writer, img: *const zstbi.Image) void {
// downscale the longest side to MAX_DIM (keeping aspect) when it's bigger.
var scaled: ?zstbi.Image = null;
defer if (scaled) |*s| s.deinit();
@@ -106,7 +97,7 @@ pub fn ensureLoaded(view: *View, vx: *vaxis.Vaxis, gpa: std.mem.Allocator, write
const nh = @max(1, img.height * MAX_DIM / longest);
scaled = img.resize(nw, nh);
break :blk &scaled.?;
- } else &img;
+ } else img;
// keep a gpa-owned copy of the pixels for the PETSCII renderer.
view.rgba = gpa.dupe(u8, src.data) catch &.{};
@@ -123,6 +114,28 @@ pub fn ensureLoaded(view: *View, vx: *vaxis.Vaxis, gpa: std.mem.Allocator, write
view.handle = vx.transmitPreEncodedImage(writer, b64, @intCast(src.width), @intCast(src.height), .rgba) catch null;
}
+// Decode (RGBA), downscale to MAX_DIM, keep the pixels for PETSCII, and — when the
+// terminal supports kitty graphics — transmit them once. Runs from the render loop,
+// which owns the tty writer. On failure `handle` stays null (PETSCII still works).
+pub fn ensureLoaded(view: *View, vx: *vaxis.Vaxis, gpa: std.mem.Allocator, writer: *std.Io.Writer) void {
+ if (view.tried) return;
+ view.tried = true;
+ var pathbuf: [4096]u8 = undefined;
+ const pz = std.fmt.bufPrintZ(&pathbuf, "{s}", .{view.path}) catch return;
+ var img = zstbi.Image.loadFromFile(pz, 4) catch return; // force 4 components = RGBA
+ defer img.deinit();
+ keepDecodedImage(view, vx, gpa, writer, &img);
+}
+
+pub fn ensureLoadedFromMemory(view: *View, bytes: []const u8, vx: *vaxis.Vaxis, gpa: std.mem.Allocator, writer: *std.Io.Writer) void {
+ if (view.tried) return;
+ view.tried = true;
+ if (bytes.len == 0) return;
+ var img = zstbi.Image.loadFromMemory(bytes, 4) catch return; // force 4 components = RGBA
+ defer img.deinit();
+ keepDecodedImage(view, vx, gpa, writer, &img);
+}
+
// (Re)build the cached PETSCII grid for the current body size, if PETSCII drawing
// is active and the size changed. Runs from the render loop (which has gpa).
pub fn ensureGrid(view: *View, gpa: std.mem.Allocator, body_cols: u16, body_rows: u16) void {