Playing with exif
Exif information is most commonly encountered in pictures from digital cameras. I don’t have a lot of requirements surrounding exif, just the following:
- Losslessly rotate a jpeg image, and also rotate its exif thumbnail and set the exif rotation flag to “Doesn’t need to be rotated”.
- Set the file’s modify time to be the same as its exif timestamp (necessary if there’s been any transformation on the image).
- Change the create time in the exif header if it somehow got wrong. I had to do this when my camera forgot the date and time completely.
- Copy exif information from a RAW file and into a corresponding jpeg (since RawStudio stupidly doesn’t do this for me).
- Totally delete the exif information before putting images on the web.
I had been using jpegtran to rotate my jpegs, and then jhead to update the mtime. I wasn’t totally happy with jhead in particular, because it seems too windowsy and not very complete. Anyway, image rotation worked well with
jpegtran -rotate 90 etc, and jhead did its job:
jhead -ft image.jpg sets the mtime to what exif says, and
jhead -de image.jpg deletes the header altogether. But there are better solutions!
Exiftran is a part of fbida. I stumbled across it and discovered that, unlike jpegtran, it updates the exif information. So now my image rotation commands are:
Rotate 270 degrees (ie anti-clockwise):
% exiftran -2 -o rotated.jpg original.jpg
Rotate 180 degrees
% exiftran -1 -o rotated.jpg original.jpg
Rotate 90 degrees (ie clockwise)
% exiftran -9 -o rotated.jpg original.jpg
And the one I like the best:
Rotate automatically based on the exif rotation tag
% exiftran -a -o rotated.jpg original.jpg
Exiftran can also fix up the mess jpegtran left behind, by using the -ni switch (to not rotate the jpeg, but still rotate the thumbnail and update the rotation tag). The -i switch tells exiftran to write the rotated image out to the original filename, and -p tells it to keep the original mtime when using -i. Someday I may stop using gqview for rotation altogether, and simply do
% exiftran -aip *.jpg
Exiv2 is a program and library for manipulating the exif header. And it doesn’t just work on jpegs, but on any file with exif, such as TIFFs and RAW files. exiv2 is a complicated beast. The options to solve my problems are:
Set the mtime of the file to the exif creation time (like the old jhead -ft did).
% exiv2 mv -T abc.jpg
Copy the exif headers from the Nikon RAW files in /tmp to the correspondingly named jpegs in /data. Not all the exif data makes sense, since the RAW file has been converted to a jpeg, but as far as I’m concerned, it’s close enough. I mostly need the time, and possibly the aperture and shutter speed etc., and that’s all still valid.
% exiv2 in -k -l /tmp -S .nef /data/*.jpg
Remove exif headers from the jpeg file.
% exiv2 rm *.jpg
Neither jhead nor exiv2 can cope with the timestamp used by one of my cameras when the camera’s date hasn’t been set. I have this problem because somehow the camera forgot the date and time and took a bunch of photos without them. As a result I’ve been getting this message:
Failed to parse or convert timestamp +0000:00:00 00:00:00
Goodness knows why none of these programs can only adjust the date, rather than setting it. Anyway, I’ve been able to solve the problem using a hex editor. Thankfully the timestamps (there are 3 of them) are quite easily found and edited in plain text.