Maintain image resolution in screen grab - iphone

In my app, the user is able to put stickers on top of a photo. When they go to save their creation, I do a screen grab and store it in a UIImage:
UIGraphicsBeginImageContextWithOptions(self.mainView.bounds.size, NO, [UIScreen mainScreen].scale);
[self.mainView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *resultImage = [UIGraphicsGetImageFromCurrentImageContext() retain];
UIGraphicsEndImageContext();
(where self.mainView has a subview UIImageView which holds the photo, and another subview UIView which holds the stickers).
I am wondering, is it possible to do a screen shot in this manner, and maintain the resolution of the aforementioned photo?

The following will 'flatten' two UIImages into one while maintaining the resolution of the original image(s):
CGSize photoSize = photoImage.size;
UIGraphicsBeginImageContextWithOptions(photoSize, NO, 0.0);
CGRect photoRect = CGRectMake(0, 0, photoSize.width, photoSize.height);
// Add the original photo into the context
[photoImage drawInRect:photoRect];
// Add the sticker image with its upper left corner set to where the user placed it
[stickerImage drawAtPoint:stickerView.frame.origin];
// Get the resulting 'flattened' image
UIImage *flattenedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
The above assumes photoImage and stickerImage are both instances of UIImage and stickerView is a UIView with containing the stickerImage and thus will be able to use the stickerView frame to determine its origin.
If you have multiple stickers, just iterate through the collection.

If you are looking to save an image of your current view then this might help you.
UIGraphicsBeginImageContext(self.scrollView.contentSize);
[self.scrollView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGImageRef imageRef = CGImageCreateWithImageInRect(finalImage.CGImage,
CGRectMake(scrollView.contentOffset.x, scrollView.contentOffset.y,
scrollView.frame.size.width, scrollView.frame.size.height));
UIImage *screenImage = [UIImage imageWithCGImage:imageRef scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp];
CGImageRelease(imageRef);

Related

How to position an object over an image and store it

I am creating a "cartoonizer" application, which takes an image as an input and modifies it so as to format it in comics style.
At the moment, the original image is stored in a UIImageView, and I access to it by doing:
imageView.image
I was wondering whether it is possible to position an object on the image imageView.image (like a balloon) and then store the image with the object on it, like if it was originally part of the image content.
Thank you in advance.
You can do it like this, assuming you have correct opacity in the top image.
Like you said you get your image from imageView.image:
From here: blend two uiimages based on alpha/transparency of top image
UIImage *bottomImage = [UIImage imageNamed:#"bottom.png"];
UIImage *image = [UIImage imageNamed:#"top.png"];
CGSize newSize = CGSizeMake(width, height);
UIGraphicsBeginImageContext( newSize );
// Use existing opacity as is
[bottomImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
// Apply supplied opacity
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height) blendMode:kCGBlendModeNormal alpha:0.8];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
More compositing techniques here: http://mobile.tutsplus.com/tutorials/iphone/ios-sdk-advanced-uiimage-techniques/

Xcode 4.3 How do I save a region of my app screen?

I am creating a native app on Xcode 4.3 and deploying to target iOS 5. The app is a basically a greeting card creator. I am having trouble figuring out how to save a portion of the screen from within the app.
What I want to do is this:
I am offering the user a button, that says "e-mail". when they click the button, the app should 'save' their card as an image and then 'paste' that into an email body.
The reason this is different than other answers on this website is that the area I want to save is made up of 4 'elements'. There is a background graphic that is the tilted card background, then there is a text field where users can type a message and then next to that is a picture area where they can choose their own picture to put on the card.
Here is a photo of what I am talking about:
http://marklopezdesigns.com/mydownloadz!/screenshotCard3.png
How do I save a 'composite' high res of these?
And then how do I get that into an email body message?
The reason i am asking how to 'save' it is because I want to be able to offer users another button that says "save to camera roll" and "send as message". I figure if I can understand how to save this high-res to a variable, then I should be off and running.
Thanks in advance for the help.
========
Here's the solution below
========
...so after a bit of fiddling. Finally got what I wanted. Here's the codebase I have in my method that fires upon touch of the "Save to Album" button:
- (IBAction)savePhoto{
CGRect rect;
rect = CGRectMake(11,50 ,305, 262);
UIView *cardViewer = [[UIView alloc] initWithFrame:rect];
UIGraphicsBeginImageContext(cardViewer.bounds.size);
//make view background transparent
cardViewer.backgroundColor = [UIColor colorWithWhite:0.0 alpha:0.0];
cardViewer.opaque = NO;
//stuff items into a subview for capturing
[self.view addSubview:cardViewer];
[cardViewer addSubview:self.tiltedCard];
[cardViewer addSubview:self.bigCardView];
[cardViewer addSubview:self.cardWords];
[cardViewer addSubview:self.photoView];
[cardViewer.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGImageRef imageRef = CGImageCreateWithImageInRect([viewImage CGImage], rect);
UIImage *img = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil);
//put everything back where it belongs
[self.view addSubview:self.tiltedCard];
[self.view addSubview:self.bigCardView];
[self.view addSubview:self.cardWords];
[self.view addSubview:self.photoView];
[cardViewer removeFromSuperview];
}
To capture just an area of the screen, specify the bounds using CGRectMake.
CGRect rect = CGRectMake(50, 50, 100, 100);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.view.layer renderInContext:context];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
In the example above we are capturing a 100px by 100px region beginning at x:50px and y:50px.
maybe get the picture of the layer by rendering the layer context and grabbing the image, I use this for displaying fancy animations
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
To capture just an area of the screen, use the UIView or SubView and just specify the bounds using CGRectMake.
CGRect rect = CGRectMake(10, 10, 200, 200);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.YourView.layer renderInContext:context]; // Make sure here you are using the greetingcardView rather than self.view
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Note: self.view will capture the whole screen so simply render the view wherever.

How to take a screenshot of a part of an app's window?

I'm trying to save a screenshot of a part of the screen with all views and layers merged. The only way I know how to do this is with the code below.
The code below creates an 80x80 square, but with a top left corner at 0,0.
How can I cut a smaller rectangle out of a full page screenshot? For example I have a 320x480 full window screenshot, but I only need an 80x80 square centered at 160,240?
UIGraphicsBeginImageContext(smallView.frame.size);
[appDelegate.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Thank you!
after getting the screenshot image crop the required part using this
CGImageRef imageRef = CGImageCreateWithImageInRect([screenshot CGImage], cropRect);
UIImage *result = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
Untested suggestion...
UIGraphicsBeginImageContext(smallView.frame.size);
[appDelegate.window.layer renderInContext:UIGraphicsGetCurrentContext()];
CGRect cropRect = UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
CGRectMake(160.0,240.0,smallView.frame.size.width,smallView.frame.size.height);
CGImageRef croppedImageRef = CGImageCreateWithImageInRect(screenshot.CGImage,cropRect);
UIImage *croppedScreenshot = [UIImage imageWithCGImage:croppedImageRef];
CGImageRelease(croppedImageRef);
UIGraphicsEndImageContext();

convert rectangular image to square image using objective c

I am working on creating an image gallery which has thumbnails in different sizes. I want to convert these rectangle thumbnails to square size so that all of them could appear similar in size. I dont mind cropping it from extended portion but I am not sure how to do it. can anyone please help me?
Thanks
Pankaj
You need to use the image in rect method passing in the image and the required bounds...
CGImageRef imageRef = CGImageCreateWithImageInRect([anImage CGImage], requiredBounds);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
I have added this to a UIImage category (UIImage+Resize) in the following post, you can download the source code as well - Categories example
Well if you use an UIImageView to display your images (wich I am more than sure that you do) you can set it's contentMode property to UIViewContentModeScaleAspectFill. This should 'crop' your image to the boundaries of your UIImageView. In case your image will go out of the boundaries of the UIImageView make sure clipsToBounds is also set to YES.
Let me know if that helps.
I'm using the next method. The input are the UIImage to scale and the size of the UIImageView's frame where the UIImage is. It works when the frame's height and width are equal.
One important thing: I keep the image's ratio. I don't expand the image to cover the full square. If you want to do it you have to change the 'drawInRect' line for [self drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)]; and remove the if-else.
- (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
CGFloat scaleRatio;
if (image.size.width > image.size.height) {
scaleRatio = image.size.height/image.size.width;
}else{
scaleRatio = image.size.width/image.size.height;
}
CGAffineTransform scaleTransform = CGAffineTransformMakeScale(scaleRatio, scaleRatio);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextConcatCTM(context, scaleTransform);
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0);
if (image.size.width > image.size.height) {
[image drawInRect:CGRectMake(0, (newSize.height/2)-(newSize.height*scaleRatio/2), newSize.width, newSize.height*scaleRatio)];
}else{
[image drawInRect:CGRectMake((newSize.width/2)-(newSize.width*scaleRatio/2), 0, newSize.width*scaleRatio, newSize.height)];
}
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}

Erase a rect of an UIImageView

I want to know, how can I erase a custom rect (with, for example, an UIView in IB or something else) of an UIImageView in order to display an other UIImageView positioned underneath.
I didn't manage to do it using some response in the forum...
This will clear a rect in an image:
- (UIImage *)clearRect:(CGRect)rect inImage:(UIImage *)image {
if (UIGraphicsBeginImageContextWithOptions != NULL)
UIGraphicsBeginImageContextWithOptions([image size], NO, 0.0);
else
UIGraphicsBeginImageContext([image size]);
CGContextRef context = UIGraphicsGetCurrentContext();
[image drawInRect:CGRectMake(0.0, 0.0, [image size].width, [image size].height)];
CGContextClearRect(context, rect);
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}
Just load your image and clear the rects before assigning it to the image view:
UIImage *image = [UIImage imageNamed:#"Image.png"];
UIImage *maskedImage = [self clearRect:CGRectMake(10.0, 10.0, 50.0, 50.0) inImage:image];
[imageView setImage:maskedImage];
probably not the best solution but you can do the other way and take the 4 parts around the rect separately and combine them afterwards without the inner rect. You would repeat this as long as you have rect's to crop out.
You cannot clear the UIImageView itself because this just draws the UIImage. So you have erase the rect in the UIImage. Create a bitmap context, draw the image into it. Erase the part you want to "see through" with CGContextClearRect. When create a new new image from the bitmap context.