2

I can load normal images: public.image types.
The Apple proRaw(adobe raw image type: DNG format) can be used in iPhone 12 series.
So, I captured with RAW image and I want to load the DNG file from app.
But I can't load the image using PHPicker. Normally, the codes below.

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;
                ...
            }
        }];
    }

In comment 1 line, returned NO.
How to load raw image using PHPicker?

strawnut
  • 359
  • 5
  • 21
  • You would need to set up the PHPickerConfiguration with the photo library, obtain the asset identifier, and return to the library to get the RAW data. – matt Jan 26 '21 at 05:06
  • @matt I understand what you mean. If obtain PHAsset using the asset identifier, need to authorize to access photo library. But, actually PHPicker does not need to get authorization to access photo library. I want to keep this spec there is not authorization. – strawnut Jan 26 '21 at 07:12
  • Cool but then you cannot get the RAW data. – matt Jan 26 '21 at 07:28
  • @matt what the... I just need not RAW data, but full-sized image. Can I export UIImage from RAW data image? Just image. not additional data like depth info, geo data... – strawnut Jan 27 '21 at 01:15

2 Answers2

3

Using loadFileRepresentation to get the photo's data into a CGImage object worked for me. Something like:

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)
    ...
}

or

[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];
        ...
    }
}];

You may need to get the correct orientation using CGImageSourceCopyPropertiesAtIndex to get the metadata dictionary, find the correct value with the kCGImagePropertyOrientation key, transform it from CGImagePropertyOrientation to UIImage.Orientation, and pass it to the UIImage initializer.

It's a bit more involved than just using loadObjectOfClass but it won't require photo access authorization.

Eduardo Arenas Prada
  • 1,072
  • 1
  • 7
  • 14
-1
  1. You can use this code also. for opening new PHPicker.

  2. For More Knowledge about PHPicker in WWDC21 PHPicker WWDC20 Video and PHPicker WWDC21 Video

  3. WWDC PHPicker Notes PHPicker Notes


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)
   }
}
Chandan
  • 283
  • 2
  • 6
  • 1
    Yes, but this just don't work for RAW photos - you get nil when trying to `loadObject(ofClass: UIImage.self)` – Palli Sep 29 '22 at 13:44