def get_datetime_of_image(img_path: Path) -> datetime: meta = ImageMetadata(str(img_path)) meta.read() return meta.get("Exif.Image.DateTime").value
def read_exif(self, input_temp_file): fields = [ 'ImageSize', 'ProfileDescription', 'ColorType', 'FileType', 'Transparency' ] fields += self.context.config.EXIF_FIELDS_TO_KEEP command = [ '-s', '-s', ] command += ['-{0}'.format(i) for i in fields] # T172556 We read EXIF Orientation with pyexiv2 because exiftool is # unreliable for that field (overzealous in the way it interprets the field). # We can't replace all use of exiftool with pyexiv2 because ICC profile # support was only introduced in exiv2 0.26 (not available on Jessie yet) # and it can only extract the ICC profile, not get its name/description upfront. # Which would make the sRGB replacement more difficult (it's unclear how many # variations of the binary content for that family of profiles there are). metadata = ImageMetadata(input_temp_file.name) try: # T178072 pyexviv2 writes to stderr even if the exception is caught logging.disable(logging.ERROR) metadata.read() logging.disable(logging.NOTSET) if 'Exif.Image.Orientation' in metadata.exif_keys: # Distinctive key name to avoid colliding with EXIF_FIELDS_TO_KEEP self.exif['Pyexiv2Orientation'] = metadata.get('Exif.Image.Orientation').value except IOError: logging.disable(logging.NOTSET) self.debug('[IM] Could not read EXIF with pyexiv2') stdout = Engine.exiftool.command( context=self.context, pre=command, input_temp_file=input_temp_file ) for s in stdout.splitlines(): values = s.split(': ', 1) self.exif[values[0]] = values[1] self.debug('[IM] EXIF: %r' % self.exif) if 'ImageSize' in self.exif: self.internal_size = map(int, self.exif['ImageSize'].split('x')) else: # Have not been able to find a test file where that EXIF field comes up unpopulated self.internal_size = (1, 1) # pragma: no cover # If we encounter any non-sRGB ICC profile, we save it to re-apply # it to the result if 'ProfileDescription' not in self.exif: self.debug('[IM] File has no ICC profile') return expected_profile = self.context.config.EXIF_TINYRGB_ICC_REPLACE.lower() profile = self.exif['ProfileDescription'].lower() if profile == expected_profile: self.icc_profile_path = self.context.config.EXIF_TINYRGB_PATH self.debug('[IM] File has sRGB profile') return self.debug('[IM] File has non-sRGB profile') command = [ '-icc_profile', '-b', '-m', ] self.icc_profile_saved = Engine.exiftool.command( context=self.context, pre=command, input_temp_file=input_temp_file )