This question already has answers here:
Take screenshot of the window
(2 answers)
Closed 9 years ago.
I obtained this code from the apple documentation...
+ (UIImage *)screenshot {
CGSize imageSize = [[UIScreen mainScreen] bounds].size;
if (NULL != UIGraphicsBeginImageContextWithOptions) {
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
} else {
UIGraphicsBeginImageContext(imageSize);
}
CGContextRef context = UIGraphicsGetCurrentContext();
for (UIWindow *window in [[UIApplication sharedApplication] windows]) {
if (![window respondsToSelector:#selector(screen)] || [window screen] == [UIScreen mainScreen]) {
CGContextSaveGState(context);
CGContextTranslateCTM(context, [window center].x, [window center].y);
CGContextConcatCTM(context, [window transform]);
CGContextTranslateCTM(context,
-[window bounds].size.width * [[window layer] anchorPoint].x,
-[window bounds].size.height * [[window layer] anchorPoint].y);
[[window layer] renderInContext:context];
CGContextRestoreGState(context);
}
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
However, I have one small issue with it. I want to include the status bar in my screenshot. How do I do this? Or is there a better method to do this with?
-Henry
Here is the way I ended up doing this...
+ (UIImage *)screenshot {
CGImageRef screen = UIGetScreenImage();
UIImage *image = [UIImage imageWithCGImage:screen];
CGImageRelease(screen);
return image;
}
Although it is not App Store approvable it is the best way to do it.
Related
I have one imageview which is changing on every few seconds with curl animation. I want to take the video of that so for that what I am doing is, I take the screenshots every seconds and create video from that.
But I am unable to take the screenshot when image is animating, at that time it will return the screenshot in which image is stable or not animating.
I am using below code to take screenshot of image
{
CGSize imageSize = [[UIScreen mainScreen] bounds].size;
if (NULL != UIGraphicsBeginImageContextWithOptions)
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
else
UIGraphicsBeginImageContext(imageSize);
CGContextRef context = UIGraphicsGetCurrentContext();
// Iterate over every window from back to front
for (UIWindow *window in [[UIApplication sharedApplication] windows])
{
if (![window respondsToSelector:#selector(screen)] || [window screen] == [UIScreen mainScreen])
{
// -renderInContext: renders in the coordinate space of the layer,
// so we must first apply the layer's geometry to the graphics context
CGContextSaveGState(context);
// Center the context around the window's anchor point
CGContextTranslateCTM(context, [window center].x, [window center].y);
// Apply the window's transform about the anchor point
CGContextConcatCTM(context, [window transform]);
// Offset by the portion of the bounds left of and above the anchor point
CGContextTranslateCTM(context,
-[window bounds].size.width * [[window layer] anchorPoint].x,
-[window bounds].size.height * [[window layer] anchorPoint].y);
// Render the layer hierarchy to the current context
[[[window layer] presentationLayer] renderInContext:context];
// Restore the context
CGContextRestoreGState(context);
}
}
// Retrieve the screenshot image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Does any one have idea about it?
Thanks in advance.
-Austin
I think you should be using:
[[[[window contentView] layer] presentationLayer] renderInContext:context];
in order to capture the current state of the animation, not the origin or destination states
According to your code, you seem to snapshot the screen.
So just try this:
[[UIScreen mainScreen] snapshotViewAfterScreenUpdates:NO]
Otherwise:
[yourAnimatedView.layer.presentationLayer snapshotViewAfterScreenUpdates:NO]
I'm trying to create a screenshot tweak for iOS 7 but all i am able to save is a blank image.
This is my code:
UIView *screenshotView = [[UIScreen mainScreen] snapshotViewAfterScreenUpdates:NO];
UIGraphicsBeginImageContext(screenshotView.bounds.size);
[[screenshotView layer] renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[UIImageJPEGRepresentation(image, 1.0) writeToFile:fname atomically:YES];
Does anyone have a solution?
thank you
It appears you should not use snapshotViewAfterScreenUpdates to render images (see raywenderlich forum) but drawViewHierarchyInRect instead:
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, 0.0f);
[self.view drawViewHierarchyInRect:self.view.frame afterScreenUpdates:NO];
UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
for compatibility reason i still haven't used snapshotViewAfterScreenUpdates but the following code works. give it a try.
UIGraphicsBeginImageContextWithOptions(size, myView.opaque, 2.0);
[myView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// do something with theImage
Set the output on a UIImageView
- (UIImage *)screenshot
{
CGSize imageSize = CGSizeZero;
UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
if (UIInterfaceOrientationIsPortrait(orientation)) {
imageSize = [UIScreen mainScreen].bounds.size;
} else {
imageSize = CGSizeMake([UIScreen mainScreen].bounds.size.height, [UIScreen mainScreen].bounds.size.width);
}
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();
for (UIWindow *window in [[UIApplication sharedApplication] windows]) {
CGContextSaveGState(context);
CGContextTranslateCTM(context, window.center.x, window.center.y);
CGContextConcatCTM(context, window.transform);
CGContextTranslateCTM(context, -window.bounds.size.width * window.layer.anchorPoint.x, -window.bounds.size.height * window.layer.anchorPoint.y);
if (orientation == UIInterfaceOrientationLandscapeLeft) {
CGContextRotateCTM(context, M_PI_2);
CGContextTranslateCTM(context, 0, -imageSize.width);
} else if (orientation == UIInterfaceOrientationLandscapeRight) {
CGContextRotateCTM(context, -M_PI_2);
CGContextTranslateCTM(context, -imageSize.height, 0);
} else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {
CGContextRotateCTM(context, M_PI);
CGContextTranslateCTM(context, -imageSize.width, -imageSize.height);
}
if ([window respondsToSelector:#selector(drawViewHierarchyInRect:afterScreenUpdates:)]) {
[window drawViewHierarchyInRect:window.bounds afterScreenUpdates:YES];
} else {
[window.layer renderInContext:context];
}
CGContextRestoreGState(context);
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
I have been testing how to post screenshot images to Facebook. All the images I've taken have a little blur. How can I remove the blur in the screenshots? Below is the method that takes the image.
-(UIImage*)takeASnapshot
{
UIView *glView = [[CCDirector sharedDirector] view];
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)])
UIGraphicsBeginImageContextWithOptions(glView.bounds.size, NO, [UIScreen mainScreen].scale);
else
UIGraphicsBeginImageContext(glView.bounds.size);
[glView drawViewHierarchyInRect:glView.bounds afterScreenUpdates:YES];
UIImage *screenShot ;
screenShot = UIGraphicsGetImageFromCurrentImageContext();
NSData *imageData = UIImageJPEGRepresentation(screenShot, 0.60);
screenShot = [UIImage imageWithData:imageData];
UIGraphicsEndImageContext();
return screenShot;
}
Try this.
- (UIImage*)screenshot
{
// Create a graphics context with the target size
// On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration
// On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
CGSize imageSize = [[UIScreen mainScreen] bounds].size;
if (NULL != UIGraphicsBeginImageContextWithOptions)
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
else
UIGraphicsBeginImageContext(imageSize);
CGContextRef context = UIGraphicsGetCurrentContext();
// Iterate over every window from back to front
for (UIWindow *window in [[UIApplication sharedApplication] windows])
{
if (![window respondsToSelector:#selector(screen)] || [window screen] == [UIScreen mainScreen])
{
// -renderInContext: renders in the coordinate space of the layer,
// so we must first apply the layer's geometry to the graphics context
CGContextSaveGState(context);
// Center the context around the window's anchor point
CGContextTranslateCTM(context, [window center].x, [window center].y);
// Apply the window's transform about the anchor point
CGContextConcatCTM(context, [window transform]);
// Offset by the portion of the bounds left of and above the anchor point
CGContextTranslateCTM(context,
-[window bounds].size.width * [[window layer] anchorPoint].x,
-[window bounds].size.height * [[window layer] anchorPoint].y);
// Render the layer hierarchy to the current context
[[window layer] renderInContext:context];
// Restore the context
CGContextRestoreGState(context);
}
}
// Retrieve the screenshot image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
When I take a screen shot programmatically with the code below it leaves a white strip where the status bar is supposed to be. I know you cannot capture the status bar but I just want the white blank strip cropped out.
- (UIImage*)captureView:(UIView *)view
{
CALayer *layer = [[UIApplication sharedApplication] keyWindow].layer;
CGFloat scale = [UIScreen mainScreen].scale;
UIGraphicsBeginImageContextWithOptions(layer.frame.size, NO, scale);
[layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
I duplicate my answer from another question https://stackoverflow.com/a/16067463/837244, it should solve your problems :
I had written this below small class previously. You can make use of it. The latter function gets screenshot of whole screen (and it is obtained from apple's guide, so it is definitely safe). And the first part which I've added, handles different scales (retina or regular). May it help.
#import "ScreenshotTaker.h"
#import <QuartzCore/QuartzCore.h>
#implementation ScreenshotTaker
+(UIImage *) captureRectOfScreen:(CGRect) rect
{
UIImage *wholeScreen = [ScreenshotTaker screenshot];
//Add status bar height
rect.origin.y += UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation) ? [[UIApplication sharedApplication] statusBarFrame].size.width : [[UIApplication sharedApplication] statusBarFrame].size.height;
//NSLog(#"%#",NSStringFromCGSize([wholeScreen size]));
CGFloat scale = wholeScreen.scale;
rect.origin.x *= scale;
rect.origin.y *= scale;
rect.size.width *= scale;
rect.size.height *= scale;
UIImage *cropped = [UIImage imageWithCGImage:CGImageCreateWithImageInRect([wholeScreen CGImage], rect) scale:wholeScreen.scale orientation:wholeScreen.imageOrientation];
//NSLog(#"Whole Screen Capt :%# Scale: %f",NSStringFromCGSize([wholeScreen size]), wholeScreen.scale);
//NSLog(#"Rect to Crop :%# Cropped :%#",NSStringFromCGRect(rect), NSStringFromCGSize([cropped size]));
return cropped;
}
+(UIImage *) screenshot
{
// Create a graphics context with the target size
// On iOS 4 and later, use UIGraphicsBeginImageContextWithOptions to take the scale into consideration
// On iOS prior to 4, fall back to use UIGraphicsBeginImageContext
CGSize imageSize = [[UIScreen mainScreen] bounds].size;
if (NULL != UIGraphicsBeginImageContextWithOptions)
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
else
UIGraphicsBeginImageContext(imageSize);
CGContextRef context = UIGraphicsGetCurrentContext();
// Iterate over every window from back to front
for (UIWindow *window in [[UIApplication sharedApplication] windows])
{
if (![window respondsToSelector:#selector(screen)] || [window screen] == [UIScreen mainScreen])
{
// -renderInContext: renders in the coordinate space of the layer,
// so we must first apply the layer's geometry to the graphics context
CGContextSaveGState(context);
// Center the context around the window's anchor point
CGContextTranslateCTM(context, [window center].x, [window center].y);
// Apply the window's transform about the anchor point
CGContextConcatCTM(context, [window transform]);
// Offset by the portion of the bounds left of and above the anchor point
CGContextTranslateCTM(context,
-[window bounds].size.width * [[window layer] anchorPoint].x,
-[window bounds].size.height * [[window layer] anchorPoint].y);
// Render the layer hierarchy to the current context
[[window layer] renderInContext:context];
// Restore the context
CGContextRestoreGState(context);
}
}
// Retrieve the screenshot image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
#end
I tried below steps to capture screenshot but got black backround for MPMoviePlayerController
-(UIImage*)screenshot
{
CGSize imageSize = [[UIScreen mainScreen] bounds].size;
CGFloat imageScale = imageSize.width / FRAME_WIDTH;
if (NULL != UIGraphicsBeginImageContextWithOptions)
UIGraphicsBeginImageContextWithOptions(imageSize, NO, imageScale);
else
UIGraphicsBeginImageContext(imageSize);
CGContextRef context = UIGraphicsGetCurrentContext();
for (UIWindow *window in [[UIApplication sharedApplication] windows])
{
if (![window respondsToSelector:#selector(screen)] || [window screen] == [UIScreen mainScreen])
{
CGContextSaveGState(context);
CGContextTranslateCTM(context, [window center].x, [window center].y);
CGContextConcatCTM(context, [window transform]);
CGContextTranslateCTM(context,
-[window bounds].size.width * [[window layer] anchorPoint].x,
-[window bounds].size.height * [[window layer] anchorPoint].y);
[[window layer] renderInContext:context];
CGContextRestoreGState(context);
}
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
get image from MPMoviePlayerController like this on action of button:
-(void)getScreenShotOfMPMoviePlayerController:(MPMoviePlayerController *)mpPlayer
{
UIImage *thumbnail = [mpPlayer thumbnailImageAtTime:yourMoviePlayerObject.currentPlaybackTime
timeOption:MPMovieTimeOptionNearestKeyFrame];
}
EDIT : Merge both images as one image taken from MPMoviePlayerController with the ScreenShot taken from UIWindow.
Refer ios-merging-two-images-of-different-size link for merging.