// # pin_image // zig version 0.16.0 // depends on libSDL2, LibSDL2_image // build zig build-exe pin_image.zig -lc -lSDL2 -lSDL2_image // example usage: // $ grim -g "$(slurp)" - | ./pin_image // $ cat image.png | pin_image // supports png and jpg const std = @import("std"); const c = @cImport({ @cInclude("SDL2/SDL.h"); @cInclude("SDL2/SDL_image.h"); }); pub fn main(init: std.process.Init) !void { var buf: [1024]u8 = undefined; var reader = std.Io.File.Reader.init(std.Io.File.stdin(), init.io, &buf); const data = try reader.interface.allocRemaining(init.gpa, .unlimited); defer init.gpa.free(data); if (c.SDL_Init(c.SDL_INIT_VIDEO) != 0) return error.Init; defer c.SDL_Quit(); const image_flags = c.IMG_INIT_PNG | c.IMG_INIT_JPG; if ((c.IMG_Init(image_flags) & image_flags) != image_flags) return error.ImageInit; defer c.IMG_Quit(); const rw = c.SDL_RWFromMem(data.ptr, @intCast(data.len)) orelse return error.RWFromMem; const surface: *c.SDL_Surface = c.IMG_Load_RW(rw, 1) orelse return error.ImageLoad; defer c.SDL_FreeSurface(surface); const window = c.SDL_CreateWindow("stdin image", c.SDL_WINDOWPOS_CENTERED, c.SDL_WINDOWPOS_CENTERED, surface.w, surface.h, c.SDL_WINDOW_SHOWN | c.SDL_WINDOW_RESIZABLE) orelse return error.WindowCreate; defer c.SDL_DestroyWindow(window); const renderer = c.SDL_CreateRenderer(window, -1, c.SDL_RENDERER_ACCELERATED | c.SDL_RENDERER_PRESENTVSYNC) orelse return error.RendererCreate; defer c.SDL_DestroyRenderer(renderer); const texture = c.SDL_CreateTextureFromSurface(renderer, surface) orelse return error.TextureCreate; defer c.SDL_DestroyTexture(texture); var running = true; while (running) { var event: c.SDL_Event = undefined; while (c.SDL_PollEvent(&event) != 0) { if (event.type == c.SDL_QUIT) { running = false; } } _ = c.SDL_RenderClear(renderer); _ = c.SDL_RenderCopy(renderer, texture, null, null); _ = c.SDL_RenderPresent(renderer); } }