PHAsset:使用元数据保存新图像
Posted
技术标签:
【中文标题】PHAsset:使用元数据保存新图像【英文标题】:PHAsset: Saving a new image with metadata 【发布时间】:2015-11-30 02:34:10 【问题描述】:我正在使用 UIImagePickerController 来允许用户使用相机拍照。当代理被调用时,我想将图像保存到照片库/相机胶卷,我使用 PHAssetChangeRequest 执行此操作。问题是文档说我可以使用 UIImagePickerControllerMediaMetadata 中的字典将其包含为元数据,但 PHAssetChangeRequest 似乎没有执行此操作的参数。保存时如何包含此元数据?谢谢!
【问题讨论】:
你找到办法了吗? 很遗憾没有。文档要么非常不透明,要么错误。 我知道我无法相信这个库有多糟糕,根本不符合 Apple 的标准 【参考方案1】:您可以使用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
【讨论】:
我不确定 CGImageDestinationAddImageFromSource 是否可以这样工作。至少根据文档,它没有。 @DagÅgren 我认为 CGImageDestinationAddImageFromSource 效果很好。我在这个库中使用了这个方法好几个月了:github.com/zhangao0086/DKImagePickerController/blob/develop/… 这就是我要找的。节省了我的一周【参考方案2】:从我通过阅读源代码可以理解的情况来看,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 属性,可以在图像中找到其他元数据。
【讨论】:
以上是关于PHAsset:使用元数据保存新图像的主要内容,如果未能解决你的问题,请参考以下文章