24

Is there any way to check if bitmaps are the same? can someone help me out?

Nanne
  • 64,065
  • 16
  • 119
  • 163
CMA
  • 2,758
  • 5
  • 28
  • 40

5 Answers5

77

Bitmap class has method "sameAs" you can use that method to compare two bitmap

http://developer.android.com/reference/android/graphics/Bitmap.html#sameAs%28android.graphics.Bitmap%29

Ketan Parmar
  • 2,962
  • 19
  • 27
16

It should be something like this:

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());
}
altumano
  • 2,676
  • 2
  • 26
  • 20
11

This question seems old but I spent some time on this issue today and here is what I did.

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;
    }
}
Kyle O.
  • 376
  • 2
  • 7
  • 4
    you can simplify the statment to return Arrays.equals(pixels1, pixels2); instead "if (Arrays.equals(pixels1, pixels2)) { return true; } else { return false; }" – ademar111190 Jul 29 '14 at 19:42
2

Depending on how you define the same. If you mean the exact same file, you can do an md5sum of the files. That will be the same for every type of file I guess.

Because you specifically make the distinction for bitmap files, you might be interested in files that differ in size. That's a bit harder. If they are the same size, but not completely the same (but look really much like eachother) you can compare each separate pixel, and if enough pixels (threshold 1) are close enough to each other in color (threshold 2) you can declare them as being the same.

You can getPixel(int,int) to get the color, see this page

Nanne
  • 64,065
  • 16
  • 119
  • 163
1

The main issue for APIs less than 12 is that we get OutOfMemory error for big file resolutions. I solved it by spitting bitmaps into pieces (10 in the example) and then comparing them by Bytes:

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;
}
Ayaz Alifov
  • 8,334
  • 4
  • 61
  • 56