【发布时间】:2019-05-03 15:08:32
【问题描述】:
我想在 Go 中编写一个照片过滤器,将其用作 WebAssembly 模块。
Go 的类型为 js.Value。我可以在上面Get、Set、Index 和Call。但是如何在 Go 中快速使用来自 ImageData.data 的像素数组呢?使用data.Index(index).Int() 和.SetIndex(..., ...) 之类的东西非常慢。而且我没有检查这是否得到正确的结果。
第一次尝试非常慢(大约比 JS 或 Rust 慢 50 倍):
func Convolve(canvas js.Value, matrix []float64, factor float64) {
side := int(math.Sqrt(float64(len(matrix))))
halfSide := int(side / 2)
context := canvas.Call("getContext", "2d")
source := context.Call("getImageData", 0.0, 0.0, canvas.Get("width").Int(), canvas.Get("height").Int())
sourceData := source.Get("data")
imageWidth := source.Get("width").Int()
imageHeight := source.Get("height").Int()
output := context.Call("createImageData", imageWidth, imageHeight)
outputData := output.Get("data")
for y := 0; y < imageHeight; y++ {
for x := 0; x < imageWidth; x++ {
outputIndex := (y * imageWidth + x) * 4
r := 0.0
g := 0.0
b := 0.0
for cy := 0; cy < side; cy++ {
for cx := 0; cx < side; cx++ {
scy := y + cy - halfSide
scx := x + cx - halfSide
if scy >= 0 && scy < imageHeight && scx >= 0 && scx < imageWidth {
sourceIndex := (scy * imageWidth + scx) * 4
modify := matrix[cy * side + cx]
r += sourceData.Index(sourceIndex).Float() * modify
g += sourceData.Index(sourceIndex + 1).Float() * modify
b += sourceData.Index(sourceIndex + 2).Float() * modify
}
}
}
outputData.SetIndex(outputIndex, r * factor)
outputData.SetIndex(outputIndex + 1, g * factor)
outputData.SetIndex(outputIndex + 2, b * factor)
outputData.SetIndex(outputIndex + 3, sourceData.Index(outputIndex + 3))
}
}
context.Call("putImageData", output, 0, 0);
}
【问题讨论】:
-
我不确定 webassembly 能否在如此简单的场景中为您提供加速。在 JS 和 WS 之间切换的开销可能大于收益。
-
您认为照片滤镜是一个简单的场景吗?如果我用 9x9 矩阵和全高清图片在 Javascript 中运行它,处理起来需要很长时间。我想说这并不比 3D 计算复杂。
标签: image go slice webassembly