Search code examples
iosobjective-cuiimagensdata

Compare two images to check if they are same


I got a Profile view with a ImageView where a User can change their picture. I'm saving my old & new image to compare them. I would like to know if they're the same, so if they are I dont need to push the new one to my Server.

I tried this but it doesn't really work:

+ (NSData*)returnImageAsData:(UIImage *)anImage {
    // Get an NSData representation of our images. We use JPEG for the larger image
    // for better compression and PNG for the thumbnail to keep the corner radius transparency
    float i_width = 400.0f;
    float oldWidth = anImage.size.width;
    float scaleFactor = i_width / oldWidth;

    float newHeight = anImage.size.height * scaleFactor;
    float newWidth = oldWidth * scaleFactor;

    UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
    [anImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    NSData *imageData = UIImageJPEGRepresentation(newImage, 0.5f);

    return imageData;
}

+ (BOOL)image:(UIImage *)image1 isEqualTo:(UIImage *)image2
{

    NSData *data1 = [self returnImageAsData:image1];
    NSData *data2 = [self returnImageAsData:image2];

    return [data1 isEqual:data2];
}

Any idea how to check if two images are same?

End result:

+ (NSData*)returnImageAsData:(UIImage *)anImage {
    // Get an NSData representation of our images. We use JPEG for the larger image
    // for better compression and PNG for the thumbnail to keep the corner radius transparency
//    float i_width = 400.0f;
//    float oldWidth = anImage.size.width;
//    float scaleFactor = i_width / oldWidth;
//    
//    float newHeight = anImage.size.height * scaleFactor;
//    float newWidth = oldWidth * scaleFactor;
//    
//    UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
//    [anImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
//    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
//    UIGraphicsEndImageContext();

    NSData *imageData = UIImageJPEGRepresentation(anImage, 0.5f);

    return imageData;
}

+ (BOOL)image:(UIImage *)image1 isEqualTo:(UIImage *)image2
{
    CGSize size1 = image1.size;
    CGSize size2 = image2.size;

    if (CGSizeEqualToSize(size1, size2)) {
        return YES;
    }

    NSData *data1 = UIImagePNGRepresentation(image1);
    NSData *data2 = UIImagePNGRepresentation(image2);

    return [data1 isEqual:data2];
}

Solution

  • If you want to see if the 2 images are pixel-identical, it should be pretty easy.

    Saving the images to JPEG is likely to cause problems because JPEG is a lossy format.

    As others have suggested, first make sure the height and width of both images match. If not, stop. The images are different.

    If those match, use a function like UIImagePNGRepresentation() to convert the image to a lossless data format. Then use isEqual on the NSData objets you get back.

    If you want to check if the images LOOK the same (like 2 photographs of the same scene), you have a much, much harder problem on your hands. You might have to resort to a package like OpenCV to compare the images.

    EDIT: I don't know if UIImage has a custom implementation of isEqual that you can use to compare two images. I'd try that first.

    Looking at the docs, UIImage also conforms to NSCoding, so you could use archivedDataWithRootObject to convert the images to data. That would probably be faster than PNG encoding them.

    Finally, you could get a pointer to the images' underlying CGImage objects, get their data providers, and compare their byte-streams that way.