How to easily resize/optimize an image size with iOS?

后端 未结 18 1396
温柔的废话
温柔的废话 2020-11-22 11:05

My application is downloading a set of image files from the network, and saving them to the local iPhone disk. Some of those images are pretty big in size (widths larger tha

18条回答
  •  遥遥无期
    2020-11-22 11:48

    According to this session, iOS Memory Deep Dive, we had better use ImageIO to downscale images.

    The bad of using UIImage downscale images.

    • Will decompress original image into memory
    • Internal coordinate space transforms are expensive

    Use ImageIO

    • ImageIO can read image sizes and metadata information without dirtying memory.

    • ImageIO can resize images at cost of resized image only.

    About Image in memory

    • Memory use is related to the dimensions of the images, not the file size.
    • UIGraphicsBeginImageContextWithOptions always uses SRGB rendering-format, which use 4 bytes per pixel.
    • A image have load -> decode -> render 3 phases.
    • UIImage is expensive for sizing and to resizing

    For the following image, if you use UIGraphicsBeginImageContextWithOptions we only need 590KB to load a image, while we need 2048 pixels x 1536 pixels x 4 bytes per pixel = 10MB when decoding

    while UIGraphicsImageRenderer, introduced in iOS 10, will automatically pick the best graphic format in iOS12. It means, you may save 75% of memory by replacing UIGraphicsBeginImageContextWithOptions with UIGraphicsImageRenderer if you don't need SRGB.

    This is my article about iOS images in memory

    func resize(url: NSURL, maxPixelSize: Int) -> CGImage? {
        let imgSource = CGImageSourceCreateWithURL(url, nil)
        guard let imageSource = imgSource else {
            return nil
        }
    
        var scaledImage: CGImage?
        let options: [NSString: Any] = [
                // The maximum width and height in pixels of a thumbnail.
                kCGImageSourceThumbnailMaxPixelSize: maxPixelSize,
                kCGImageSourceCreateThumbnailFromImageAlways: true,
                // Should include kCGImageSourceCreateThumbnailWithTransform: true in the options dictionary. Otherwise, the image result will appear rotated when an image is taken from camera in the portrait orientation.
                kCGImageSourceCreateThumbnailWithTransform: true
        ]
        scaledImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, options as CFDictionary)
    
        return scaledImage
    }
    
    
    let filePath = Bundle.main.path(forResource:"large_leaves_70mp", ofType: "jpg")
    
    let url = NSURL(fileURLWithPath: filePath ?? "")
    
    let image = resize(url: url, maxPixelSize: 600)
    
    

    or

    // Downsampling large images for display at smaller size
    func downsample(imageAt imageURL: URL, to pointSize: CGSize, scale: CGFloat) -> UIImage {
        let imageSourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary
        let imageSource = CGImageSourceCreateWithURL(imageURL as CFURL, imageSourceOptions)!
        let maxDimensionInPixels = max(pointSize.width, pointSize.height) * scale
        let downsampleOptions =
            [kCGImageSourceCreateThumbnailFromImageAlways: true,
            kCGImageSourceShouldCacheImmediately: true,
            // Should include kCGImageSourceCreateThumbnailWithTransform: true in the options dictionary. Otherwise, the image result will appear rotated when an image is taken from camera in the portrait orientation.
            kCGImageSourceCreateThumbnailWithTransform: true,
            kCGImageSourceThumbnailMaxPixelSize: maxDimensionInPixels] as CFDictionary
        let downsampledImage =
            CGImageSourceCreateThumbnailAtIndex(imageSource, 0, downsampleOptions)!
        return UIImage(cgImage: downsampledImage)
    }
    
    

提交回复
热议问题