golang生成wasm,js调用wasm

457 阅读2分钟

不过多废话,展示完整步骤

GO

package main
import (
	"bytes"
	"fmt"
	"image"
	"image/draw"
	"image/jpeg"
	"log"
	"syscall/js"
)

func CropImage(this js.Value, inputs []js.Value) interface{} {
	imageData := inputs[0]
	x := inputs[1].Int()
	y := inputs[2].Int()
	w := inputs[3].Int()
	h := inputs[4].Int()
	// 将 JavaScript Uint8Array 转换为 Go 字节切片
	dataBytes := make([]byte, imageData.Length())
	js.CopyBytesToGo(dataBytes, imageData)

	// 裁剪图像
	croppedImage, err := cropHandle(dataBytes, x, y, w, h)
	if err != nil {
		log.Println("Error cropping image:", err)
		return nil
	}

	// 创建一个新的 Uint8Array,并将裁剪后的图像数据复制进去
	croppedArray := js.Global().Get("Uint8Array").New(len(croppedImage))
	js.CopyBytesToJS(croppedArray, croppedImage)

	return croppedArray
}

func cropHandle(dataBytes []byte, X, Y, W, H int) ([]byte, error) {
	// 使用 image 包解码图像数据
	img, _, err := image.Decode(bytes.NewReader(dataBytes))
	if err != nil {
		return nil, fmt.Errorf("error decoding image: %w", err)
	}

	// 创建一个 WxH 大小的图像
	croppedImg := image.NewRGBA(image.Rect(0, 0, W, H))

	//从X,Y位置开始裁剪图像
	draw.Draw(croppedImg, croppedImg.Bounds(), img, image.Point{X, Y}, draw.Src)

	// 编码裁剪后的图像为 JPEG 格式
	var buf bytes.Buffer
	err = jpeg.Encode(&buf, croppedImg, nil)
	if err != nil {
		return nil, fmt.Errorf("error encoding image: %w", err)
	}

	return buf.Bytes(), nil
}

func main() {
	c := make(chan struct{}, 0)

	js.Global().Set("CropImage", js.FuncOf(CropImage))

	<-c
}

这里给了一个示例,导出了一个裁剪图像的函数,接收Uint8Array类型数据和裁剪起始坐标以及裁剪宽高

使用下面的命令打包wasm文件,cmd窗口执行,注意golang需要版本>11

set GOOS=js   
set GOARCH=wasm  
go build -o main.wasm main.go

html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline' 'unsafe-eval'">
    <script src="wasm_exec.js"></script>
    <title>GO_wasm测试</title>
</head>

<body>
    <img style="width: 300px;" src="http://annew.320.io:8880/api/uploads/file/1f6439b8442141db143a319722917241_20240124113134.jpg" alt="">
    <p>使用wasm裁剪上面的图像</p>
    <hr>
</body>
<script>
    const go = new Go();

    WebAssembly.instantiateStreaming(fetch("./main.wasm"), go.importObject)
        .then((result) => {
            go.run(result.instance);

            fetch("http://annew.320.io:8880/api/uploads/file/1f6439b8442141db143a319722917241_20240124113134.jpg")
                .then(response => response.blob())
                .then(blob => {
                    return blob.arrayBuffer();
                })
                .then(arrayBuffer => {
                    // 创建 Uint8Array
                    const uint8Array = new Uint8Array(arrayBuffer);

                    const CropImageValue = CropImage(uint8Array,340,860,2320,2370);
                    // console.log(CropImageValue);
                    const img = document.createElement('img');
                    img.src = URL.createObjectURL(new Blob([CropImageValue], { type: 'image/jpeg' }));
                    img.width = 300;
                    document.body.appendChild(img);
                });
        }).catch((err) => {
            console.error(err);
        });


    function CropImage(uint8Array,X,Y,W,H) {
        return window.wasmCropImage(uint8Array,X,Y,W,H);
    }
</script>

</html>

wasm_exec.js 从golang的安装目录获取:C:\Program Files\Go\misc\wasm

image.png

js示例,获取图片的文件流,转为uint8Array,并传递给golang导出的函数获得处理后的uint8Array数据,再将其渲染到页面。

效果如下:

image.png

[在线体验地址]([ maxone.space:8086/)