如何使用Javascript将原始图像字节数组转换为PNG图像

时间:2019-06-26 08:43:51

标签: javascript angular html5-canvas

我有一个原始图像(.raw格式,没有任何图像标题),我想将其转换为PNG格式以显示在画布上。我尝试将原始图像转换为RGBA,并且成功(通过操作字节并在画布中使用ImageData API)。现在,我需要将原始图像转换为PNG。

我尝试过,

  1. 从响应中获取图像并创建数组缓冲区
  2. 创建创建的图像arraybuffer的UInt8Array。
  3. 将其转换为base64:png内容

有人可以帮我吗?

我尝试了多种在Internet上找到的解决方案,但是它们都不适合我。

  1. 创建blob并使用它构建对象URL并显示在画布上-无效
  2. 将PNG图像标头添加到字节数组并显示在画布上。

    fetch(image.src).then(resp => {  // load from original source
      return resp.arrayBuffer();
      //return resp.blob();      // obtain a blob
    }).then(arrayBuffer => {
      let int8array = new Uint8Array(arrayBuffer);
      let base64content = this.arrayBufferToBase64(int8array.buffer);
      let newImg = document.createElement('img');
      newImg.src = 'data:image/png;base64,' + base64content;
      this.context.drawImage(newImg, 0, 0);
    });
    
    arrayBufferToBase64( buffer ) {
    let binary = '';
    let bytes = new Uint8Array( buffer );
    var len = bytes.byteLength;
    for (let i = 0; i < len; i++) {
        binary += String.fromCharCode( bytes[ i ] );
    }
    return window.btoa( binary );
    }
    

    我希望在画布上绘制一个png图像,但我看到的是空画布。

  3. 我还尝试了将PNG图像标头直接添加到图像的bytearray内容

    fetch(image.src).then(resp => {
          return resp.arrayBuffer();
        }).then(arrayBuffer => {
          let int8array = new Uint8Array(arrayBuffer);
          let signature = new Uint8Array([137, 80, 78, 71, 13, 10, 26, 10]);
          let newArray = new Uint8Array(int8array.length + signature.length);
          newArray.set(signature);
          newArray.set(int8array, signature.length);
          const imgData = this.uint8ToImageData(newArray, 500, 500);
          this.context.putImageData(imgData, 0, 0);
     });
     uint8ToImageData(uint8, width, height) {
          let iData = this.context.createImageData(width, height);
          for (let i = 0; i < uint8.length; i++) {
            iData.data[i] = uint8[i];
          }
          return iData;
      }

我至少可以看到画布上显示的图像,但是与原始图像不同。

1 个答案:

答案 0 :(得分:0)

如果图像具有RGBA阵列格式,并且可以将其打印到画布上,则只需使用canvas.toDataURL()即可获得"data:image/png;base64,ABCDEFG..."之类的PNG字符串

我所知道的canvas.toDataURL的唯一限制是,如果您直接从画布上加载了另一个站点的图像(即通过ctx.drawImage),它将使画布进入“损坏”状态,因此您无法访问该图片(尽管这可能仅适用于访问ImageData API)。但是,如果您远程加载原始图像数据并使用ImageData API,我认为它不会被触发,因此以下示例应该可以工作:

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');

canvas.width = 200;
canvas.height = 150;

ctx.fillStyle = 'lightblue';
ctx.fillRect(0, 0, canvas.width, canvas.height)

ctx.fillStyle = 'blue';
ctx.fillText('Testing', canvas.width/2 - 20, canvas.height/2);

document.getElementById('dump').innerText = canvas.toDataURL();
#canvas {
  border: 1px solid black;
}
<canvas id='canvas'></canvas>
<p>As you can see the textarea has the PNG data url of the canvas</p>
<textarea id='dump'></textarea>