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
+
+
+
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);
+ }
+ }
+}