0

I use this code, but it very slow. Is there any other way to do it? I tried use methods indexOfObject and containsObject for array of images but it not works for me.

        BOOL haveDublicate = NO;
        UIImage *i = [ImageManager imageFromPath:path];
        NSArray *photoImages = [ImageManager imagesFromPaths:photoPaths];
        for (UIImage *saved in photoImages)
        {
            if ([ UIImagePNGRepresentation( saved ) isEqualToData:
                 UIImagePNGRepresentation( i ) ])
            {
                haveDublicate = YES;
            }
        }
rmaddy
  • 314,917
  • 42
  • 532
  • 579

1 Answers1

0

I think you should check the size of the image first. If size and scale of both images are equal, check the pixel data directly for equality, and not the images PNG representation. this will be much faster. (The link shows you how to get the pixel data. To compare it, use memcmp.)

From that post (slightly modified):

NSData *rawDataFromUIImage(UIImage *image)
{
    assert(image);

    // Get the image into the data buffer
    CGImageRef imageRef = [image CGImage];
    NSUInteger width = CGImageGetWidth(imageRef);
    NSUInteger height = CGImageGetHeight(imageRef);
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    int byteSize = height * width * 4;
    unsigned char *rawData = (unsigned char*) malloc(byteSize);
    NSUInteger bytesPerPixel = 4;
    NSUInteger bytesPerRow = bytesPerPixel * width;
    NSUInteger bitsPerComponent = 8;
    CGContextRef context = CGBitmapContextCreate(rawData, width, height,
                    bitsPerComponent, bytesPerRow, colorSpace,
                    kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
    CGColorSpaceRelease(colorSpace);

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
    CGContextRelease(context);
    return [NSData dataWithBytes:rawData length:byteSize];
}

About why this is faster: UIImagePNGRepresentation (1) fetches the raw binary data and then (2) converts it to PNG format. Skipping the second step can only improve performance, because it is much more work than just doing step 1. And memcmp is faster than everything else in this example.

Community
  • 1
  • 1
Michael
  • 6,451
  • 5
  • 31
  • 53
  • 1
    In addition, make sure you get the pixel data for 'i' outside of the loop, as this will not change. In the original code above, you are getting the png data for i every time, so it would immediately be twice as fast just by moving UIImagePNGRepresentation( i ) outside of the loop. Another optimisation would be to break the loop (add a 'break' statement) after you have found a duplicate, otherwise you'll continue to check all the other images after finding a duplicate image. – NigelG May 25 '14 at 11:58
  • @NigelG that's right. this will speed it up by up to 100%. – Michael May 25 '14 at 16:32