如何有效地找出PNG是否只包含白色和透明像素?我的输入图片基本上是透明的,上面有一些手写笔记。认可必须非常可靠。我的当前代码在加载位图后循环所有像素,但执行时间太长。我正在寻找更好/更快的解决方案。
public static boolean isEmpty(Bitmap bmp)
{
int[] pixels = new int[bmp.getWidth() * bmp.getHeight()];
bmp.getPixels(pixels, 0, bmp.getWidth(), 0, 0, bmp.getWidth(), bmp.getHeight());
for (int i : pixels)
{
if (!(Color.alpha(i) == 0 || (Color.blue(i) == 255 && Color.red(i) == 255 && Color.green(i) == 255)))
return false;
}
return true;
}
答案 0 :(得分:2)
另一个想法可能是:
1 - 将图片缩小到非常小的尺寸(例如100 x 100像素) 2 - 分析嵌套for循环中的每个像素颜色(对于y包括x - 反之亦然) 3 - 如果所有这些10000像素的alpha都为0(只需使用一个计数器,每次检查的像素的alpha为0时,你都会增加),你可以很好地近似确认图像是完全透明的。
答案 1 :(得分:1)
我认为有史以来最快的方法是直接分析PNG源,甚至不用解压缩来构建位图。我尝试了不同大小的图像,每个图像只有一种颜色(例如全绿色,全红色,全黑色,全透明),用十六进制编辑器查看字节,我发现输出PNG非常小(非常明显) ,给定非常小的熵),IDAT
部分包含重复模式(随图像大小增长)。
我正在研究如何理解IDAT部分和位模式以提供代码示例,但我认为这种方法可行。
另一方面,通过对位图上的像素进行采样,您只有一个统计答案,我的意思是" 99%它是空的" ,或" 85%它是空的" :你不能通过不检查所有像素来肯定地告诉是/否(当然!可能正是你要找的东西)
答案 2 :(得分:1)
一种优化循环的方法(即使没有基准,我们也可以说多少)在语言级别(避免函数调用,假设运行时已经没有这样做):
for (int pixel : pixels) {
if ((pixel & 0xFF000000) != 0 || (pixel & 0xFFFFFF) != 0xFFFFFF) return false;
}
答案 3 :(得分:0)
所有Alpha通道设置为0的图像不为空。无论每个像素的内容如何,它都与图像的分辨率一样大。
考虑到这一点,如果你想在不检查所有内容的情况下尝试查看图像是否“隐身”,最好的办法是对像素进行随机抽样并检查它们。这个确实有可能给你一个假阳性或假阴性,但它足够可靠,可以持续使用。我将给出一个测试100个随机像素的示例,但是当您感觉舒服时,可以提高或降低该像素。
public static boolean isEmpty(Bitmap bmp)
{
Random rand = new Random();
int currentPixel;
for(int i = 0; i < 100; i++)
{
currentPixel = bmp.getPixel(rand.getNextInt(bmp.getWidth(), rand.getNextInt(bmp.getHeight());
if(Color.alpha(currentPixel) == 0)
{
return false;
}
}
return true;
}
由于我不知道您正在测试的图像的性质,您可以使用的指标是检查图像的5%随机像素样本。