Screenshot of MKMapView doesn't work - ios

This is my code:
What am I doing wrong?? I simply want to take a screenshot of an MKMapView displaying a given Location. Taking the screenshot and placing it in an UIImage works fine, but the MKMapView looks really wierd, as if it hasn't been rendered. What's wrong?
if(PageControllerMain.currentPage == 0) {
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)]) {
UIGraphicsBeginImageContextWithOptions(MainPage1MapContainer.bounds.size, MainPage1MapContainer.opaque, 0.0);
}
else {
UIGraphicsBeginImageContext(self.view.bounds.size);
}
UIGraphicsBeginImageContextWithOptions(MainPage1MapContainer.bounds.size, MainPage1MapContainer.opaque, 0.0);
[MainPage1MapContainer.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData * data = UIImagePNGRepresentation(image);
[data writeToFile:#"MapImagePage1.png" atomically:YES];
OverallMainMapContainer.image = image;
}

Related

Covert UIVIew to UIImage without presenting/displaying UIView

I am using method to convert UIView to UIImage and its doing a great job when UIView (to be converted to UIImage) is already present/displayed. But my requirement is to convert UIView to UIImage without displaying UIView. Unfortunately, this code is failing in this case and I am stuck. Any help will be appreciated.
I am using the following method:
+ (UIImage *) imageWithView:(UIView *)view
{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, [[UIScreen mainScreen] scale]);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
Your code is likely failing because you're not laying out the subviews of your view (which is done automatically when you add a view as a subview). Try something like the method I wrote below:
+ (UIImage *)imageFromView:(UIView *)view sized:(CGSize)size
{
// layout the view
view.frame = CGRectMake(0, 0, size.width, size.height);
[view setNeedsLayout];
[view layoutIfNeeded];
// render the image
UIGraphicsBeginImageContextWithOptions(size, view.opaque, 0.0f);
[view drawViewHierarchyInRect:view.bounds afterScreenUpdates:NO];
UIImage *renderedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return renderedImage;
}
Assuming you have already got a working view, this code should work to convert the UIView to a UIImage (I'm using it to convert a gradient into an image and display the image onto a UIProgressView.
Swift:
let renderer = UIGraphicsImageRenderer(size: gradientView.bounds.size)
let image = renderer.image { ctx in
gradientView.drawHierarchy(in: gradientView.bounds, afterScreenUpdates: true)
}
Objective C:
UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:gradientView.bounds.size];
UIImage *gradientImage = [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {
[gradientView drawViewHierarchyInRect:gradientView.bounds afterScreenUpdates:true];
}];
_progressView.progressImage = gradientImage;
The above code should allow you to convert any UIView to a UIImage. You should ideally be running it in the viewWillAppear (as at this point the view controller will have the correct layout sizes). If you have any problems getting this to work you can have a look at these example projects that I made for a guide on this very topic! Objective C, Swift.
Hide all subviews, and then snapshot UIview to UIImage should work, see code below
+ (UIImage *)custom_snapshotScreenInView:(UIView *)contentView
{
if (!contentView) {
return nil;
}
CGSize size = contentView.bounds.size;
UIGraphicsBeginImageContextWithOptions(size, NO, [UIScreen mainScreen].scale);
CGRect rect = contentView.bounds;
[contentView drawViewHierarchyInRect:rect afterScreenUpdates:YES];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
return image;
}
+ (UIImage *)custom_snapshotScreenWithoutSubviews:(UIView *)contentView
{
// save hidden view's hash
NSMutableArray *hideViewsHashs = [[NSMutableArray alloc]initWithCapacity:contentView.subviews.count];
for (UIView *subview in contentView.subviews) {
if (subview.hidden == NO) {
[hideViewsHashs addObject:#(subview.hash)];
NSLog(#"Dikey:video:snap:hash = %#", #(subview.hash));
}
subview.hidden = YES;
}
// view to image
UIImage *image = [UIImage custom_snapshotScreenInView:contentView];
// restore
for (UIView *subview in contentView.subviews) {
if ([hideViewsHashs containsObject:#(subview.hash)]) {
subview.hidden = NO;
NSLog(#"Dikey:video:snap:restore:hash = %#", #(subview.hash));
}
}
// finish
return image;
}

How to take screen shot in iOS device programmatically for SOS?

Using new API's like
snapshotViewAfterScreenUpdates
resizableSnapshotViewFromRect
drawViewHierarchyInRect
Using these i want to take photo in any format and need to send.
try this
UIView *screenshotView = [[UIScreen mainScreen] snapshotViewAfterScreenUpdates:NO];
UIImage *snapshotImage = [self imageFromView:screenshotView];
- (UIImage *)imageFromView:(UIView *)view
{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, 0.0);
[view drawViewHierarchyInRect:view.bounds afterScreenUpdates:YES];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}

IOS How to take screenshot of only image in uiimageview

I want to take screenshot of only image in imageview. I have tried following code but it will take screenshot of imageview .
CGRect grabRect = CGRectMake(self.vwBackup.frame.origin.x,self.vwBackup.frame.origin.y,self.vwBackup.frame.size.width,self.vwBackup.frame.size.height);
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);
self.ImgEditableView.image=viewImage;
Here i have attached image of taken screenshot with above code:
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)])
UIGraphicsBeginImageContextWithOptions(self.displayImageView.bounds.size, NO, [UIScreen mainScreen].scale);
else
UIGraphicsBeginImageContext(self.displayImageView.bounds.size);
[self.displayImageView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData * imgData = UIImagePNGRepresentation(image);
if(imgData)
{
[imgData writeToFile:#"screenshot.png" atomically:YES];
}
else
NSLog(#"error while taking screenshot");

How to take screenshot of expandable uitableview programmatically

I tried to take screenshot of expandable uitableview, I tried to take a screenshot of uitableview but I was not able do that , then I changed tableview frame size to tableview content size. After taking screenshot I changed frame size to old frame size. Now the problem is that I am having expandable section in table view. I'm able to take screenshot of unexpanded table view cell in my screenshot. I need to take the screenshot of unexpanded table view cell content too.
by using this category file u can take the screen shot what ever visible in the screen....
#interface UIImage (MyImage)
+ (UIImage*)imageFromView:(UIView*)view;
+ (UIImage*)imageFromView:(UIView*)view scaledToSize:(CGSize)newSize;
+ (UIImage*)imageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize;
+ (void)beginImageContextWithSize:(CGSize)size;
+ (UIImage *)croppedImage:(UIImage *)myImage :(CGRect)bounds;
#end
#import "UIImage+MyImage.h"
#implementation UIImage (MyImage)
+ (void)beginImageContextWithSize:(CGSize)size
{
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)]) {
if ([[UIScreen mainScreen] scale] == 2.0) {
UIGraphicsBeginImageContextWithOptions(size, YES, 2.0);
} else {
UIGraphicsBeginImageContext(size);
}
} else {
UIGraphicsBeginImageContext(size);
}
}
+ (void)endImageContext
{
UIGraphicsEndImageContext();
}
+ (UIImage*)imageFromView:(UIView*)view
{
[self beginImageContextWithSize:[view bounds].size];
BOOL hidden = [view isHidden];
[view setHidden:NO];
[[view layer] renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
[self endImageContext];
[view setHidden:hidden];
return image;
}
+ (UIImage*)imageFromView:(UIView*)view scaledToSize:(CGSize)newSize
{
UIImage *image = [self imageFromView:view];
if ([view bounds].size.width != newSize.width ||
[view bounds].size.height != newSize.height) {
image = [self imageWithImage:image scaledToSize:newSize];
}
return image;
}
+ (UIImage*)imageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize
{
[self beginImageContextWithSize:newSize];
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
[self endImageContext];
return newImage;
}
+ (UIImage *)croppedImage:(UIImage *)myImage :(CGRect)bounds {
CGImageRef imageRef = CGImageCreateWithImageInRect(myImage.CGImage, bounds);
UIImage *croppedImage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGSize asd = croppedImage.size;
return croppedImage;
}
#end
the method call will be....
yourImageView.image= [UIImage imageFromView:(UIView*)yourTableViewInstance ]
try this....

Save UIView to a transparent PNG

I have a UIView and I want it to be stored as a transparent PNG, i.e. without the UIVIew background color...
I am currently using this code and it's working OK but with the background color :(
UIGraphicsBeginImageContext(self.bounds.size);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage* image1 = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *imageData = UIImagePNGRepresentation(image1);
[imageData writeToFile:filePath atomically:YES];
So does anyone have any idea about getting this image as a transparent one?
Thank you in advance..
In my case, I forgot the opaque property. It should be set to NO:
view.opaque = NO;
Change the background color to [UIColor clear], draw the image and then set the background color back to the original color.
Since GUI updates will fire only on the next runloop cycle, the user should not see any flickering.
UIColor* color=self.backgroundColor;
view.backgroundColor=[UIColor clearColor];
UIGraphicsBeginImageContext(self.bounds.size);
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage* image1 = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *imageData = UIImagePNGRepresentation(image1);
[imageData writeToFile:filePath atomically:YES];
self.backgroundColor=color;
As an addition to Gilad's answer. On retina display this may cause some quality issues. To get the retina context you may use this code from this post.
UIColor* color=self.backgroundColor;
view.backgroundColor=[UIColor clearColor];
// This is for retina render check
UIWindow *keyWindow = [[UIApplication sharedApplication] keyWindow];
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)])
UIGraphicsBeginImageContextWithOptions(YourView.frame.size, NO, [UIScreen mainScreen].scale);
else
UIGraphicsBeginImageContext(keyWindow.bounds.size);
// And it goes up to here the rest stays the same
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage* image1 = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *imageData = UIImagePNGRepresentation(image1);
[imageData writeToFile:filePath atomically:YES];
self.backgroundColor=color;
For Objective-c you have to set opaque = NO
+ (UIImage *) imageWithView:(UIView *)view
{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, [[UIScreen mainScreen] scale]);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
For Swift you have to set opaque = false
func imageWithView(inView: UIView) -> UIImage? {
UIGraphicsBeginImageContextWithOptions(inView.bounds.size, false, 0.0)
if let context = UIGraphicsGetCurrentContext() {
inView.layer.render(in: context)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
return nil
}

Resources