2012-01-05 246 views
90

是否有任何方法检查PNG图像的选定(x,y)点是否透明?如何从图像中获取像素的x,y坐标颜色?

+1

可以将图像以某种方式被加载在画布元素上? – 2012-01-05 22:50:54

+0

如果没有其他方法,那么 – 2012-01-05 22:51:46

+2

这就是必须完成的。 – 2012-01-05 22:53:43

回答

149

基于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。这样可以防止站点为登录用户提供自定义图像资源,攻击者想要读取图像以获取信息。您可以通过从相同服务器提供映像或实施Cross-origin resource sharing来解决问题。

+2

繁荣 - 令人敬畏的工作。我知道我应该像这样做一个小提琴,但是太胖了,太懒了。你在这里杀了它 – 2012-01-10 00:03:17

+0

为了正确,你需要设置画布的坐标空间,即设置宽度和高度以匹配图像尺寸。 CSS宽度和高度仅用于拉伸布局的最终​​画布,当它是未显示的元素时无法帮助。试试类似$('');.或者这种方式不适用于屏幕外的画布? – fabspro 2012-12-12 14:13:02

+0

@fabspro:这是一个很好的观点。由于通过上下文绘制和读取图像数据,宽度和高度值是没有意义的。他们没有任何不良影响,因为画布不是上下文扭曲的原因,我没有看到这种影响我的演示,只是因为图像比上下文的初始宽度/高度小。我会相应地进行更新,尽管在画布本身上访问'.width'和'.height'比连接更安全。 – 2012-12-14 21:20:17

15

画布将是一个伟大的方式来做到这一点,正如@pst上面所说。看看这个答案的一个很好的例子:

getPixel from HTML Canvas?

一些代码,将成为您专门和:

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值。

0

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

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

对于具有透明背景,并在坐标(0,0)(150150)两个像素证明我用下面(300×300)图像。

enter image description here

控制台输出:

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

var canvas = document.getElementById("canvas"); 
 
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> 
 
<canvas id="canvas" width="500" height="344"></canvas>