-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
293 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta charset="utf-8"> | ||
<title>Seam Carving</title> | ||
<link rel="stylesheet" href="styles.css"> | ||
<link rel="icon" href="data:image/png;base64,AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////////////////////////////////8AAD//AAAf/wAAD/8AAA4xB/4OMQf8DgEAAA8DAAAfAQAAGAAAABgAB/wMCAf8D4cAAB+HAAAfzwAAP/8AAH////////////////////////////////////////////8="> | ||
</head> | ||
<body> | ||
<h1>Seam Carving</h1> | ||
<div id="image-container"> | ||
<fieldset class="settings-container"> | ||
<legend style="color:black;font-weight:bold;font-family:sans-serif;">Settings</legend> | ||
<div id="buttons-container"> | ||
<button id="remove-button">Remove seam</button> | ||
</div> | ||
<p id="size"></p> | ||
</fieldset> | ||
<canvas id="canvas-seam"></canvas> | ||
<script src="seam-carving.js"></script> | ||
</div> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
(function () { | ||
let wasmPromise = fetch("seam_carving.wasm"); | ||
var wasmExports = null; | ||
const text_decoder = new TextDecoder(); | ||
let image = null; | ||
|
||
const removeButton = document.getElementById("remove-button"); | ||
const canvas = document.getElementById("canvas-seam"); | ||
const ctx = canvas.getContext("2d"); | ||
canvas.ondragover = function (event) { | ||
event.preventDefault(); | ||
}; | ||
|
||
function displayImageSize() { | ||
let sizeElement = document.getElementById("size"); | ||
sizeElement.textContent = "size: " + canvas.width + "×" + canvas.height + " px."; | ||
} | ||
|
||
canvas.ondrop = function (event) { | ||
event.preventDefault(); | ||
let img = new Image(); | ||
img.onload = function () { | ||
canvas.width = img.width; | ||
canvas.height = img.height; | ||
ctx.drawImage(img, 0, 0); | ||
image = ctx.getImageData(0, 0, canvas.width, canvas.height); | ||
original = new ImageData(image.width, image.height); | ||
original.data.set(image.data); | ||
displayImageSize(); | ||
}; | ||
img.src = URL.createObjectURL(event.dataTransfer.files[0]); | ||
}; | ||
|
||
function displayImage(file) { | ||
const reader = new FileReader(); | ||
reader.onload = function (e) { | ||
const imageData = e.target.result; | ||
const img = document.createElement("img"); | ||
img.src = imageData; | ||
img.onload = function () { | ||
canvas.width = img.width; | ||
canvas.height = img.height; | ||
ctx.drawImage(img, 0, 0); | ||
image = ctx.getImageData(0, 0, canvas.width, canvas.height); | ||
original = new ImageData(image.width, image.height); | ||
original.data.set(image.data); | ||
displayImageSize(); | ||
}; | ||
}; | ||
reader.readAsDataURL(file); | ||
} | ||
|
||
const fileInput = document.createElement("input"); | ||
fileInput.type = "file"; | ||
fileInput.style.display = "none"; | ||
fileInput.addEventListener("change", function (e) { | ||
const file = e.target.files[0]; | ||
displayImage(file); | ||
}); | ||
|
||
canvas.addEventListener("click", function () { | ||
fileInput.click(); | ||
}); | ||
|
||
function decodeString(ptr, len) { | ||
if (len === 0) return ""; | ||
return text_decoder.decode(new Uint8Array(wasmExports.memory.buffer, ptr, len)); | ||
} | ||
|
||
WebAssembly.instantiateStreaming(wasmPromise, { | ||
js: { | ||
log: function (ptr, len) { | ||
const msg = decodeString(ptr, len); | ||
console.log(msg); | ||
}, | ||
now: function () { | ||
return performance.now(); | ||
}, | ||
}, | ||
}).then(function (obj) { | ||
wasmExports = obj.instance.exports; | ||
window.wasm = obj; | ||
console.log("wasm loaded"); | ||
|
||
let copy = null; | ||
function seamCarve() { | ||
if (copy) { | ||
ctx.putImageData(copy, 0, 0); | ||
} | ||
const rows = image.height; | ||
const cols = image.width; | ||
const rgbaSize = rows * cols * 4; | ||
const rgbaPtr = wasmExports.alloc(rgbaSize); | ||
const seamSize = rows * 4; | ||
const seamPtr = wasmExports.alloc(seamSize); | ||
const extraSize = rows * cols * 10; | ||
const extraPtr = wasmExports.alloc(extraSize); | ||
var rgba = new Uint8ClampedArray(wasmExports.memory.buffer, rgbaPtr, rgbaSize); | ||
var seam = new Uint32Array(wasmExports.memory.buffer, seamPtr, image.height); | ||
image = ctx.getImageData(0, 0, canvas.width, canvas.height); | ||
rgba.set(image.data); | ||
wasmExports.seam_carve(rgbaPtr, rows, cols, extraPtr, extraSize, seamPtr, rows); | ||
canvas.width = cols - 1; | ||
image = ctx.getImageData(0, 0, canvas.width, canvas.height); | ||
rgba = new Uint8ClampedArray(wasmExports.memory.buffer, rgbaPtr, rgbaSize - 4 * rows); | ||
|
||
image.data.set(rgba); | ||
ctx.putImageData(image, 0, 0); | ||
copy = ctx.getImageData(0, 0, canvas.width, canvas.height); | ||
displayImageSize(); | ||
|
||
for (let i = 1; i < rows; ++i) { | ||
ctx.beginPath(); | ||
ctx.moveTo(seam[i - 1], [i - 1]); | ||
ctx.lineTo(seam[i], [i]); | ||
ctx.strokeStyle = "red"; | ||
ctx.lineWidth = 1; | ||
ctx.stroke(); | ||
} | ||
|
||
wasmExports.free(rgbaPtr, rgbaSize); | ||
wasmExports.free(extraPtr, extraSize); | ||
} | ||
removeButton.addEventListener("click", () => { | ||
seamCarve(); | ||
}); | ||
}); | ||
})(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
const std = @import("std"); | ||
const assert = std.debug.assert; | ||
const builtin = @import("builtin"); | ||
|
||
const Image = @import("zignal").Image; | ||
const isColor = @import("zignal").colorspace.isColor; | ||
const Rgb = @import("zignal").Rgb; | ||
const Rgba = @import("zignal").Rgba; | ||
|
||
pub const std_options: std.Options = .{ | ||
.logFn = if (builtin.cpu.arch.isWasm()) @import("js.zig").logFn else std.log.defaultLog, | ||
.log_level = if (builtin.mode == .Debug) .debug else .info, | ||
}; | ||
|
||
pub fn computeEnergy( | ||
edges: Image(u8), | ||
energy: *Image(u32), | ||
) void { | ||
assert(edges.rows == energy.rows and edges.cols == energy.cols); | ||
const rows = edges.rows; | ||
const cols = edges.cols; | ||
for (0..cols) |c| energy.data[c] = edges.data[c]; | ||
for (1..rows) |r| { | ||
for (0..cols) |c| { | ||
var min: u32 = std.math.maxInt(u32); | ||
var i: isize = -1; | ||
while (i <= 1) : (i += 1) { | ||
var x: isize = @as(isize, @intCast(c)) + i; | ||
if (x == energy.cols) x = @intCast(energy.cols - 1); | ||
const y: isize = @as(isize, @intCast(r)) - 1; | ||
if (energy.at(y, x)) |val| { | ||
min = @min(val.*, min); | ||
} | ||
} | ||
const pos = r * edges.cols + c; | ||
energy.data[pos] = edges.data[pos] + min; | ||
} | ||
} | ||
} | ||
|
||
pub fn computeSeam(energy: Image(u32), seam: []usize) void { | ||
assert(energy.rows == seam.len); | ||
const row: usize = energy.rows - 1; | ||
seam[row] = 0; | ||
for (0..energy.cols) |c| { | ||
const pos1 = row * energy.cols + c; | ||
const pos2 = row * energy.cols + seam[row]; | ||
if (energy.data[pos1] < energy.data[pos2]) { | ||
seam[row] = c; | ||
} | ||
} | ||
|
||
var y: isize = @intCast(energy.rows - 2); | ||
while (y >= 0) : (y -= 1) { | ||
const r: usize = @intCast(y); | ||
seam[r] = seam[r + 1]; | ||
var i: isize = -1; | ||
while (i <= 1) : (i += 1) { | ||
var x: isize = @as(isize, @intCast(seam[r + 1])) + i; | ||
if (x == energy.cols) x = @intCast(energy.cols - 1); | ||
if (energy.at(y, x)) |curr| { | ||
if (energy.at(y, @intCast(seam[r]))) |prev| { | ||
if (curr.* < prev.*) { | ||
seam[r] = @intCast(x); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
pub fn removeSeam(comptime T: type, image: *Image(T), seam: []const usize) void { | ||
assert(image.rows == seam.len); | ||
const size = image.rows * image.cols; | ||
var pos: usize = 0; | ||
for (0..image.rows) |r| { | ||
for (0..image.cols) |c| { | ||
if (c == seam[r]) continue; | ||
image.data[pos] = image.data[r * image.cols + c]; | ||
pos += 1; | ||
} | ||
} | ||
|
||
image.cols -= 1; | ||
image.data = image.data[0..(size - image.rows)]; | ||
} | ||
|
||
pub export fn seam_carve(rgba_ptr: [*]Rgba, rows: usize, cols: usize, extra_ptr: ?[*]u8, extra_len: usize, seam_ptr: [*]usize, seam_size: usize) void { | ||
assert(seam_size == rows); | ||
const size = rows * cols; | ||
var image = Image(Rgba).init(rows, cols, rgba_ptr[0..size]); | ||
|
||
const allocator: std.mem.Allocator = blk: { | ||
if (extra_ptr) |ptr| { | ||
@setRuntimeSafety(true); | ||
assert(extra_len > size * 9); | ||
var fba = std.heap.FixedBufferAllocator.init(ptr[0..extra_len]); | ||
break :blk fba.allocator(); | ||
} else if (builtin.cpu.arch.isWasm() and builtin.os.tag == .freestanding) { | ||
@panic("ERROR: extra_ptr can't be null when running in WebAssembly."); | ||
} else if (builtin.link_libc) { | ||
break :blk std.heap.c_allocator; | ||
} else { | ||
break :blk std.heap.page_allocator; | ||
} | ||
}; | ||
|
||
var edges = Image(u8).initAlloc(allocator, rows, cols) catch @panic("OOM"); | ||
defer edges.deinit(allocator); | ||
image.sobel(allocator, &edges) catch @panic("OOM"); | ||
|
||
var energy_map = Image(u32).initAlloc(allocator, image.rows, image.cols) catch @panic("OOM"); | ||
defer energy_map.deinit(allocator); | ||
computeEnergy(edges, &energy_map); | ||
|
||
const seam = seam_ptr[0..seam_size]; | ||
computeSeam(energy_map, seam); | ||
|
||
removeSeam(Rgba, &image, seam); | ||
} | ||
|
||
pub export fn transpose(rgba_ptr: [*]Rgba, rows: usize, cols: usize) void { | ||
for (0..rows) |r| { | ||
for (0..cols) |c| { | ||
const orig_pos = r * cols + c; | ||
const tran_pos = c * rows + r; | ||
const temp = rgba_ptr[orig_pos]; | ||
rgba_ptr[orig_pos] = rgba_ptr[tran_pos]; | ||
rgba_ptr[tran_pos] = temp; | ||
} | ||
} | ||
} |