js滤镜灰度计算_js 图片灰度转换 wasm性能对比

这篇博客探讨了使用原生JavaScript和WebAssembly(WASM)进行图片灰度转换的性能。实验表明,虽然原生JS在简单循环操作上速度较快,但涉及到IO操作时,WASM的性能可能会稍逊一筹。文章通过代码示例展示了两种方法的实现,并进行了性能测试。
摘要由CSDN通过智能技术生成

简单的循环操作, 原生js的速度也很快, 对于需要进行io的wasm来说, 性能反而会稍微慢一点

原地操作数组, 会有一些提升的空间

40b454757443d24c0ec27dd406b6cf73.png

a0109e11fb2e30ba0a38008d332f141a.png

js版本

19f280031ff38da90dea381917f451bd.png

Title

const grayJs = (data, w, h) => {

const size = w * h;

for (let i = 0; i < size; i++) {

const j = i * 4;

const g = ((data[j] + data[j + 1] + data[j + 2]) / 3) | 0;

// const g = Number((data[j] + data[j + 1] + data[j + 2]) / 3)

data[j] = data[j + 1] = data[j + 2] = g;

}

};

const input = document.getElementById("input");

const canvas = document.createElement("canvas");

const output = document.createElement("canvas");

const test = () => {

const w = input.width;

const h = input.height;

canvas.width = output.width = w;

canvas.height = output.height = h;

const ctx = canvas.getContext("2d");

ctx.drawImage(input, 0, 0);

document.body.append(canvas);

const imageData = ctx.getImageData(0, 0, w, h);

const i = new Uint8ClampedArray();

console.log(imageData);

imageData.data[0] = 0;

const st = +new Date();

grayJs(imageData.data, w, h);

console.log("time:", +new Date() - st, imageData.data.length);

console.log(imageData);

output.getContext("2d").putImageData(imageData, 0, 0);

document.body.append(output);

};

document.addEventListener("click", test);

wasm版本

f7faeb4130e73dc09494ea7db2d921c0.png

Document

let imageData;

let w;

let h;

const input = document.getElementById("input");

const canvas = document.createElement("canvas");

const output = document.createElement("canvas");

input.onload = () => {

w = input.width;

h = input.height;

canvas.width = output.width = w;

canvas.height = output.height = h;

const ctx = canvas.getContext("2d");

ctx.drawImage(input, 0, 0);

document.body.append(canvas);

imageData = ctx.getImageData(0, 0, w, h);

// console.log("imageData", imageData.data.length);

};

Module.onRuntimeInitialized = () => {

console.log("===", imageData, w, h);

console.log("wasm", Module);

};

function test() {

const size = imageData.data.length;

const ccall = Module.ccall;

const numBytes = size * Uint8Array.BYTES_PER_ELEMENT;

// console.log("size", { size, numBytes, w, h });

const ptr = Module._malloc(numBytes);

const heapBytes = new Uint8Array(Module.HEAP8.buffer, ptr, numBytes);

const imageDataBuffer = Uint8Array.from(imageData.data);

// console.log("imageDataBuffer", imageDataBuffer);

heapBytes.set(new Uint8Array(imageDataBuffer));

const st = +new Date();

const resultPtr = ccall(

"grayCpp",

"Uint8Array",

["Uint8Array", "number", "number"],

[heapBytes.byteOffset, w, h]

);

console.log("time:", +new Date() - st);

// console.log("resultPtr", resultPtr);

const resultArray = new Uint8Array(

Module.HEAP8.buffer,

resultPtr,

size

);

// console.log("resultArray", resultArray);

const result = new Uint8ClampedArray(resultArray);

// console.log("result", result.length);

const outputData = new ImageData(result, w, h);

output.getContext("2d").putImageData(outputData, 0, 0);

document.body.append(output);

}

document.addEventListener("click", test);

7d8a5d243d01c87d00f721ec5ca45b5f.png

grayCpp.cpp

#include

#include

#include

#include

using namespace std;

extern "C"

{

uint8_t *grayCpp(uint8_t *data, int w, int h);

}

uint8_t *grayCpp(uint8_t *data, int w, int h)

{

int byteSize = sizeof(uint8_t) * w * h * 4;

cout << "byteSize:" << byteSize << endl;

uint8_t *ptr = (uint8_t *)malloc(byteSize);

memcpy(ptr, data, byteSize);

uint8_t g;

int size = w * h;

int j = 0;

for (int i = 0; i < size; i++)

{

j = i * 4;

g = (data[j] + data[j + 1] + data[j + 2]) / 3;

ptr[j] = ptr[j + 1] = ptr[j + 2] = g;

}

return ptr;

}

int main(int argc, char **argv)

{

return 0;

}

/*

emcc -O3 -s \

-s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap","ccall"]' \

-s EXPORTED_FUNCTIONS='["_main","_grayCpp"]' \

-s ALLOW_MEMORY_GROWTH \

grayCpp.cpp

*/

grayC.c

#include

#include

#include

EMSCRIPTEN_KEEPALIVE

void grayCpp(uint8_t *data, int w, int h)

{

int i,j;

uint8_t g;

int size = w * h;

for ( i = 0; i < size; i++) {

j = i * 4;

g = ((data[j] + data[j + 1] + data[j + 2]) / 3);

// const g = Number((data[j] + data[j + 1] + data[j + 2]) / 3)

data[j] = data[j + 1] = data[j + 2] = g;

}

}

EMSCRIPTEN_KEEPALIVE

uint8_t* create_buffer(int width, int height)

{

return (uint8_t *)malloc(width * height * 4 * sizeof(uint8_t));

}

int main(int argc, char **argv)

{

// int i;

// for (i = 0; i < 10; i++)

// printf("hello %d %d \n", i, fib(1));

create_buffer(1,1);

return 0;

}

// emcc fib.c -s WASM=1 -s -o fib.html

// emcc fib.cpp -s WASM=1 -s -o fib.html

// emcc -O3 -s WASM=1 -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap","fib"]' fib.cpp

// emcc -O3 -s WASM=1 -s ALLOW_MEMORY_GROWTH -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap","create_buffer","grayCpp"]' grayCpp.cpp

// emcc -O3 -s WASM=1 -s ALLOW_MEMORY_GROWTH -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap","create_buffer","grayCpp"]' grayCpp.c

/*

emcc -O3 -s WASM=1 -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap"]' \

-I libwebp \

grayCpp.cpp \

-s ALLOW_MEMORY_GROWTH \

emcc -O3 -s WASM=1 -s ALLOW_MEMORY_GROWTH -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap","fib"]' grayCpp.cpp

emcc -O3 -s WASM=1 -s ALLOW_MEMORY_GROWTH -s EXTRA_EXPORTED_RUNTIME_METHODS='["cwrap","ccall","create_buffer","grayCpp"]' grayCpp.cpp

*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值