Questions tagged [uiimage]

The basic image handling class of Cocoa-Touch on iOS. It is Available in iOS 2.0 and later.

A UIImage object is a high-level way to display image data. You can create images from files, from Quartz image objects, or from raw image data you receive. The UIImage class also offers several options for drawing images to the current graphics context using different blend modes and opacity values.The questions related to this can be tagged using

Image objects are immutable, so you cannot change their properties after creation. This means that you generally specify an image’s properties at initialization time or rely on the image's metadata to provide the property value. In some cases, however, the UIImage class provides convenience methods for obtaining a copy of the image that uses custom values for a property.

In low-memory situations, image data may be purged from a UIImage object to free up memory on the system. This purging behavior affects only the image data stored internally by the UIImage object and not the object itself. When you attempt to draw an image whose data has been purged, the image object automatically reloads the data from its original file. This extra load step, however, may incur a small performance penalty.

The simplest way to load an image is with the imageNamed method, however this loads the data into memory and (generally) doesn't release it, so this is only ideal for small, frequently-used images.

UIImage *bgImage = [UIImage imageNamed:@"background.jpg"];

Use imageWithContentsOfFile to read image data from a file. This method doesn't cache the image to memory.

UIImage *bgImage = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"background" ofType:@"jpg"]]

Resources:


Can I Get To The Original File Representing This Image on the Disk?

As of iOS 4, you can, but it's very annoying. Use the following code to get an AssetsLibrary URL for the image, and then pass the URL to assetForURL:resultBlock:failureBlock:

NSURL *referenceURL = [info objectForKey:UIImagePickerControllerReferenceURL];
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
[library assetForURL:referenceURL resultBlock:^(ALAsset *asset) {
    // code to handle the asset here
} failureBlock:^(NSError *error) {
    // error handling
}];
[library release];

It's annoying because the user is asked if your application can access your current location, which is rather confusing since you are actually trying to access the user's photo library. Unless you're actually trying to get at the EXIF location data, the user is going to be a bit confused.

Make sure to include the AssetsLibrary framework to make this work.

How Can I Look At The Underlying Pixels of the UIImage?

Since the UIImage is immutable, you can't look at the direct pixels. However, you can make a copy. The code to this looks something like this:

UIImage* image = ...; // An image
NSData* pixelData = (NSData*) CGDataProviderCopyData(CGImageGetDataProvider(image.CGImage));
unsigned char* pixelBytes = (unsigned char *)[pixelData bytes];

// Take away the red pixel, assuming 32-bit RGBA
for(int i = 0; i < [pixelData length]; i += 4) {
        pixelBytes[i] = 0; // red
        pixelBytes[i+1] = pixelBytes[i+1]; // green
        pixelBytes[i+2] = pixelBytes[i+2]; // blue
        pixelBytes[i+3] = pixelBytes[i+3]; // alpha
}

However, note that CGDataProviderCopyData provides you with an "immutable" reference to the data - meaning you can't change it (and you may get a BAD_ACCESS error if you do). Look at the next question if you want to see how you can modify the pixels.

How Do I Modify The Pixels of the UIImage?

The UIImage is immutable, meaning you can't change it. Apple posted a great article on how to get a copy of the pixels and modify them, and rather than copy and paste it here, you should just go read the article.

Once you have the bitmap context as they mention in the article, you can do something similar to this to get a new UIImage with the modified pixels:

CGImageRef ref = CGBitmapContextCreateImage(bitmap);
UIImage* newImage = [UIImage imageWithCGImage:ref];

Do remember to release your references though, otherwise you're going to be leaking quite a bit of memory.

How Do I Resize the Image?

Unfortunately, there is no defined way how to resize an image. Also, it's important to note that when you resize it, you'll get a new image - you're not modifying the old one.

There are a couple of methods to do the resizing. I'll present them both here, and explain the pros and cons of each.

Method 1: Using UIKit

+ (UIImage*)imageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize
{
    // Create a graphics image context
    UIGraphicsBeginImageContext(newSize);

    // Tell the old image to draw in this new context, with the desired
    // new size
    [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];

    // Get the new image from the context
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();

    // End the context
    UIGraphicsEndImageContext();

    // Return the new image.
    return newImage;
}

This method is very simple, and works great. It will also deal with the UIImageOrientation for you, meaning that you don't have to care whether the camera was sideways when the picture was taken. However, this method is not thread safe, and since thumbnailing is a relatively expensive operation (approximately ~2.5s on a 3G for a 1600 x 1200 pixel image), this is very much an operation you may want to do in the background, on a separate thread.

Method 2: Using CoreGraphics

+ (UIImage*)imageWithImage:(UIImage*)sourceImage scaledToSize:(CGSize)newSize;
{
    CGFloat targetWidth = newSize.width;
    CGFloat targetHeight = newSize.height;

    CGImageRef imageRef = [sourceImage CGImage];
    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
    CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);

    if (bitmapInfo == kCGImageAlphaNone) {
        bitmapInfo = kCGImageAlphaNoneSkipLast;
    }

    CGContextRef bitmap;

    if (sourceImage.imageOrientation == UIImageOrientationUp || sourceImage.imageOrientation == UIImageOrientationDown) {
        bitmap = CGBitmapContextCreate(NULL, targetWidth, targetHeight, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    } else {
        bitmap = CGBitmapContextCreate(NULL, targetHeight, targetWidth, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    }   

    if (sourceImage.imageOrientation == UIImageOrientationLeft) {
        CGContextRotateCTM (bitmap, M_PI_2); // + 90 degrees
        CGContextTranslateCTM (bitmap, 0, -targetHeight);

    } else if (sourceImage.imageOrientation == UIImageOrientationRight) {
        CGContextRotateCTM (bitmap, -M_PI_2); // - 90 degrees
        CGContextTranslateCTM (bitmap, -targetWidth, 0);

    } else if (sourceImage.imageOrientation == UIImageOrientationUp) {
        // NOTHING
    } else if (sourceImage.imageOrientation == UIImageOrientationDown) {
        CGContextTranslateCTM (bitmap, targetWidth, targetHeight);
        CGContextRotateCTM (bitmap, -M_PI); // - 180 degrees
    }

    CGContextDrawImage(bitmap, CGRectMake(0, 0, targetWidth, targetHeight), imageRef);
    CGImageRef ref = CGBitmapContextCreateImage(bitmap);
    UIImage* newImage = [UIImage imageWithCGImage:ref];

    CGContextRelease(bitmap);
    CGImageRelease(ref);

    return newImage; 
}

The benefit of this method is that it is thread-safe, plus it takes care of all the small things (using correct color space and bitmap info, dealing with image orientation) that the UIKit version does.

How Do I Resize and Maintain Aspect Ratio (like the AspectFill option)?

It is very similar to the method above, and it looks like this:

+ (UIImage*)imageWithImage:(UIImage*)sourceImage scaledToSizeWithSameAspectRatio:(CGSize)targetSize;
{  
    CGSize imageSize = sourceImage.size;
    CGFloat width = imageSize.width;
    CGFloat height = imageSize.height;
    CGFloat targetWidth = targetSize.width;
    CGFloat targetHeight = targetSize.height;
    CGFloat scaleFactor = 0.0;
    CGFloat scaledWidth = targetWidth;
    CGFloat scaledHeight = targetHeight;
    CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

    if (CGSizeEqualToSize(imageSize, targetSize) == NO) {
        CGFloat widthFactor = targetWidth / width;
        CGFloat heightFactor = targetHeight / height;

        if (widthFactor > heightFactor) {
            scaleFactor = widthFactor; // scale to fit height
        }
        else {
            scaleFactor = heightFactor; // scale to fit width
        }

        scaledWidth  = width * scaleFactor;
        scaledHeight = height * scaleFactor;

        // center the image
        if (widthFactor > heightFactor) {
            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 
        }
        else if (widthFactor < heightFactor) {
            thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
        }
    }     

    CGImageRef imageRef = [sourceImage CGImage];
    CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
    CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);

    if (bitmapInfo == kCGImageAlphaNone) {
        bitmapInfo = kCGImageAlphaNoneSkipLast;
    }

    CGContextRef bitmap;

    if (sourceImage.imageOrientation == UIImageOrientationUp || sourceImage.imageOrientation == UIImageOrientationDown) {
        bitmap = CGBitmapContextCreate(NULL, targetWidth, targetHeight, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    } else {
        bitmap = CGBitmapContextCreate(NULL, targetHeight, targetWidth, CGImageGetBitsPerComponent(imageRef), CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);

    }   

    // In the right or left cases, we need to switch scaledWidth and scaledHeight,
    // and also the thumbnail point
    if (sourceImage.imageOrientation == UIImageOrientationLeft) {
        thumbnailPoint = CGPointMake(thumbnailPoint.y, thumbnailPoint.x);
        CGFloat oldScaledWidth = scaledWidth;
        scaledWidth = scaledHeight;
        scaledHeight = oldScaledWidth;

        CGContextRotateCTM (bitmap, M_PI_2); // + 90 degrees
        CGContextTranslateCTM (bitmap, 0, -targetHeight);

    } else if (sourceImage.imageOrientation == UIImageOrientationRight) {
        thumbnailPoint = CGPointMake(thumbnailPoint.y, thumbnailPoint.x);
        CGFloat oldScaledWidth = scaledWidth;
        scaledWidth = scaledHeight;
        scaledHeight = oldScaledWidth;

        CGContextRotateCTM (bitmap, -M_PI_2); // - 90 degrees
        CGContextTranslateCTM (bitmap, -targetWidth, 0);

    } else if (sourceImage.imageOrientation == UIImageOrientationUp) {
        // NOTHING
    } else if (sourceImage.imageOrientation == UIImageOrientationDown) {
        CGContextTranslateCTM (bitmap, targetWidth, targetHeight);
        CGContextRotateCTM (bitmap, -M_PI); // - 180 degrees
    }

    CGContextDrawImage(bitmap, CGRectMake(thumbnailPoint.x, thumbnailPoint.y, scaledWidth, scaledHeight), imageRef);
    CGImageRef ref = CGBitmapContextCreateImage(bitmap);
    UIImage* newImage = [UIImage imageWithCGImage:ref];

    CGContextRelease(bitmap);
    CGImageRelease(ref);

    return newImage; 
}

The method we employ here is to create a bitmap with the desired size, but draw an image that is actually larger, thus maintaining the aspect ratio.

So We've Got Our Scaled Images - How Do I Save Them To Disk?

This is pretty simple. Remember that we want to save a compressed version to disk, and not the uncompressed pixels. Apple provides two functions that help us with this (documentation is here):

NSData* UIImagePNGRepresentation(UIImage *image);
NSData* UIImageJPEGRepresentation (UIImage *image, CGFloat compressionQuality);

And if you want to use them, you'd do something like:

UIImage* myThumbnail = ...; // Get some image
NSData* imageData = UIImagePNGRepresentation(myThumbnail);

Now we're ready to save it to disk, which is the final step (say into the documents directory):

// Give a name to the file
NSString* imageName = @"MyImage.png";

// Now, we have to find the documents directory so we can save it
// Note that you might want to save it elsewhere, like the cache directory,
// or something similar.
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* documentsDirectory = [paths objectAtIndex:0];

// Now we get the full path to the file
NSString* fullPathToFile = [documentsDirectory stringByAppendingPathComponent:imageName];

// and then we write it out
[imageData writeToFile:fullPathToFile atomically:NO];

You would repeat this for every version of the image you have.

How Do I Load These Images Back Into Memory?

Just look at the various UIImage initialization methods, such as +imageWithContentsOfFile: in the Apple documentation.


Information sourced from a now deleted Stack Overflow post: UIImagePickerController, UIImage, Memory and More?

9082 questions
458
votes
34 answers

Loading/Downloading image from URL on Swift

I'd like to load an image from a URL in my application, so I first tried with Objective-C and it worked, however, with Swift, I've a compilation error: 'imageWithData' is unavailable: use object construction 'UIImage(data:)' My function:…
QuentR
  • 4,667
  • 3
  • 10
  • 12
432
votes
25 answers

How can I change image tintColor in iOS and WatchKit

I have an UIImageView called "theImageView", with UIImage in a single color (transparent background) just like the left black heart below. How can I change the tint color of this image programmatically in iOS 7 or above, as per the tint method used…
chewy
  • 7,828
  • 6
  • 39
  • 68
412
votes
32 answers

The simplest way to resize an UIImage?

In my iPhone app, I take a picture with the camera, then I want to resize it to 290*390 pixels. I was using this method to resize the image : UIImage *newImage = [image _imageScaledToSize:CGSizeMake(290, 390) …
pimpampoum
  • 5,376
  • 6
  • 20
  • 27
342
votes
20 answers

iOS UIImagePickerController result image orientation after upload

I am testing my iPhone application on an iOS 3.1.3 iPhone. I am selecting/capturing an image using a UIImagePickerController: UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init]; [imagePicker…
james
  • 25,347
  • 17
  • 92
  • 109
307
votes
17 answers

How to capture UIView to UIImage without loss of quality on retina display

My code works fine for normal devices but creates blurry images on retina devices. Does anybody know a solution for my issue? + (UIImage *) imageWithView:(UIView *)view { UIGraphicsBeginImageContext(view.bounds.size); [view.layer…
Daniel
  • 3,271
  • 4
  • 17
  • 17
305
votes
35 answers

UIImageView missing images in Launch Screen on device

I have an app that supports iOS8 and later, built in Xcode 7 and I am using a XIB for a Launch Screen (I do not have launch images). The view contains a single UILabel with the app version, and 2 UIImageViews with images that are both present in…
MFW
  • 3,061
  • 2
  • 9
  • 3
242
votes
8 answers

How can I get the height and width of an uiimage?

From the URL Image in Mail I'm adding image to mail view. It will show full image. But I want to calculate, proportionally change the height and width of the image. How can I get the height and width of UIImage?
Satyam
  • 14,636
  • 29
  • 122
  • 234
242
votes
24 answers

Convert between UIImage and Base64 string

Does anyone know how to convert a UIImage to a Base64 string, and then reverse it? I have the below code; the original image before encoding is good, but I only get a blank image after I encode and decode it. NSData *imageData =…
changey
  • 15,519
  • 7
  • 23
  • 31
214
votes
15 answers

How to animate the change of image in an UIImageView?

I have an UIImageView with an image. Now I have a completely new image (graphic file), and want to display that in this UIImageView. If I just set myImageView.image = newImage; the new image is visible immediately. Not animatable. I want it to…
dontWatchMyProfile
  • 42,456
  • 49
  • 169
  • 255
200
votes
15 answers

How to save picture to iPhone photo library?

What do I need to do to save an image my program has generated (possibly from the camera, possibly not) to the system photo library on the iPhone?
jblocksom
  • 12,545
  • 5
  • 32
  • 30
192
votes
10 answers

How do I export UIImage array as a movie?

I have a serious problem: I have an NSArray with several UIImage objects. What I now want to do, is create movie from those UIImages. But I don't have any idea how to do so. I hope someone can help me or send me a code snippet which does something…
Nuker
  • 2,408
  • 5
  • 17
  • 30
188
votes
10 answers

UIImageView aspect fit and center

I have an image view, declared programmatically, and I am setting its image, also programmatically. However, I find myself unable to set the image to both fit the aspect and align centre to the image view. In other words, I want the image to: Scale…
Ravi Vooda
  • 5,016
  • 5
  • 17
  • 25
182
votes
19 answers

How to Rotate a UIImage 90 degrees?

I have a UIImage that is UIImageOrientationUp (portrait) that I would like to rotate counter-clockwise by 90 degrees (to landscape). I don't want to use a CGAffineTransform. I want the pixels of the UIImage to actually shift position. I am using a…
RexOnRoids
  • 13,842
  • 33
  • 94
  • 134
168
votes
15 answers

Setting UIButton image results in blue button in iOS 7

On iOS 6 SDK I wrote the following lines of code to display an image inside a button: NSURL *thumbURL2 = [NSURL URLWithString:@"http://example.com/thumbs/2.jpg"]; NSData *thumbData2 = [NSData dataWithContentsOfURL:thumbURL2]; UIImage *thumb2 =…
user2665539
  • 1,691
  • 2
  • 10
  • 3
158
votes
7 answers

Creating a UIImage from a UIColor to use as a background image for UIButton

I'm creating a colored image like this: CGRect rect = CGRectMake(0, 0, 1, 1); UIGraphicsBeginImageContext(rect.size); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetFillColorWithColor(context, …
Thorsten
  • 12,213
  • 16
  • 58
  • 79
1
2 3
99 100