I would like to add a background to my taken screenshot, but something went wrong. The return of the image is only the background without the screenshot. HereĀ“s my code, can you fix it please?
- (UIImage *)screenshot
{
UIImage *backgroundImage = [UIImage imageNamed:#"iphoneframe.png"];
UIGraphicsBeginImageContext(backgroundImage.size);
[backgroundImage drawInRect:CGRectMake(0, 0, backgroundImage.size.width, backgroundImage.size.height)];
UIGraphicsBeginImageContext(self.view.frame.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIGraphicsEndImageContext();
[screenshot drawInRect:CGRectMake(backgroundImage.size.width - screenshot.size.width, backgroundImage.size.height - screenshot.size.height, screenshot.size.width, screenshot.size.height)];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
return image;
}
Background/Frame I want to put around the screenshot: http://oi45.tinypic.com/2qvv2tv.jpg
Prototype Image, which should be returned: http://i.stack.imgur.com/hg1nW.png
Update: The problem was solved with the tips from #panayot-panayotov and #jrturton - the idea was to remove second UIGraphicsBeginImageContext & place UIGraphicsEndImage Context(); above return Image;, but now the picture is like this: pbs.twimg.com/media/BnlkN9wIAAEG-ue.jpg:large - how can we fix this? Any ideas?
You're creating two image contexts, and drawing a different image in each one. Don't create the second context (UIGraphicsBeginImageContext...), and move the end context call until after you've taken out the final image, and you should be fine.
It's also worth noting that you should use the newer 'with options' version when making an image context - this will allow you to draw properly on retina devices.
Related
I'm trying in my app to take a screenshot of the current screen contents, where my TilingView (based on CATiledLayers) displays a number of transparent large tiled images.
Also I added some subViews to the TilingView, which are magically captured in the screenshot, however the underlying contents of the TilingView is not captured!??
The following code-snippets takes a snapshot of the visible screen, which seems to work well for a NON CATiledLayer based view-hierarchy, but unfortunately doesn't work for my setup. Even if I pass the topmost superview of the TilingView (being the actual UIViewController.view), I see only in my snapshot the StatusBar, NavigationBar, the TilingViews subViews and the TabBar, but again NOT the TilingViews contents.
- (UIImage*)captureView:(UIView *)viewToCapture {
CGRect rect = [[UIScreen mainScreen] bounds];
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[viewToCapture.layer renderInContext:context];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Does anybody know or see here what I'm missing? Do I need to delve deeper into the CG-related display stack with some, for me, unknown CG-API calls? Thanks in advance.
By searching some more in StackOverflow I've found code which seems to do what I wanted. Basically I need to change the above method into:
- (UIImage*)captureView:(UIView*)viewToCapture {
UIGraphicsBeginImageContextWithOptions(viewToCapture.bounds.size, NO, [UIScreen mainScreen].scale);
[viewToCapture drawViewHierarchyInRect:viewToCapture.bounds afterScreenUpdates:YES];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Thanks go to the question/answer at: How to get a screenshot of a view containing GPUImageView?
The images that goes through here are PNGs of different shapes with a transparent background. In addition to merging them (which works fine), I'd like to give the new image a couple of pixels thick outline. But I can't seem to manage that.
(So just to clarify, I'm after an outline around the actual shapes in the context, not a rectangle around the entire image.)
+ (UIImage *)mergeBackgroundImage:(UIImage *)backgroundImage withOverlayingImage:(UIImage *)overlayImage{
UIGraphicsBeginImageContextWithOptions(backgroundImage.size, NO, backgroundImage.scale);
[backgroundImage drawInRect:CGRectMake(0, 0, backgroundImage.size.width, backgroundImage.size.height)];
[overlayImage drawInRect:CGRectMake(backgroundImage.size.width - overlayImage.size.width, backgroundImage.size.height - overlayImage.size.height, overlayImage.size.width, overlayImage.size.height)];
//Add stroke.
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}
Thanks for your time!
Markus
If you make a CALayer who's backing is set to a CGImage of your image, you can then use it as a masking layer for your layer that requires an outline1. And once you've done that, you can render your layer into another context, and then get another UIImage from that.
// edit: Something like what's describe in this answer.
I have been trying to do this since forever. I have a camera overlay. I want to get my final image to be the part of the image viewable from the in-built camera.
What I did was make CGRect with dimensions equal to the square in the camera. Then I tried cropping it using this function.
- (UIImage *)imageByCropping:(UIImage *)imageToCrop toRect:(CGRect)rect
{
CGImageRef imageRef = CGImageCreateWithImageInRect([imageToCrop CGImage], rect);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return croppedImage;
}
I called it like this
CGRect rect = CGRectMake(10, 72, 300, 300);
UIImage *realImage = [self imageByCropping:[self.capturedImages objectAtIndex:0] toRect:rect];
What I get is a bad quality image with the wrong orientation.
::EDIT::
With Nitin's answer I can crop the correct part of the screen but the problem is it crops the view that follows the camera view, 'the confirmation view'. I suspect this is because Nitin's code uses
UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
and because the ViewController in which all this is happening because the View Controller for the Confirmation View is the Controller in which this code is being executed. I will try to explain this with a small map
CameraOverlay.xib(it uses this xib to create an overlay) <===== CameraOverlayViewController ---------> ConfirmationView
So when first the ViewController is evoked(button on Tab bar), it opens the camera(UIImagePickerController) with an overlay over it. Then once user clicks an image, the image is shown on the ConfirmationView.
What I think is happening is when
UIGraphicsBeginImageContextWithOptions(self.view.frame.size, YES, 1.0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
these lines are being executed, the View at that time is ConfirmationView.
Note: I call the function in
(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info method.
Refer Drawing and printing Guide.
The default coordinate system is different between CoreGraphics and UIKit. I think your issue is because of this fact.
Using these may help you solve the issue
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context , 0.0, rect.size.height);
CGContextScaleCTM(context , 1.0, -1.0);
I have an image that I would like to use as the background for a UIToolBar in an iOS 5+ app. The background image changes according to actions taken on the view. The image is larger than the UIToolBar, so the image needs to be resized as a reduction rather than increasing the size.
After review of the other questions on here, as well as other research into the issue, the resolution recommended does not work. The recommendation is as follows:
UIImage *topimg = [[UIImage imageNamed:#"headerBar-Human.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
[_headerBar setBackgroundImage:topimg forToolbarPosition:UIToolbarPositionTop barMetrics:UIBarMetricsDefault];
I have tried with different values in the UIEdgeInsetsMake call with no luck. The problem is that the image is not shown at all. The default blue toolbar background is shown.
If I remove the resizableImageWithCapInsets function the image will show, but only the portion of the image covered by the toolbar rect coordinates.
I have also tried creating a UIImageView, adding the image and adding it to the toolbar, but the results are the same.
Does anyone have any suggestions?
You can use this function to resize your backgroundImage :
- (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize
{
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
I suggest to call this function with your _headerBar.frame.size as second parameter.
I would like to take an image and duplicate it. Then increase it by 105% and overlay it on the original image.
What is the correct way to do this on iOS?
This is your basic code for drawing the image and then saving it as an image again:
- (UIImage *)renderImage:(UIImage *)image atSize:(CGSize)size
{
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0.0, 0.0, size.width, size.height)];
// draw anything else into the context
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Where it says "draw anything else into the context" you can draw the image at a reduced size by setting the appropriate rect to draw in. Then, call the renderImage method with whatever size you want the full image to be. You can use CGContextSetAlpha to set the transparency.