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();
Related
I was researching how to make a circle image by code in objective-c these two days. I found several way to do this, but no matter which way, the image created is not an exact circle, which is cut. Please see following code and image:
CGRect rect = CGRectMake(0.0f, 0.0f, radius*2.0f, radius*2.0f);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillEllipseInRect(context, rect);
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
If you look at the image carefully, you will find that the edge has been cut.
Finally I found if I change the code as following:
CGRect rect = CGRectMake(0.0f, 0.0f, radius*2.0f+4, radius*2.0f+4);
CGRect rectmin = CGRectMake(2.0f, 2.0f, radius*2, radius*2);
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, color.CGColor);
CGContextFillEllipseInRect(context, rectmin);
UIImage* image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
The result is much better, but I don't think it's a nice solution. Does anybody know exactly what's the problem of my first code snippet? Thanks in advance.
p.s. all the screenshots are captured from the simulator.
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
}
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);
I am trying to apply a color fill to the MKAnnotation. I found some code that pretty much works but for some reason the filled image is upside down after applying the fill to it.
Here is the current code that I am running on a map pin.
CGRect rect = CGRectMake(0, 0, self.image.size.width, self.image.size.height);
UIGraphicsBeginImageContext(self.image.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClipToMask(context, rect, self.image.CGImage);
CGContextSetFillColorWithColor(context, [[UIColor grayColor] CGColor]);
CGContextFillRect(context, rect);
CGContextRotateCTM(context, 90);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImage *flippedImage = [UIImage imageWithCGImage:img.CGImage
scale:1.0 orientation:self.image.imageOrientation];
self.image = flippedImage;
Here is what the pins look like after this code runs.
http://d.pr/i/UaPU
I was thinking that if I applied the current image orientation to the flippedImage that would do the trick but that did not work. I also tried setting self.image = img; and removing the flippedImage var completely but the result is still the same.
CGContext coordinate system is flipped vertically in regard to UIView coordinate system.
Just flip it like this:
CGContextTranslateCTM(ctx, 0, imageHeight);,
CGContextScaleCTM(ctx, 1, -1);
if you want to capture the screen is ios app , you can use the following codes:
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
currentCaptureImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
but I want to capture the picture from a specific point, e.g. (start.x, start.y) and with a specific width and height, how can I do this ??
i just google it and got best answer From How to capture a specific size of the self.view
UIGraphicsBeginImageContextWithOptions(CGSizeMake(300, 320), YES, 0.);
[self.view.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
If your view was, for example, 600x320 and you wanted to capture the middle 300 points in width, you'd translate the context 150 points to the left:
UIGraphicsBeginImageContextWithOptions(CGSizeMake(300, 320), YES, 0.);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, -150.f, 0.f);
[self.view.window.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();