简体   繁体   English

如何将 UIImage 转换为 Swift 中的 HEIF / HEIC 数据?

[英]How can I convert from UIImage to HEIF / HEIC Data in Swift?

Is NSKeyedArchiver appropriate to convert UIImage to Data ? NSKeyedArchiver是否适合将UIImage转换为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?还是矫枉过正,使用pngData()更合适?

let image = UIImage(named: somePath)
let data = image?.pngData()

and how can I convert from UIImage to HEIF / HEIC Data ?以及如何将UIImage转换为 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.不可以。切勿使用 NSKeyedArchiver 将图像转换为数据。 Choose an image format (HEIC, PNG, JPEG, etc) and get its data representation.选择一种图像格式(HEIC、PNG、JPEG 等)并获取其数据表示形式。 You should only use PNG when saving images to use in your UI.保存要在 UI 中使用的图像时,您应该只使用 PNG。 Most of the time jpeg is the preferred choice.大多数时候 jpeg 是首选。 If the device supports HEIC it is an option considering the image quality and reduced data size.如果设备支持 HEIC,考虑到图像质量和减少的数据大小,它是一个选项。

If you need to check if the user device supports HEIC type you can do it as follow:如果您需要检查用户设备是否支持 HEIC 类型,您可以按以下方式进行:

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:如果您需要将图像转换为 HEIC,则需要从UIImage CGImage UIImageimageOrientation转换为CGImagePropertyOrientation以在创建其数据表示时保留方向:

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
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM