I'm writing a script to save metadata to jpg images and resize them for Wordpress. It's been going well, working with jpegs and pngs until I try and use it on an image directly after resizing a jpg (but not a png) with PIL.Image.thumbnail()
I've tried to compress it all down in to one easy-to-read class to help with anyone who can help answer the question. The main class is MetaGator (meta mitigator) which writes the attributes 'title' and 'description' to the appropriate metadata field in the file.
import PIL
from PIL import Image
from PIL import PngImagePlugin
from pyexiv2.metadata import ImageMetadata
from PIL import Image
import os
import re
from time import time, sleep
class MetaGator(object):
"""docstring for MetaGator"""
def __init__(self, path):
super(MetaGator, self).__init__()
if not os.path.isfile(path):
raise Exception("file not found")
self.dir, self.fname = os.path.split(path)
def write_meta(self, title, description):
name, ext = os.path.splitext(self.fname)
title, description = map(str, (title, description))
if( ext.lower() in ['.png']):
try:
new = Image.open(os.path.join(self.dir, self.fname))
except Exception as e:
raise Exception('unable to open image: '+str(e))
meta = PngImagePlugin.PngInfo()
meta.add_text("title", title)
meta.add_text("description", description)
try:
new.save(os.path.join(self.dir, self.fname), pnginfo=meta)
except Exception as e:
raise Exception('unable to write image: '+str(e))
elif(ext.lower() in ['.jpeg', '.jpg']):
try:
imgmeta = ImageMetadata(os.path.join(self.dir, self.fname))
imgmeta.read()
except IOError:
raise Exception("file not found")
for index, value in (
('Exif.Image.DocumentName', title),
('Exif.Image.ImageDescription', description),
('Iptc.Application2.Headline', title),
('Iptc.Application2.Caption', description),
):
print " -> imgmeta[%s] : %s" % (index, value)
if index in imgmeta.iptc_keys:
imgmeta[index] = [value]
if index in imgmeta.exif_keys:
imgmeta[index] = value
imgmeta.write()
else:
raise Exception("not an image file")
def read_meta(self):
name, ext = os.path.splitext(self.fname)
title, description = '', ''
if(ext.lower() in ['.png']):
oldimg = Image.open(os.path.join(self.dir, self.fname))
title = oldimg.info.get('title','')
description = oldimg.info.get('description','')
elif(ext.lower() in ['.jpeg', '.jpg']):
try:
imgmeta = ImageMetadata(os.path.join(self.dir, self.fname))
imgmeta.read()
except IOError:
raise Exception("file not found")
for index, field in (
('Iptc.Application2.Headline', 'title'),
('Iptc.Application2.Caption', 'description')
):
if(index in imgmeta.iptc_keys):
value = imgmeta[index].value
if isinstance(value, list):
value = value[0]
if field == 'title': title = value
if field == 'description': description = value
else:
raise Exception("not an image file")
return {'title':title, 'description':description}
if __name__ == '__main__':
print "JPG test"
fname_src = '<redacted>.jpg'
fname_dst = '<redacted>-test.jpg'
metagator_src = MetaGator(fname_src)
metagator_src.write_meta('TITLE', time())
print metagator_src.read_meta()
image = Image.open(fname_src)
image.thumbnail((10,10))
image.save(fname_dst)
metagator_dst = MetaGator(fname_dst)
metagator_dst.write_meta('TITLE', time())
print metagator_dst.read_meta()
sleep(5)
metagator_dst = MetaGator(fname_dst)
metagator_dst.write_meta('TITLE', time())
print metagator_dst.read_meta()
print "PNG test"
fname_src = '<redacted>.png'
fname_dst = '<redacted>-test.png'
metagator_src = MetaGator(fname_src)
metagator_src.write_meta('TITLE', time())
print metagator_src.read_meta()
image = Image.open(fname_src)
image.thumbnail((10,10))
image.save(fname_dst)
metagator_dst = MetaGator(fname_dst)
metagator_dst.write_meta('TITLE', time())
print metagator_dst.read_meta()
sleep(5)
metagator_dst = MetaGator(fname_dst)
metagator_dst.write_meta('TITLE', time())
print metagator_dst.read_meta()
The code I used to test it is in main and gives the following output:
JPG test
-> imgmeta[Exif.Image.DocumentName] : TITLE
-> imgmeta[Exif.Image.ImageDescription] : 1429683541.3
-> imgmeta[Iptc.Application2.Headline] : TITLE
-> imgmeta[Iptc.Application2.Caption] : 1429683541.3
{'description': '1429683541.3', 'title': 'TITLE'}
-> imgmeta[Exif.Image.DocumentName] : TITLE
-> imgmeta[Exif.Image.ImageDescription] : 1429683541.31
-> imgmeta[Iptc.Application2.Headline] : TITLE
-> imgmeta[Iptc.Application2.Caption] : 1429683541.31
{'description': '', 'title': ''}
-> imgmeta[Exif.Image.DocumentName] : TITLE
-> imgmeta[Exif.Image.ImageDescription] : 1429683546.32
-> imgmeta[Iptc.Application2.Headline] : TITLE
-> imgmeta[Iptc.Application2.Caption] : 1429683546.32
{'description': '', 'title': ''}
PNG test
{'description': '1429683546.32', 'title': 'TITLE'}
{'description': '1429683546.83', 'title': 'TITLE'}
{'description': '1429683551.83', 'title': 'TITLE'}
As you can see, in the JPG test, it works fine on a normal file, but doesn't work at all after PIL resizes an image. This doesn't happen with the .PNG, which uses PIL to save the metadata, which would make me suggest that it's pyexiv2 that is the problem.
What should I try? Any suggestions would be helpful.
Thank you.