Javascript

时间:2018-04-16 20:07:48

标签: javascript html5 base64 compression grayscale

我使用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位通道?

2 个答案:

答案 0 :(得分:2)

  

我使用Javascript和HTML5从内置网络摄像头捕获帧,并打算以BASE64格式将它们异步发送到我的服务器。

     

问题是这些帧的总大小很大!

嗯,是的,您正在拍摄原始图像,然后通过将该blob编码为base64而不必要地增加33%的存储开销。

删除Base-64编码

您可以使用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);