RhetTbull / osxphotos

Python app to work with pictures and associated metadata from Apple Photos on macOS. Also includes a package to provide programmatic access to the Photos library, pictures, and metadata.
MIT License
2.17k stars 100 forks source link

AdjustmentInfo doesn't work for some files, especially video #384

Open RhetTbull opened 3 years ago

RhetTbull commented 3 years ago

For some photos, notably movies and slow-mo videos, the decode of the adjustmentsData field fails even though there's data in the field. This happens for about 60 of my 1000+ images that have adjustments.

python working/adjustments_zlib.py ~/Pictures/Photos\ Library.photoslibrary/resources/renders/D/D984FD90-45AE-428F-8753-080B7547D70A.plist
/Users/rhet/Pictures/Photos Library.photoslibrary/resources/renders/D/D984FD90-45AE-428F-8753-080B7547D70A.plist
Traceback (most recent call last):
  File "working/adjustments_zlib.py", line 31, in <module>
    adjustments = decode_adjustments_from_plist(plist)
  File "working/adjustments_zlib.py", line 22, in decode_adjustments_from_plist
    zlib.decompress(plist_dict["adjustmentData"], -zlib.MAX_WBITS).decode()

Even if using the Photos private framework to decode, there's no decoded data:

python working/adjustments.py ~/Pictures/Photos\ Library.photoslibrary/resources/renders/D/D984FD90-45AE-428F-8753-080B7547D70A.plist
/Users/rhet/Pictures/Photos Library.photoslibrary/resources/renders/D/D984FD90-45AE-428F-8753-080B7547D70A.plist
None
RhetTbull commented 3 years ago

if editor=="ScreenshotServices", the adjustment data appears to be a bplist so we could decode those:

'data': b'bplist00\xd4\x01\x02\x03\x04\x05\x06\x18\x19X$versionX$objectsY$archiverT$top\x12\x00\x01\x86\xa0\xa5\x07\x08\x0f\x10\x11U$null\xd3\t\n\x0b\x0c\r\x0e_\x10\x13CropInfoCurrentRectV$class_\x10\x11CropInfoTotalSize\x80\x03\x80\x04\x80\x02Z{375, 667}_\x10\x14{{0, 0}, {375, 347}}\xd2\x12\x13\x14\x15Z$classnameX$classes_\x10\x1dSSSScreenshotModificationInfo\xa2\x16\x17_\x10\x1dSSSScreenshotModificationInfoXNSObject_\x10\x0fNSKeyedArchiver\xd1\x1a\x1bTroot\x80\x01\x00\x08\x00\x11\x00\x1a\x00#\x00-\x002\x007\x00=\x00C\x00J\x00`\x00g\x00{\x00}\x00\x7f\x00\x81\x00\x8c\x00\xa3\x00\xa8\x00\xb3\x00\xbc\x00\xdc\x00\xdf\x00\xff\x01\x08\x01\x1a\x01\x1d\x01"\x00\x00\x00\x00\x00\x00\x02\x01\x00\x00\x00\x00\x00\x00\x00\x1c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01$', 'editor': '', 'format_id': 'ScreenshotServices', 'base_version': 0, 'format_version': '1.0', 'adjustments': [], 'metadata': None, 'orientation': 0, 'adjustment_format_version': None, 'version_info': None, 'timestamp': '2020-11-11T19:29:32+00:00'}

Also true if editor == "com.apple.mobileslideshow"

and editor == "", format_id == "com.apple.video.slowmo":

{'data': b'bplist00\xd1\x01\x02ZslowMotion\xd2\x03\x04\x05\x16WregionsTrate\xa1\x06\xd1\x07\x08YtimeRange\xd2\t\n\x0b\x14UstartXduration\xd4\x0c\r\x0e\x0f\x10\x11\x12\x13UflagsUvalueYtimescaleUepoch\x10\x03\x12\x17\xb8\xff\x80\x12;\x9a\xca\x00\x10\x00\xd4\x0c\r\x0e\x0f\x10\x15\x12\x13\x12n\xb4\xa8U">\x00\x00\x00\x08\x0b\x16\x1b#(*-7<BKTZ`jprw|~\x87\x8c\x00\x00\x00\x00\x00\x00\x01\x01\x00\x00\x00\x00\x00\x00\x00\x17\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x91', 'editor': '', 'format_id': 'com.apple.video.slomo', 'base_version': 0, 'format_version': '1.1', 'adjustments': [], 'metadata': None, 'orientation': 0, 'adjustment_format_version': None, 'version_info': None, 'timestamp': '2020-11-11T19:29:21+00:00'}
RhetTbull commented 3 years ago

In the case of ScreenshotServices, the bplist appears to be an NSKeyedArchiver archived object...look at placeinfo.py

In case of slowmo videos, bplist appears to be an ordinary plist.