2012-06-19 150 views
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。任何人都可以告訴我爲什麼我做錯了?

+0

見下面我的反應。我也試過了上面的代碼,它總是返回null作爲.getDrawingCache()讀取文檔的位圖,看起來好像它需要繪製視圖 - 查看更新的響應 – Idistic

回答

1

不知道什麼是錯的代碼,如果有的話,但你嘗試Bitmap.sameAs(Bitmap)

+0

我得到錯誤「The method sameAs(Bitmap)是未定義的類型位圖「 –

+0

該方法標記 - 從以下版本:API級別12 - 所以我想不適用於您的平臺版本。 – sudocode

0

UPDATE:下面的代碼工作正常,但上述代碼似乎總是從.getDrawingCache()不知道這是你的問題或沒有返回null。我沒有時間去太深考慮這一點,但你可能會檢查getDrawingCache() returns null看到一個類似的問題是如何解決的,否則,請您提供logcat的。


下面是API 15(不是真的檢查過嚴格)的sameAs的功能,在API推出了端口12

一個他們做的特別檢查,看是否該圖像是alpha通道,以及一些優化的,以避免陣列檢查,如果可能的(可能不是你的使用情況的問題),還不如採取開源的優勢,當你可以;-)

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); 
} 
+0

當我將它複製到我的代碼中時,它在「A.getPixels()」上崩潰-_- –

+0

@LiLi Liu讓我看看 – Idistic

+0

@LiLi Liu我用相同,不同大小,相同大小的不同內容它工作得很好。請發佈您的logcat輸出,以便我們可以看到確切的錯誤 – Idistic

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; 
}