简体   繁体   中英

How to convert the raw image byte array to PNG image using Javascript

I have a raw image (in .raw format without any image header), which I want to convert to PNG format to display on canvas. I tried to convert the raw image to RGBA and it was successful(by manipulating the bytes and using ImageData API in canvas). Now I need to convert the raw image to PNG.

I tried by,

  1. Fetching the image and create array buffer from the response
  2. create UInt8Array of the image arraybuffer created.
  3. convert it to base64:png content

Could anyone help me please?

I have tried multiple solutions found on internet, but none of them works for me.

  1. Creating a blob and using it construct an Object URL and display on canvas - Not worked
  2. Adding PNG image header to byte array and display on canvas.

     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 ); } 

    I would expect a png image drawn on canvas as the result, but I am seeing empty canvas.

  3. I also tried by adding the PNG image header directly to the bytearray content of image

    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;
      }

I could atleast see an image displayed on canvas, but different than the original one.

If you have the image in an RGBA array format and you can print it to the canvas, you can simply use canvas.toDataURL() to get a PNG string like "data:image/png;base64,ABCDEFG..."

The only limitation I know of with canvas.toDataURL is that if you have loaded an image from another site directly the canvas (ie via ctx.drawImage ) it will put the canvas into a 'broken' state so that you cannot access the image (this may only apply accessing the ImageData API though). However, if you remotely load the raw image data and use the ImageData API I do not think it will be triggered, so the following example should work:

 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> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM