9

I have a question about comparing UIImages in Objective-C when one image has already been through a save and load process using the NSSearchPathForDirectoriesInDomains method.

The aim of what I want is to direct the user to a new screen upon a click depending on what the image displays.

For simplicity let's say that there are two possibilities - a black image and a green image. Clicking on the black image takes you to xib1 and clicking the green image takes you to xib2.

This is simple enough and has been working until I have implemented a save and load system.

To save I do the following:

paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
pngFilePath = [NSString stringWithFormat:@"%@/test.png",documentsDirectory];
data1 = [NSData dataWithData:UIImagePNGRepresentation([level1part1 objectAtIndex:0])];
[data1 writeToFile:pngFilePath atomically:YES];

and to load I do the following:

paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
pngFilePath = [NSString stringWithFormat:@"%@/test.png",documentsDirectory];
UIImage *image = [UIImage imageWithContentsOfFile:pngFilePath];
[button1 setImage:image forState:UIControlStateNormal];

This is fine and when I quit the program and restart it the image is retained on the screen as I wish it to be. Hypothetically let's say that image now appearing on button1 is the green image.

When I call the following code after clicking on the button with id of sender (this is button1):

if(sender.currentImage == [UIImage imageNamed:self.greenImage])
{
    VisitAlreadyCorrectScreen *screen = [[VisitAlreadyCorrectScreen alloc] initWithNibName:nil bundle:nil];
    screen.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    [self presentModalViewController:screen animated:YES];
}

even though the currentImage is the green image and is the same picture as the green image I am comparing it to, I think because I saved the green image into memory in the save process the comparison doesn't work as they are held in different places in the memory - verified by the following NSLog:

Current Image: <UIImage: 0x95614c0>, and Yes Image: <UIImage: 0xde748f0>

I cannot work out how to compare the two images so that in this case they match (they both relate to the same image I have in the resource folder). Does anyone have any suggestions at all?

Please let me know if I have not explained well enough what the problem is!

Thanks in advance!

user1309044
  • 317
  • 3
  • 13
  • If you don't need 100% pixel-by-pixel comparison, you can use this, which is about 50 times faster than Paul N's solution: http://stackoverflow.com/a/19668235/423171 – cprcrack Oct 29 '13 at 20:19
  • It might be worth considering extending UIImage to add some identifier fields and compare methods. (Not sure how happy UIImage is to be extended.) – Hot Licks Nov 18 '13 at 21:57

2 Answers2

26

You can compare the image name or the image URL if it was downloaded from Internet, it will also be faster than comparing the images.

Also, the problem is that by using the == operator you are comparing the memory addresses of the images 0x95614c0 and 0xde748f0. That's why is not equal. You are comparing if they are the same object, not if the images are equal.

To compare images use: As mentioned on Fls'Zen answer.

if ([UIImagePNGRepresentation(blackImage) isEqualToData:UIImagePNGRepresentation(greenImage)])
Paul N
  • 1,901
  • 1
  • 22
  • 32
  • Hi Paul - thanks for your reply - I've used tags to identify between different buttons that hold my images and this works fine but can you even tag an image? Also, the code you provided I had already tried in my code to no avail - still is not recognising they are the same. – user1309044 Jun 26 '12 at 22:21
  • You are right, you can't I guess I confused myself with the ImageView, I also confirmed than the isEqual method doesn't work for images as it also compares the pointer of the object, I apologize for pointing you in a wrong direction, I updated my answer with the only method I found to compare the images then. – Paul N Jun 26 '12 at 22:35
  • Not to worry Paul - am appreciative for the response in the first place! – user1309044 Jun 26 '12 at 22:52
  • Another approach that worked for me is : if (![objImage isEqual: [UIImage imageNamed:@"image_name.png"]]) { ... } – Jayprakash Dubey Jan 10 '14 at 07:26
4

Your images certainly have different addresses since one is loaded from your application bundle and one is loaded from the documents directory. The [UIImage imageNamed:] function only returns images from the application bundle.

If you really want to compare the images by contents, check out this SO question. In the first answer, a hash value s computed for an image. In your code, you could compare the hash values of the two images you have. The second answer compares the images directly, in case hashes make you nervous.

I recommend going a different route and having your application track which image is loaded outside of the image itself.

Community
  • 1
  • 1
Fls'Zen
  • 4,594
  • 1
  • 29
  • 37
  • 1
    Hi Fls'Zen - thanks for your reply. I had a look at the link you mentioned and while the first method seemed quite extravagant for a fairly trivial task (which I'd have to replicate numerous other times) I attempted the second method that you pointed me too which unfortunately didn't work either (they didn't match). I might just create a bool or binary array that updates whenever the image changes and base my action on the value of that variable. I'll keep the question open incase anyone has any further answers - thanks for the response it is much appreciated! – user1309044 Jun 26 '12 at 22:53