Как программно загрузить необработанное изображение с помощью PHPicker в iOS?
Могу загружать обычные изображения: типы public.image.
Apple proRaw(тип изображения Adobe Raw: формат DNG) можно использовать в iPhone 12 серии.
Итак, я сделал снимок в формате RAW и хочу загрузить файл DNG из приложения.
Но я не могу загрузить изображение с помощью PHPicker. Обычно коды ниже.
PHPickerConfiguration *configuration = [[PHPickerConfiguration alloc] init];
configuration.filter = [PHPickerFilter anyFilterMatchingSubfilters:@[[PHPickerFilter imagesFilter], [PHPickerFilter livePhotosFilter]]];
PHPickerViewController *pickerController = [[PHPickerViewController alloc] initWithConfiguration:configuration];
pickerController.delegate = self;
[pickerController setModalPresentationStyle:UIModalPresentationCustom];
[pickerController setModalTransitionStyle:UIModalTransitionStyleCrossDissolve];
[viewController presentViewController:pickerController animated:YES completion:nil];
-(void)picker:(PHPickerViewController *)picker didFinishPicking:(NSArray<PHPickerResult *> *)results API_AVAILABLE(ios(14)) {
[picker dismissViewControllerAnimated:YES completion:nil];
PHPickerResult *result = [results firstObject];
if ([result.itemProvider canLoadObjectOfClass:[UIImage class]]) { // 1
[result.itemProvider loadObjectOfClass:[NSObject class] completionHandler:^(__kindof id<NSItemProviderReading> _Nullable object, NSError * _Nullable error) {
if ([object isKindOfClass:[UIImage class]]) {
UIImage *image = object;
...
}
}];
}
В строке комментария 1 возвращается NO.
Как загрузить необработанное изображение с помощью PHPicker?
3 ответа
С использованием
loadFileRepresentation
чтобы получить данные фотографии в
CGImage
объект работал для меня. Что-то типа:
result.itemProvider.loadFileRepresentation(forTypeIdentifier: "public.image") { url, _ in
guard let url = url,
let data = NSData(contentsOf: url),
let source = CGImageSourceCreateWithData(data, nil),
let cgImage = CGImageSourceCreateImageAtIndex(source, 0, nil) else {
// handle
}
let image = UIImage(cgImage)
...
}
или же
[result.itemProvider loadFileRepresentationForTypeIdentifier:@"public.image" completionHandler:^(NSURL * _Nullable url, NSError * _Nullable error) {
if (url) {
NSData *data = [NSData dataWithContentsOfURL:url];
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL);
CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, 0, NULL);
UIImage *image = [UIImage imageWithCGImage:cgImage];
...
}
}];
Вам может понадобиться получить правильную ориентацию, используя
CGImageSourceCopyPropertiesAtIndex
чтобы получить словарь метаданных, найдите правильное значение с помощью
kCGImagePropertyOrientation
ключ, преобразовать его из
CGImagePropertyOrientation
к
UIImage.Orientation
, и передать его в
UIImage
инициализатор.
Это немного сложнее, чем просто использование
loadObjectOfClass
но для этого не потребуется авторизация доступа к фотографиям.
Я нашел решение, которое сделает это без потери качества изображения RAW:
itemProvider.loadFileRepresentation(forTypeIdentifier: "public.image") { url, _ in
guard let url = url else {
debugPrint("No RAW Url")
return
}
guard let imageSource = CGImageSourceCreateWithURL(url as CFURL, nil) else {
debugPrint("Could not create image source from URL")
return
}
let options = [kCGImageSourceShouldCache: false] as CFDictionary
guard let cgImage = CGImageSourceCreateImageAtIndex(imageSource, 0, options) else {
debugPrint("Could not create CGImage from source")
return
}
let image = UIImage(cgImage: cgImage)
}
Вы также можете использовать этот код. для открытия нового PHPicker .
Для получения дополнительных знаний о PHPicker в видео WWDC21 PHPicker WWDC20 и видео PHPicker WWDC21
WWDC Заметки PHPicker Заметки PHPicker
import Photos
import PhotosUI
// MARK: - PHPicker Configurations (PHPickerViewControllerDelegate)
extension ViewController: PHPickerViewControllerDelegate {
func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
picker.dismiss(animated: true, completion: .none)
results.forEach { result in
result.itemProvider.loadObject(ofClass: UIImage.self) { reading, error in
guard let image = reading as? UIImage, error == nil else { return }
DispatchQueue.main.async {
self.profilePictureOutlet.image = image
// TODO: - Here you get UIImage
}
result.itemProvider.loadFileRepresentation(forTypeIdentifier: "public.image") { [weak self] url, _ in
// TODO: - Here You Get The URL
}
}
}
}
/// call this method for `PHPicker`
func openPHPicker() {
var phPickerConfig = PHPickerConfiguration(photoLibrary: .shared())
phPickerConfig.selectionLimit = 1
phPickerConfig.filter = PHPickerFilter.any(of: [.images, .livePhotos])
let phPickerVC = PHPickerViewController(configuration: phPickerConfig)
phPickerVC.delegate = self
present(phPickerVC, animated: true)
}
}