0

我正在尝试比较两个不同的视图来比较图像,看看它是否相同。这是我的代码...

public boolean equals(View view1,  View view2){

    view1.setDrawingCacheEnabled(true);
    view1.buildDrawingCache();
    Bitmap b1 = view1.getDrawingCache();

    view2.setDrawingCacheEnabled(true);
    view2.buildDrawingCache();
    Bitmap b2 = view2.getDrawingCache();

    ByteBuffer buffer1 = ByteBuffer.allocate(b1.getHeight() * b1.getRowBytes());
    b1.copyPixelsToBuffer(buffer1);

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

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

但是,无论如何,这将返回 true。谁能告诉我为什么我做错了?

4

3 回答 3

1

不确定该代码有什么问题(如果有的话),但是您是否尝试过 Bitmap.sameAs(Bitmap)

于 2012-06-19T21:57:12.860 回答
0

UPDATE: The code below works fine, but your code above seems to always return null from the .getDrawingCache() not sure if this is your problem or not. I don't have the time to look too deeply into this, but you might check getDrawingCache() returns null to see how a similar problem was solved, else please provide you logcat.


Here is a port (not really checked too stringently) of the sameAs function from API 15, introduced in API 12

One special check they do is to see if the image is alpha channel, and a few optimization's to avoid the array check if possible (probably not an issue with your use case) might as well take advantage of the open source when you can ;-)

boolean SameAs(Bitmap A, Bitmap B) {

    // Different types of image
    if(A.getConfig() != B.getConfig())
        return false; 

    // Different sizes 
    if (A.getWidth() != B.getWidth())
        return false; 
    if (A.getHeight() != B.getHeight())
        return false; 

    // Allocate arrays - OK because at worst we have 3 bytes + Alpha (?) 
    int w = A.getWidth();
    int h = A.getHeight();

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

    A.getPixels(argbA, 0, w, 0, 0, w, h); 
    B.getPixels(argbB, 0, w, 0, 0, w, h); 

    // Alpha channel special check 
    if (A.getConfig() == Config.ALPHA_8) {
        // in this case we have to manually compare the alpha channel as the rest is garbage.
        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);
}
于 2012-06-19T22:42:33.617 回答
0

@Idistic 的回答帮助我获得了另一种解决方案,该解决方案也适用于可能导致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;
}
于 2016-11-07T16:50:17.700 回答