Taking Screenshot of UIView using UIButton - objective-c

I am trying to make an app with a button that will take a screenshot of the object drawn on the device's screen and save it on the device's photo gallery...
How will i able to do that? any idea?

UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *screenShotimage = UIGraphicsGetImageFromCurrentImageContext();
UIImageWriteToSavedPhotosAlbum(screenShotimage, nil, nil, nil);
UIGraphicsEndImageContext();
This code will take screen shot of your screen and will save the image in photo gallery

Apple describes a way to do it here : http://developer.apple.com/library/ios/#qa/qa1703/_index.html
- (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;
}
And remember #import <QuartzCore/QuartzCore.h>

Related

Draw lines in UIView not supported for multiple screen sizes?

I want to draw lines in a UIView with based the UIView's height. (i.e) line height should be equal to the UIView's height. For that i'm using the following code.
- (void)testDraw :(void(^)(UIImage *image, UIImage *selectedImage))done
{
CGSize imageSize = CGSizeMake(1000, self.bounds.size.height);
//Begin the animation by checking the screen is retina / ordinary
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)])
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0f);
else
UIGraphicsBeginImageContext(imageSize);
CGContextRef context = UIGraphicsGetCurrentContext();
for (NSInteger intSample=0; intSample < 1000; intSample++) {
if(intSample % self.samplesPerSecond == 0){
//draw separator line
[self drawLine:context fromPoint:CGPointMake(intSample, 0) toPoint:CGPointMake(intSample, self.frame.size.height) color:self.lineColor lineWidth:2.0];
}
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
CGRect drawRect = CGRectMake(0, 0, image.size.width, self.frame.size.height);
[self.progressColor set];
UIRectFillUsingBlendMode(drawRect, kCGBlendModeSourceAtop);
UIImage *tintedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
done(image, tintedImage);
}
//Draw the line based on the value received
- (void) drawLine:(CGContextRef) context fromPoint:(CGPoint) fromPoint toPoint:(CGPoint) toPoint color:(UIColor*) color lineWidth:(float) lineWidth{
CGContextBeginPath(context);
//add the lines with sizes that u want
CGContextSetAlpha(context,1.0);
CGContextSetLineWidth(context, lineWidth);
CGContextSetStrokeColorWithColor(context, [color CGColor]);
CGContextMoveToPoint(context, fromPoint.x, fromPoint.y);
CGContextAddLineToPoint(context, toPoint.x, toPoint.y);
CGContextStrokePath(context);
}
When i execute the above code with it working fine in 3.5 inch display, It's working fine. But when i run the same code in 4-inch the line height is not increasing based on the UIView. The lines are not working as like auto layouts.
Thanks in advance, Can anyone give your suggestion to fix this issue.

UIGraphicsGetImageFromCurrentImageContext in ios7

I want to make screen capture and I use UIGraphicsBeginImageContextWithOptions. But on ios 7 there are some strange lines where the view's finished. The image is not sharpe. On ios 6 is fine with this code.
This is the code i use for that:
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();

Image appearing pixelerated

This is what I am trying to do
Create a UIImage View.
Do some drawing on it
Press a share button to share the image with the drawings on it.
My code works perfect on iPad and iPhone. Problem comes with retina display. So my guess is some scale is not handled correctly, but not sure what I am doing wrong. This is my code
// Create the UIImageView named centerCanvas
// Do the drawing
CGPoint origin = centerCanvas.frame.origin;
CGSize size = centerCanvas.frame.size;
CGSize screenSize = [self returnScreenSize];
CGRect rect = CGRectMake(origin.x, origin.y, size.width, size.height);
UIGraphicsBeginImageContext(screenSize);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.view.layer renderInContext:context];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGImageRef imageRef = CGImageCreateWithImageInRect([img CGImage], rect);
[shareView setImage:[UIImage imageWithCGImage:imageRef]];
-(CGSize) returnScreenSize
{
CGRect screenBounds = [[UIScreen mainScreen] bounds];
CGFloat screenScale = [[UIScreen mainScreen] scale];
CGSize screenSize = CGSizeMake(screenBounds.size.width * screenScale,screenBounds.size.height * screenScale);
return screenSize;
}
Try using
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
instead of the old UIGraphicsBeginImageContext, which uses a scale factor (third argument above) equal to 1. By giving 0.0 as a scale factor you get a scale factor for your current screen. Have a look at the reference.

How to darken a PNG?

I may point out that Drawing and Rendering in Objective-C is my weakness. Now, here's my problem.
I want to add a 'Day/Night' feature to my game. It has got lots of objects on a map. Every object is a UIView containing some data in variables and some UIImageViews: the sprite, and some of the objects have a hidden ring (used to show selection).
I want to be able to darken the content of the UIView, but I can't figure out how. The sprite is a PNG with transparency. I've just managed to add a black rectangle behind the sprite using this:
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
CGContextSetRGBFillColor(ctx, 0, 0, 0, 0.5);
CGContextFillRect(ctx, rect);
CGContextRestoreGState(ctx);
As I've read, this should be done in the drawRect method. Help please!
If you want to understand better my scenario, the App where I'm trying to do this is called 'Kipos', at the App Store.
Floris497's approach is a good strategy for a blanket darkening for more than one image at a time (probably more what you're after in this case). But here's a general purpose method to generate darker UIImages (while respecting alpha pixels):
+ (UIImage *)darkenImage:(UIImage *)image toLevel:(CGFloat)level
{
// Create a temporary view to act as a darkening layer
CGRect frame = CGRectMake(0.0, 0.0, image.size.width, image.size.height);
UIView *tempView = [[UIView alloc] initWithFrame:frame];
tempView.backgroundColor = [UIColor blackColor];
tempView.alpha = level;
// Draw the image into a new graphics context
UIGraphicsBeginImageContext(frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[image drawInRect:frame];
// Flip the context vertically so we can draw the dark layer via a mask that
// aligns with the image's alpha pixels (Quartz uses flipped coordinates)
CGContextTranslateCTM(context, 0, frame.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
CGContextClipToMask(context, frame, image.CGImage);
[tempView.layer renderInContext:context];
// Produce a new image from this context
CGImageRef imageRef = CGBitmapContextCreateImage(context);
UIImage *toReturn = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
UIGraphicsEndImageContext();
[tempView release];
return toReturn;
}
The best way would be to add a core image filter to the layer that darkened it. You could use CIExposureAdjust.
CIFilter *filter = [CIFilter filterWithName:#"CIExposureAdjust"];
[filter setDefaults];
[filter setValue:[NSNumber numberWithFloat:-2.0] forKey:#"inputEV"];
view.layer.filters = [NSArray arrayWithObject:filter];
Here is how to do it:
// inputEV controlls the exposure, the lower the darker (e.g "-1" -> dark)
-(UIImage*)adjustImage:(UIImage*)image exposure:(float)inputEV
{
CIImage *inputImage = [[CIImage alloc] initWithCGImage:[image CGImage]];
UIImageOrientation originalOrientation = image.imageOrientation;
CIFilter* adjustmentFilter = [CIFilter filterWithName:#"CIExposureAdjust"];
[adjustmentFilter setDefaults];
[adjustmentFilter setValue:inputImage forKey:#"inputImage"];
[adjustmentFilter setValue:[NSNumber numberWithFloat:-1.0] forKey:#"inputEV"];
CIImage *outputImage = [adjustmentFilter valueForKey:#"outputImage"];
CIContext* context = [CIContext contextWithOptions:nil];
CGImageRef imgRef = [context createCGImage:outputImage fromRect:outputImage.extent] ;
UIImage* img = [[UIImage alloc] initWithCGImage:imgRef scale:1.0 orientation:originalOrientation];
CGImageRelease(imgRef);
return img;
}
Remember to import:
#import <QuartzCore/Quartzcore.h>
And add CoreGraphics and CoreImage frameworks to your project.
Tested on iPhone 3GS with iOS 5.1
CIFilter is available starting from iOS 5.0.
draw a UIView (a black one) over it and set "User interaction enabled" to NO
hope you can do something with this.
then use this to make it dark
[UIView animateWithDuration:2
animations:^{nightView.alpha = 0.4;}
completion:^(BOOL finished){ NSLog(#"done making it dark"); ]; }];
to make it light
[UIView animateWithDuration:2
animations:^{nightView.alpha = 0.0;}
completion:^(BOOL finished){ NSLog(#"done making it light again"); ]; }];

iPhone screen capture for a view

On iphone, is it possible to "screen capture" an UIView and all its subview? If it is possible, how?
I found this, but I haven't tried it myself.
Here you find the used -renderInContext.
I transformed the code above to a category on UIView.
call it like this: [aView saveScreenshotToPhotosAlbum];
#import <QuartzCore/QuartzCore.h>
- (UIImage*)captureView {
CGRect rect = [[UIScreen mainScreen] bounds];
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.layer renderInContext:context];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
- (void)saveScreenshotToPhotosAlbum {
UIImageWriteToSavedPhotosAlbum([self captureView], nil, nil, nil);
}