Forum Archive

New photos module read metadata

AlainG

Photos read metadata

I am looking at the new photos module. Is it possible to read metadata like description and tags from photos? That would be really cool as it is missing from iOS.

Phuket2

@AlainG , to me it does not look like it. Mind you I haven't done much with photos. There maybe extra you can do with objc. Someone else would have to answer that. But the below snippet might be useful for you.

import photos
album = photos.get_screenshots_album()
screenshots = album.assets
x = screenshots[0]
attr_lst = [a for a in dir(x) if not a.startswith('_')]

for k in attr_lst:
    print(k, getattr(x , k))

print(help(x))
AlainG

Thanks for the quick reply and code ! Awesome! I will look at it a See you on the bitstream ! Alain further.

Phuket2

@AlainG , keep an eye on your post here. Someone might have a way to help you that I dont know about.

zrzka

If you need more properties, like more detailed metada, just check the code at the end of this response. It's for Pythonista 3.1.1 (311014, beta). Output of this code is:

Asset properties
 {
    ColorModel = RGB;
    Depth = 8;
    Orientation = 1;
    PixelHeight = 2048;
    PixelWidth = 2732;
    ProfileName = "Display P3";
    "{Exif}" =     {
        DateTimeOriginal = "2017:08:24 16:48:37";
        PixelXDimension = 2732;
        PixelYDimension = 2048;
        UserComment = Screenshot;
    };
    "{JFIF}" =     {
        DensityUnit = 0;
        JFIFVersion =         (
            1,
            0,
            1
        );
        XDensity = 72;
        YDensity = 72;
    };
    "{TIFF}" =     {
        Orientation = 1;
    };
}
#!python3

from objc_util import ObjCClass, ObjCBlock, ObjCInstance, retain_global
from ctypes import c_void_p
import photos

PHContentEditingInputRequestOptions = ObjCClass('PHContentEditingInputRequestOptions')
CIImage = ObjCClass('CIImage')


def get_last_screenshot():
    album = photos.get_screenshots_album()
    assets = album.assets
    if assets:
        return assets[0]  # PHAsset - https://developer.apple.com/documentation/photos/phasset?language=objc
    return None


def get_asset_properties(asset, handler):
    def _block(_cmd, editing_input, info):
        url = ObjCInstance(editing_input).fullSizeImageURL()
        if not url:
            handler(asset, None)
            return

        image = CIImage.imageWithContentsOfURL_(url)
        if image:
            handler(asset, image.properties())
        else:
            handler(asset, None)

    options = PHContentEditingInputRequestOptions.alloc().init()
    options.setNetworkAccessAllowed_(True)

    block = ObjCBlock(_block, argtypes=[c_void_p, c_void_p, c_void_p])
    retain_global(block)
    ObjCInstance(asset).requestContentEditingInputWithOptions_completionHandler_(options, block)


def main():
    screenshot = get_last_screenshot()
    if not screenshot:
        print('No screenshot')
        return

    def handler(asset, properties):
        print('Asset properties\n', properties)

    get_asset_properties(screenshot, handler)


if __name__ == '__main__':
    main()
omz

@zrzka I suspect that you could make this code significantly simpler by using photos.Asset.get_image_data().

I also suspect that getting the keywords/tags from the Mac Photos app may not actually be possible.

zrzka

@omz yup, here it is, ..., but not sure if it always contains original with all these EXIF datas, ... Long time I did use Photos.framework, AssetsLibrary.framework, ... Apple is constantly changing it.

#!python3

import photos
from objc_util import ObjCClass

CIImage = ObjCClass('CIImage')


def get_last_screenshot():
    album = photos.get_screenshots_album()
    assets = album.assets
    if assets:
        return assets[0]  # PHAsset - https://developer.apple.com/documentation/photos/phasset?language=objc
    return None


def get_asset_properties(asset):
    data = asset.get_image_data().read()
    image = CIImage.imageWithData_(data)
    return image.properties()


def main():
    screenshot = get_last_screenshot()
    if not screenshot:
        print('No screenshot')
        return

    properties = get_asset_properties(screenshot)
    print(properties)


if __name__ == '__main__':
    main()
cvp

I use piexif module from Github and I can read all exifs from a photo, even ones from Apple.

omz

@cvp Neat! Might make sense to bundle that with Pythonista.

zrzka

Just tried CIImage image properties on a photo with keywords, location, faces, ... and here's the output. Unable to find keywords only, everything else is there. Maybe worth adding as Asset.properties property?

alexhamberg

Hello, maybe you can try WidsMob Mac Photo Viewer to browse all pictures in EXIF mode. Thus, you can get all photo metadata by one click.