将存储 RGBA 的 Uint8Array 数组保存到 .png 文件

Pha*_*sed 3 javascript webgl three.js

我目前正在尝试将特定区域中 ThreeJS 的屏幕截图保存到文件中。

到目前为止,我只是尝试将图像显示到新选项卡中,我已经可以使用它了

window.open(renderer.domElement.toDataURL("image/png"));
Run Code Online (Sandbox Code Playgroud)

渲染器是一个 THREE.WebGLRenderer 对象,其preserveDrawingBuffer: true

但这使用了整个场景,所以我切换到:

    var gl = renderer.getContext();
    var pixels = new Uint8Array(width * height * 4);
    gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
    window.open("data:image/png;base64," + btoa(String.fromCharCode.apply(null, pixels)));
Run Code Online (Sandbox Code Playgroud)

这样做,除了灰色轮廓的正方形之外,没有任何东西被渲染

轮廓灰色方块

Pha*_*sed 5

在意识到数据的格式不正确后,找到了一个解决方案。

    var gl = renderer.getContext();
    var pixels = new Uint8Array(width * height * 4);
    gl.readPixels(x, y, width, height, gl.RGBA, gl.UNSIGNED_BYTE, pixels);

    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext("2d");
    var imageData = ctx.createImageData(width, height);

    for(var i = 0; i < imageData.data.length; i+=4) {
        imageData.data[i + 0] = pixels[i + 0];
        imageData.data[i + 1] = pixels[i + 1];
        imageData.data[i + 2] = pixels[i + 2];
        imageData.data[i + 3] = pixels[i + 3];
    }

    ctx.putImageData(imageData,0,0);
    window.open(canvas.toDataURL("image/png"));
    canvas.remove();
Run Code Online (Sandbox Code Playgroud)

这不是最好的方法,但它奏效了。

  • 由于您只是复制整个阵列,因此无需一次复制一个像素。一个简单的循环 `for (var i = 0; i &lt; pixel.length; ++i) { imageData.data[i] = pixel[i]; }`会工作 (2认同)