Android中比较位图图像

24

有没有办法检查位图是否相同?有人能帮忙吗?

5个回答

78

7
请注意,sameAs方法直到API v12(即Android 3.1)才被引入,因此对于旧版本来说并没有什么帮助。 - Ithildin
6
最低SDK版本为14,所有功能/事物。 - Blundell
最低SDK版本为19,所有的事情。 - ADev
1
几乎到2019年了,所有的事情。 - lelloman
几乎到2024年了,一切都在发生变化。 - undefined
显示剩余2条评论

16

应该像这样:

public boolean equals(Bitmap bitmap1, Bitmap bitmap2) {
    ByteBuffer buffer1 = ByteBuffer.allocate(bitmap1.getHeight() * bitmap1.getRowBytes());
    bitmap1.copyPixelsToBuffer(buffer1);

    ByteBuffer buffer2 = ByteBuffer.allocate(bitmap2.getHeight() * bitmap2.getRowBytes());
    bitmap2.copyPixelsToBuffer(buffer2);

    return Arrays.equals(buffer1.array(), buffer2.array());
}

@Photon,我还没有遇到这个方法的任何异常。 - Exterminator13
3
内存不足异常,即使在Galaxy S3上也会出现。 - Trikaldarshiii
尝试在后台线程中调用此方法,或使用AsyncTask。 - Cyph3rCod3r
2
上述方法非常占用内存。对于一个以ARGB格式存储的2000万像素图像,它将尝试使用至少160 MB的RAM来进行比较(每个图像80 MB = 20 MP *每像素4字节)。 - Gesh

11

这个问题似乎有点老,但我今天花了一些时间解决了它,以下是我的做法。

private static boolean compare(Bitmap b1, Bitmap b2) {
    if (b1.getWidth() == b2.getWidth() && b1.getHeight() == b2.getHeight()) {
        int[] pixels1 = new int[b1.getWidth() * b1.getHeight()];
        int[] pixels2 = new int[b2.getWidth() * b2.getHeight()];
        b1.getPixels(pixels1, 0, b1.getWidth(), 0, 0, b1.getWidth(), b1.getHeight());
        b2.getPixels(pixels2, 0, b2.getWidth(), 0, 0, b2.getWidth(), b2.getHeight());
        if (Arrays.equals(pixels1, pixels2)) {
            return true;
        } else {
            return false;
        }
    } else {
        return false;
    }
}

4
可以简化这个语句为:return Arrays.equals(pixels1, pixels2);,不需要写成 if (Arrays.equals(pixels1, pixels2)) { return true; } else { return false; } 的形式。 - ademar111190

2
根据您对“同一文件”的定义。如果您指的是“完全相同的文件”,您可以对文件进行md5sum处理。我想每种类型的文件都是一样的。
因为您特别区分了位图文件,您可能会对大小不同的文件感兴趣。那就有点难了。如果它们的大小相同,但不完全相同(但看起来非常相似),则可以比较每个单独的像素,如果足够多的像素(阈值1)在颜色上足够接近(阈值2),则可以将它们声明为相同。
您可以使用getPixel(int,int)获取颜色,请参见此页面

1
主要问题是对于小于12的API,我们在处理大文件分辨率时会出现“OutOfMemory”错误。我通过将位图分成几部分(例如,分成10个)并通过字节进行比较来解决这个问题:
private boolean compareBitmaps(Bitmap bitmap1, Bitmap bitmap2)
{
    if (Build.VERSION.SDK_INT > 11)
    {
        return bitmap1.sameAs(bitmap2);
    }

    int chunkNumbers = 10;
    int rows, cols;
    int chunkHeight, chunkWidth;
    rows = cols = (int) Math.sqrt(chunkNumbers);
    chunkHeight = bitmap1.getHeight() / rows;
    chunkWidth = bitmap1.getWidth() / cols;

    int yCoord = 0;
    for (int x = 0; x < rows; x++)
    {
        int xCoord = 0;
        for (int y = 0; y < cols; y++)
        {
            try
            {
                Bitmap bitmapChunk1 = Bitmap.createBitmap(bitmap1, xCoord, yCoord, chunkWidth, chunkHeight);
                Bitmap bitmapChunk2 = Bitmap.createBitmap(bitmap2, xCoord, yCoord, chunkWidth, chunkHeight);

                if (!sameAs(bitmapChunk1, bitmapChunk2))
                {
                    recycleBitmaps(bitmapChunk1, bitmapChunk2);
                    return false;
                }

                recycleBitmaps(bitmapChunk1, bitmapChunk2);

                xCoord += chunkWidth;
            }
            catch (Exception e)
            {
                return false;
            }
        }
        yCoord += chunkHeight;
    }

    return true;
}

private boolean sameAs(Bitmap bitmap1, Bitmap bitmap2)
{
    // Different types of image
    if (bitmap1.getConfig() != bitmap2.getConfig())
        return false;

    // Different sizes 
    if (bitmap1.getWidth() != bitmap2.getWidth())
        return false;

    if (bitmap1.getHeight() != bitmap2.getHeight())
        return false;

    int w = bitmap1.getWidth();
    int h = bitmap1.getHeight();

    int[] argbA = new int[w * h];
    int[] argbB = new int[w * h];

    bitmap1.getPixels(argbA, 0, w, 0, 0, w, h);
    bitmap2.getPixels(argbB, 0, w, 0, 0, w, h);

    // Alpha channel special check 
    if (bitmap1.getConfig() == Bitmap.Config.ALPHA_8)
    {
        final int length = w * h;
        for (int i = 0; i < length; i++)
        {
            if ((argbA[i] & 0xFF000000) != (argbB[i] & 0xFF000000))
            {
                return false;
            }
        }
        return true;
    }

    return Arrays.equals(argbA, argbB);
}

private void recycleBitmaps(Bitmap bitmap1, Bitmap bitmap2)
{
    bitmap1.recycle();
    bitmap2.recycle();
    bitmap1 = null;
    bitmap2 = null;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接