scritcher/src/magick.zig

86 lines
2.1 KiB
Zig
Raw Normal View History

2019-07-22 22:28:55 +00:00
// imagemagick plugins
const std = @import("std");
const images = @import("image.zig");
2022-04-27 23:01:09 +00:00
const log = std.log.scoped(.scritcher_magick);
2019-07-22 22:28:55 +00:00
const Image = images.Image;
const mc = @cImport({
@cInclude("wand/magick_wand.h");
});
2019-07-22 23:32:50 +00:00
pub const MagickContext = struct {
wand: *mc.MagickWand,
pub fn init() !MagickContext {
2019-07-23 00:50:11 +00:00
mc.InitializeMagick(null);
2019-07-22 23:32:50 +00:00
var wand = mc.NewMagickWand();
if (wand == null) return error.WandCreateFail;
return MagickContext{
.wand = wand.?,
};
}
pub fn deinit(self: *MagickContext) void {
_ = mc.DestroyMagickWand(self.wand);
2019-07-23 00:50:11 +00:00
mc.DestroyMagick();
2019-07-22 23:32:50 +00:00
}
pub fn doErr(self: *MagickContext) !void {
2022-04-27 23:01:12 +00:00
_ = self;
2019-07-22 23:32:50 +00:00
return error.WandError;
}
};
fn magickLoad(image: *Image) !MagickContext {
2019-07-22 23:32:50 +00:00
var mctx = try MagickContext.init();
errdefer mctx.deinit();
2023-08-05 00:50:59 +00:00
var curpath = try image.allocator.dupeZ(u8, image.curpath);
2019-07-22 23:32:50 +00:00
defer image.allocator.free(curpath);
2022-10-08 18:14:56 +00:00
log.debug("loading '{s}'", .{curpath});
2019-07-23 00:50:11 +00:00
if (mc.MagickReadImage(mctx.wand, curpath.ptr) != 1)
return error.MagickReadFail;
2019-07-22 23:32:50 +00:00
return mctx;
}
2019-07-22 23:32:50 +00:00
2019-07-23 01:15:06 +00:00
fn magickSave(image: *Image, wand: *mc.MagickWand) !void {
const allocator = image.allocator;
2019-07-22 23:32:50 +00:00
2019-07-23 01:15:06 +00:00
var tmpnam = try images.temporaryName(allocator);
2023-08-05 00:50:59 +00:00
var c_tmpnam = try allocator.dupeZ(u8, tmpnam);
2019-07-23 01:15:06 +00:00
defer allocator.free(c_tmpnam);
2019-07-22 23:32:50 +00:00
2022-04-27 23:01:09 +00:00
log.debug("\tmagick: saving to '{s}'..", .{c_tmpnam});
2019-07-23 01:15:06 +00:00
if (mc.MagickWriteImage(wand, c_tmpnam.ptr) != 1)
return error.MagickWriteFail;
2019-07-23 01:15:06 +00:00
2022-10-08 18:14:56 +00:00
log.debug("OK", .{});
try image.reopen(tmpnam);
}
2019-07-23 01:22:01 +00:00
/// Rotate the given image.
/// bgfill must point to a null-terminated string.
pub fn runRotate(image: *Image, deg: f32, bgfill: []const u8) !void {
var mctx = try magickLoad(image);
defer mctx.deinit();
2019-07-23 01:15:06 +00:00
var bg = mc.NewPixelWand();
2019-07-23 00:50:11 +00:00
defer mc.DestroyPixelWand(bg);
2019-07-23 01:22:01 +00:00
if (mc.PixelSetColor(bg, bgfill.ptr) != 1)
2019-07-23 00:50:11 +00:00
return error.PixelSetColorFail;
2019-07-23 01:22:01 +00:00
if (mc.MagickRotateImage(mctx.wand, bg, deg) != 1)
2019-07-23 00:50:11 +00:00
return error.RotateFail;
2019-07-23 01:15:06 +00:00
try magickSave(image, mctx.wand);
2019-07-22 22:28:55 +00:00
}