diff --git a/README.md b/README.md index d258198..e9c3445 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Zignal - + Zignal is an image processing library heavily inspired by the amazing [dlib](http://dlib.net). @@ -48,6 +48,7 @@ They can be accessed from [here](https://bfactory-ai.github.io/zignal/examples/) Currently, there are examples for: - [Color space conversions](https://bfactory-ai.github.io/zignal/examples/colorspace.html) - [Face alignment](https://bfactory-ai.github.io/zignal/examples/face-alignment.html) +- [Perlin noise generation](https://bfactory-ai.github.io/zignal/examples/perlin.html) ## Acknowledgements diff --git a/examples/build.zig b/examples/build.zig index 7363683..1743fca 100644 --- a/examples/build.zig +++ b/examples/build.zig @@ -3,8 +3,9 @@ const std = @import("std"); pub fn build(b: *std.Build) void { const target = b.standardTargetOptions(.{}); const optimize = b.standardOptimizeOption(.{}); - _ = buildModule(b, "face_alignment", target, optimize); _ = buildModule(b, "colorspace", target, optimize); + _ = buildModule(b, "face_alignment", target, optimize); + _ = buildModule(b, "perlin", target, optimize); const fmt_step = b.step("fmt", "Run zig fmt"); const fmt = b.addFmt(.{ diff --git a/examples/lib/index.html b/examples/lib/index.html index b3512bb..99d46f9 100644 --- a/examples/lib/index.html +++ b/examples/lib/index.html @@ -15,6 +15,7 @@

Examples

diff --git a/examples/lib/main.js b/examples/lib/main.js deleted file mode 100644 index de0b8cf..0000000 --- a/examples/lib/main.js +++ /dev/null @@ -1,2 +0,0 @@ -(function () { -})(); diff --git a/examples/lib/perlin.html b/examples/lib/perlin.html new file mode 100644 index 0000000..30d7077 --- /dev/null +++ b/examples/lib/perlin.html @@ -0,0 +1,44 @@ + + + + + Perlin Noise + + + + +

Perlin Noise

+
+
+ Settings +
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + +
+ + diff --git a/examples/lib/styles.css b/examples/lib/styles.css index 7031600..7d1430a 100644 --- a/examples/lib/styles.css +++ b/examples/lib/styles.css @@ -10,12 +10,6 @@ position: relative; } -.grid-container { - display: grid; - grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); - grid-gap: 20px; -} - #form { width: 300px; margin: 10px; @@ -30,6 +24,10 @@ top: 0px; } +#canvas { + border: 1px solid black; +} + #video { position: absolute; } diff --git a/examples/src/js.zig b/examples/src/js.zig index bd82bbd..179f705 100644 --- a/examples/src/js.zig +++ b/examples/src/js.zig @@ -1,7 +1,6 @@ const std = @import("std"); const builtin = @import("builtin"); const assert = std.debug.assert; -const gpa = std.heap.wasm_allocator; pub const js = struct { extern "js" fn log(ptr: [*]const u8, len: usize) void; @@ -29,10 +28,10 @@ pub fn logFn( } export fn alloc(len: usize) [*]u8 { - const slice = gpa.alloc(u8, len) catch @panic("OOM"); + const slice = std.heap.wasm_allocator.alloc(u8, len) catch @panic("OOM"); return slice.ptr; } export fn free(ptr: [*]const u8, len: usize) void { - gpa.free(ptr[0..len]); + std.heap.wasm_allocator.free(ptr[0..len]); } diff --git a/examples/src/perlin.zig b/examples/src/perlin.zig new file mode 100644 index 0000000..bd7206f --- /dev/null +++ b/examples/src/perlin.zig @@ -0,0 +1,60 @@ +const std = @import("std"); +const builtin = @import("builtin"); +const perlin = @import("zignal").perlin; +const Rgba = @import("zignal").Rgba; +const Image = @import("zignal").Image; + +pub const std_options: std.Options = .{ + .logFn = if (builtin.cpu.arch.isWasm()) @import("js.zig").logFn else std.log.defaultLog, + .log_level = .info, +}; + +var opts = perlin.Options(f32){ + .amplitude = 1, + .frequency = 1, + .octaves = 1, + .persistence = 0.5, + .lacunarity = 2, +}; + +pub export fn set_amplitude(val: f32) void { + std.log.debug("setting amplitude to {d}", .{val}); + opts.amplitude = val; +} +pub export fn set_frequency(val: f32) void { + std.log.debug("setting frequency to {d}", .{val}); + opts.frequency = val; +} + +pub export fn set_octaves(val: usize) void { + std.log.debug("setting octaves to {d}", .{val}); + opts.octaves = val; +} + +pub export fn set_persistence(val: f32) void { + std.log.debug("setting persistence to {d}", .{val}); + opts.persistence = val; +} + +pub export fn set_lacunarity(val: f32) void { + std.log.debug("setting lacunarity to {d}", .{val}); + opts.lacunarity = val; +} + +pub export fn generate(rgba_ptr: [*]Rgba, rows: usize, cols: usize) void { + const size = rows * cols; + const image = Image(Rgba).init(rows, cols, rgba_ptr[0..size]); + for (0..image.rows) |r| { + const y: f32 = @as(f32, @floatFromInt(r)) / @as(f32, @floatFromInt(image.rows)); + for (0..image.cols) |c| { + const pos = r * image.cols + c; + const x: f32 = @as(f32, @floatFromInt(c)) / @as(f32, @floatFromInt(image.cols)); + const val: u8 = @intFromFloat( + @max(0, @min(255, @round( + 255 * (opts.amplitude / 2 * (perlin.generate(f32, x, y, 0, opts) + opts.amplitude)), + ))), + ); + image.data[pos] = Rgba.fromGray(val, 255); + } + } +}