Serialize canvas content to ArrayBuffer and deserialize again

后端 未结 3 1723
囚心锁ツ
囚心锁ツ 2021-01-02 02:27

I have two canvas, and I want to pass the content of canvas1, serialize it to an ArrayBuffer, and then load it in canvas2. In the future I will send the canvas1 content to t

相关标签:
3条回答
  • 2021-01-02 02:49

    Consider using canvas.toBlob() instead of context.getImageData() if you want compact data rather than a raw ImageData object.

    Example:

    const imageIn = document.querySelector('#image-in');
    const imageOut = document.querySelector('#image-out');
    const canvas = document.querySelector('#canvas');
    const imageDataByteLen = document.querySelector('#imagedata-byte-length');
    const bufferByteLen = document.querySelector('#arraybuffer-byte-length');
    
    const mimeType = 'image/png';
    
    imageIn.addEventListener('load', () => {
    
      // Draw image to canvas.
      canvas.width = imageIn.width;
      canvas.height = imageIn.height;
      const ctx = canvas.getContext('2d');
      ctx.drawImage(imageIn, 0, 0);
    
      // Convert canvas to ImageData.
      const imageData = ctx.getImageData(0, 0, imageIn.width, imageIn.height);
      imageDataByteLen.textContent = imageData.data.byteLength + ' bytes.';
    
      // Convert canvas to Blob, then Blob to ArrayBuffer.
      canvas.toBlob((blob) => {
        const reader = new FileReader();
        reader.addEventListener('loadend', () => {
          const arrayBuffer = reader.result;
          bufferByteLen.textContent = arrayBuffer.byteLength + ' bytes.';
    
          // Dispay Blob content in an Image.
          const blob = new Blob([arrayBuffer], {type: mimeType});
          imageOut.src = URL.createObjectURL(blob);
        });
        reader.readAsArrayBuffer(blob);
      }, mimeType);
    
    });
    
    <h1>Canvas ↔ ArrayBuffer</h1>
    
    <h2>1. Source <code>&lt;img&gt;</code></h2>
    <img id="image-in" src="https://ucarecdn.com/a0338bfa-9f88-4ce7-b53f-e6b61000df89/" crossorigin="">
    
    <h2>2. Canvas</h2>
    <canvas id="canvas"></canvas>
    
    <h2>3. ImageData</h2>
    <p id="imagedata-byte-length"></p>
    
    <h2>4. ArrayBuffer</h2>
    <p id="arraybuffer-byte-length"></p>
    
    <h2>5. Final <code>&lt;img&gt;</code></h2>
    <img id="image-out">
    

    JSFiddle: https://jsfiddle.net/donmccurdy/jugzk15b/

    Also note that images must be hosted on a service that provides CORS headers, or you'll see errors like "The canvas has been tainted by cross-origin data."

    0 讨论(0)
  • 2021-01-02 02:51

    The ImageData you get from getImageData() is already using an ArrayBuffer (used by the Uint8ClampedArray view). Just grab it and send it:

    var imageData = context.getImageData(x, y, w, h);
    var buffer = imageData.data.buffer;  // ArrayBuffer
    

    To set it again:

    var imageData = context.createImageData(w, h);
    imageData.data.set(incomingBuffer);
    

    You probably want to consider some form of byte encoding though (such as f.ex base-64) as any byte value above 127 (ASCII) is subject to character encoding used on a system. Or make sure all steps on the trip uses the same (f.ex. UTF8).

    0 讨论(0)
  • 2021-01-02 02:51

    Create an ArrayBuffer and send it into to the Uint8Array constructor, then send the buffer using websockets:

    var img1 = context.getImageData(0, 0, 400, 320);
    var data=img1.data;
    var buffer = new ArrayBuffer(data.length);
    var binary = new Uint8Array(buffer);
    for (var i=0; i<binary.length; i++) {
        binary[i] = data[i];
    }
    websocket.send(buffer);
    

    [ Previous answer using canvas.toDataURL removed ]

    0 讨论(0)
提交回复
热议问题