【问题标题】:Optimal grayscale Image compression in JavascriptJavascript中的最佳灰度图像压缩
【发布时间】:2018-04-16 20:07:47
【问题描述】:

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

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

我的想法是将这些 RGBA 图像从 4 个通道变为 1 个(因为我确实需要 8 位灰度帧)。

下面的 sn-p(以及我发现的所有其他)将它们转换为灰度,但再次使用 4 通道并使用画布方法 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 位通道?

【问题讨论】:

  • 您可以尝试使用toDataURL('image/webp'),因为它可以使用调色板,因此应该从灰度中获得一些良好的压缩,默认为 PNG 和最有可能是 32 位。 webp 也将进行无损和有损压缩,因为没有无损我假设您将第二个参数设置为 1..
  • 谢谢@Keith,webp 格式可以帮助压缩

标签: javascript html base64 compression grayscale


【解决方案1】:

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

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

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

放弃 Base-64 编码

您可以使用 Fetch API 以二进制形式将 blob 直接发布到您的服务器。不需要文本兼容性废话和开销。

fetch('/image-storage', {
  method: 'POST',
  body: blob
});

您可以通过在画布上调用 .toBlob() 来获取您的 blob。

不要使用原始图像

您的来源是网络摄像头...您真的需要原始像素吗?可能不是。当您在画布上调用 .toBlob() 时,请改用 WebP 或 JPEG 等有损格式。即使使用高质量设置,您也会节省大量数据。

如果你必须有原始灰度...

使用您想要的任何方法计算灰度像素,并将它们写入缓冲区。在您的 fetch POST 正文中使用该缓冲区。

【讨论】:

  • 你说的很中肯!!! Base-64 编码和原始像素在这里是不必要的。
【解决方案2】:

所以你已经有一个字节数组 - 我不明白你为什么要转换回图像并将这个图像转换为 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);

【讨论】:

    猜你喜欢
    • 2019-03-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-03
    • 1970-01-01
    • 2021-02-06
    • 2012-08-31
    • 2010-09-06
    相关资源
    最近更新 更多