Генерировать хэш из UIImage
Я пытаюсь сравнить два UIImages из файловой системы, чтобы убедиться, что они одинаковые. Очевидно, я не могу использовать хэш-метод NSObject, так как это возвращает хэш объекта, а не фактические данные изображения.
Я обнаружил, что код генерирует хеш MD5 из строки, но я не обнаружил, как реализовать его для UIImage.
Как я могу использовать хэширование UIImage? Или мой метод сравнения с изображениями полностью отключен?
Ответы
Ответ 1
Я завершил работу с помощью следующего кода для выполнения задачи. Обратите внимание, что для этого требуется импортировать <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]
];
Ответ 2
Менее оптимальное решение:
[ UIImagePNGRepresentation( uiImage1 ) isEqualToData:
UIImagePNGRepresentation( uiImage2 ) ];
В основном это сравнивает PNG-кодированные данные двух изображений. Поскольку подобие изображения является сложным предметом, более эффективные и быстрые решения могут быть разработаны на основе того, что именно является конечной целью (т.е. Вы хотите сравнить изображения, пиксель за пикселем или просто приблизительное сходство, которое могло бы использовать версию с пониженной дискретизацией источника изображение и т.д.).
Ответ 3
UIImage Hashing
Swift-код для хеширования UIImage с алгоритмом SHA256 в swift 4.2. Вы можете использовать другие алгоритмы, которые могут быть быстрее или генерировать меньше дубликатов, но этого достаточно для большинства случаев использования.
Просто yourUIImage.sha256()
код где-нибудь в свой проект и используйте его так: 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, который импортирует CommonCrypto. Если у вас его нет, выполните следующие действия:
- Создать новый файл → Файл заголовка → Сохранить как
BridgingHeader
- В настройках сборки → заголовок моста Objective-C → добавить
ProjectName/BridgingHeader.h
- Поместите
#import <CommonCrypto/CommonHMAC.h>
в свой заголовочный файл
Дублирующая вероятность
Вероятность дублирования низкая, но вы можете сравнительно легко перейти на SHA512, если получили огромные наборы данных:
Дубликат Вероятность о:
![enter image description here]()
Источник: https://crypto.stackexchange.com/questions/24732/probability-of-sha256-collisions-for- sure-amount-of-hashed-values
Ответ 4
более элегантный код ниже
+(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;
}