0

2 つの異なるビューを比較して、画像を比較して同じかどうかを確認しようとしています。これは私のコードです...

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

更新: 以下のコードは正常に動作しますが、上記のコードは常に .getDrawingCache() から null を返すようで、これが問題かどうかはわかりません。これについて詳しく調べる時間はありませんが、getDrawingCache() が nullを返すことを確認して、同様の問題がどのように解決されたかを確認してください。そうでない場合は、logcat を提供してください。


これは、API 12 で導入された API 15 の sameAs 関数のポートです (あまり厳密にはチェックされていません)。

彼らが行う特別なチェックの1つは、画像がアルファチャンネルであるかどうかを確認することです。可能であれば配列チェックを回避するためのいくつかの最適化(おそらくユースケースの問題ではない)は、可能な場合はオープンソースを利用することもできます;- )

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 に答える