2014-03-06 13 views
7

Ich habe zwei Canvas, und ich möchte den Inhalt von canvas1 übergeben, serialisieren Sie es zu einem ArrayBuffer, und laden Sie es dann in canvas2. In Zukunft werde ich den Inhalt von canvas1 an den Server senden, ihn verarbeiten und an canvas2 zurücksenden, aber im Moment möchte ich ihn nur serialisieren und deserialisieren.Canvas-Inhalt in ArrayBuffer serialisieren und erneut deserialisieren

fand ich diese Art und Weise der Leinwand Informationen in Bytes des Erhaltens:

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

Und fand auch auf diese Weise von Set der Informationen zu einem Image Objekt:

var blob = new Blob([binary], { type: "image/png" }); 
var urlCreator = window.URL || window.webkitURL; 
var imageUrl = urlCreator.createObjectURL(blob); 
var img = new Image(); 
img.src = imageUrl; 

Aber leider funktioniert es nicht scheinen zu arbeiten.

Welches wäre der richtige Weg?

Danke.

Antwort

12

Die Imagedata Sie bekommen getImageData() verwendet bereits einen ArrayBuffer (verwendet von der Uint8ClampedArray Ansicht). packen Sie es einfach aus und senden es:

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

es erneut eingestellt:

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

Sie wollen wahrscheinlich irgendeine Form von Byte-Codierung obwohl (wie f.ex Base-64) wie jedes Byte berücksichtigen Wert über 127 (ASCII) unterliegt der Zeichencodierung, die auf einem System verwendet wird. Oder stellen Sie sicher, dass alle Schritte auf der Reise dieselben verwenden (z. B. UTF8).

+0

Funktioniert nicht im IE, da IE immer noch CanvasPixelArray anstelle von Uint8ClampedArray verwendet (CanvasPixelArray's imageData.data hat keinen .buffer). – markE

+0

@markE True, aber in jedem anderen Browser ...(wie immer) :) – K3N

+0

Das verflixte IE! In letzter Zeit ist es jedoch viel besser geworden. :) – markE

4

ein Arraybuffer erstellen und diesen in den Uint8Array Konstruktor senden, senden Sie dann den Puffer WebSockets mit:

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

[Zurück Antwort unter Verwendung canvas.toDataURL removed]

+0

Ich muss es in Binär tun. – vtortola

+0

Warum? Sie können image-to-binary entweder auf der Clientseite oder der Serverseite konvertieren. Das Problem ist der binäre Transport - die Konvertierung in Binärdateien ist einfach. – markE

+0

Da die Verbindung ein Websocket ist, der Daten im Binärformat akzeptiert. Deshalb bitte ich, es in Binärform zu tun. – vtortola

0

Verwenden Sie canvas.toBlob() anstelle von context.getImageData(), wenn Sie kompakte Daten lieber als ein rohes ImageData Objekt möchten.

Beispiel:

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/

Beachten Sie auch, dass Bilder auf einem Dienst gehostet werden müssen, die CORS-Header bereitstellt, oder Sie werden Fehler wie „Die Leinwand zu sehen war durch Ursprungsdaten beschädigt. "

Verwandte Themen