Interpolation issue after renderInContext:UIGraphicsGetCurrentContext(), iOS - 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);

Related

drawViewHierarchyInRect not working

I have a map view, which can display a SVG map.
I used to use renderInContext to get the UIImage, however its performance is not ideal and I heard iOS 7 has new APIs to do such things, which is drawViewHierarchyInRect
Now I want to turn this map view into UIImage or a screenshot as UIView by drawViewHierarchyInRect
However,
If I use drawViewHierarchyInRect, no valid UIImage I can get neither, I suspect they are the same reason
The code for snapshotView,
PS: for performance, I don't add _mapView into any views
-(void)drawRect:(CGRect)rect {
UIGraphicsBeginImageContextWithOptions(_mapView.bounds.size, _mapView.opaque, [[UIScreen mainScreen] scale]);
CGContextRef context = UIGraphicsGetCurrentContext();
// [mapView.layer renderInContext:context];
[_mapView drawViewHierarchyInRect:_mapView.bounds afterScreenUpdates:YES];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.thumbImageView = [[UIImageView alloc] initWithImage:image];
[self addSubview:self.thumbImageView];
}

UINavigationBar appears gray in screenshot

I am taking a screenshot of my app's current view using the code below. I have a UIViewController embedded inside a UINavigationController. The method is being called in the UIViewController.
In the screenshot, the navigation bar is colored gray even though the barTintColor is set to another color. Why is this happening?
-(UIImage *)generateScreenshot {
CGFloat scale = [[UIScreen mainScreen] scale];
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, NO, scale);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.view.layer renderInContext:context];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return viewImage;
}
I think the problem should be that you are rendering a view which doesn't include the navigation bar,Replace [self.view.layer renderInContext:context]; with
[[appDelegate window].layer renderInContext:context];
Hope It Helps...:)

CALayer renderInContext draws a blank image

This code works:
UIGraphicsBeginImageContextWithOptions(aRect.size, NO, 0.0);
[self.view drawViewHierarchyInRect:aRect afterScreenUpdates:YES];
anImageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
but I need to support iOS 5 and 6. My Googling says this code ought to work:
UIGraphicsBeginImageContextWithOptions(aRect.size, NO, 0.0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
anImageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
but the image is blank. How do I take a snapshot of a view in iOS 5 and 6?
The solution was to scale the view to fit it the bounds of the graphics context. Most examples I found of this assume that the source view and the destination context are the same size. The graphics context I was using was much smaller than the view being snapshotted, and it was actually just clipping a corner of the view that was transparent.
UIGraphicsBeginImageContextWithOptions(aRect.size, NO, 0.0);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGFloat scale = CGRectGetWidth(aRect) / CGRectGetWidth(self.view.bounds);
CGContextScaleCTM(ctx, scale, scale);
[self.view.layer renderInContext:ctx];
anImageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

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 a UIView to a UIImage larger than it is on screen

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;
}

Resources