【问题标题】:html5 canvas always returns 8bits of color when using getImageData()html5 画布在使用 getImageData() 时总是返回 8 位颜色
【发布时间】:2013-12-04 18:32:00
【问题描述】:

我正在使用 html5 画布来渲染和图像,对图像进行一些基本的编辑,而不是尝试使用 getImageData(0 函数来读取像素并做一些工作。我注意到你,无论位深度如何源图像是(8 位、16 位、24 位)getImageData() 方法允许返回 8 位(256 色)。这是不可取的。我希望 getImageData(0 方法吐出尽可能多的颜色收到了。

我已经阅读了文档,画布应该能够处理你扔给它的任何位深度(象征性地),但我看不到任何地方可以将位深度设置得更高

【问题讨论】:

    标签: html image canvas getimagedata 8-bit


    【解决方案1】:

    Canvas 将总是返回 24 位 数据 + 8 位 Alpha 通道 (RGBA)。每个分量值当然会有 8 位或 256 个值。这是每个规范。它永远不会返回 8 位索引图像数据,但是,如果您以某种方式遇到 8 位(索引)图像数据,那么您可能正在读取错误的数据或从对象/数组中读取数据。

    来自specification

    图像数据。数据

    Returns the one-dimensional array containing the data in RGBA order,
    as integers in the range 0 to 255.
    

    并且只是为了涵盖相反的方面:如果您使用 2 - 256 种颜色在 8 位索引调色板图像(例如 PNG-8 或 GIF)中绘制,它们的索引调色板将始终转换为 RGBA 缓冲区(实际上已转换为在加载时由浏览器转换为 RGBA,因此这不是画布本身所做的)。

    要从画布中读取数据,您有两个级别(或三个用于更高级的用途),包含各种信息的图像数据对象,包括对实际像素阵列视图的引用:

    var imageData = context.getImageData(x, y, w, h);
    

    从这个对象中,我们获得像素的数据视图,默认情况下是Uint8ClampedArray 视图:

    var pixelData = imageData.data;
    

    对于更高级的用法,我们可以从中获取原始字节缓冲区(如果您需要提供其他视图,即 Uint32Array),可以从以下位置获取:

    var rawBytes = pixelData.buffer;
    var buffer32 = new Uint32Array(rawBytes);
    

    但让我们坚持使用默认的 8 位钳位视图 - 要从中读取,您需要知道像素总是打包成 RGBA 或作为 32 位值。所以我们可以通过这样做得到一个像素:

    var r = pixelData[0];
    var g = pixelData[1];
    var b = pixelData[2];
    var a = pixelData[3];
    

    下一个像素将从索引 4 开始,依此类推。

    如果您出于某种原因需要将调色板减少为索引调色板,您必须自己提供算法。有很多从简单和坏到更复杂和准确的。但这不是你可以用画布开箱即用的东西。一些指针可以在 this answer 中找到,或者您可以使用库 such as this 从画布创建(动画)GIF。

    还要注意,如果绘制到画布中的图像不满足跨域要求 (CORS),则画布将被“污染”(安全方面),getImageData() 将返回一个设置了值的数组为 0。

    【讨论】:

    • new Uint32Array”有什么意义? 8 位 已经 不是真正的字节吗?
    • 性能。您允许 CPU 每个周期突发读取 32 位而不是 8x4。您可以对通常更快的值执行位移。同样,您可以使用掩码和 AND/OR/等。操作。您可以简化以 1:1 为基础引用每个像素的坐标,而不是 1:4+4..
    • Uint32Array 是否击败 Int32Array
    【解决方案2】:

    ImageData(由getImageData 返回)属性data 为您提供一个数组,其中每个条目是一个按红色、绿色、蓝色和alpha 顺序排列的颜色通道,而不是实际颜色。例如

    red=imgData.data[0];
    green=imgData.data[1];
    blue=imgData.data[2];
    alpha=imgData.data[3];
    colour = '#' + (red<16)?'0':'' + red.toString(16) +
    (green<16)?'0':'' + green.toString(16) +
    (blue<16)?'0':'' + blue.toString(16);
    

    【讨论】:

    • 是的,但是当我循环遍历所有数据并将每种(唯一)颜色放入数组中时,无论图像的位深度如何,我总是得到 256
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-06-19
    • 1970-01-01
    • 1970-01-01
    • 2012-10-13
    • 2012-07-21
    • 2011-12-08
    • 2012-09-18
    相关资源
    最近更新 更多