Render a UIView to a UIImage larger than it is on screen - ios

I would like to render a UIView into a UIImage. However, I would like to render it much larger than it is on screen, without pixilation.
At present I am using...
UIGraphicsBeginImageContextWithOptions(size, YES, 0.0);
[self.pageViewController.view.layer renderInContext:context];
renderedViewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
I have tried...
self.pageViewController.view.transform = CGAffineTransformMakeScale(4.0f, 4.0f);
This changes the size of the view but the original size is rendered before the view is scaled.
I have also tried...
CGContextScaleCTM(UIGraphicsGetCurrentContext(), 4.0, 4.0);
but this just scales up the low resolution image giving a poor quality result.
Setting the...
UIView contentScaleFactor
hasn't helped me render the UIView any larger either.

Try This you will get 2x size image of view if device supports retina
- (UIImage *)imageOfView:(UIView *)view
{
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)]) {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0.0);
} else {
UIGraphicsBeginImageContext(view.bounds.size);
}
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}

Related

Scale up UIView with UIImage without affecting resolution of UIImage

My problem is when I'm scaling up my UIView's background image it gets anti-aligning and very blurry although the original image is in high resolution and very bright.
The process of scaling happens when I make an animation on the UIView to scale it. I'm scaling UIView using the transform property of UIView.
The code I'm using to make the UIImage fit into new scale is:
-(UIImage *)imageResize :(UIImage*)image withSize:(CGSize)size
{
CGSize newSize = self.bounds.size;
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
And I'm assigning the background color with this line:
self.backgroundColor = [UIColor colorWithPatternImage:[self imageResize:img withSize:(CGSize)size]];
I guess you should try to apply screen resolution in this line:
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
Should look like this
CGFloat screenScale = [[UIScreen mainScreen] scale];
UIGraphicsBeginImageContextWithOptions(newSize, NO, screenScale);

Taking screenshot of UIView which having subview with CATransform3DMakeRotation

I am trying to generate screenshot of UIView which having subview with CATransform3DMakeRotation. Screenshot is generated but it doesn't contain Rotation.
Is it possible to achieve this?
Actual View:
ScreenShot Image
Using following call to Flip the view horizontally...
currentView.layer.transform = CATransform3DConcat(currentView.layer.transform,CATransform3DMakeRotation(M_PI, 0.0, 1.0, 0.0f));
Code for taking screen shot
+ (UIImage *) imageWithView:(UIView *)view
{
CGSize screenDimensions = view.bounds.size;
// Create a graphics context with the target size
// (last parameter takes scale into account)
UIGraphicsBeginImageContextWithOptions(screenDimensions, NO, 0);
// Render the view to a new context
CGContextRef context = UIGraphicsGetCurrentContext();
[view.layer renderInContext:context];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
The "renderInContext" only works for Affine transform. So convert the 3D transform into affine transform like this
currentView.layer.affineTransform = CATransform3DGetAffineTransform(CATransform3DConcat(currentView.layer.transform,CATransform3DMakeRotation(M_PI, 0.0, 1.0, 0.0f)));
Try this code
CGSize newSize = CGSizeMake(yourview.frame.size.width , yourview.frame.size.height);
UIGraphicsBeginImageContextWithOptions(newSize,YES,2.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
[yourview.layer renderInContext:context];
[yourview drawRect:yourview.frame];
UIImage *screenShot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
This might work, try it:
CGRect grabRect = CGRectMake(40,40,300,200);
//for retina displays
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)]) {
UIGraphicsBeginImageContextWithOptions(grabRect.size, NO, [UIScreen mainScreen].scale);
} else {
UIGraphicsBeginImageContext(grabRect.size);
}
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(ctx, -grabRect.origin.x, -grabRect.origin.y);
[self.view.layer renderInContext:ctx];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(viewImage, nil, nil, nil);
i have achieved this in one of my application by doing a little tweak like first i capture the whole screen's screen shot and then crop it with the desired frame i need here is a sample code from my app.
- (UIImage *) croppedPhoto
{
[imgcropRectangle setHidden:TRUE];
UIGraphicsBeginImageContext(self.view.frame.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Create bitmap image from original image data,
// using rectangle to specify desired crop area
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], self.imgcropRectangle.frame);
UIImage *result = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
[imgcropRectangle setHidden:FALSE];
return result;
}
here imgcropRectangle is the UIImageView's object that defines my desired rectangle so i use it's frame for cropping from full screen to desired output. Hope it will help you :)
Try rendering view.layer.presentationLayer instead of view.layer
use this and before passing the view check its subviews :
+ (UIImage *) imageWithView:(UIView *)view
{
UIGraphicsBeginImageContext(CGSizeMake(view.frame.size.width, view.frame.size.height));
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return viewImage
}

Render UIView to image without subviews

I want to convert a UIView to a UIImage
- (UIImage *)renderToImage:(UIView *)view {
if(UIGraphicsBeginImageContextWithOptions != NULL) {
UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, 0.0);
} else {
UIGraphicsBeginImageContext(view.frame.size);
}
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Two questions:
I have subviews on my view. Is there a way to create an image of the view without any of the subviews? Ideally id like to not have to remove them just to add them back later.
Also, it isn't rendering the images properly on retina devices. I followed the advice here to use context with options but it did not help. How to capture UIView to UIImage without loss of quality on retina display
You have to hide the subviews that you not want to be in the image of view. Below is the Method that render image of view for retina devices too.
- (UIImage *)imageOfView:(UIView *)view
{
// This if-else clause used to check whether the device support retina display or not so that
// we can render image for both retina and non retina devices.
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)])
{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
} else {
UIGraphicsBeginImageContext(view.bounds.size);
}
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
- (CGImageRef)toImageRef
{
int width = self.frame.size.width;
int height = self.frame.size.height;
CGContextRef ref = CGBitmapContextCreate(NULL, width, height, 8, width*4, CGColorSpaceCreateDeviceRGB(), kCGImageAlphaNoneSkipLast);
[self drawRect:CGRectMake(0.0, 0.0, width, height) withContext:ref];
CGImageRef result = CGBitmapContextCreateImage(ref);
CGContextRelease(ref);
return result;
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
// move your drawing commands from here...
[self drawRect:rect withContext:context];
}
- (void)drawRect:(CGRect)rect withContext:(CGContextRef)context
{
// ...to here
}

Snapshot of UIView gets blurry. Need solution

I need to capture a view and then I have to crop some portion of that view.
I am using captureView to capture and cropView to crop portion. This is my original image and This is my output image. I want clear Image. I tried to make scale as 0.0f but it didn't work. Any suggestion acceptatble.
- (UIImage *)captureView:(UIView *)view {
CGRect rect = [view bounds];
UIGraphicsBeginImageContextWithOptions(rect.size,NO,2.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
[view.layer renderInContext:context];
UIImage *capturedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return capturedImage;
}
- (UIImage *) cropView:(UIImage *)originalImage frame:(CGRect)frame{
CGImageRef imageRef = CGImageCreateWithImageInRect([originalImage CGImage], frame);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return croppedImage;
}
How did you check the resulting image? Did you save it as a JPG with quality loss? Try using PNG representatiion for lossless results
Also, change the scale constant 2.0f to [[UIScreen mainscreen] scale] to be device independent.

Interpolation issue after renderInContext:UIGraphicsGetCurrentContext(), iOS

I have a few UIVies butted edge to edge. THe views completely cover the superView. Looks great in display, but when rendered the adjoining edges are visible, that is to sat a line appears between them. Since the views look perfect in display, I imagine it must be interpolation of the pixels of the views that causes this.
Anyone know how to fix this?
The image below is a render. On the device or simulator the lines would not be visible.
render code
-(void)renderImage {
CGSize renderSize = CGSizeMake(masterView.frame.size.width, masterView.frame.size.height);
UIGraphicsBeginImageContext(renderSize);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextConcatCTM(context, [[masterView layer] affineTransform]);
[[masterView layer] renderInContext:UIGraphicsGetCurrentContext()];
renderedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
CGContextRestoreGState(context);
UIImageWriteToSavedPhotosAlbum(renderedImage, self, #selector(image:didFinishSavingWithError:contextInfo:), nil);
masterView.transform = CGAffineTransformIdentity;
}
Core graphics attempts to anti alias your views. You need to tell it not to do that.
Consider the following example which renders self, a UIView, as a UIImage without anti aliasing:
UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, [[UIScreen mainScreen] scale]);
CGContextSetAllowsAntialiasing(UIGraphicsGetCurrentContext(), FALSE);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
try:
UIGraphicsBeginImageContextWithOptions(renderSize, false, [[UIScreen mainScreen] scale]);
instead of:
UIGraphicsBeginImageContext(renderSize);

Resources