【问题标题】:How can I convert from UIImage to HEIF / HEIC Data in Swift?如何在 Swift 中将 UIImage 转换为 HEIF / HEIC 数据?
【发布时间】:2020-09-01 22:15:50
【问题描述】:

NSKeyedArchiver 是否适合将UIImage 转换为Data

do {
    let data = try NSKeyedArchiver.archivedData(withRootObject: UIImage(named: somePath), requiringSecureCoding: true)
    ...
} catch {
    print(error)
}

或者是不是矫枉过正,使用pngData() 更合适?

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

我如何从 UIImage 转换为 HEIF / HEIC Data

目标是将图像保存到设备的文件系统中。

【问题讨论】:

    标签: ios swift uiimage nsdata heic


    【解决方案1】:

    没有。永远不要使用 NSKeyedArchiver 将您的图像转换为数据。选择一种图像格式(HEIC、PNG、JPEG 等)并获取其数据表示。在保存要在 UI 中使用的图像时,您应该只使用 PNG。大多数情况下,jpeg 是首选。如果设备支持 HEIC,则考虑到图像质量和减小的数据大小,这是一个选项。

    如果您需要检查用户设备是否支持 HEIC 类型,您可以这样做:

    var isHeicSupported: Bool {
        (CGImageDestinationCopyTypeIdentifiers() as! [String]).contains("public.heic")
    }
    

    如果您需要将图像转换为 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) }
    }
    

    用于无损压缩:

    if isHeicSupported, let heicData = image.heic {
        // write your heic image data to disk
    }
    

    或为您的图像添加压缩:

    if isHeicSupported, let heicData = image.heic(compressionQuality: 0.75) {
        // write your compressed heic image data to disk
    }
    

    【讨论】:

    • 如果我想在写入磁盘的每个图像中包含一些元数据,例如时间戳,我要么使用这些元属性对UIImage 进行子类化,要么将图像包装在具有属性的结构中,推荐的数据序列化是什么?
    • 为什么需要时间戳?可以使用url资源创建日期
    • 如果您需要图像的名称,您可以使用 Apple IMG_0000.heic 或类似名称
    • 您可以轻松地对图像进行排序并生成下一个数字或按顺序生成一个整数并将最后一个数字存储在 UserDefaults 中
    • developer.apple.com/documentation/foundation/urlresourcekey/…extension URL { var contentAccessDate: Date? { (try? resourceValues(forKeys: [.contentAccessDateKey]))?.contentAccessDate } }
    猜你喜欢
    • 2022-11-07
    • 1970-01-01
    • 1970-01-01
    • 2023-03-20
    • 2018-02-21
    • 2015-11-24
    • 2020-12-31
    • 2019-10-20
    • 1970-01-01
    相关资源
    最近更新 更多