我使用Javascript和HTML5从内置网络摄像头捕获帧,并打算以BASE64格式将它们异步发送到我的服务器。
问题是这些镜架的总尺寸很大!
我的想法是将这些RGBA图像从4个通道转换为1(因为我真的需要8位灰度帧)。
以下代码段(以及我找到的所有其他代码段)将它们变为灰度,但再次使用4通道并使用canvas方法toDataURL()
将它们转换为BASE64格式。因此,总大小保持不变。
var imgData = ctx.getImageData(0, 0, 34, 26);
let grayscale = []; // desired one channel 8-bit array
for (var y = 0; y < imgData.height; y++) {
for (var x = 0; x < imgData.width; x++) {
var i = y * 4 * imgData.width + x * 4;
var weighted =
Math.floor( // round in order to use 8-bit integers
0.299 * imgData.data[i] +
0.587 * imgData.data[i + 1] +
0.114 * imgData.data[i+2]
);
imgData.data[i] = weighted;
imgData.data[i + 1] = weighted;
imgData.data[i + 2] = weighted;
grayscale.push(weighted);
}
}
cxt.putImageData(
imgData,
0,
0,
0,
0,
imgData.width,
imgData.height
);
b64 = cxt.canvas.toDataURL().split(",")[1];
我的问题如下:
如何使用最少的字节数仅发送所需的一个8位通道?
答案 0 :(得分:2)
我使用Javascript和HTML5从内置网络摄像头捕获帧,并打算以BASE64格式将它们异步发送到我的服务器。
问题是这些帧的总大小很大!
嗯,是的,您正在拍摄原始图像,然后通过将该blob编码为base64而不必要地增加33%的存储开销。
您可以使用Fetch API将blob以二进制方式直接发布到您的服务器。无需文本兼容性废话和开销。
fetch('/image-storage', {
method: 'POST',
body: blob
});
你可以在画布上调用.toBlob()
来获取你的blob。
您的来源是网络摄像头......您真的需要原始像素吗?可能不是。当您在画布上调用.toBlob()
时,请使用WebP或JPEG等有损格式。即使使用高质量设置,您也可以节省大量数据。
使用您想要的任何方法计算灰度像素,并将它们写入缓冲区。在你的获取POST主体中使用该缓冲区。
答案 1 :(得分:0)
所以你已经有了一个字节数组 - 我不明白你为什么要转换回图像并将这个图像转换为base64。您也可以简单地将字节移动到字符串中,并将此字符串编码为base64。
var imgData = ctx.getImageData(0, 0, 34, 26);
let binary = '';
for (var y = 0; y < imgData.height; y++) {
for (var x = 0; x < imgData.width; x++) {
var i = y * 4 * imgData.width + x * 4;
var weighted =
Math.floor( // round in order to use 8-bit integers
0.299 * imgData.data[i] +
0.587 * imgData.data[i + 1] +
0.114 * imgData.data[i+2]
);
binary += String.fromCharCode(weighted);
}
}
// do the conversion
b64 = window.btoa(binary);