3

Let's say I want to find out the size of an image, so if a user tries to load a 10,000x10,000 pixel image in my iPad app I can present them with a dialog and not crash. If I do [UIImage imageNamed:] or [UIImage imageWithContentsOfFile:] that will load my potentially large image into memory immediately.

If I use Core Image instead, say like this:

CIImage *ciImage = [CIImage imageWithContentsOfURL:[NSURL fileURLWithPath:imgPath]];

Then ask my new CIImage for its size:

CGSize imgSize = ciImage.extent.size;

Will that load the entire image into memory to tell me this, or will it just look at the metadata of the file to discover the size of the image?

Cory Imdieke
  • 14,140
  • 8
  • 36
  • 46

1 Answers1

9

The imageWithContentsOfURL function loads the image into memory, yes.

Fortunately Apple implemented CGImageSource for reading image metadata without loading the actual pixel data into memory in iOS4, you can read about how to use it in this blog post (conveniently it provides a code sample on how to get image dimensions).

EDIT: Pasted code sample here to protect against link rot:

#import <ImageIO/ImageIO.h>

NSURL *imageFileURL = [NSURL fileURLWithPath:...];
CGImageSourceRef imageSource = CGImageSourceCreateWithURL((CFURLRef)imageFileURL, NULL);
if (imageSource == NULL) {
    // Error loading image
    ...
    return;
}

NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                     [NSNumber numberWithBool:NO], (NSString *)kCGImageSourceShouldCache,nil];
CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, (CFDictionaryRef)options);
if (imageProperties) {
    NSNumber *width = (NSNumber *)CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelWidth);
    NSNumber *height = (NSNumber *)CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelHeight);
    NSLog(@"Image dimensions: %@ x %@ px", width, height);
    CFRelease(imageProperties);
}

The full API reference is also available here.

andycam
  • 1,682
  • 14
  • 27
  • Ahh, well boo that CIImage won't do what I want but yay that there is something else. I don't suppose you know of a way to resize an image from data into something more manageable so I can still present a smaller version of my huge image to the user instead of just a dialog that says "no"? – Cory Imdieke Jul 27 '12 at 01:31
  • Indeed I do, have done it before. You could just include the method described in [this post](http://stackoverflow.com/a/2658801/465893) in your class, or even add the method as a category on UIImage [like so](https://gist.github.com/3185714) (You can add that in a prefix/header class and then it's an available method for any UIImage)! – andycam Jul 27 '12 at 01:42
  • Ah but that method requires the UIImage to be presented to resize, which means it would be in memory - so a huge image would crash the app on the initial UIImage creation before I could resize it. – Cory Imdieke Jul 27 '12 at 18:40
  • Correct. I thought it was the only way, but according to [this great answer](http://stackoverflow.com/a/5860390/465893) CGImageSource can handle that too! – andycam Jul 27 '12 at 22:06