Compare commits
10 commits
2151afb115
...
c128960451
Author | SHA1 | Date | |
---|---|---|---|
c128960451 | |||
f9aa226d9e | |||
510b4d9336 | |||
4a49b39159 | |||
e469c84d1b | |||
6775773674 | |||
8784f3baf9 | |||
73794e1867 | |||
b056a0edb3 | |||
67c9f425bb |
9 changed files with 4245 additions and 11 deletions
|
@ -13,7 +13,7 @@ glitch art "framework", ???????? language??? something?
|
||||||
- zig at https://ziglang.org
|
- zig at https://ziglang.org
|
||||||
- libc, lilv and libsndfile
|
- libc, lilv and libsndfile
|
||||||
- an appreciation for glitched anime girls on your hard drive
|
- an appreciation for glitched anime girls on your hard drive
|
||||||
- optional: imagemagick to convert from whatever to bmp
|
- graphicsmagick for the `rotate` command
|
||||||
|
|
||||||
## plugin depedencies:
|
## plugin depedencies:
|
||||||
- lv2 default plugins (most specifically the eg-amp plugin)
|
- lv2 default plugins (most specifically the eg-amp plugin)
|
||||||
|
@ -37,8 +37,3 @@ scritcher examples/middle_amp.scri blah.bmp
|
||||||
// blah_g1.bmp, the second saves to blah_g2.bmp, etc.
|
// blah_g1.bmp, the second saves to blah_g2.bmp, etc.
|
||||||
$your_image_viewer blah_g1.bmp
|
$your_image_viewer blah_g1.bmp
|
||||||
```
|
```
|
||||||
|
|
||||||
## todo
|
|
||||||
|
|
||||||
- search other plugins
|
|
||||||
- conquer the world for glitchy anime girls
|
|
||||||
|
|
|
@ -10,7 +10,11 @@ pub fn build(b: *Builder) void {
|
||||||
exe.linkSystemLibrary("sndfile");
|
exe.linkSystemLibrary("sndfile");
|
||||||
exe.linkSystemLibrary("c");
|
exe.linkSystemLibrary("c");
|
||||||
|
|
||||||
|
exe.linkSystemLibrary("GraphicsMagickWand");
|
||||||
|
exe.linkSystemLibrary("GraphicsMagick");
|
||||||
|
|
||||||
exe.addIncludeDir("/usr/include/lilv-0");
|
exe.addIncludeDir("/usr/include/lilv-0");
|
||||||
|
exe.addIncludeDir("/usr/include/GraphicsMagick");
|
||||||
|
|
||||||
const run_cmd = exe.run();
|
const run_cmd = exe.run();
|
||||||
run_cmd.step.dependOn(b.getInstallStep());
|
run_cmd.step.dependOn(b.getInstallStep());
|
||||||
|
|
|
@ -114,7 +114,7 @@ Parameters:
|
||||||
- `gain`: Gain, 0..12, default 0
|
- `gain`: Gain, 0..12, default 0
|
||||||
- `noClip`: Soft Clip (assumed boolean), 0..1, default 0
|
- `noClip`: Soft Clip (assumed boolean), 0..1, default 0
|
||||||
|
|
||||||
## `delay seed gain feedback_pc tap_count first_delay delay_range delay_scale delay_rand_pc gain_scale wet`
|
## `delay split index seed gain feedback_pc tap_count first_delay delay_range delay_scale delay_rand_pc gain_scale wet`
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
- `seed`: Random seed, 0..1000, default 0
|
- `seed`: Random seed, 0..1000, default 0
|
||||||
|
@ -159,9 +159,11 @@ Parameters:
|
||||||
- `repeat_bytes`, Amount of bytes to preload with random data and repeat
|
- `repeat_bytes`, Amount of bytes to preload with random data and repeat
|
||||||
throughout the image slice
|
throughout the image slice
|
||||||
|
|
||||||
## TODO `echo split index delay`
|
## `rotate deg bgfill`
|
||||||
|
|
||||||
Run an echo filter on the given loaded file.
|
Rotate the image by `deg` degrees, filling the resulting triangles with `bgfill`.
|
||||||
|
|
||||||
|
`bgfill` is a hex string, e.g `#000000`.
|
||||||
|
|
||||||
## `quicksave`
|
## `quicksave`
|
||||||
|
|
||||||
|
|
3
examples/rotate.scri
Normal file
3
examples/rotate.scri
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
load :0;
|
||||||
|
rotate 30 #ff00ff;
|
||||||
|
quicksave;
|
|
@ -67,7 +67,7 @@ fn sf_tell(file: *c.SNDFILE) i64 {
|
||||||
return -frames;
|
return -frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn temporaryName(allocator: *std.mem.Allocator) ![]u8 {
|
pub fn temporaryName(allocator: *std.mem.Allocator) ![]u8 {
|
||||||
const template_start = "/temp/temp_";
|
const template_start = "/temp/temp_";
|
||||||
const template = "/tmp/temp_XXXXXXXX";
|
const template = "/tmp/temp_XXXXXXXX";
|
||||||
var nam = try allocator.alloc(u8, template.len);
|
var nam = try allocator.alloc(u8, template.len);
|
||||||
|
@ -146,6 +146,8 @@ pub const Image = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close(self: *Image) void {
|
pub fn close(self: *Image) void {
|
||||||
|
//self.allocator.free(self.path);
|
||||||
|
//self.allocator.free(self.curpath);
|
||||||
var st: i32 = c.sf_close(self.sndfile);
|
var st: i32 = c.sf_close(self.sndfile);
|
||||||
|
|
||||||
if (st != 0) {
|
if (st != 0) {
|
||||||
|
@ -338,7 +340,7 @@ pub const Image = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn saveTo(self: *Image, out_path: []const u8) !void {
|
pub fn saveTo(self: *Image, out_path: []const u8) !void {
|
||||||
std.debug.warn("saved to '{}'\n", out_path);
|
std.debug.warn("\timg: copy from '{}' to '{}'\n", self.curpath, out_path);
|
||||||
try std.fs.copyFile(self.curpath, out_path);
|
try std.fs.copyFile(self.curpath, out_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,8 @@ pub const CommandType = enum {
|
||||||
RevDelay,
|
RevDelay,
|
||||||
Noise,
|
Noise,
|
||||||
WildNoise,
|
WildNoise,
|
||||||
|
|
||||||
|
Rotate,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Command = struct {
|
pub const Command = struct {
|
||||||
|
@ -159,6 +161,9 @@ pub const Lang = struct {
|
||||||
// custom implementations (not lv2)
|
// custom implementations (not lv2)
|
||||||
_ = try self.keywords.put("noise", .Noise);
|
_ = try self.keywords.put("noise", .Noise);
|
||||||
_ = try self.keywords.put("wildnoise", .WildNoise);
|
_ = try self.keywords.put("wildnoise", .WildNoise);
|
||||||
|
|
||||||
|
// even more custom
|
||||||
|
_ = try self.keywords.put("rotate", .Rotate);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(self: *Lang, data: []const u8) !CommandList {
|
pub fn parse(self: *Lang, data: []const u8) !CommandList {
|
||||||
|
|
80
src/magick.zig
Normal file
80
src/magick.zig
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
// 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, wand: *mc.MagickWand) !void {
|
||||||
|
const allocator = image.allocator;
|
||||||
|
|
||||||
|
var tmpnam = try images.temporaryName(allocator);
|
||||||
|
var c_tmpnam = try std.cstr.addNullByte(allocator, tmpnam);
|
||||||
|
defer allocator.free(c_tmpnam);
|
||||||
|
|
||||||
|
std.debug.warn("\tmagick: saving to '{}'..", c_tmpnam);
|
||||||
|
|
||||||
|
if (mc.MagickWriteImage(wand, c_tmpnam.ptr) != 1)
|
||||||
|
return error.MagickWriteFail;
|
||||||
|
|
||||||
|
image.curpath = tmpnam;
|
||||||
|
std.debug.warn("OK\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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();
|
||||||
|
|
||||||
|
var bg = mc.NewPixelWand();
|
||||||
|
defer mc.DestroyPixelWand(bg);
|
||||||
|
|
||||||
|
if (mc.PixelSetColor(bg, bgfill.ptr) != 1)
|
||||||
|
return error.PixelSetColorFail;
|
||||||
|
|
||||||
|
if (mc.MagickRotateImage(mctx.wand, bg, deg) != 1)
|
||||||
|
return error.RotateFail;
|
||||||
|
|
||||||
|
try magickSave(image, mctx.wand);
|
||||||
|
}
|
4124
src/magick_wand.zig
Normal file
4124
src/magick_wand.zig
Normal file
File diff suppressed because it is too large
Load diff
|
@ -3,6 +3,7 @@ const lang = @import("lang.zig");
|
||||||
const images = @import("image.zig");
|
const images = @import("image.zig");
|
||||||
const plugin = @import("plugin.zig");
|
const plugin = @import("plugin.zig");
|
||||||
const custom = @import("custom.zig");
|
const custom = @import("custom.zig");
|
||||||
|
const magick = @import("magick.zig");
|
||||||
|
|
||||||
const Position = plugin.Position;
|
const Position = plugin.Position;
|
||||||
const ParamList = plugin.ParamList;
|
const ParamList = plugin.ParamList;
|
||||||
|
@ -257,6 +258,18 @@ pub const Runner = struct {
|
||||||
try image.runCustomPlugin(custom.WildNoise, pos, map);
|
try image.runCustomPlugin(custom.WildNoise, pos, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn rotateCmd(
|
||||||
|
self: *Runner,
|
||||||
|
deg: f32,
|
||||||
|
bgfill: []const u8,
|
||||||
|
) !void {
|
||||||
|
var image = try self.getImage();
|
||||||
|
var c_bgfill = try std.cstr.addNullByte(self.allocator, bgfill);
|
||||||
|
defer self.allocator.free(c_bgfill);
|
||||||
|
|
||||||
|
try magick.runRotate(image, deg, c_bgfill);
|
||||||
|
}
|
||||||
|
|
||||||
fn runCommand(self: *Runner, cmd: *lang.Command) !void {
|
fn runCommand(self: *Runner, cmd: *lang.Command) !void {
|
||||||
var params = ParamList.init(self.allocator);
|
var params = ParamList.init(self.allocator);
|
||||||
defer params.deinit();
|
defer params.deinit();
|
||||||
|
@ -418,6 +431,12 @@ pub const Runner = struct {
|
||||||
try self.wildNoiseCmd(pos, &map);
|
try self.wildNoiseCmd(pos, &map);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
.Rotate => blk: {
|
||||||
|
const deg = try cmd.floatArgAt(0);
|
||||||
|
const bgfill = try cmd.argAt(1);
|
||||||
|
try self.rotateCmd(deg, bgfill);
|
||||||
|
},
|
||||||
|
|
||||||
else => blk: {
|
else => blk: {
|
||||||
std.debug.warn("Unsupported command: {}\n", cmd.command);
|
std.debug.warn("Unsupported command: {}\n", cmd.command);
|
||||||
break :blk RunError.UnknownCommand;
|
break :blk RunError.UnknownCommand;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue