def test_read_value_from_exif_and_iptc(self): # Create an image. file_descriptor, file_path = tempfile.mkstemp(suffix='.jpg') os.close(file_descriptor) Image.new('RGB', (1, 1)).save(file_path, 'JPEG') metadata = pyexiv2.Image(file_path) metadata.readMetadata() keys = ('Exif.Image.ImageDescription', 'Iptc.Application2.Caption') exif_val = 'Test file with Exif description tag' iptc_val = 'Test file with IPTC description tag' # Read metadata from image after conflicting Exif and IPTC # have been added to the image. Exif should be preferred. metadata['Exif.Image.ImageDescription'] = exif_val metadata['Iptc.Application2.Caption'] = iptc_val metadata.writeMetadata() metadata = pyexiv2.Image(file_path) metadata.readMetadata() self.assertEqual(read_value_from_exif_and_iptc(metadata, *keys), exif_val) # Read metadata value when image contains only Exif. _del_img_key(metadata, 'Iptc.Application2.Caption') metadata.writeMetadata() self.assertEqual(read_value_from_exif_and_iptc(metadata, *keys), exif_val) # Read metadata value when image contains only IPTC. _del_img_key(metadata, 'Exif.Image.ImageDescription') metadata['Iptc.Application2.Caption'] = iptc_val metadata.writeMetadata() metadata = pyexiv2.Image(file_path) metadata.readMetadata() self.assertEqual(read_value_from_exif_and_iptc(metadata, *keys), iptc_val) # Attempt to read nonexistent metadata. _del_img_key(metadata, 'Iptc.Application2.Caption') metadata.writeMetadata() self.assertEqual(read_value_from_exif_and_iptc(metadata, *keys), None) # Clean up. os.remove(file_path)
def sync_metadata_from_file(self, commit=True): """\ Synchronizes the image metadata from the filesystem to the object. This reads certain properties of the object from Exif and/or IPTC tags in the image file itself, allowing the information to be portable from outside of this application. Metadata is only actually written to the database if the values do not match up, however. Returns True if metadata needed to be written to the database; False otherwise. """ if not self.metadata_sync_enabled: return False try: image_metadata = pyexiv2.Image(self.image.path) image_metadata.readMetadata() except IOError: self.metadata_sync_enabled = False self.save() return False mod_instance = False # whether or not database needs written to # sync description mod_attr = not value_synced_with_exif_and_iptc( self.description, image_metadata, 'Exif.Image.ImageDescription', 'Iptc.Application2.Caption') mod_instance = mod_attr or mod_instance if mod_attr: value = read_value_from_exif_and_iptc(image_metadata, 'Exif.Image.ImageDescription', 'Iptc.Application2.Caption') if value is None: value = str() self.description = value # sync artist mod_attr = not value_synced_with_exif_and_iptc( self.artist, image_metadata, 'Exif.Image.Artist', 'Iptc.Application2.Byline') mod_instance = mod_attr or mod_instance if mod_attr: value = read_value_from_exif_and_iptc(image_metadata, 'Exif.Image.Artist', 'Iptc.Application2.Byline') if value is None: value = str() self.artist = value # sync country mod_attr = not value_synced_with_iptc(self.country, image_metadata, 'Iptc.Application2.CountryName') mod_instance = mod_attr or mod_instance if ('Iptc.Application2.CountryName' in image_metadata.iptcKeys() and mod_attr): value = image_metadata['Iptc.Application2.CountryName'] if value is None: value = str() self.country = value # sync province_state mod_attr = not value_synced_with_iptc( self.province_state, image_metadata, 'Iptc.Application2.ProvinceState') mod_instance = mod_attr or mod_instance if ('Iptc.Application2.ProvinceState' in image_metadata.iptcKeys() and mod_attr): value = image_metadata['Iptc.Application2.ProvinceState'] if value is None: value = str() self.province_state = value # sync city mod_attr = not value_synced_with_iptc(self.city, image_metadata, 'Iptc.Application2.City') mod_instance = mod_attr or mod_instance if 'Iptc.Application2.City' in image_metadata.iptcKeys() and mod_attr: value = image_metadata['Iptc.Application2.City'] if value is None: value = str() self.city = value # sync location mod_attr = not value_synced_with_iptc(self.location, image_metadata, 'Iptc.Application2.SubLocation') mod_instance = mod_attr or mod_instance if ('Iptc.Application2.SubLocation' in image_metadata.iptcKeys() and mod_attr): value = image_metadata['Iptc.Application2.SubLocation'] if value is None: value = str() self.location = value # sync time_created mod_attr = not datetime_synced_with_exif_and_iptc( self.time_created, image_metadata, 'Exif.Photo.DateTimeOriginal', 'Iptc.Application2.DateCreated', 'Iptc.Application2.TimeCreated') mod_instance = mod_attr or mod_instance if mod_attr: self.time_created = read_datetime_from_exif_and_iptc( image_metadata, 'Exif.Photo.DateTimeOriginal', 'Iptc.Application2.DateCreated', 'Iptc.Application2.TimeCreated') # sync keywords mod_attr = not value_synced_with_iptc(self.keyword_list, image_metadata, 'Iptc.Application2.Keywords') mod_instance = mod_attr or mod_instance if ('Iptc.Application2.Keywords' in image_metadata.iptcKeys() and mod_attr): self.keyword_list = image_metadata['Iptc.Application2.Keywords'] if mod_instance and commit: self.save() return mod_instance