How to compare two UIImage objects

I am developing one application. In that I use imageviews .SO before changing the UIImageview image, I need to take this image in a UIimage obejct and compare it with another UIimage object to find both. sam or not. So please tell me how to do this.

+58
ios
Jul 05 2018-12-12T00:
source share
11 answers

One way is to first convert them to image data, and then compare them.

 - (BOOL)image:(UIImage *)image1 isEqualTo:(UIImage *)image2 { NSData *data1 = UIImagePNGRepresentation(image1); NSData *data2 = UIImagePNGRepresentation(image2); return [data1 isEqual:data2]; } 
+120
Jul 05 '12 at 11:01
source share

Fast implementation of @Simon answer:

 func image(image1: UIImage, isEqualTo image2: UIImage) -> Bool { let data1: NSData = UIImagePNGRepresentation(image1)! let data2: NSData = UIImagePNGRepresentation(image2)! return data1.isEqual(data2) } 

Or by extending UIImage based on @nhgrif's suggestion:

 import UIKit extension UIImage { func isEqualToImage(image: UIImage) -> Bool { let data1: NSData = UIImagePNGRepresentation(self)! let data2: NSData = UIImagePNGRepresentation(image)! return data1.isEqual(data2) } } 
+20
Nov 26 '15 at 11:41
source share

when using [UIImage imageNamed:] , we can use isEqual: otherwise we could compare the data.

+8
Nov 06 '12 at 1:22
source share

The correct answer depends on "What comparison do you want to do?".

  • The easiest way is to simply compare the data.
  • If you want to know if the image was created from one local file , you can use -isEqual: (but there is a dangerous way, because I'm not sure what will happen if the image cache is for some reason).
  • The difficult way is to provide a pixel comparison (of course, the system will spend more time on it). I can’t provide the code from our corporate library for a legal reason :(

But you can check out a good example in the facebook ios-snapshot-test-case facebook project here: link directly to the file you need . You can use performance tests to measure process time.

For Great Justice, I will copy the code below:

 - (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; } 
+6
Apr 20 '16 at 8:25
source share

Converting images to JPG / PNG or using access identifiers is either an expensive operation or fragile and prone to failure.

Here I follow Apple's suggestion in the following link :

The isEqual (:) method is the only reliable way to determine if two images contain the same image data. The image objects that you create may be different from each other, even if you initialize them with the same cached image data. The only way to determine their equality is to use the isEqual (:) method, which compares the actual image data. Listing 1 shows the right and wrong ways to compare the image.

To simplify things, I create the following extension to do comparisons to avoid the problem of converting the first image:

 import UIKit extension UIImage { func isEqual(to image: UIImage) -> Bool { return isEqual(image) } } 

With this, I can now set an example to compare it with a pair of images:

 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 
+5
Jun 07 '17 at 2:53 on
source share

My preferred (quick) solution

 import UIKit func ==(lhs: UIImage, rhs: UIImage) -> Bool { guard let data1 = UIImagePNGRepresentation(lhs), data2 = UIImagePNGRepresentation(rhs) else { return false } return data1.isEqual(data2) } 
+4
Mar 17 '16 at 1:02
source share

Swift 3

There are two ways. How: -

1) Use the isEqual () function.

  self.image?.isEqual(UIImage(named: "add-image")) 

2) Use accessibilityIdentifier

Set the access identifier as the image name

 myImageView.image?.accessibilityIdentifier = "add-image" 

Then use the following code.

 extension UIImageView { func getFileName() -> String? { // First set accessibilityIdentifier of image before calling. let imgName = self.image?.accessibilityIdentifier return imgName } } 

Finally, a method call method to determine

 myImageView.getFileName() 
+4
Apr 13 '17 at 10:50
source share

Compare original image size

For a less expensive method, first compare the image size. Even if there is a slight change in the image, the size will be different.

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

Successfully tested when comparing images from a single source (the same size, format, etc.).

+2
Jul 23 '15 at 13:32
source share

I'm not sure about comparing UIImage data, as that would be expensive. What you can do is subclass Uimage and add a tag property, then compare the tag before changing the image. to appoint

0
Jul 03 '15 at 21:38
source share

if you know the name of a single image, this will help you ....

 CGImageRef cgImage = [imageView.image CGImage]; if (cgImage == [UIImage imageNamed:@"imagename.png"].CGImage) { // True Statement } 
-one
May 03 '17 at 10:38 a.m.
source share

Well, you can also use the "tag" property to identify objects in the last stages of your program. Just set the integer value and you're good to go

-2
Sep 05 '12 at 13:20
source share



All Articles