如何检查图像的特定像素是不是透明?

Posted

技术标签:

【中文标题】如何检查图像的特定像素是不是透明?【英文标题】:How to check if a specific pixel of an image is transparent?如何检查图像的特定像素是否透明? 【发布时间】:2012-02-03 18:43:30 【问题描述】:

有什么方法可以检查 PNG 图像的选定 (x,y) 点是否透明?

【问题讨论】:

图片能否以某种方式加载到 Canvas 元素上? 如果没有别的办法,那么 【参考方案1】:

正如@pst 上面所说,Canvas 将是一个很好的方法。查看这个答案以获得一个很好的例子:

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

【讨论】:

这不是评论者所问的(似乎),并且根本没有回答这个问题。接受的答案确实有效。我建议删除这个答案...【参考方案2】:

根据 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 来解决此问题。

【讨论】:

繁荣 - 很棒的工作。我知道我应该做这样的小提琴,但太胖太懒了。你在这里杀了它 要做到这一点,您需要设置画布的坐标空间,即设置宽度和高度以匹配图像尺寸。 CSS 宽度和高度仅用于拉伸最终的画布以进行布局,当它是未显示的元素时,这无济于事。尝试类似 $('');。或者这是否不适用于离屏画布? 使用此 ***.com/questions/11334452/event-offsetx-in-firefox 为 Firefox jsfiddle.net/9SEMf/622 修复它 您不能将它用于远程图像。 “无法从画布获取图像数据,因为画布已被跨域数据污染。SecurityError: 试图突破用户代理的安全策略。” 还有一点需要注意:由于色彩空间校正,使用 drawImage 渲染的像素值可能与图像中的值不同。好在只有图像包含色彩空间信息时才会发生这种情况。【参考方案3】:

前面的两个答案演示了如何使用 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"));
&lt;script src="https://www.marvinj.org/releases/marvinj-0.7.js"&gt;&lt;/script&gt;

【讨论】:

【参考方案4】:

与:i &lt;&lt; 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);

【讨论】:

【参考方案5】:

基于 Brian Nickel 的回答,仅将源图像的所需单个像素绘制到 1*1 像素画布上,这比仅绘制整个图像以获得单个像素更有效:

function getPixel(img, x, y) 

    let canvas = document.createElement('canvas');
    canvas.width = 1;
    canvas.height = 1;
    canvas.getContext('2d').drawImage(img, x, y, 1, 1, 0, 0, 1, 1);;
    let pixelData = canvas.getContext('2d').getImageData(0, 0, 1, 1).data;

    return pixelData;   

【讨论】:

效果很好!谢谢!

以上是关于如何检查图像的特定像素是不是透明?的主要内容,如果未能解决你的问题,请参考以下文章

使具有特定颜色的图像的每个像素透明

如何使用GD检查图像是不是具有透明度?

带有像素图的透明 QLabel

在图像上查找透明像素并使相同像素在另一个图像上透明

如何从图像中选择像素,并减少Android编程中该像素的不透明度

css/javascript:检查触发悬停效果的图像像素