【问题标题】:Is is possible to read pixel data from base64 images?是否可以从 base64 图像中读取像素数据?
【发布时间】:2012-08-02 12:45:34
【问题描述】:

所以这里我有一个 base64 编码的 png 图片:

iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==

我使用atob() 对其进行了解码。原来是:

PNG

IHDRo&åIDAT×cøÿÿ?Ã Ã Ð1ñXÍõ5ËÑIEND®B`

是否可以从此字符串中取出颜色值? (不使用<canvas>

PS:好像有可能,因为我找到了一个演示:
http://labs.calyptus.eu/JSBin/Demo/Viewer.html
但我不确定他是怎么做到的。

【问题讨论】:

  • 我看到一个用 JavaScript 编写的 PNG 库在某处漂浮,但它只将原始像素数据编码为 PNG 图像。你也许可以扭转它。我认为使用 Canvas 会容易得多。
  • 您是否查看了您链接到的页面的来源?

标签: javascript base64


【解决方案1】:

在不依赖画布或浏览器渲染周期的情况下执行此操作会很有用。例如,如果您需要在单元测试运行器等无头环境中完成这项工作。

这可以在名为 png.js 的库的帮助下实现

const PNGReader = require('png.js');

function parseDataImage(data: string) {
  console.log('Data is', data); // Data is data:image/png;base64,iVBORw0KGgoAAAANSUh...
  const base64 = data.split(',')[1];
  console.log('Base64 is', base64); // Base64 is iVBORw0KGgoAAAANSUh...
  const bytes = atob(base64); // Base64 Decode
  console.log('Bytes are', bytes); // Bytes are <Some binary data>
  const png = new PNGReader(bytes);
  png.parse((err, png) => {
    console.log('Pixels are', png.pixels); // Pixels are Buffer{0: 255, 1: 0, 2: 65, ...
  });
}

【讨论】:

    【解决方案2】:

    在您指向的页面的源代码中,有一个函数使用 PNG.js 和其他一些实用程序来执行您想要的操作:

    function show(data){
        var png = new PNG(data);
        var img = document.getElementById('image'), limg = document.getElementById('largeimage');
        document.getElementById('nativeimage').src = 'data:image/png;base64,' + data;
        img.innerHTML = '';
        limg.innerHTML = '';
        img.style.width = png.width + 'px';
        img.style.height = png.height + 'px';
        limg.style.width = (png.width * 3) + 'px';
        limg.style.width = (png.height * 3) + 'px';
        var line;
        while(line = png.readLine())
        {
            for (var x = 0; x < line.length; x++){
                var px = document.createElement('div'), px2 = document.createElement('div');
                px.className = px2.className = 'pixel';
                px.style.backgroundColor = px2.style.backgroundColor = '#' + line[x].toString(16).padRight('0', 6);
                img.appendChild(px);
                limg.appendChild(px2);
            }
        }
    }
    

    如果您查看此函数中的循环,您会注意到它正在逐行读取 PNG 并绘制像素。

    一个简化的例子是:

    var png = new PNG(data); // data is the base64 encoded data
    var line;
    var y = 0;
    while(line = png.readLine())
    {
        for (var x = 0; x < line.length; x++){
            var pixel = doSomethingWithPixelData(x, y, '#' + line[x].toString(16).padRight('0', 6));
        }
        y++;
    }
    
    function doSomethingWithPixelData(x, y, color) {
        // guess what? do something with pixel data here ;)
    }
    

    【讨论】:

    • 真的很好!我一定会调查的。
    • 是的,它有效! jsfiddle.net/DerekL/6VqwC 但是,当我尝试放入更大的图像时,它有时会显示Filter 2/3/4 not implemented。不知道为什么,但它适用于较小的 PNG。
    • 这是此脚本的限制。过滤器还没有全部用 javascript 实现。尝试搜索脚本的更新版本。
    • He 说“我在演示中跳过了隔行扫描、alpha 和一些过滤器。它并不是一个完全可用的原型,也不是一个参考库。”所以我认为他不会更新它。
    • 这是哪个 PNG.js? npmjs.com/package/png.js 似乎没有 readline 函数,它的 parse 函数似乎不支持 base64 数据。
    【解决方案3】:

    不,您不能直接从该字符串中获取颜色值。您必须以某种方式解码 PNG 图像数据(已压缩)。使用&lt;canvas&gt; 是一种方法。

    【讨论】:

    • 我不认为 PNG 或 base64 编码有什么神奇之处,使得 JavaScript 无法读取。 Base64 编码很容易反转。尽管这可能很耗时,但任何愿意花时间阅读 PNG 规范的人都可以在 JavaScript 中实现一个从 PNG 数据中读取颜色值的函数。哎呀,您甚至可以使用十六进制编辑器和计算器手动完成。
    • 是的,这是可能的,但不像我说的那样直接。是的,您可以在 Javascript 中实现 PNG 解码。这会很烦人也很困难,而且肯定有人已经做到了。
    • 但我所说的直接执行(与任何其他图像库执行此操作的方式相同:通过查看二进制数据并根据 PNG 对其进行解码)眼镜)。从头开始编写图像库总是很辛苦,可能不是最好的解决方案,但仍然可以直接读取 PNG 数据。一种间接的方法是让浏览器或其他一些软件将 PNG 解码为更易于访问的格式,例如 Canvas 中的像素数组。
    • 我猜你使用的是另一种意义上的“直接”。我的意思是,如果不首先实际解码 PNG 图像,就无法从原始 PNG 图像数据中恢复 individual 像素颜色值。相比之下,通过计算出正确的偏移量并获取字符串中该位置的字节,可能(尽管仍然很烦人)从未压缩的 BMP 数据中获取特定的像素颜色值。跨度>
    • 嗯,是的,从这个意义上说你是对的。您必须先处理整个 PNG 图像以对其进行解压缩,然后才能获取特定的像素值。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-25
    • 1970-01-01
    • 1970-01-01
    • 2016-06-12
    相关资源
    最近更新 更多