如何比较两个UIImage对象
我正在开发一个应用程序。在那里我使用imageviews
.SO之前UIImageview
图像我需要在UIimage
obejct中获取该图像,并与另一个UIImage
对象进行比较,find两者都是山姆或不。 所以请告诉我如何做到这一点。
一种方法是先将它们转换为图像数据,然后进行比较。
- (BOOL)image:(UIImage *)image1 isEqualTo:(UIImage *)image2 { NSData *data1 = UIImagePNGRepresentation(image1); NSData *data2 = UIImagePNGRepresentation(image2); return [data1 isEqual:data2]; }
@ Simon的答案的快速实现:
func image(image1: UIImage, isEqualTo image2: UIImage) -> Bool { let data1: NSData = UIImagePNGRepresentation(image1)! let data2: NSData = UIImagePNGRepresentation(image2)! return data1.isEqual(data2) }
或者根据@ nhgrif的build议来扩展UIImage:
import UIKit extension UIImage { func isEqualToImage(image: UIImage) -> Bool { let data1: NSData = UIImagePNGRepresentation(self)! let data2: NSData = UIImagePNGRepresentation(image)! return data1.isEqual(data2) } }
当同时使用[UIImage imageNamed:]
,我们可以使用isEqual:
否则我们可以比较数据。
最初比较图像大小
对于较便宜的方法,请首先比较图像大小。 即使图像内部有小的变化,尺寸也会不同。
NSData *data1 = UIImagePNGRepresentation(image1); NSData *data2 = UIImagePNGRepresentation(image2); if(data1.length == data2.length) { // if required, compare the data to confirm it if(data1 isEqual:data2) { // images are exactly same } else { // even though size is same images are different } } else { // images are different. }
在比较来自同一来源的图像(相同尺寸,格式等)下成功进行testing。
正确的答案取决于“你想做什么样的比较?”。
- 最简单的方法就是比较数据。
- 如果你想知道图像是从一个本地文件创build的 – 你可以使用-isEqual :(但是有一个危险的方法,因为我不确定,如果图像caching由于某种原因而被清除会发生什么)。
- 困难的方法是提供每像素比较 (当然,系统将花费更多的时间)。 由于法律原因,我无法提供我们公司的图书馆的代码:(
但是你可以在这里检查facebook的ios-snapshot-test-case项目的好例子: 右键连接到需要的文件 。 您可以使用性能testing来衡量处理时间。
对于伟大的正义,我会从下面复制代码:
- (BOOL)fb_compareWithImage:(UIImage *)image tolerance:(CGFloat)tolerance { NSAssert(CGSizeEqualToSize(self.size, image.size), @"Images must be same size."); CGSize referenceImageSize = CGSizeMake(CGImageGetWidth(self.CGImage), CGImageGetHeight(self.CGImage)); CGSize imageSize = CGSizeMake(CGImageGetWidth(image.CGImage), CGImageGetHeight(image.CGImage)); // The images have the equal size, so we could use the smallest amount of bytes because of byte padding size_t minBytesPerRow = MIN(CGImageGetBytesPerRow(self.CGImage), CGImageGetBytesPerRow(image.CGImage)); size_t referenceImageSizeBytes = referenceImageSize.height * minBytesPerRow; void *referenceImagePixels = calloc(1, referenceImageSizeBytes); void *imagePixels = calloc(1, referenceImageSizeBytes); if (!referenceImagePixels || !imagePixels) { free(referenceImagePixels); free(imagePixels); return NO; } CGContextRef referenceImageContext = CGBitmapContextCreate(referenceImagePixels, referenceImageSize.width, referenceImageSize.height, CGImageGetBitsPerComponent(self.CGImage), minBytesPerRow, CGImageGetColorSpace(self.CGImage), (CGBitmapInfo)kCGImageAlphaPremultipliedLast ); CGContextRef imageContext = CGBitmapContextCreate(imagePixels, imageSize.width, imageSize.height, CGImageGetBitsPerComponent(image.CGImage), minBytesPerRow, CGImageGetColorSpace(image.CGImage), (CGBitmapInfo)kCGImageAlphaPremultipliedLast ); if (!referenceImageContext || !imageContext) { CGContextRelease(referenceImageContext); CGContextRelease(imageContext); free(referenceImagePixels); free(imagePixels); return NO; } CGContextDrawImage(referenceImageContext, CGRectMake(0, 0, referenceImageSize.width, referenceImageSize.height), self.CGImage); CGContextDrawImage(imageContext, CGRectMake(0, 0, imageSize.width, imageSize.height), image.CGImage); CGContextRelease(referenceImageContext); CGContextRelease(imageContext); BOOL imageEqual = YES; // Do a fast compare if we can if (tolerance == 0) { imageEqual = (memcmp(referenceImagePixels, imagePixels, referenceImageSizeBytes) == 0); } else { // Go through each pixel in turn and see if it is different const NSInteger pixelCount = referenceImageSize.width * referenceImageSize.height; FBComparePixel *p1 = referenceImagePixels; FBComparePixel *p2 = imagePixels; NSInteger numDiffPixels = 0; for (int n = 0; n < pixelCount; ++n) { // If this pixel is different, increment the pixel diff count and see // if we have hit our limit. if (p1->raw != p2->raw) { numDiffPixels ++; CGFloat percent = (CGFloat)numDiffPixels / pixelCount; if (percent > tolerance) { imageEqual = NO; break; } } p1++; p2++; } } free(referenceImagePixels); free(imagePixels); return imageEqual; }
Swift 3
有两种方法。 喜欢:-
1)使用isEqual()函数。
self.image?.isEqual(UIImage(named: "add-image"))
2)使用accessibilityIdentifier
将accessibilityIdentifier设置为图像名称
myImageView.image?.accessibilityIdentifier = "add-image"
然后使用下面的代码。
extension UIImageView { func getFileName() -> String? { // First set accessibilityIdentifier of image before calling. let imgName = self.image?.accessibilityIdentifier return imgName } }
最后,找出方法的调用方式
myImageView.getFileName()
我的首选(Swift)解决scheme
import UIKit func ==(lhs: UIImage, rhs: UIImage) -> Bool { guard let data1 = UIImagePNGRepresentation(lhs), data2 = UIImagePNGRepresentation(rhs) else { return false } return data1.isEqual(data2) }
将图像转换为JPG / PNG格式,或者依赖辅助function标识符,要么是昂贵的操作,要么脆弱,容易出错。
在这里,我遵循苹果提供的build议在以下链接 :
isEqual( :)方法是确定两个图像是否包含相同图像数据的唯一可靠方法。 即使使用相同的caching图像数据初始化它们,您创build的图像对象也可能彼此不同。 确定其平等的唯一方法是使用isEqual( :)方法,它比较实际的图像数据。 清单1展示了比较图像的正确和不正确的方法。
为了简化,我创build了下面的扩展来进行比较,以便我可以避免转换第一个图像的问题:
import UIKit extension UIImage { func isEqual(to image: UIImage) -> Bool { return isEqual(image) } }
有了这个,我现在可以设置一个例子来比较一对图像:
let imageA = UIImage(named: "a")! let imageB = UIImage(named: "b")! let imageC = UIImage(named: "a")! print(imageA.isEqual(to: imageA)) // true print(imageA.isEqual(to: imageC)) // true print(imageA.isEqual(to: imageB)) // false
我不确定如何比较UIImage数据,因为它是昂贵的。 你可以做的是子类Uimage并添加标签属性你自己,然后比较标签之前更改图像。 分配
那么你也可以使用“标签”属性来识别程序后期的对象。 只要设置整数值,你就可以走了
如果你知道一个图像名称,它会帮助你….
CGImageRef cgImage = [imageView.image CGImage]; if (cgImage == [UIImage imageNamed:@"imagename.png"].CGImage) { // True Statement }