如何从图像中获取像素的x,y坐标颜色?


Answers:


198

基于Jeff的答案,您的第一步将是创建PNG的画布表示。以下内容将创建一个屏幕外画布,该画布的宽度和高度与您的图像相同,并在其上绘制图像。

var img = document.getElementById('my-image');
var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height);

之后,当用户单击时,使用event.offsetXevent.offsetY获取位置。然后可以用来获取像素:

var pixelData = canvas.getContext('2d').getImageData(event.offsetX, event.offsetY, 1, 1).data;

因为您只抓取一个像素,所以pixelData是一个包含四个像素的R,G,B和A值的四项数组。对于Alpha,任何小于255的值都表示某种程度的透明度,0表示完全透明。

这是一个jsFiddle示例:http : //jsfiddle.net/thirtydot/9SEMf/869/ 为了方便起见,我使用jQuery,但这并不是必需的。

注意: getImageData属于浏览器的同源策略以防止数据泄漏,这意味着如果您用来自另一个域的图像或(来自某些域的SVG,但我相信,某些浏览器可能已经解决了)SVG弄脏画布,则该技术将失败。这可以防止站点为已登录的用户提供自定义图像资产并且攻击者想要读取图像以获取信息的情况。您可以通过从同一服务器提供映像或实现跨域资源共享来解决该问题。


3
繁荣-很棒的工作。我知道我应该做这样的小提琴,但又胖又懒。您在这里杀了它
Jeff Escalante 2012年

为使此正确,您需要设置画布的坐标空间,即设置宽度和高度以匹配图像尺寸。CSS宽度和高度仅用于拉伸最终的画布以进行布局,当它是未显示的元素时无济于事。尝试类似$('<canvas width ='+ img.width +'height ='+ img.height +'/>');之类的东西。还是这不适用于屏幕外画布?
fabspro 2012年

@fabspro:这是一个很好的观点。由于绘制和读取图像数据是通过上下文完成的,因此宽度和高度值毫无意义。它们没有任何不良影响,因为画布而不是上下文是扭曲的,而我没有在演示中看到这种影响的原因仅仅是因为图像小于上下文的初始宽度/高度。我将进行相应的更新,尽管与通过串联相比,在画布上进行访问.width和安全性.height更高。
布赖恩·尼克


6
您不能将其用于远程图像。“由于画布已被跨域数据污染,因此无法从画布获取图像数据。SecurityError:试图突破用户代理的安全策略。”
Karl Glaser 2013年

18

正如@pst所说,Canvas是实现此目的的好方法。查看此答案以获取一个好例子:

HTML Canvas中的getPixel?

也可以为您提供服务的一些代码:

var imgd = context.getImageData(x, y, width, height);
var pix = imgd.data;

for (var i = 0, n = pix.length; i < n; i += 4) {
  console.log pix[i+3]
}

这将逐行进行,因此您需要将其转换为x,y并将for循环转换为直接检查或在内部运行条件。

再次阅读您的问题,看来您希望能够使该人单击。使用jquery的click事件可以很容易地做到这一点。只需在点击处理程序中运行上述代码即可:

$('el').click(function(e){
   console.log(e.clientX, e.clientY)
}

那些应该抓住你的x和y值。


这不是评论者问的(貌似),根本不回答问题。接受的答案确实有效。我建议删除此答案...
Agamemnus

5

前面的两个答案演示了如何使用Canvas和ImageData。我想提出一个带有可运行示例并使用图像处理框架的答案,因此您无需手动处理像素数据。

MarvinJ提供了image.getAlphaComponent(x,y)方法该方法仅返回x,y坐标中像素的透明度值。如果此值为0,则像素是完全透明的,介于1和254之间的值为透明级别,最后为255是不透明的。

为了演示,我使用了下面的图片(300x300),该图片具有透明背景,并且在坐标(0,0)(150,150)处有两个像素。

在此处输入图片说明

控制台输出:

(0,0):透明
(150,150):NOT_TRANSPARENT

image = new MarvinImage();
image.load("https://i.imgur.com/eLZVbQG.png", imageLoaded);

function imageLoaded(){
  console.log("(0,0): "+(image.getAlphaComponent(0,0) > 0 ? "NOT_TRANSPARENT" : "TRANSPARENT"));
  console.log("(150,150): "+(image.getAlphaComponent(150,150) > 0 ? "NOT_TRANSPARENT" : "TRANSPARENT"));
}
<script src="https://www.marvinj.org/releases/marvinj-0.7.js"></script>


2

与: i << 2

const data = context.getImageData(x, y, width, height).data;
const pixels = [];

for (let i = 0, dx = 0; dx < data.length; i++, dx = i << 2) {
    if (data[dx+3] <= 8)
        console.log("transparent x= " + i);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.