Tôi gặp sự cố khi cập nhật siêu dữ liệu của hình ảnh và lưu lại hình ảnh đó vào thư viện Ảnh. Mọi thứ hoạt động ngoại trừ siêu dữ liệu hình ảnh sau khi bị thay đổi đã thiếu các mục nhập trước đó và tôi không nhận được bất kỳ lỗi nào thao tác hình ảnh hoặc thực thi khối thay đổi thư viện ảnh. Ngoài ra, từ điển trước khi nó được viết trở lại vào hình ảnh trông giống như bản gốc cộng với từ điển của tôi trong trình gỡ rối.Thiếu siêu dữ liệu hình ảnh khi lưu hình ảnh được cập nhật vào PhotoKit
Câu hỏi của tôi là:
- Tôi đang làm gì sai có thể gây ra viết lại tính hiện trở lại với dữ liệu bổ sung để quét sạch những gì đang có?
- Có cách nào tốt hơn, kinh điển hơn để thực hiện việc này không? Có vẻ như rất nhiều cơ chế cập nhật một số dữ liệu meta trong một hình ảnh. Nó có vẻ giống như Những gì mọi người khác đang làm.
EDIT:
Trước khi tất cả các Exif và Tiff giá trị tiết kiệm có mặt. Đây là toàn bộ các siêu dữ liệu sau khi lưu vào hình ảnh bằng cách sử dụng mã bên dưới:
["PixelHeight": 2448, "PixelWidth": 3264, "{Exif}": {
ColorSpace = 1;
PixelXDimension = 3264;
PixelYDimension = 2448;}, "Depth": 8, "ProfileName": sRGB IEC61966-2.1, "Orientation": 1, "{TIFF}": {
Orientation = 1;}, "ColorModel": RGB, "{JFIF}": {
DensityUnit = 0;
JFIFVersion = (
1,
0,
1
);
XDensity = 72;
YDensity = 72;}]
Mã, tất cả trong Swift 3, thử nghiệm trên iOS 10.1
Các công việc cơ bản là:
// Get a mutable copy of the existing Exif meta
let mutableMetaData = getMutableMetadataFrom(imageData: data)
// Check to see if it has the {GPS} entry, if it does just exit.
if let _ = mutableMetaData[kCGImagePropertyGPSDictionary as String] {
callback(imageAsset, true, nil)
return
}
// Add the {GPS} tag to the existing metadata
let clLocation = media.location!.asCLLocation()
mutableMetaData[kCGImagePropertyGPSDictionary as String] =
clLocation.asGPSMetaData()
// Attach the new metadata to the existing image
guard let newImageData = attach(metadata: mutableMetaData, toImageData: data) else {
callback(imageAsset, false, nil)
return
}
let editingOptions = PHContentEditingInputRequestOptions()
imageAsset.requestContentEditingInput(with: editingOptions) { editingInput, info in
guard let editingInput = editingInput else { return }
let library = PHPhotoLibrary.shared()
let output = PHContentEditingOutput(contentEditingInput: editingInput)
output.adjustmentData = PHAdjustmentData(formatIdentifier: "Project", formatVersion: "0.1",
data: "Location Adjustment".data(using: .utf8)!)
do {
try newImageData.write(to: output.renderedContentURL, options: [.atomic])
} catch {
callback(imageAsset, false, error)
return
}
library.performChanges({
let changeRequest = PHAssetChangeRequest(for: imageAsset)
changeRequest.location = clLocation
changeRequest.contentEditingOutput = output
}, completionHandler: { success, error in ... ...
các phương pháp helper cho công việc là:
func attach(metadata: NSDictionary, toImageData imageData:Data) -> Data? {
guard
let imageDataProvider = CGDataProvider(data: imageData as CFData),
let cgImage = CGImage(jpegDataProviderSource: imageDataProvider, decode: nil,
shouldInterpolate: true, intent: .defaultIntent),
let newImageData = CFDataCreateMutable(nil, 0),
let type = UTTypeCreatePreferredIdentifierForTag(kUTTagClassMIMEType,
"image/jpg" as CFString, kUTTypeImage),
let destination = CGImageDestinationCreateWithData(newImageData,
(type.takeRetainedValue()), 1, nil) else {
return nil
}
CGImageDestinationAddImage(destination, cgImage, metadata as CFDictionary)
CGImageDestinationFinalize(destination)
guard
let newProvider = CGDataProvider(data: newImageData),
let newCGImage = CGImage(jpegDataProviderSource: newProvider, decode: nil,
shouldInterpolate: false, intent: .defaultIntent) else {
return nil
}
return UIImageJPEGRepresentation(UIImage(cgImage: newCGImage), 1.0)
}
func getMutableMetadataFrom(imageData data : Data) -> NSMutableDictionary {
let imageSourceRef = CGImageSourceCreateWithData(data as CFData, nil)
let currentProperties = CGImageSourceCopyPropertiesAtIndex(imageSourceRef!, 0, nil)
let mutableDict = NSMutableDictionary(dictionary: currentProperties!)
return mutableDict
}
Ngoài ra asGPSMetaData
là một phần mở rộng trên CLLocation
hơn là một phiên bản Swift 3 của this Gist
đúng - tính đến ngày hôm nay, UIImage không lưu giữ metadata. Tài liệu sẽ được cập nhật ngay để phản ánh điều này. – Bobjt
Vẫn không có cách nào có thể cho uiimage để bảo vệ siêu dữ liệu? Nó có thể âm thanh không liên quan nhưng nó không, trần với tôi. Tôi có một ứng dụng ảnh sử dụng GPUImage, khi tôi sử dụng hình ảnh đầu vào như ảnh chụp màn hình của điện thoại, nó làm biến dạng hình ảnh nhưng khi sử dụng hình ảnh đầu vào như ảnh chụp bằng cam của điện thoại, nó sẽ không làm biến dạng nó, tôi đã nhận thấy ảnh chụp màn hình không bảo vệ siêu dữ liệu nhưng bức ảnh máy ảnh làm, bất kỳ cách nào để sửa chữa nó? @Ray Pendergraph –
Tôi không chắc chắn điều này có thể là "cố định" vì nó không phải là một lỗi thực sự. Một UIImage thực sự chỉ là biểu diễn bộ nhớ của một hình ảnh cho iOS (không được ghi chép một cách rõ ràng, nhưng không phải là một sự tách biệt không phổ biến với các khung công tác UI) và như vậy sẽ không mang bất kỳ siêu dữ liệu nào với nó. Đây là lý do tại sao bạn sẽ phải sử dụng tài sản để lấy dữ liệu. Ảnh chụp màn hình cũng có dữ liệu Exif (không có dữ liệu GPS). –