Is NSKeyedArchiver
appropriate to convert UIImage
to Data
?
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: UIImage(named: somePath), requiringSecureCoding: true)
...
} catch {
print(error)
}
Or is it overkill and using pngData()
is more appropriate?
let image = UIImage(named: somePath)
let data = image?.pngData()
and how can I convert from UIImage
to HEIF / HEIC Data
?
The goal is to save the image to the device's file system.
No. Never use NSKeyedArchiver to convert your image to Data. Choose an image format (HEIC, PNG, JPEG, etc) and get its data representation. You should only use PNG when saving images to use in your UI. Most of the time jpeg is the preferred choice. If the device supports HEIC it is an option considering the image quality and reduced data size.
If you need to check if the user device supports HEIC type you can do it as follow:
var isHeicSupported: Bool {
(CGImageDestinationCopyTypeIdentifiers() as! [String]).contains("public.heic")
}
If you need to convert your image to HEIC you need to get a CGImage
from your UIImage
and convert your UIImage
's imageOrientation
to CGImagePropertyOrientation
to preserve the orientation when creating its data representation:
extension UIImage {
var heic: Data? { heic() }
func heic(compressionQuality: CGFloat = 1) -> Data? {
guard
let mutableData = CFDataCreateMutable(nil, 0),
let destination = CGImageDestinationCreateWithData(mutableData, "public.heic" as CFString, 1, nil),
let cgImage = cgImage
else { return nil }
CGImageDestinationAddImage(destination, cgImage, [kCGImageDestinationLossyCompressionQuality: compressionQuality, kCGImagePropertyOrientation: cgImageOrientation.rawValue] as CFDictionary)
guard CGImageDestinationFinalize(destination) else { return nil }
return mutableData as Data
}
}
extension CGImagePropertyOrientation {
init(_ uiOrientation: UIImage.Orientation) {
switch uiOrientation {
case .up: self = .up
case .upMirrored: self = .upMirrored
case .down: self = .down
case .downMirrored: self = .downMirrored
case .left: self = .left
case .leftMirrored: self = .leftMirrored
case .right: self = .right
case .rightMirrored: self = .rightMirrored
@unknown default:
fatalError()
}
}
}
extension UIImage {
var cgImageOrientation: CGImagePropertyOrientation { .init(imageOrientation) }
}
Usage for lossless compression:
if isHeicSupported, let heicData = image.heic {
// write your heic image data to disk
}
or adding compression to your image:
if isHeicSupported, let heicData = image.heic(compressionQuality: 0.75) {
// write your compressed heic image data to disk
}