https://developer.apple.com/documentation/photokit/browsing_and_modifying_photo_albums
I am thinking of making a photo editing application (photo rotation application) by referring to the sample project that can be downloaded from this URL.
In this sample project, when I try to filter photos with sepia or chrome, some photos work and some do not work.
When things don't work, usually run into errors like the one below.
Can't edit the asset: Optional (Error Domain = NSCocoaErrorDomain Code = -1 "(null)")
I don't even know the correlation between photos that succeed and photos that fail to edit.
It's strange that Apple's genuine photo app can rotate all photos.
Is the structure different from the genuine app?
How can I successfully edit (filter and rotate) all kinds of photos based on this sample code?
The code below is the code in the sample project.
It seems that the image is generated using ".ciContext.writeJPEGRepresentation
Code Block language PHPhotoLibrary.shared().performChanges({ let request = PHAssetChangeRequest(for: self.asset) request.contentEditingOutput = output }
Seems to be making changes to the photos stored in the library.
Sample Project
Code Block language // Returns a filter-applier function for the named filter. // Use the function as a handler for a UIAlertAction object. /// - Tag: ApplyFilter func getFilter(_ filterName: String) -> (UIAlertAction) -> Void { func applyFilter(_: UIAlertAction) { // Set up a handler to handle prior edits. let options = PHContentEditingInputRequestOptions() options.canHandleAdjustmentData = { $0.formatIdentifier == self.formatIdentifier && $0.formatVersion == self.formatVersion } // Prepare for editing. asset.requestContentEditingInput(with: options, completionHandler: { input, info in guard let input = input else { fatalError("Can't get the content-editing input: \(info)") } // This handler executes on the main thread; dispatch to a background queue for processing. DispatchQueue.global(qos: .userInitiated).async { // Create adjustment data describing the edit. let adjustmentData = PHAdjustmentData(formatIdentifier: self.formatIdentifier, formatVersion: self.formatVersion, data: filterName.data(using: .utf8)!) // Create content editing output, write the adjustment data. let output = PHContentEditingOutput(contentEditingInput: input) output.adjustmentData = adjustmentData // Select a filtering function for the asset's media type. let applyFunc: (String, PHContentEditingInput, PHContentEditingOutput, @escaping () -> Void) -> Void if self.asset.mediaSubtypes.contains(.photoLive) { applyFunc = self.applyLivePhotoFilter } else if self.asset.mediaType == .image { applyFunc = self.applyPhotoFilter } else { applyFunc = self.applyVideoFilter } // Apply the filter. applyFunc(filterName, input, output, { // When the app finishes rendering the filtered result, commit the edit to the photo library. PHPhotoLibrary.shared().performChanges({ let request = PHAssetChangeRequest(for: self.asset) request.contentEditingOutput = output }, completionHandler: { success, error in if !success { print("Can't edit the asset: \(String(describing: error))") } }) }) } }) } return applyFilter } func applyPhotoFilter(_ filterName: String, input: PHContentEditingInput, output: PHContentEditingOutput, completion: () -> Void) { // Load the full-size image. guard let inputImage = CIImage(contentsOf: input.fullSizeImageURL!) else { fatalError("Can't load the input image to edit.") } //MARK: Apply the filter and Rotation let outputImage = inputImage .oriented(forExifOrientation: input.fullSizeImageOrientation) .applyingFilter(filterName, parameters: [:]).oriented(.right) // Write the edited image as a JPEG. do { //MARK: I get errors here try self.ciContext.writeJPEGRepresentation(of: outputImage, to: output.renderedContentURL, colorSpace: inputImage.colorSpace!, options: [:]) } catch let error { fatalError("Can't apply the filter to the image: \(error).") } completion() }
I would appreciate it if you could answer
Thank you in advance.