快速:对于HEIC图像,PHAssetChangeRequest失败

5

我希望对来自相册(由iPhone相机拍摄)的图像进行编辑,例如进行JPEG压缩,但当输入的图像是HEIC格式时失败,但对于JPEG图像可以正常工作。

我通过UIImagePickerController方法在PHAsset对象中检索图像:

func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let asset = info[UIImagePickerController.InfoKey.phAsset] as? PHAsset {
            self.asset = asset
        }

        //...
    } 

该函数编辑所选图像:

func editImage() {
if let _asset = self.asset {
        _asset.requestContentEditingInput(with: nil, completionHandler: { (contentEditingInput, info) in
            let fullURL: URL?
            fullURL = contentEditingInput!.fullSizeImageURL

            let output = PHContentEditingOutput(contentEditingInput:
                contentEditingInput!)
            let archivedData = try? NSKeyedArchiver.archivedData(withRootObject: "HEICEditor", requiringSecureCoding: false)
            let adjustmentData =
                PHAdjustmentData(formatIdentifier:
                    "HEICEditor.App",
                                 formatVersion: "1.0",
                                 data: archivedData!)

            output.adjustmentData = adjustmentData
            let imageData = UIImage.init(contentsOfFile: fullURL!.path)?.jpegData(compressionQuality: 0.5)

            do {
                try imageData!.write(to: output.renderedContentURL, options: .atomic)
            } catch let error {
                print("error writing data:\(error)")
            }

            PHPhotoLibrary.shared().performChanges({
                let request = PHAssetChangeRequest(for: _asset)
                request.contentEditingOutput = output

            }, completionHandler: { (result, error) in
               print("error writing data:\(error)")

            })

        })

    }
}

这个项目提供了一个样例 HEIC 图片,可以在以下链接中找到:https://github.com/maysamsh/Swift-Playground-EditHEIC

  • 注意1:通过查看EXIF信息,你可以判断一张图片是否为HEIC格式。或者,选择一张图片并点击“编辑图片”按钮,你可以在预览图像的顶部看到完整名称。

  • 注意2:由于某些原因,在将HEIC图片从iPhone发送到Mac并再次发送回iPhone时,它可以在新副本上正常工作,仍然是HEIC格式,并保留原始图像方向。

1个回答

3

下面是操作步骤:创建一个CGImageDestination,将输出写入.renderedContentURL,执行the PHAssetChangeRequest()

func editImage() {
    if let _asset = self.asset {
        let options = PHContentEditingInputRequestOptions()
        options.canHandleAdjustmentData = {(adjustmeta: PHAdjustmentData)
            -> Bool in
            return true
        }
        _asset.requestContentEditingInput(with: options, completionHandler: { (contentEditingInput, info) in
            let fullURL: URL?
            fullURL = contentEditingInput!.fullSizeImageURL
            let output = PHContentEditingOutput(contentEditingInput:
                contentEditingInput!)
            let archivedData = try? NSKeyedArchiver.archivedData(withRootObject: "HEICEditor", requiringSecureCoding: false)
            let adjustmentData =
                PHAdjustmentData(formatIdentifier:
                    "HEICEditor.App",
                                 formatVersion: "1.0",
                                 data: archivedData!)


            let orientation = contentEditingInput?.fullSizeImageOrientation
            let outputURL = output.renderedContentURL
            let cgImage = {
                () -> CGImage in
                let image = UIImage.init(contentsOfFile: fullURL!.path)!
                let imageData = image.jpegData(compressionQuality: 1)
                let ciImage = CIImage(data: imageData!)!.oriented(forExifOrientation: orientation!)

                return CIContext(options: nil).createCGImage(ciImage, from: ciImage.extent)!
            }()

            let cgImageDestination = CGImageDestinationCreateWithURL(outputURL as CFURL, kUTTypeJPEG, 1, nil)!
            CGImageDestinationAddImage(cgImageDestination, cgImage, [
                kCGImageDestinationLossyCompressionQuality as String:0.7
                ] as CFDictionary)
            CGImageDestinationFinalize(cgImageDestination)


            output.adjustmentData = adjustmentData
            self.infoLabel.text = "fullSizeImageURL: \(fullURL?.lastPathComponent ?? "N/A")\n" +
            "renderedContentURL: \(output.renderedContentURL.lastPathComponent)"

            PHPhotoLibrary.shared().performChanges({
                let request = PHAssetChangeRequest(for: _asset)
                request.contentEditingOutput = output
            }, completionHandler: { (result, error) in
                print("result: \(result), error: \(String(describing: error))")
            })

        })

    }
}

kUTTypeJPEG在哪里?我收到了“无法在范围内找到'kUTTypeJPEG'”的消息。如何导入? - elp
可能需要导入 Photos - Maysam
在文件顶部添加 import Photos - Maysam
1
不是,我解决了,使用“public.jpeg”作为字符串。 - elp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接