tags:

views:

95

answers:

1

My digital camera takes pictures with a very high resolution, and I have a PIL script to shrink them to 800x600 (or 600x800). However, it would be nice for the resultant file to retain the original timestamp. I noticed in the docs that I can use a File object instead of a name in PIL's image save method, but I don't know if that will help or not.

My code is basically name, ext = os.path.splitext(filename)

# open an image file (.bmp,.jpg,.png,.gif) you have in the working folder
image = Image.open(filename)

width = 800
height = 600

w, h = image.size
if h > w:
    width = 600
    height = 800

name = name + ".jpg"
shunken = image.resize((width, height), Image.ANTIALIAS)
shunken.save(name)

Thank you for any help you can give!

+4  A: 

Use shutil.copystat

It appears that PIL does not save EXIF metadata. To copy the EXIF data using Python you could use pyexiv2. This is how Phatch, a batch photo resizer program written in Python, deals with EXIF data, for example.

I'm not sure if you're using Ubuntu, but if so, installation is easy since pyexiv2 is provided by python-pyexiv2 package.

Edit: If you don't mind losing the EXIF metadata, and would simply like to use the EXIF datetime stamp as the resized image's modification date, then you can do it without the pyexiv2 package, thus saving you an extra dependency. Here's how:

import os
import time
import Image
import ExifTags   # This is provided by PIL
img=Image.open(filename,'r')

PIL can read EXIF data, but cannot yet write EXIF data. We can access the data using the _getexif() method:

d = dict((ExifTags.TAGS[k], v) for k, v in img._getexif().items())
print(d['DateTimeOriginal'])

Parsing the timestamp may depend on what format the camera uses. This works for my camera; YMMV. The dateutils package allows you to parse a wide variety of timestamps without you having to pre-specify the format, but that's another story.

timestamp=time.strptime(d['DateTimeOriginal'],"%Y:%m:%d %H:%M:%S")

Here's an alternative way to swap the width and height:

w, h = img.size
width,height = 800,600
if h > w: width,height = height,width

Resizing the image, and using os.utime to fix the atime and mtime:

filename = filename + "-800x600.jpg"
shunken = img.resize((width, height), Image.ANTIALIAS)
shunken.save(filename)
st = os.stat(filename)
os.utime(filename,(st.st_atime,time.mktime(timestamp)))
unutbu
I ended up using os.utime to change the system's notion of date, but pyexiv2 was very useful it reading the time I really wanted, thank you.
Ckhrysze
@Ckhrysze: PIL can read EXIF metadata; it just can't write it. So you could eliminate the dependency on `pyexiv2` if you wish. See my edit for example.
unutbu
I had no idea cameras tagged photos with so much information. Once I started playing around with the pyexiv2 library, I actually ended up tagging the new image with a lot of the original data, since I also just learned that lots of programs pick up on them.On the other hand, being able to do everything with PIL would also be nice, and now I have options. Thanks again!
Ckhrysze