2011-06-17 94 views
8

我正在做一些圖像處理代碼,其中我從URL下載一些圖像(作爲BufferedImage)並將其傳遞給圖像處理器。要檢查兩個圖像文件是否相同..Checksum或哈希?

我想避免多次向圖像處理器傳遞相同的圖像(因爲圖像處理操作的成本很高)。圖像的URL結束點(如果它們是相同的圖像)可能會有所不同,因此我可以通過該URL防止出現這種情況。所以我打算做一個校驗和或散列來確定代碼是否再次遇到相同的圖像。

對於md5,我嘗試了Fast MD5,它爲圖像生成了20K +字符長度的十六進制校驗和值(某些示例)。當涉及到數據庫存儲時,顯然存儲這個20K字符散列值將成爲一個問題。因此我嘗試了CRC32(來自java.util.zip.CRC32)。它確實生成了比哈希小得多的長度校驗和。

我明白校驗和和散列是出於不同的目的。爲了上面解釋的目的,我可以使用CRC32嗎?它會解決目的還是我不得不嘗試比這兩個更多的東西?

謝謝, 阿比

+1

[校驗和散列和是相同的(http://en.wikipedia.org/wiki/Checksum)。其實你只是看看不同的算法。 – 2011-06-17 06:33:15

+1

128位MD5哈希值應該足夠您的目的。 – Thor 2011-06-17 06:35:08

+5

順便說一句 - MD5應該創建一個128位散列值,而crc32有32位......你做了什麼來產生20k +長度的十六進制校驗和? – 2011-06-17 06:35:10

回答

1

校驗和散列基本上是相同的。你應該能夠計算任何種類的散列。一般的MD5通常就足夠了。如果你喜歡,你可以存儲大小和md5散列(我認爲它是16字節)。

如果兩個文件有不同的大小,它們是不同的文件。你甚至不需要計算數據散列。如果您不太可能擁有許多重複文件,並且文件類型較大(例如,使用相機拍攝的JPG照片),則此優化可能會讓您花費大量時間。

如果兩個或多個文件的大小相同,則可以計算散列並進行比較。

如果兩個散列值相同,則可以比較實際數據,看看它是否完全不同。這是非常非常不可能的,但理論上是可能的。您的散列值越大(md5爲16個字節,而CR32只有4個),兩個不同文件將具有相同散列的可能性越小。 雖然只需要10分鐘的編程來執行這個額外的檢查,所以我會說:比對不起更安全。 :)

若要進一步優化此功能,只要兩個文件具有相同的大小,就可以比較它們的數據。無論如何你需要閱讀這些文件來計算它們的哈希,所以爲什麼不直接比較它們,只要它們是具有特定大小的唯一兩個。

+0

也許可能存在一個問題,即將已處理的文件與新文件進行比較。校驗和或散列佔用的空間更少 – SJuan76 2011-06-17 06:55:03

+0

這是真的,我從來沒有把整個文件存儲在數據庫中進行比較,只是說一次運行就不需要計算散列值。存儲數據以檢查新添加的文件,那麼存儲哈希值或者可以選擇僅存儲文件大小是有意義的,並且只有在兩個文件大小相同的情況下才計算(並存儲)哈希值es匹配。這將節省空間,並節省磁盤IO。 – GolezTrol 2011-06-17 07:48:16

5

CRC和MD5之間的區別在於,篡改文件以匹配「目標」MD5比篡改文件以匹配「目標」校驗和更困難。由於這對您的程序來說似乎沒有問題,因此您使用哪種方法應該沒有關係。也許MD5可能會佔用更多的CPU資源,但我不知道這種不同會有什麼關係。

主要問題應該是摘要的字節數。

如果你正在做一個整數校驗和將意味着,對於一個2K大小的文件,你將2^2048個組合適合2^32個組合 - >對於每個CRC值,你將有2^64可能匹配它的文件。如果你有一個128位的MD5,那麼你有2^16個可能的衝突。

您計算的代碼越大,碰撞的可能性越小(因爲計算得到的代碼均勻分佈),所以比較安全。

總之,爲了minimice可能出現的錯誤,我想第一個分類應使用文件大小......先比較文件的大小,如果他們匹配,則比較校驗/哈希值。

-3

用於比較兩個圖像緩衝可以使用BufferedImage.equals()爲簡單起見,你可以使用BufferedImage.hashCode()來獲得圖像的哈希值,這是快速和快速。

+6

'equals()'和'hashCode()'都回退到默認的'Object'實現,不能用來比較'BufferedImage'的兩個不同實例 – 2011-12-20 23:49:46