5

我正在将图像绘制到 HTML 画布上并从中获取图像数据以查找特定像素的颜色。该图像是一张地图,其中每个国家的颜色都不同。我想将 .getImageData() 返回的颜色交叉引用到我手工制作的颜色列表中,以查找任何给定像素所在的国家/地区。

我的问题是,我在画布上绘制的图像和绘制的图像颜色略有不同。

这是绘制到画布上的原始图片:

原图

这是我将画布下载为 PNG 时得到的图片:

结果

两者看起来几乎相同,但如果你下载它们并在照片编辑软件中打开它们,你会发现它们不是。例如,上图中的灰色海洋为 73,73,73,255,下图中的灰色海洋为 71,71,71,255。

我仍然可以完成确定像素所在国家/地区的目标,但我需要根据我下载的图片在绘制到画布后创建一个新列表。

这似乎是一个非常奇怪的问题。

如果有人想知道,我的代码如下所示:

HTML:

<img scr="active_map.png" class="active" id="activeImage">
<canvas id="activeCanvas" width="439px" height="245px">Your Browser Doesn't Support HTML5 Canvases... Sorry :( </canvas>

JS:

var activeCanvas = document.getElementById('activeCanvas')
var activeContext = activeCanvas.getContext("2d");
var activeImage = document.getElementById('activeImage')
activeContext.drawImage(activeImage,0,0);
var activePixelData = activeContext.getImageData(0,0,439,245)["data"];

另外,我正在为 Ubuntu 使用 Firefox 31

-谢谢您的帮助

4

2 回答 2

4

正如@GameAlchemist 所提到的,您使用的PNG 存在潜在的伽马校正问题,即RGB 值不会被一致地解释。

Henri Sivonen 的PNG Gamma “修正”的悲伤故事</a> 提供了非常透彻的分析。简而言之:

为了补偿不同的伽马,在其上创作图像的系统的显示伽马和显示图像的系统的显示伽马都需要被显示图像的软件知道。PNG 格式提供了一种将创作系统的显示伽玛(的倒数)存储到图像文件的方法。由写入文件的程序存储图像的本机显示伽玛,然后由显示文件的程序进行补偿。

他建议使用Pngcrush删除可能导致这种不一致的颜色配置文件。我已经确认他的技术 ( pngcrush -rem gAMA -rem cHRM -rem iCCP -rem sRGB infile.png outfile.png) 确实有效。这是您修改后的图像:

在此处输入图像描述

您会注意到它小了 6KB。我已经确认这在 Firefox 之前和之后都可以正常工作(从 71、71、71 的 RGB 值到 73、73、73 的值)。

于 2015-01-04T19:04:36.960 回答
3

浏览器可以自由地预乘 alpha 并且(正如 GameAlchemist 所说)进行 gamma 校正。

结果是不同的浏览器显示的颜色值可能与 FF 显示的颜色值略有不同。

可能的解决方法:

  • 假设浏览器会弄乱您的确切颜色,那么让您的测试在该国原始颜色周围的一小部分颜色上成功。

  • 向客户端发送一个预先计算的数组,表示画布上的每个像素,其中包含该像素下的哪个国家/地区。该数组类似于 .getImageData,但每个像素只有 1 个值——该值将是该像素的国家代码。

  • 计算勾勒出每个国家的路径。然后,您可以使用 context.isPointInPath 来测试鼠标是否在一个国家/地区内。DougX 做得很好:http ://dougx.net/map/

  • 如果内存是一个问题,您可以重构上面的预先计算的数组以使用树结构中的对象。例如:

    1. 将您的地图划分为 9x4 网格(或 4x2 或其他)。
    2. 为每个网格单元创建一个对象数组。对象可能如下所示:{ x0:297, x1:353 y0:91, y1:94 country:55 } where countryCodes[55]='China'。此示例对象表示 (353-297)*(94-91)==224 像素。
    3. 在鼠标单击时,计算鼠标所在的网格单元,然后扫描数组,直到找到确切的鼠标 [x,y]。您可以从网格数组中省略所有海洋坐标,因此如果您的测试未找到匹配项,您可以假设鼠标在海洋中。
于 2015-01-04T19:01:31.893 回答