我有两个画布,我想传递canvas1的内容,将其序列化为ArrayBuffer,然后将其加载到canvas2中。将来我会将canvas1内容发送到服务器,处理它,并将其返回到canvas2,但是现在我只想序列化和反序列化它。
我找到了以字节为单位获取画布信息的方法:
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];
}
并且还发现了这种将信息设置为Image
对象的方式:
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;
但不幸的是它似乎没有用。
这是正确的做法吗?
感谢。
答案 0 :(得分:15)
从getImageData()
获得的ImageData已经在使用ArrayBuffer(由Uint8ClampedArray
视图使用)。抓住它并发送它:
var imageData = context.getImageData(x, y, w, h);
var buffer = imageData.data.buffer; // ArrayBuffer
再次设置:
var imageData = context.createImageData(w, h);
imageData.data.set(incomingBuffer);
您可能希望考虑某种形式的字节编码(例如f.ex base-64),因为高于127(ASCII)的任何字节值都受制于系统上使用的字符编码。或者确保旅程中的所有步骤都使用相同的(f.ex. UTF8)。
答案 1 :(得分:4)
创建一个ArrayBuffer并将其发送到Uint8Array构造函数,然后使用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);
[删除canvas.toDataURL的上一个答案]
答案 2 :(得分:1)
如果您想要压缩数据而不是原始ImageData对象,请考虑使用canvas.toBlob()
而不是context.getImageData()
。
示例:
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><img></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><img></code></h2>
<img id="image-out">
JSFiddle:https://jsfiddle.net/donmccurdy/jugzk15b/
另请注意,图像必须托管在提供CORS标头的服务上,否则您将看到“画布已被跨源数据污染”等错误。