Search code examples
iosswiftiphonecameraavfoundation

got error 3300 when trying to save raw photo and its alternate photo to iOS album


I found that it performs normal when not passing the alterPhoto. This is my code

let options = PHAssetResourceCreationOptions()
        options.shouldMoveFile = true
        PHPhotoLibrary.shared().performChanges{
            let creationRequest = PHAssetCreationRequest.forAsset()
            let options = PHAssetResourceCreationOptions()
                       options.shouldMoveFile = true
            creationRequest.addResource(with: .photo, fileURL: self.rawFileURL!, options: options)
            if let a = alterPhoto{
                creationRequest.addResource(with: .alternatePhoto, data: a, options: nil)
            }
        }completionHandler: { s, e in
            print(e)
        }

This is the code from apple's own document in this address,which is not a full project but an article with code pieces: https://developer.apple.com/documentation/avfoundation/photo_capture/capturing_photos_in_raw_and_apple_proraw_formats

PHPhotoLibrary.shared().performChanges {
     
            // Save the RAW (DNG) file as the main resource for the Photos asset.
            let options = PHAssetResourceCreationOptions()
            options.shouldMoveFile = true
            creationRequest.addResource(with: .photo, 
                                        fileURL: rawFileURL, 
                                        options: options)

            // Add the compressed (HEIF) data as an alternative resource. 
            let creationRequest = PHAssetCreationRequest.forAsset()
            creationRequest.addResource(with: .alternatePhoto, 
                                        data: compressedData, 
                                        options: nil)
            
        } completionHandler: { success, error in
            // Process the Photos library error.
        }
    }

I really don't know why.


Solution

  • I ran into the same issue but was able to get it working by switching the order of the HEIF and RAW: set the HEIF as the primary and the RAW as the alternate:

    PHPhotoLibrary.shared().performChanges {
                // Add the compressed (HEIF) data as the main resource for the Photos asset. 
                let creationRequest = PHAssetCreationRequest.forAsset()
                creationRequest.addResource(with: .photo, 
                                            data: compressedData, 
                                            options: nil)
    
                // Save the RAW (DNG) file an alternate resource for the Photos asset.
                let options = PHAssetResourceCreationOptions()
                options.shouldMoveFile = true
                creationRequest.addResource(with: .alternatePhoto, 
                                            fileURL: rawFileURL, 
                                            options: options)
                
            } completionHandler: { success, error in
                // Process the Photos library error.
            }
        }
    

    Update (2023-10-22): I also ran into an issue where the thumbnail displayed by Photos would be in the camera's native orientation (but opening up the full-size image was fine). I tested combinations of RAW/HEIF first, and using addResource as either data or fileURL.

    TL;DR: use addResource(with: .photo, data: heicData, options: options) and addResource(with: .alternatePhoto, fileURL: rawURL, options: options).

    Where H = HEIF and R = RAW, I came up with the following results:

    Primary Alternate Result
    H/Data R/Data Error 3300
    H/URL R/Data Error 3300
    H/Data R/URL Good
    H/URL R/URL Thumbnail not rotated
    R/URL H/Data Error 3300
    R/Data H/Data Error 3300
    R/Data H/URL Displayed as 'RAW' instead of 'JPEG + RAW' in Photos
    R/URL H/URL Displayed as 'RAW' instead of 'JPEG + RAW' in Photos

    Summarized:

    • The alternate photo must be added using addResource(with:data:options:) instead of addResource(with:fileURL:options:).
    • The RAW file must be added as the .alternatePhoto or Photos will not (at least not in the UI) recognize the HEIF.
    • If the primary photo is added using addResource(with:data:options:), it does not correctly read orientation metadata when generating the thumbnail.