从UIImage生成哈希

时间:2009-11-06 01:16:51

标签: iphone cocoa-touch hash

我正在尝试比较文件系统中的两个UIImages以查看它们是否相同。显然,我不能使用NSObject的哈希方法,因为这会返回对象的哈希值,而不是实际的图像数据。

我发现代码从字符串生成MD5哈希,但我还没有发现如何为UIImage实现它。

我应该怎样去散步UIImage?或者我的方法是完全关闭图像?

5 个答案:

答案 0 :(得分:36)

我使用以下代码完成任务。请注意,这需要您导入<CommonCrypto/CommonDigest.h>

unsigned char result[CC_MD5_DIGEST_LENGTH];
NSData *imageData = [NSData dataWithData:UIImagePNGRepresentation(inImage)];
CC_MD5([imageData bytes], [imageData length], result);
NSString *imageHash = [NSString stringWithFormat:
                       @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
                       result[0], result[1], result[2], result[3], 
                       result[4], result[5], result[6], result[7],
                       result[8], result[9], result[10], result[11],
                       result[12], result[13], result[14], result[15]
                       ];

答案 1 :(得分:9)

不太理想的解决方案:

[ UIImagePNGRepresentation( uiImage1 ) isEqualToData: 
      UIImagePNGRepresentation( uiImage2 ) ];

这基本上比较了2个图像的PNG编码数据。由于图像相似性是一个复杂的主题,因此可以根据最终目标的确切设计出更好更快的解决方案(即,您希望比较图像,逐个像素,还是只是近似相似性,这可能会使用源的下采样版本图像等)。

答案 2 :(得分:4)

UIImage散列

Swift代码,用于在swift 4.2中使用SHA256算法对UIImage进行哈希处理。您还可以使用其他算法,这些算法可能更快或产生更少的重复,但是对于大多数用例而言,这一算法已经足够了。

只需将代码放在项目中的某个位置并像这样使用它即可:<script> function showProduct(str) { if (str=="") { document.getElementById("products").innerHTML=""; return; } if (window.XMLHttpRequest) { // code for IE7+, Firefox, Chrome, Opera, Safari xmlhttp=new XMLHttpRequest(); } else { // code for IE6, IE5 xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.onreadystatechange=function() { if (this.readyState==4 && this.status==200) { document.getElementById("products").innerHTML=this.responseText; } } xmlhttp.open("GET","filter.php?q="+str,true); xmlhttp.send(); } </script>

yourUIImage.sha256()

桥接标题

通过这种方式,您需要导入CommonCrypto的桥接头。如果您没有,请按照以下步骤操作:

  1. 创建新文件->头文件->另存为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 } }
  2. 在“构建设置”中->“ Objective-C桥接标题”->添加BridgingHeader
  3. ProjectName/BridgingHeader.h放在标题文件中

重复概率

重复概率很低,但是如果您有大量数据集,则可以相对容易地升级到SHA512:

  

重复概率约为:

     

enter image description here

     

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

答案 3 :(得分:1)

下面更优雅的代码

+(NSString *)MD5HexDigest:(NSData *)input {
    unsigned char result[CC_MD5_DIGEST_LENGTH];

    CC_MD5(input.bytes, (unsigned int)input.length, result);
    NSMutableString *ret = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH*2];
    for (int i = 0; i<CC_MD5_DIGEST_LENGTH; i++) {
        [ret appendFormat:@"%02x",result[i]];
    }
    return ret;
}

答案 4 :(得分:1)

这个更新的片段应该可以工作。感谢 andreas's answer 提供大纲。

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