Created
February 18, 2021 05:56
-
-
Save RhetTbull/5778d8d937f3a546fc6a5ede5a5f2c3e to your computer and use it in GitHub Desktop.
Retrieve adjustment/edit data from edited photos in Apple Photos
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" Read adjustments data for photos edited in Apple's Photos.app | |
In Catalina and Big Sur, the adjustments data (data about edits done to the photo) | |
is stored in a plist file in | |
~/Pictures/Photos Library.photoslibrary/resources/renders/X/UUID.plist | |
where X is first character of the photo's UUID string and UUID is the full UUID, | |
e.g.: ~/Pictures/Photos Library.photoslibrary/resources/renders/3/30362C1D-192F-4CCD-9A2A-968F436DC0DE.plist | |
Thanks to @neilpa who figured out how to decode this information: | |
Reference: https://github.com/neilpa/photohack/issues/4 | |
""" | |
import objc | |
from Foundation import NSClassFromString, NSData, NSPropertyListSerialization | |
# Load PhotoLibraryServices framework needed to access PFAdjustmentSerialization class | |
objc.loadBundle( | |
"PhotoLibraryServices", | |
bundle_path="/System/Library/PrivateFrameworks/PhotoLibraryServices.framework", | |
module_globals=globals(), | |
) | |
objc.registerMetaDataForSelector( | |
b"PFAdjustmentSerialization", | |
b"deserializeDictionaryFromData:error:", | |
{ | |
"retval": {"type": objc._C_ID}, | |
"arguments": { | |
2: {"type": objc._C_ID}, | |
2 + 1: {"type": objc._C_PTR + objc._C_ID, "type_override": objc._C_OUT}, | |
}, | |
}, | |
) | |
PFAdjustmentSerialization = NSClassFromString("PFAdjustmentSerialization") | |
def decode_adjustments_from_plist(plist_file): | |
with objc.autorelease_pool(): | |
plist_data, err = NSData.dataWithContentsOfFile_options_error_( | |
plist_file, 0, None | |
) | |
if err: | |
raise ValueError(f"Error reading plist data from {plist_file}: {err}") | |
plist_dict = NSPropertyListSerialization.propertyListWithData_options_format_error_( | |
plist_data, 0, None, None | |
) | |
return PFAdjustmentSerialization.deserializeDictionaryFromData_error_( | |
plist_dict[0]["adjustmentData"], None | |
) | |
if __name__ == "__main__": | |
import sys | |
for plist in sys.argv[1:]: | |
print(plist) | |
adjustments = decode_adjustments_from_plist(plist) | |
print(adjustments) | |
""" | |
python adjustments.py "/Users/rhet/Pictures/Photos Library.photoslibrary/resources/renders/3/32906695-C79A-4509-9D68-ED96833C0BE3.plist" | |
/Users/rhet/Pictures/Photos Library.photoslibrary/resources/renders/3/32906695-C79A-4509-9D68-ED96833C0BE3.plist | |
{ | |
adjustments = ( | |
{ | |
enabled = 1; | |
formatVersion = 1; | |
identifier = Effect; | |
settings = { | |
effectIntensity = 1; | |
effectName = 3DVividCool; | |
effectVersion = 1; | |
}; | |
} | |
); | |
formatVersion = 1; | |
metadata = { | |
masterHeight = 4032; | |
masterWidth = 3024; | |
orientation = 1; | |
pipelineVersion = "OSX.4"; | |
}; | |
versionInfo = { | |
appVersion = "311.0.130"; | |
buildNumber = 20B28; | |
platform = OSX; | |
schemaRevision = 1; | |
}; | |
} | |
""" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment