我正在使用 UIImagePickerController 来允许用户使用相机拍照。当代理被调用时,我想将图像保存到照片库/相机胶卷,我使用 PHAssetChangeRequest 执行此操作。问题是文档说我可以使用 UIImagePickerControllerMediaMetadata 中的字典将其包含为元数据,但 PHAssetChangeRequest 似乎没有执行此操作的参数。保存时如何包含此元数据?谢谢!
问问题
2681 次
2 回答
2
您可以使用PHAssetCreationRequest
. 为了使用PHAssetCreationRequest
,您将合并 imageData 和元数据,然后将 imageDataWithMetadata 写入相册。像这样:
if let imageDataWithMetadata = self.writeMetadata(metadata, into: imageData) {
self.saveImageDataForiOS9(imageDataWithMetadata)
}
func saveImageDataForiOS9(_ data: Data) {
var newImageIdentifier: String!
PHPhotoLibrary.shared().performChanges({
if #available(iOS 9.0, *) {
let assetRequest = PHAssetCreationRequest.forAsset()
assetRequest.addResource(with: .photo, data: data, options: nil)
newImageIdentifier = assetRequest.placeholderForCreatedAsset!.localIdentifier
} else {
// Fallback on earlier versions
}
}) { (success, error) in
DispatchQueue.main.async(execute: {
if success, let newAsset = PHAsset.fetchAssets(withLocalIdentifiers: [newImageIdentifi
// ...
} else {
// ...
}
})
}
}
对于 iOS 8,您可以使用ALAssetsLibrary
元数据保存新图像:
func saveImageDataForiOS8(_ imageData: Data, _ metadata: Dictionary<AnyHashable, Any>?) {
let library = ALAssetsLibrary()
library.writeImageData(toSavedPhotosAlbum: imageData, metadata: metadata, completionBlock: { (newURL, error) in
if let _ = error {
// ...
} else {
if let newAsset = PHAsset.fetchAssets(withALAssetURLs: [newURL!], options: nil).firstObject {
// ...
}
}
})
}
所以,最后你会得到这样的代码:
func saveImage(_ imageData: Data, metadata: Dictionary<AnyHashable, Any>?) {
if #available(iOS 9.0, *) {
if let metadata = metadata {
if let imageDataWithMetadata = self.writeMetadata(metadata, into: imageData) {
self.saveImageDataForiOS9(imageDataWithMetadata)
} else {
self.saveImageDataForiOS9(imageData)
}
} else {
self.saveImageDataForiOS9(imageData)
}
} else {
self.saveImageDataForiOS8(imageData, metadata)
}
}
func saveImageDataForiOS8(_ imageData: Data, _ metadata: Dictionary<AnyHashable, Any>?) {
let library = ALAssetsLibrary()
library.writeImageData(toSavedPhotosAlbum: imageData, metadata: metadata, completionBloc
if let _ = error {
// ...
} else {
if let newAsset = PHAsset.fetchAssets(withALAssetURLs: [newURL!], options: nil).
// ...
}
}
})
}
func saveImageDataForiOS9(_ data: Data) {
var newImageIdentifier: String!
PHPhotoLibrary.shared().performChanges({
if #available(iOS 9.0, *) {
let assetRequest = PHAssetCreationRequest.forAsset()
assetRequest.addResource(with: .photo, data: data, options: nil)
newImageIdentifier = assetRequest.placeholderForCreatedAsset!.localIdentifier
} else {
// Fallback on earlier versions
}
}) { (success, error) in
DispatchQueue.main.async(execute: {
if success, let newAsset = PHAsset.fetchAssets(withLocalIdentifiers: [newImageId
// ...
} else {
// ...
}
})
}
}
internal func writeMetadata(_ metadata: Dictionary<AnyHashable, Any>, into imageData: Data)
let source = CGImageSourceCreateWithData(imageData as CFData, nil)!
let UTI = CGImageSourceGetType(source)!
let newImageData = NSMutableData()
if let destination = CGImageDestinationCreateWithData(newImageData, UTI, 1, nil) {
CGImageDestinationAddImageFromSource(destination, source, 0, metadata as CFDictionar
if CGImageDestinationFinalize(destination) {
return newImageData as Data
} else {
return nil
}
} else {
return nil
}
}
于 2017-09-02T16:37:47.693 回答
0
从我通过阅读源代码可以理解的情况来看,Apple 所说的元数据是指资产的属性。
open var pixelWidth: Int { get }
open var pixelHeight: Int { get }
open var creationDate: Date? { get }
open var modificationDate: Date? { get }
open var location: CLLocation? { get }
open var duration: TimeInterval { get }
open var isHidden: Bool { get }
通过访问 CGImage 属性,可以在图像中找到其他元数据。
于 2017-09-02T13:24:04.423 回答