Generate hash from UIImage

Viewed 16274

I'm trying to compare two UIImages from the file system to see if they are the same. Obviously, I can't use NSObject's hash method, since this returns a hash of the object, and not the actual image data.

I found code generate an MD5 hash from a string, but I haven't discovered how to implement it for a UIImage.

How should I go about hashing a UIImage? Or is my method for comparing to images totally off?

5 Answers

UIImage Hashing

Swift Code for hashing a UIImage with the SHA256 algorithm in swift 4.2. There are other algorithms you can use, which are may faster or generate less duplicates but this one is good enough for most usecases.

Just drop the code somewhere in your Project and use it like this: yourUIImage.sha256()

extension UIImage{
    
    public func sha256() -> String{
        if let imageData = cgImage?.dataProvider?.data as? Data {
            return hexStringFromData(input: digest(input: imageData as NSData))
        }
        return ""
    }
    
    private func digest(input : NSData) -> NSData {
        let digestLength = Int(CC_SHA256_DIGEST_LENGTH)
        var hash = [UInt8](repeating: 0, count: digestLength)
        CC_SHA256(input.bytes, UInt32(input.length), &hash)
        return NSData(bytes: hash, length: digestLength)
    }
    
    private  func hexStringFromData(input: NSData) -> String {
        var bytes = [UInt8](repeating: 0, count: input.length)
        input.getBytes(&bytes, length: input.length)
        
        var hexString = ""
        for byte in bytes {
            hexString += String(format:"%02x", UInt8(byte))
        }
        
        return hexString
    }
}

Bridging Header

By the way you need a Bridging Header that imports CommonCrypto. If you don't have one follow these steps:

  1. Create new File -> Header File -> Save as BridgingHeader
  2. In Build Settings -> Objective-C Bridging Header -> add ProjectName/BridgingHeader.h
  3. Put #import <CommonCrypto/CommonHMAC.h> in your Header File

Duplicate Probability

The duplicate probability is low, but you can upgrade to SHA512 relatively easy if you got huge datasets:

The Duplicate Probability is about:

enter image description here

Source: https://crypto.stackexchange.com/questions/24732/probability-of-sha256-collisions-for-certain-amount-of-hashed-values

This updated snippet should work. Thanks to andreas's answer for the outline.

// Usage
image.sha256

// extensions
import CommonCrypto

extension UIImage {
    
    var sha256: String {
        guard let imageData = jpegData(compressionQuality: 1) else { return "" }
        return imageData.digest.hexString
    }
}

extension Data {
   
    var digest: Data {
        let digestLength = Int(CC_SHA256_DIGEST_LENGTH)
        var hash = [UInt8](repeating: 0, count: digestLength)
        CC_SHA256(bytes, UInt32(count), &hash)
        return Data(bytes: hash, count: digestLength)
    }

    var hexString: String {
        let hexString = map { String(format: "%02.2hhx", $0) }.joined()
        return hexString
    }
}
Related