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

前端 未结 17 1506
时光取名叫无心
时光取名叫无心 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 01:17

    Swift 3

    The Swift 3 solution (based on Dima's answer) with UIView extension should be like this:

    extension UIView {
        public func getSnapshotImage() -> UIImage {
            UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0)
            self.drawHierarchy(in: self.bounds, afterScreenUpdates: false)
            let snapshotImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
            UIGraphicsEndImageContext()
            return snapshotImage
        }
    }
    
    0 讨论(0)
  • 2020-11-22 01:21

    Swift 2.0:

    Using extension method:

    extension UIImage{
    
       class func renderUIViewToImage(viewToBeRendered:UIView?) -> UIImage
       {
           UIGraphicsBeginImageContextWithOptions((viewToBeRendered?.bounds.size)!, false, 0.0)
           viewToBeRendered!.drawViewHierarchyInRect(viewToBeRendered!.bounds, afterScreenUpdates: true)
           viewToBeRendered!.layer.renderInContext(UIGraphicsGetCurrentContext()!)
    
           let finalImage = UIGraphicsGetImageFromCurrentImageContext()
           UIGraphicsEndImageContext()
    
           return finalImage
       }
    
    }
    

    Usage:

    override func viewDidLoad() {
        super.viewDidLoad()
    
        //Sample View To Self.view
        let sampleView = UIView(frame: CGRectMake(100,100,200,200))
        sampleView.backgroundColor =  UIColor(patternImage: UIImage(named: "ic_120x120")!)
        self.view.addSubview(sampleView)    
    
        //ImageView With Image
        let sampleImageView = UIImageView(frame: CGRectMake(100,400,200,200))
    
        //sampleView is rendered to sampleImage
        var sampleImage = UIImage.renderUIViewToImage(sampleView)
    
        sampleImageView.image = sampleImage
        self.view.addSubview(sampleImageView)
    
     }
    
    0 讨论(0)
  • 2020-11-22 01:22

    Drop-in Swift 3.0 extension that supports the new iOS 10.0 API & the previous method.

    Note:

    • iOS version check
    • Note the use of defer to simplify the context cleanup.
    • Will also apply the opacity & current scale of the view.
    • Nothing is just unwrapped using ! which could cause a crash.

    extension UIView
    {
        public func renderToImage(afterScreenUpdates: Bool = false) -> UIImage?
        {
            if #available(iOS 10.0, *)
            {
                let rendererFormat = UIGraphicsImageRendererFormat.default()
                rendererFormat.scale = self.layer.contentsScale
                rendererFormat.opaque = self.isOpaque
                let renderer = UIGraphicsImageRenderer(size: self.bounds.size, format: rendererFormat)
    
                return
                    renderer.image
                    {
                        _ in
    
                        self.drawHierarchy(in: self.bounds, afterScreenUpdates: afterScreenUpdates)
                    }
            }
            else
            {
                UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, self.layer.contentsScale)
                defer
                {
                    UIGraphicsEndImageContext()
                }
    
                self.drawHierarchy(in: self.bounds, afterScreenUpdates: afterScreenUpdates)
    
                return UIGraphicsGetImageFromCurrentImageContext()
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 01:23

    For Swift 5.1 you can use this extension:

    extension UIView {
    
        func asImage() -> UIImage {
            let renderer = UIGraphicsImageRenderer(bounds: bounds)
    
            return renderer.image {
                rendererContext in
    
                layer.render(in: rendererContext.cgContext)
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 01:25

    All Swift 3 answers did not worked for me so I have translated the most accepted answer:

    extension UIImage {
        class func imageWithView(view: UIView) -> UIImage {
            UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0.0)
            view.layer.render(in: UIGraphicsGetCurrentContext()!)
            let img: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return img!
        }
    }
    
    0 讨论(0)
提交回复
热议问题