wasm实例开发007-图片菱形渐变

在本系列前面的文章中我们介绍了一些基础的wasm应用和2个处理图片的wasm应用,本文我们将接续介绍wasm图像处理方面的应用,利用wasm实现图片的菱形渐变。

一、菱形渐变的原理

我们设渐变中心为(midx, midY),渐变大小为size,遍历每一个像素点(x, y),并计算(x, y)(midX, midY)的绝对差值(dx, dy),将dxdy的和作为距离,并除于渐变大小得到当前像素距离渐变中心的比例r,再用255乘以1-r得到当前像素的alpha值。如果我们将计算距离的方式改为欧氏距离,则可以得到一个径向渐变。

二、C代码编写

在了解了原理之后,代码编写相对就比较简单了,C代码如下:

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <math.h>

int main() {
    return 0;
}

uint8_t *create_diamond_gradient(uint8_t *inputImageData, int width, int height, uint8_t *outputImageData, int size, int midX, int midY) {
    for (int x=0; x<width; x++) {
        for (int y=0; y<height; y++) {
            int index = (y * width + x) * 4;
            int dx = abs(x - midX);
            int dy = abs(y - midY);
            int distance = dx + dy;
            double r = (double)distance / (double)size;
            outputImageData[index] =  inputImageData[index];
            outputImageData[index+1] =  inputImageData[index+1];
            outputImageData[index+2] =  inputImageData[index+2];
            outputImageData[index+3] =  floor(255.0 * (1.0 - r));
        }
    }
    return outputImageData;
}

其中create_diamond_gradient方法是最终暴露给js调用的方法,该方法接受以下参数:

①、inputImageData 输入的图像像素数据

②、width 图像宽度

③、height 图像高度

④、outputImageData 输出的图像像素数据

⑤、size 滤镜大小

⑥、midX 滤镜的中心点x坐标

⑦、midY 滤镜的中心点y坐标

三、将C程序编译成wasm应用

将上面的C程序保存为gradient.c, 然后在.c文件相同目录下新建build.sh文件,输入以下内容并保存:

#! /usr/bin/env bash

emcc -o gradient.js ./gradient.c \
     -Oz \
     -s ALLOW_MEMORY_GROWTH=1 \
     -s EXPORTED_FUNCTIONS='["_create_diamond_gradient", "_malloc", "_free"]' \
     -s EXPORTED_RUNTIME_METHODS='["ccall", "cwrap"]' \
     -s LINKABLE=1

执行./build.sh命令,等待wasm编译完成。

五、使用js调用wasm应用

数据的传递和接受的传递和接受我们之前都讲过了,这里没有什么特别需要注意的,如果还有不了解的可以看一下前面的文章,代码如下:

const inputImageData = getImageDataByImage(imgFile);
const outputImageData = new ImageData(inputImageData.width, inputImageData.height);
const inputPointer = _malloc(inputImageData.data.byteLength);
const outputPointer = _malloc(outputImageData.data.byteLength);
Module.HEAPU8.set(inputImageData.data, inputPointer);
Module.HEAPU8.set(outputImageData.data, outputPointer);
const pointer = _create_diamond_gradient(inputPointer, inputImageData.width, inputImageData.height, outputPointer, size.value, midX.value, midY.value);
outputImageData.data.set(new Uint8ClampedArray(Module.asm.memory.buffer, pointer, outputImageData.data.length), 0);
canvas.width = outputImageData.width;
canvas.height = outputImageData.height;
ctx.putImageData(outputImageData, 0, 0);
_free(inputPointer);
_free(outputPointer);
_free(pointer);

运行效果:

六、结语

本文没有什么难点,主要是需要理解菱形渐变的算法的实现原理,其他的都是一些常规的数据的传递和接受,不过需要注意的是相比之前文章中的代码我们做了一点的简化没有重新生成Uint8Array,这是因为图像的imageData数据是一个Uint8ClampedArray,本来就是一个Uint8类型的数据,所以我们不需要做额外的处理。

在线demo:https://demo.deanhan.cn/diamond-gradient/

如需下载本文涉及的源码素材包,请在关注本站公众号后发送:diamond

系列文章导航:

第1节: Wasm实例开发001-斐波那契数列

第2节: Wasm实例开发002-最长回文字符串

第3节: wasm实例开发003-简单数据的加密解密

第4节: wasm实例开发004-矩阵乘法

第5节: wasm实例开发005-图像高斯模糊

第6节: wasm实例开发006-证件照换底色

  • 支付宝二维码 支付宝
  • 微信二维码 微信

本文地址: /js-wasm-diamond-filter.html

版权声明: 本文为原创文章,版权归 逐梦个人博客 所有,欢迎分享本文,转载请保留出处!

相关文章