How to capture UIView to UIImage without loss of quality on retina display

前端 未结 17 1478
时光取名叫无心
时光取名叫无心 2020-11-22 00:42

My code works fine for normal devices but creates blurry images on retina devices.

Does anybody know a solution for my issue?

+ (UIImage *) imageWith         


        
相关标签:
17条回答
  • 2020-11-22 00:59

    I have created a Swift extension based on @Dima solution:

    extension UIImage {
        class func imageWithView(view: UIView) -> UIImage {
            UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0)
            view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
            let img = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return img
        }
    }
    

    EDIT: Swift 4 improved version

    extension UIImage {
        class func imageWithView(_ view: UIView) -> UIImage {
            UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0)
            defer { UIGraphicsEndImageContext() }
            view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
            return UIGraphicsGetImageFromCurrentImageContext() ?? UIImage()
        }
    }
    

    Usage:

    let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))  
    let image = UIImage.imageWithView(view)
    
    0 讨论(0)
  • 2020-11-22 01:00

    Add this to method to UIView Category

    - (UIImage*) capture {
        UIGraphicsBeginImageContext(self.bounds.size);
        CGContextRef context = UIGraphicsGetCurrentContext();
        [self.layer renderInContext:context];
        UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return img;
    }
    
    0 讨论(0)
  • 2020-11-22 01:02

    The currently accepted answer is now out of date, at least if you are supporting iOS 7.

    Here is what you should be using if you are only supporting iOS7+:

    + (UIImage *) imageWithView:(UIView *)view
    {
        UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0f);
        [view drawViewHierarchyInRect:view.bounds afterScreenUpdates:NO];
        UIImage * snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return snapshotImage;
    }
    

    Swift 4:

    func imageWithView(view: UIView) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0.0)
        defer { UIGraphicsEndImageContext() }
        view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
        return UIGraphicsGetImageFromCurrentImageContext()
    }
    

    As per this article, you can see that the new iOS7 method drawViewHierarchyInRect:afterScreenUpdates: is many times faster than renderInContext:. benchmark

    0 讨论(0)
  • 2020-11-22 01:03
    - (UIImage*)screenshotForView:(UIView *)view
    {
        UIGraphicsBeginImageContext(view.bounds.size);
        [view.layer renderInContext:UIGraphicsGetCurrentContext()];
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        // hack, helps w/ our colors when blurring
        NSData *imageData = UIImageJPEGRepresentation(image, 1); // convert to jpeg
        image = [UIImage imageWithData:imageData];
    
        return image;
    }
    
    0 讨论(0)
  • 2020-11-22 01:04

    In this method just pass a view object and it will returns a UIImage object.

    -(UIImage*)getUIImageFromView:(UIView*)yourView
    {
     UIGraphicsBeginImageContext(yourView.bounds.size);
     [yourView.layer renderInContext:UIGraphicsGetCurrentContext()];
     UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();
     return image;
    }
    
    0 讨论(0)
  • 2020-11-22 01:06

    To improve answers by @Tommy and @Dima, use the following category to render UIView into UIImage with transparent background and without loss of quality. Working on iOS7. (Or just reuse that method in implementation, replacing self reference with your image)

    UIView+RenderViewToImage.h

    #import <UIKit/UIKit.h>
    
    @interface UIView (RenderToImage)
    
    - (UIImage *)imageByRenderingView;
    
    @end
    

    UIView+RenderViewToImage.m

    #import "UIView+RenderViewToImage.h"
    
    @implementation UIView (RenderViewToImage)
    
    - (UIImage *)imageByRenderingView
    {
        UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);
        [self drawViewHierarchyInRect:self.bounds afterScreenUpdates:YES];
        UIImage * snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return snapshotImage;
    }
    
    @end
    
    0 讨论(0)
提交回复
热议问题