Save bytes-edited image on specific photo album as-is

I need to save an image in Data/NSData format on a particular album on iOS device.

New data structure is important because the raw image data is generated with an algorithm.

I've tried different ways to store this raw data, but every used method, apply some data correction on the data to make the image "conform" to the (JPEG/HEIC/PNG) specifications, and I don't want this. 



Let's make an example:


I edit the data on the image, adding on the tail (or in the middle, the behavior is the same) new values, 0xAA 0xBB, 0xCC.

I want to save the image with this value at the end of the image bytes.

Code Block
Original IMAGE -VS- CUSTOM IMAGE
--------------------------------------------
35 1E 49 35 1E 49
A4 A8 B0 A4 A8 B0
1F FF D9 1F FF D9
••••••••••••••••••••AA BB CC


The only way to save the image AS-IS is to write a file using writeToFile, like this: Data().write(to: URL(string: "/path/image.png"))

In this way the data content is preserved and all is fine BUT if I need to save this image to a particular album or to camera roll the image will be edited by iOS, removing my final bytes that I've inserted (0xAA, 0xBB and 0xCC). 

This because the iOS recalculate the CRC of the image?



Code


I've used PHAssetCreationRequest (from Photos framework): 

Code Block
PHPhotoLibrary.shared().performChanges({
PHAssetChangeRequest.creationRequestForAsset(from: image)
}) { status, error in }


used also UIImageWriteToSavedPhotosAlbum: 
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil).

I've used also PHAdjustmentData value and passing my custom bytes, 

Code Block
asset.requestContentEditingInput(with: options, completionHandler: { input, info in
let adjustmentData = PHAdjustmentData(
formatIdentifier: self.formatIdentifier,
formatVersion: self.formatVersion,
data: myCustomData)
let output = PHContentEditingOutput(contentEditingInput: input)
output.adjustmentData = adjustmentData
PHPhotoLibrary.shared().performChanges({
let request = PHAssetChangeRequest(for: asset)
request.contentEditingOutput = output
}, completionHandler: { success, error in
if !success { print("can't edit asset: \(error)") }
})
})

but in this case I receive a generic error without any explanation:

can't edit asset: Optional(Error Domain=PHPhotosErrorDomain Code=-1 "(null)") 



The problem is that when I load the image using PHAsset or whatever from the camera roll, the image doesn't contain my custom 0xAABBCC bytes at the end.

Question:


How can I preserve the raw byte information while saving an image to photo album?

Accepted Reply

I'm not totally sure, but I think it's not possible to just add some random data to the end of an image file like this. Photos has its own database for storing the images and I guess they perform some kind of sanitizing/cleaning when adding new entries.

You can add custom data to a PHAsset that is stored alongside the image using PHAdjustmentData, but this is meant for storing "a description of the edits made to an asset's photo, video, or Live Photo content, which allows your app to reconstruct or revert the effects of prior editing sessions." So you would be able to read this data back, but only in an app that understands it. It won't be accessible when you just export the image out of Photos as a JPEG, for instance. And the amount of data you can store this way is also limited.

However, you might be able to store the data in the image's (EXIF) metadata somewhere. This seems to me the appropriate place.

Replies

I'm not totally sure, but I think it's not possible to just add some random data to the end of an image file like this. Photos has its own database for storing the images and I guess they perform some kind of sanitizing/cleaning when adding new entries.

You can add custom data to a PHAsset that is stored alongside the image using PHAdjustmentData, but this is meant for storing "a description of the edits made to an asset's photo, video, or Live Photo content, which allows your app to reconstruct or revert the effects of prior editing sessions." So you would be able to read this data back, but only in an app that understands it. It won't be accessible when you just export the image out of Photos as a JPEG, for instance. And the amount of data you can store this way is also limited.

However, you might be able to store the data in the image's (EXIF) metadata somewhere. This seems to me the appropriate place.