Home > Software design >  Take snapshot from UIView with lower resolution
Take snapshot from UIView with lower resolution

Time:06-30

I'm taking snapshot from a PDFView in PDFKit for streaming (20 times per sec), and I use this extesnsion

extension UIView {
    
    func asImageBackground(viewLayer: CALayer, viewBounds: CGRect) -> UIImage {
        let renderer = UIGraphicsImageRenderer(bounds: viewBounds)
        return renderer.image { rendererContext in
            viewLayer.render(in: rendererContext.cgContext)
        }
    }
}

But the output UIImage from this extension has a high resolution which make it difficult to stream. I can reduce it by this extension

extension UIImage {

    
    func resize(_ max_size: CGFloat) -> UIImage {
           // adjust for device pixel density
           let max_size_pixels = max_size / UIScreen.main.scale
           // work out aspect ratio
           let aspectRatio =  size.width/size.height
           // variables for storing calculated data
           var width: CGFloat
           var height: CGFloat
           var newImage: UIImage
           if aspectRatio > 1 {
               // landscape
               width = max_size_pixels
               height = max_size_pixels / aspectRatio
           } else {
               // portrait
               height = max_size_pixels
               width = max_size_pixels * aspectRatio
           }
           // create an image renderer of the correct size
           let renderer = UIGraphicsImageRenderer(size: CGSize(width: width, height: height), format: UIGraphicsImageRendererFormat.default())
           // render the image
           newImage = renderer.image {
               (context) in
               self.draw(in: CGRect(x: 0, y: 0, width: width, height: height))
           }
           // return the image
           return newImage
       }
}

but it add an additional workload which make the process even worse. Is there any better way?

Thanks

CodePudding user response:

You can downsample it using ImageIO which is recommended by Apple:

extension UIImage {
    func downsample(to resolution: CGSize) -> UIImage? {
        let imageSourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary
        guard let data = self.jpegData(compressionQuality: 0.75) as? CFData, let imageSource = CGImageSourceCreateWithData(data, imageSourceOptions) else {
            return nil
        }
        let maxDimensionInPixels = Swift.max(resolution.width, resolution.height) * 3
        let downsampleOptions = [
            kCGImageSourceCreateThumbnailFromImageAlways: true,
            kCGImageSourceShouldCacheImmediately: true,
            kCGImageSourceCreateThumbnailWithTransform: true,
            kCGImageSourceThumbnailMaxPixelSize: maxDimensionInPixels
        ] as CFDictionary
        guard let downsampledImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, downsampleOptions) else {
            return nil
        }
        return UIImage(cgImage: downsampledImage)
    }
}
  • Related