I am developing one application.In that i am using the imageviews
.SO before changeing the UIImageview
image I need to take that image in UIimage
obejct and compare with another UIImage
object for finding both are sam or not. So please tell me how to do that one.

- 10,888
- 3
- 34
- 64

- 809
- 1
- 6
- 8
-
Accepted answer is in [this][1] thread [1]: http://stackoverflow.com/questions/3400707/cocoa-touch-comparing-images – Mathew Varghese Jul 05 '12 at 11:01
-
You should maintain the application state and have a data model. This way you will have a clue regarding what's going on in your app. – pronebird Oct 06 '17 at 16:12
19 Answers
One way is to convert them to image data first, and then compare that.
- (BOOL)image:(UIImage *)image1 isEqualTo:(UIImage *)image2
{
NSData *data1 = UIImagePNGRepresentation(image1);
NSData *data2 = UIImagePNGRepresentation(image2);
return [data1 isEqual:data2];
}

- 25,468
- 44
- 152
- 266
-
7
-
1should this use `isEqualToData:`? legitimate question - I'm not sure when or if `isEqual:` will ever fail with NSData objects, but it seems logical to me to use the conditional test designed specifically for the class, right? – toblerpwn Apr 18 '13 at 21:37
-
UIImagePNGRepresentation is broken in that it does not take into account orientation. Two logically identical images with different orientations may not pass this check. – Micah Hainline Nov 25 '13 at 16:12
-
doens't work if one of the image is saved in CoreDate (as NSData) and the other id imageNamed – Sam Dec 24 '13 at 15:02
-
@Sam: how so? If the images are pixel-equal, then this should still work (barring the orientation issue that Micah points out) – Simon Dec 26 '13 at 17:48
-
10
-
Adding on the last comment: it's likely that there is a more efficient way to achieve what you are trying to do (for instance the answer from @Azerue below) – Kamchatka May 30 '15 at 09:59
-
A Swift implementation of @Simon's 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)
}
}

- 1,023
- 2
- 15
- 26
-
Yes I agree, however I was only translating code from another answer – Mark Tickner Feb 24 '16 at 09:03
-
-
2Now my only comment would be that rather than force unwrapping and crashing, we should return `false` if either is `nil`. `guard let data1 = UIImagePNGRepresentation(self), data2 = UIImagePNGRepresentation(image) else { return false } return data1 == data2` – nhgrif Feb 24 '16 at 12:54
-
In swift 4 need to write it like this let data1: NSData = UIImagePNGRepresentation(image1)! as NSData – Shivam Pokhriyal Aug 29 '18 at 14:54
-
1
Updated Mark Tickner's solution to Swift 4
import UIKit
extension UIImage {
func isEqualToImage(_ image: UIImage) -> Bool {
let data1 = self.pngData()
let data2 = image.pngData()
return data1 == data2
}
}
The two variables are probably overkill, but they might help explain to someone new to this. Could shorten to:
import UIKit
extension UIImage {
func isEqualToImage(_ image: UIImage) -> Bool {
return self.pngData() == image.pngData()
}
}

- 12,630
- 8
- 75
- 122

- 2,397
- 2
- 24
- 35
-
@YogeshPatel I couldn't comment, you'll have to try it. If you do, update us here! – Greg Hilston Mar 26 '20 at 14:13
-
2I already did this but it's not working for me. That's why i told you. can you please help me on this! – Yogesh Patel Mar 26 '20 at 16:35
when both using [UIImage imageNamed:]
, we can use isEqual:
, otherwise we could compare the data.
-
This isn't a really safe solution, especially when using it within an UITableView. I recommend using @Simon's solution. – Sebyddd Oct 14 '14 at 20:38
-
@Sebyddd really? have you tried using simon's solution while rendering UITableViewCells? that comparison operation is pretty expensive.. and so scrolling will be pretty choppy.. true story – abbood Jun 03 '15 at 09:01
-
@abbood yes, it might be more expensive, but from my tests this one didn't always return the right result, for some reason. Two NSObjects are considered equal if they point to the same memory address. That's what isEqual does. Therefore imageNamed returns a new instance at a different memory address. It's not really stable. – Sebyddd Jun 03 '15 at 09:08
-
@Sebyddd The default implementation of `isEqual:` inherited from `NSObject` is a simple reference comparison, yes. However some objects override this default implementation. One I know for sure, for example, is `NSString`, whose `isEqual:` is functionally equivalent to `isEqualToString:`, both of which are value comparisons--not reference comparisons. I cannot comment as to `UIImage`'s implementation of `isEqual` (whether it has overridden the inherited method or not). – nhgrif Feb 24 '16 at 00:14
The right answer depends on "What kind of comparison you want to do?".
- The easiest way is just to compare data.
- If you want to know whether image were created from one local file – you can use -isEqual: (but there is an dangerous way, because I'm not sure, what happens if image cache clear for some reason).
- The hard way is provide per-pixel comparison (surely, system will spend more time on it). I can't provide the code from our company's library because of legal reason :(
But you can check good example on facebook's ios-snapshot-test-case project here: link right to the needed file. You can use performance tests to measure process time.
For the Great Justice I'll copy code from there 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;
}

- 845
- 8
- 16
My preferred (Swift) solution
import UIKit
func ==(lhs: UIImage, rhs: UIImage) -> Bool
{
guard let data1 = UIImagePNGRepresentation(lhs),
data2 = UIImagePNGRepresentation(rhs)
else { return false }
return data1.isEqual(data2)
}

- 1,087
- 3
- 14
- 27
-
Using the default implementation with isEqual didn't work for me either, this was the only solution that worked for me. – inexcitus Dec 16 '18 at 10:51
Converting the images to JPG / PNG, or relying on accessibility identifiers is either an expensive operation, or fragile & prone to failure.
Here, I follow the suggestion provided by Apple at the following link:
The isEqual(:) method is the only reliable way to determine whether two images contain the same image data. The image objects you create may be different from each other, even when 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 illustrates the correct and incorrect ways to compare images.
To simplify things, I create the following extension for doing comparisons, so that I can avoid the issue of converting the first image:
import UIKit
extension UIImage {
func isEqual(to image: UIImage) -> Bool {
return isEqual(image)
}
}
With this, I can now setup an example to compare it on 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

- 35,668
- 12
- 125
- 132
-
9Despite Apple's documentation, I found that `isEqual` does not correctly compare the data of two UIImage instances in Obj-C; it returns false for two `UIImage` instances that contain the same data. Converting the UIImage instances to PNGs and comparing the raw data (as is done in Simon's answer) is the only way I've found to correctly do the comparison with Obj-C. – BinaryNate Nov 08 '17 at 02:32
Swift 4.x version of Facebook's comparison algorithm:
/// Value in range 0...100 %
typealias Percentage = Float
// See: https://github.com/facebookarchive/ios-snapshot-test-case/blob/master/FBSnapshotTestCase/Categories/UIImage%2BCompare.m
private func compare(tolerance: Percentage, expected: Data, observed: Data) throws -> Bool {
guard let expectedUIImage = UIImage(data: expected), let observedUIImage = UIImage(data: observed) else {
throw Error.unableToGetUIImageFromData
}
guard let expectedCGImage = expectedUIImage.cgImage, let observedCGImage = observedUIImage.cgImage else {
throw Error.unableToGetCGImageFromData
}
guard let expectedColorSpace = expectedCGImage.colorSpace, let observedColorSpace = observedCGImage.colorSpace else {
throw Error.unableToGetColorSpaceFromCGImage
}
if expectedCGImage.width != observedCGImage.width || expectedCGImage.height != observedCGImage.height {
throw Error.imagesHasDifferentSizes
}
let imageSize = CGSize(width: expectedCGImage.width, height: expectedCGImage.height)
let numberOfPixels = Int(imageSize.width * imageSize.height)
// Checking that our `UInt32` buffer has same number of bytes as image has.
let bytesPerRow = min(expectedCGImage.bytesPerRow, observedCGImage.bytesPerRow)
assert(MemoryLayout<UInt32>.stride == bytesPerRow / Int(imageSize.width))
let expectedPixels = UnsafeMutablePointer<UInt32>.allocate(capacity: numberOfPixels)
let observedPixels = UnsafeMutablePointer<UInt32>.allocate(capacity: numberOfPixels)
let expectedPixelsRaw = UnsafeMutableRawPointer(expectedPixels)
let observedPixelsRaw = UnsafeMutableRawPointer(observedPixels)
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
guard let expectedContext = CGContext(data: expectedPixelsRaw, width: Int(imageSize.width), height: Int(imageSize.height),
bitsPerComponent: expectedCGImage.bitsPerComponent, bytesPerRow: bytesPerRow,
space: expectedColorSpace, bitmapInfo: bitmapInfo.rawValue) else {
expectedPixels.deallocate()
observedPixels.deallocate()
throw Error.unableToInitializeContext
}
guard let observedContext = CGContext(data: observedPixelsRaw, width: Int(imageSize.width), height: Int(imageSize.height),
bitsPerComponent: observedCGImage.bitsPerComponent, bytesPerRow: bytesPerRow,
space: observedColorSpace, bitmapInfo: bitmapInfo.rawValue) else {
expectedPixels.deallocate()
observedPixels.deallocate()
throw Error.unableToInitializeContext
}
expectedContext.draw(expectedCGImage, in: CGRect(origin: .zero, size: imageSize))
observedContext.draw(observedCGImage, in: CGRect(origin: .zero, size: imageSize))
let expectedBuffer = UnsafeBufferPointer(start: expectedPixels, count: numberOfPixels)
let observedBuffer = UnsafeBufferPointer(start: observedPixels, count: numberOfPixels)
var isEqual = true
if tolerance == 0 {
isEqual = expectedBuffer.elementsEqual(observedBuffer)
} else {
// Go through each pixel in turn and see if it is different
var numDiffPixels = 0
for pixel in 0 ..< numberOfPixels where expectedBuffer[pixel] != observedBuffer[pixel] {
// If this pixel is different, increment the pixel diff count and see if we have hit our limit.
numDiffPixels += 1
let percentage = 100 * Float(numDiffPixels) / Float(numberOfPixels)
if percentage > tolerance {
isEqual = false
break
}
}
}
expectedPixels.deallocate()
observedPixels.deallocate()
return isEqual
}

- 6,402
- 1
- 60
- 74
I did some changes to Mark's answer and used Data and elementsEqual instead NSData and isEqual.
extension UIImage {
func isEqual(to image: UIImage) -> Bool {
guard let data1: Data = UIImagePNGRepresentation(self),
let data2: Data = UIImagePNGRepresentation(image) else {
return false
}
return data1.elementsEqual(data2)
}
}

- 91
- 1
- 4
Swift 3
There is two ways. Like:-
1) Use isEqual() function.
self.image?.isEqual(UIImage(named: "add-image"))
2) Use accessibilityIdentifier
Set the accessibilityIdentifier as 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, The calling way of method to identify
myImageView.getFileName()

- 1,025
- 13
- 17
-
myImageView.getFileName() -> Always Returns Nil.. i'd already set the accessibility identifier still this method getFileName always returns nil. – Yash Bedi Aug 30 '17 at 05:51
-
Sorry Abdul, neither these answers work for me in Swift 3.0 iOS 10.x – user3069232 Sep 08 '17 at 19:41
-
@YashBedi add this myImageView.image?.accessibilityIdentifier = "add-image" in viewdidload. – Abdul Hameed Sep 12 '17 at 06:44
Compare the image size initially
For a less expensive method, compare the image size initially. Even if there is a small change inside an 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 in comparing images from same source (same dimension, format etc).
-
I am sure that was isEqual does in the first place so no need to manually check lengths maybe? – pronebird Sep 17 '17 at 20:26
-
2I just looked into assembly and `NSData.isEqual` actually calls `NSData.isEqualToData` and it's indeed checks lengths before checking memory contents (it does that by calling `memcmp`). Therefore you can call `data1.isEqual(data2)` without performance implications. – pronebird Sep 19 '17 at 18:54
-
@andy Can you please test the same with logging time stamps and share the data? please try taking screen shots in loop, let say 10 screen shots in a second and log the time stamps with its difference on both scenarios. – Anulal S Sep 20 '17 at 04:33
-
Yeah this is unnecessary, trust the internal isEqual implementation to be done efficiently unless you can demonstrate otherwise. – trapper Feb 27 '18 at 02:52
This method works great:
func isEqualImages(_ image1: UIImage, and image: UIImage) -> Bool {
let data1: Data? = UIImagePNGRepresentation(image1)
let data: Data? = UIImagePNGRepresentation(image)
return data1 == data
}

- 3,788
- 6
- 26
- 40
Swift 5.x
You can just use
let image: UIImage!
let anotherImage: UIImage!
image == anotherImage

- 12,630
- 8
- 75
- 122
Short-hand and Swifty solution
extension UIImage: Equatable {
static func ==(lhs: UIImage, rhs: UIImage) -> Bool {
return lhs.pngData() == rhs.pngData()
}
}

- 11
- 1
I needed to detect differences within the video feed frames and threshold that difference in order to decide to do something within my code. You can use a similar pixel comparison to look at the pngData of the UIImage.
see my answer here

- 654
- 7
- 10
i not sure about comparing the UIImage data as it would be prettry expensive. What you could do is subclass Uimage and add tag property your self and then compare tag before changing the image. assign

- 91
- 2
- 7
if one image name is known to you,it will help you....
CGImageRef cgImage = [imageView.image CGImage];
if (cgImage == [UIImage imageNamed:@"imagename.png"].CGImage) {
// True Statement
}

- 1,563
- 20
- 28
-
1`CGImageRef` is a pointer, comparing two pointers does not guarantee equality of the images. `UIImage.image(named:)` caches images so this may work because you use that method, e.g. you retrieve the same image twice and compare it. But this may break in case of low memory warning. – pronebird Oct 06 '17 at 16:07
We need to use isEqualToData method in Objective-C. The Apple document states that
Two data objects are equal if they hold the same number of bytes, and if the bytes at the same position in the objects are the same.
- (BOOL)image:(UIImage *)image1 isEqualTo:(UIImage *)image2
{
NSData *data1 = UIImagePNGRepresentation(image1);
NSData *data2 = UIImagePNGRepresentation(image2);
return [data1 isEqualToData:data2];
}

- 2,201
- 21
- 24
Well you can also the 'tag' property to identify the objects at latter stages of your program. Just set the integer value and you are good to go

- 258
- 6
- 16
-
3UIImage do not have tag properties. You've must have mistaken the OP with UIImageViews. – Jay Q. Jul 02 '15 at 08:13