// imagemagick plugins const std = @import("std"); const images = @import("image.zig"); const Image = images.Image; const mc = @import("magick_wand.zig"); pub const MagickContext = struct { wand: *mc.MagickWand, pub fn init() !MagickContext { mc.InitializeMagick(null); var wand = mc.NewMagickWand(); if (wand == null) return error.WandCreateFail; return MagickContext{ .wand = wand.?, }; } pub fn deinit(self: *MagickContext) void { _ = mc.DestroyMagickWand(self.wand); mc.DestroyMagick(); } pub fn doErr(self: *MagickContext) !void { return error.WandError; } }; fn magickLoad(image: *Image) !MagickContext { var mctx = try MagickContext.init(); errdefer mctx.deinit(); var curpath = try std.cstr.addNullByte(image.allocator, image.curpath); defer image.allocator.free(curpath); std.debug.warn("loading '{}'\n", curpath); if (mc.MagickReadImage(mctx.wand, curpath.ptr) != 1) return error.MagickReadFail; return mctx; } fn magickSave(image: *Image, mctx: *MagickContext) !void { var tmpnam = try images.temporaryName(image.allocator); defer image.allocator.free(tmpnam); var c_tmpnam = try std.cstr.addNullByte(image.allocator, tmpnam); defer image.allocator.free(c_tmpnam); std.debug.warn( "\tmagick: saving from '{}' to '{}'\n", image.curpath, c_tmpnam, ); if (mc.MagickWriteImage(mctx.wand, c_tmpnam.ptr) != 1) return error.MagickWriteFail; } pub fn runRotate(image: *Image) !void { var mctx = try magickLoad(image); defer mctx.deinit(); var bg = mc.NewPixelWand().?; defer mc.DestroyPixelWand(bg); if (mc.PixelSetColor(bg, c"#ffffff") != 1) return error.PixelSetColorFail; if (mc.MagickRotateImage(mctx.wand, bg, 30) != 1) return error.RotateFail; try magickSave(image, &mctx); }