Skip to content

Instantly share code, notes, and snippets.

@yhkaplan
Created February 25, 2022 05:37
Show Gist options
  • Save yhkaplan/58c94ab5c711a829e9374bc32d3bc76b to your computer and use it in GitHub Desktop.
Save yhkaplan/58c94ab5c711a829e9374bc32d3bc76b to your computer and use it in GitHub Desktop.
Downsample images to reduce memory impact
enum ImageDownsampler {
private static let pixelSize = 2_000
/// - URL: https://christianselig.com/2020/09/phpickerviewcontroller-efficiently/
static func downsample(imageAt url: URL) -> Data? {
let sourceOptions: [CFString: Any] = [kCGImageSourceShouldCache: false]
let downsampleOptions: [CFString: Any] = [
kCGImageSourceCreateThumbnailFromImageAlways: true,
kCGImageSourceCreateThumbnailWithTransform: true,
kCGImageSourceThumbnailMaxPixelSize: pixelSize
]
let destinationOptions: [CFString: Any] = [
kCGImageDestinationLossyCompressionQuality: 0.95
]
let data = NSMutableData()
guard
let source = CGImageSourceCreateWithURL(url as CFURL, sourceOptions as CFDictionary),
let cgImage = CGImageSourceCreateThumbnailAtIndex(source, 0, downsampleOptions as CFDictionary),
let imageDestination = CGImageDestinationCreateWithData(data, kUTTypeJPEG, 1, nil)
else { return nil }
CGImageDestinationAddImage(imageDestination, cgImage, destinationOptions as CFDictionary)
CGImageDestinationFinalize(imageDestination)
return data as Data
}
static func downsample(data sourceData: Data, quality: CGFloat) -> Data? {
let sourceOptions: [CFString: Any] = [kCGImageSourceShouldCache: false]
let downsampleOptions: [CFString: Any] = [
kCGImageSourceCreateThumbnailFromImageAlways: true,
kCGImageSourceCreateThumbnailWithTransform: true,
kCGImageSourceThumbnailMaxPixelSize: pixelSize
]
let destinationOptions: [CFString: Any] = [
kCGImageDestinationLossyCompressionQuality: quality
]
let targetData = NSMutableData()
guard
let source = CGImageSourceCreateWithData(sourceData as CFData, sourceOptions as CFDictionary),
let cgImage = CGImageSourceCreateThumbnailAtIndex(source, 0, downsampleOptions as CFDictionary),
let imageDestination = CGImageDestinationCreateWithData(targetData, kUTTypeJPEG, 1, nil)
else { return nil }
CGImageDestinationAddImage(imageDestination, cgImage, destinationOptions as CFDictionary)
CGImageDestinationFinalize(imageDestination)
return targetData as Data
}
/// - URL: https://developer.apple.com/videos/play/wwdc2018-219/?time=640
static func downsample(imageAt data: Data, toSize size: CGSize, scale: CGFloat) -> UIImage? {
let sourceOptions: [CFString: Any] = [kCGImageSourceShouldCache: false]
let maxPixelSize: CGFloat = max(size.height, size.width) * scale
let downsampleOptions: [CFString: Any] = [
kCGImageSourceCreateThumbnailFromImageAlways: true,
kCGImageSourceShouldCacheImmediately: true,
kCGImageSourceCreateThumbnailWithTransform: true,
kCGImageSourceThumbnailMaxPixelSize: maxPixelSize
]
guard
let imageSource = CGImageSourceCreateWithData(data as CFData, sourceOptions as CFDictionary),
let downsampledImage = CGImageSourceCreateThumbnailAtIndex(
imageSource,
0,
downsampleOptions as CFDictionary
)
else { return nil }
return UIImage(cgImage: downsampledImage)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment