dogsheep / dogsheep-photos

Upload your photos to S3 and import metadata about them into a SQLite database
Apache License 2.0
170 stars 15 forks source link

Try out ExifReader #22

Open simonw opened 4 years ago

simonw commented 4 years ago

https://pypi.org/project/ExifReader/

New fork that should be able to handle EXIF in HEIC files.

Forked here: https://github.com/ianare/exif-py/issues/102#issuecomment-626376522

Refs #3

RhetTbull commented 4 years ago

@simonw FYI, osxphotos includes a built in ExifTool class that uses exiftool to read and write exif data. It's not exposed yet in the docs because I really only use it right now in the osphotos command line interface to write tags when exporting. In v0.28.16 (just pushed) I added an ExifTool.as_dict() method which will give you a dict with all the exif tags in a file. For example:

import osxphotos
photos = osxphotos.PhotosDB().photos()
exiftool = osxphotos.exiftool.ExifTool(photos[0].path)
exifdata = exiftool.as_dict()
tags = exifdata["IPTC:Keywords"]

Not as elegant perhaps as a python only implementation because ExifTool has to make subprocess calls to an external tool but exiftool is by far the best tool available for reading and writing EXIF data and it does support HEIC.

As for implementation, ExifTool uses a singleton pattern so the first time you instantiate it, it spawns an IPC to exiftool but then keeps it open and uses the same process for any subsequent calls (even on different files).

simonw commented 4 years ago

Interesting - do you know if there's anything the exiftool process handles that ExifReader doesn't?

I'm actually just going to extract a subset of the EXIF data at first - since the original photo files will always be available I don't feel the need to get everything out for the first step.

My plan is to use EXIF to help support photo collections that aren't in Apple Photos - I'm going to build a database table keyed by the sha256 of each photo that extracts the camera make, lens, a few settings (ISO, aperture etc) and the GPS lat/lon.

RhetTbull commented 4 years ago

I'm not familiar with ExifReader. I wrote my own wrapper around exiftool because I wanted a simple way to write EXIF data when exporting photos (e.g. writing out to PersonInImage and keywords to IPTC:Keywords) and the existing python packages like pyexiftool didn't do quite what I wanted. If all you're after is the camera and shot info, that's available in ZEXTENDEDATTRIBUTES table. I've got an open issue #11 to add this to osxphotos but it hasn't bubbled to the top of my backlog yet.

osxphotos will give you the location info: PhotoInfo.location returns a tuple of (lat, lon) though this info is in ZEXTENDEDATTRIBUTES too (though it might not be correct as I believe Photos creates this table at import and the user might have changed the location of a photo, e.g. if camera didn't have GPS).

CREATE TABLE ZEXTENDEDATTRIBUTES (
  Z_PK INTEGER PRIMARY KEY, Z_ENT INTEGER, 
  Z_OPT INTEGER, ZFLASHFIRED INTEGER, 
  ZISO INTEGER, ZMETERINGMODE INTEGER, 
  ZSAMPLERATE INTEGER, ZTRACKFORMAT INTEGER, 
  ZWHITEBALANCE INTEGER, ZASSET INTEGER, 
  ZAPERTURE FLOAT, ZBITRATE FLOAT, ZDURATION FLOAT, 
  ZEXPOSUREBIAS FLOAT, ZFOCALLENGTH FLOAT, 
  ZFPS FLOAT, ZLATITUDE FLOAT, ZLONGITUDE FLOAT, 
  ZSHUTTERSPEED FLOAT, ZCAMERAMAKE VARCHAR, 
  ZCAMERAMODEL VARCHAR, ZCODEC VARCHAR, 
  ZLENSMODEL VARCHAR
);
RhetTbull commented 4 years ago

I've added support for the above exif data to v0.28.17 of osxphotos. PhotoInfo.exif_info will return an ExifInfo dataclass object with the following properties:

    flash_fired: bool
    iso: int
    metering_mode: int
    sample_rate: int
    track_format: int
    white_balance: int
    aperture: float
    bit_rate: float
    duration: float
    exposure_bias: float
    focal_length: float
    fps: float
    latitude: float
    longitude: float
    shutter_speed: float
    camera_make: str
    camera_model: str
    codec: str
    lens_model: str

It's not all the EXIF data available in most files but is the data Photos deems important to save. Of course, you can get all the exif_data

Note: this only works in Photos 5. As best as I can tell, EXIF data is not stored in the database for earlier versions.