Mar 30
Recently there have been some interesting developer news related to working with images on the iPhone.
- First there is Chris Greening’s open source project simple-iphone-image-processing, that provides a set of common image processing tasks .
- Today I listened to the Mobile Orchard’s podcast Interview with Paul Cantrell, and the discussion was about UIKit, views, layers, etc. This was the most enlightening information I’ve come across on this topic ever. Highly recommended.
So, I thought I’d contribute a few UIImage routines that I’ve found useful.
Combine two UIImages
To add two UIImages together you need to make use of Graphics Context.
- (UIImage *)addImage:(UIImage *)image1 toImage:(UIImage *)image2 { UIGraphicsBeginImageContext(image1.size); // Draw image1 [image1 drawInRect:CGRectMake(0, 0, image1.size.width, image1.size.height)]; // Draw image2 [image2 drawInRect:CGRectMake(0, 0, image2.size.width, image2.size.height)]; UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return resultingImage; }
Create a UIImage from a part of another UIImage
This requires a round-trip to Core Graphics land:
- (UIImage *)imageFromImage:(UIImage *)image inRect:(CGRect)rect { CGImageRef sourceImageRef = [image CGImage]; CGImageRef newImageRef = CGImageCreateWithImageInRect(sourceImageRef, rect); UIImage *newImage = [UIImage imageWithCGImage:newImageRef]; CGImageRelease(newImageRef); return newImage; }
Save UIImage to Photo Album
This is just a one-liner:
UIImageWriteToSavedPhotosAlbum(image, self, @selector(imageSavedToPhotosAlbum: didFinishSavingWithError: contextInfo:), context);
And to know if the save was successful:
- (void)imageSavedToPhotosAlbum:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo { NSString *message; NSString *title; if (!error) { title = NSLocalizedString(@"SaveSuccessTitle", @""); message = NSLocalizedString(@"SaveSuccessMessage", @""); } else { title = NSLocalizedString(@"SaveFailedTitle", @""); message = [error description]; } UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:message delegate:nil cancelButtonTitle:NSLocalizedString(@"ButtonOK", @"") otherButtonTitles:nil]; [alert show]; [alert release]; }
April 1st, 2009 at 13:03
Thanks for UIGraphicsBeginImageContext()! Somehow I’d never discovered it. Very useful indeed.
Glad you liked the podcast!
April 21st, 2009 at 19:10
Nice blog.. thanks for the info! What are you using to display the code snippets in your blog?
April 22nd, 2009 at 10:19
@Johnny: Thanks for the feedback! For displaying code snippets I’m using this WP plugin: Google Syntax Highlighter for WordPress which in turn is built upon this open source project: Google Syntax Highlighter.
April 23rd, 2009 at 07:28
Thanks for posting this. But you have any idea why if use UIGraphicsBeginImageContext it will not work unless I set the last 3 options to nil? If I use your code, it just crashes simulator.
April 24th, 2009 at 18:16
@MPY: I’m not sure what you mean. UIGraphicsBeginImageContext only takes one parameter, a CGSize.
April 24th, 2009 at 11:03
These are really good tricks. Can we draw a rectangle on the image and then display on screen? I have image on which I want to draw rectangle and then display on scree.
April 24th, 2009 at 18:12
@Vishal: Yes, you should be able to draw a rect in between UIGraphicsBeginImageContext() and UIGraphicsEndImageContext(). And then render the resulting image to the screen.
January 10th, 2010 at 20:27
how do you do image effects like blurring, bumping, and distortions/warping?
can you use Core Image Filters? If not, what else can you try? Thanks.
January 11th, 2010 at 07:48
@jeff: I have not developed any iPhone apps with that type of image effects, so I don’t know what the best way to do this is.
January 18th, 2010 at 06:40
thanks for providing source codes for simple image processing based on iPhone.
I have one question here , do you have try to use the opencv to iPhone ? I have searched that there are a lot people tried to compiler opencv based on iPhone, but never see one real application which use opencv to do image processing.
Thanks
January 18th, 2010 at 08:51
@Forrest: Sorry, I have not used opencv.
March 25th, 2010 at 05:26
@Nick,
actually if you can make full use of opencv based on iPhone, that will be wonderful !
Opencv is so powerful that you do not need to write any image processing algorithm. Just use them from OpenCV.
Welcome for discussing on this topic with me , my contact is :
SKYPE : forrest.shi
EMAIL : forrest.shi@gmail.com
May 16th, 2010 at 23:48
Hi,
It is interesting indeed but I’m having trouble adding the source to my project.
I’ve downloaded the sample program and my understading is that the wrapper comes in 2 files : Image.mm and Image.h
When I add those two files, it expects it to be Objective-C code but it’s not.
I tried to compare the target settings on the 2 projects and I still don’t have a clue.
Could someone explain to me how to do this ??
Thanks
May 17th, 2010 at 16:37
@Art: A file with the extension .mm is typically used for C++. That may be why Xcode gets confused.
October 16th, 2010 at 02:29
Thanks for the merge image tip! Appreciate it. 🙂
November 17th, 2010 at 05:25
Thanks for the info on handling UIImageWriteToSavedPhotosAlbum.
December 18th, 2010 at 03:51
Nica share….
Btw, i ever compile opencv on the iphone simulator. It was wonderfull, but lil bit confusing me to convert betwen UIImage to Iplimage and vice versa, and some of the rule of instant method parameter. So i tried to find another way to did it..
I have one question, can use CGImage Class to do image processing in realtime like opencv did?
Thx b4
January 10th, 2011 at 14:56
There’s a project that achieves fast image processing from the video camera, that is open source. It can help start anyone in the right direction –
http://www.hatzlaha.co.il/150842/FAST-Corner-V2
Thanks! 🙂
June 25th, 2011 at 04:41
Regarding: `UIImageWriteToSavedPhotosAlbum(image, self, @selector(imageSavedToPhotosAlbum: didFinishSavingWithError: contextInfo:), context);`
I’ve seen many examples showing: `UIImageWriteToSavedPhotosAlbum(imageCopy, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);`
so I replaced `image` with `imageSavedToPhotosAlbum`, but it complained that `context`, which is at the end of your line, is an undeclared identifier. If I replace it with nil, the app crashes returning the following error: *** Terminating app due to uncaught exception ‘NSInvalidArgumentException’, reason: ‘+[NSInvocation invocationWithMethodSignature:]: method signature argument cannot be nil’ I’m using ios 4.3.3 and Xcode 4.0.2. Any suggestions?
June 25th, 2011 at 16:46
@Sal: The method name “imageSavedToPhotosAlbum:” is arbitrary, but it must exist in your code because this method will be called when UIImageWriteToSavedPhotosAlbum completes. Other code examples may use the method name “image:”. This is just as valid. I just happen to like very long, descriptive method names.
The context parameter is only passed back to your method defined in the @selector. You can pass in the name of the image saved or some other information that might be useful in the called method. If you don’t want any such information to be passed back to your code, then pass nil to the UIImageWriteToSavedPhotosAlbum function.
July 20th, 2011 at 21:20
Hi, I’m not sure I understand how to combine the two images. I tried testing the code in my method file but how to I call the resulting image? Is there an xcode example for this?
Thanks
July 22nd, 2011 at 16:33
@Hakimo: The resulting image is returned from the addImage: method. You can use this in any way that you would normally use an UIImage object.
November 1st, 2011 at 07:48
Great tips! Regarding the function
– (UIImage *)addImage:(UIImage *)image1 toImage:(UIImage *)image2
It seems like this works perfectly on simulator and 320×480 screens, but if you jump to 640×960, image2’s dimensions are calculated at 320×480 sizes (even if you have the @2x file ready). This is only happening for image2; image1 is calculated at the correct Retina size. Curious.
February 12th, 2012 at 00:48
Hi Mark,
Here is an adaptation of the routine that can be used for @2x images.
I have written it based on the sources I make reference to, including this page; thus please note the URL REF comments.
// BEGIN CODE
– (UIImage*) mergeTwoImages : (UIImage*) topImage : (UIImage*) bottomImage {
// URL REF: http://iphoneincubator.com/blog/windows-views/image-processing-tricks
// URL REF: http://stackoverflow.com/questions/1309757/blend-two-uiimages?answertab=active#tab-top
// URL REF: http://www.waterworld.com.hk/en/blog/uigraphicsbeginimagecontext-and-retina-display
int width = bottomImage.size.width;
int height = bottomImage.size.height;
CGSize newSize = CGSizeMake(width, height);
static CGFloat scale = -1.0;
if (scale= 4.0) {
scale = [screen scale];
}
else {
scale = 0.0; // Use the standard API
}
}
if (scale>0.0) {
UIGraphicsBeginImageContextWithOptions(newSize, NO, scale);
}
else {
UIGraphicsBeginImageContext(newSize);
}
[bottomImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
[topImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height) blendMode:kCGBlendModeNormal alpha:1.0];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
// END CODE
April 11th, 2012 at 17:35
i want to allow the app user, to add his face on famous celebrities bodies, and then save the image to camera roll?how can i do that? any ideas?
July 9th, 2012 at 01:37
I am at the end of my app now and for whatever reason I am drawing a blank. I decided to implement your code into my app. Well I pasted it in and then renamed some of the UIImage variables and I get a “Use of undeclared identifier” error. I know I am forgetting something, but for the life of me, every combination that I try, I get wrong. Can you mention the additional missing code that is not here please?
Thanks