Overlaying exif tags onto viewed image

Being blessed with a pretty rub­bish mem­ory I’ve become a big fan of Spaced Rep­e­ti­tion Sys­tems over the years. I’ve tried sev­eral but have set­tled down with the reas­sur­ingly sim­ple mnemosyne pro­gram. mnemosyne has been out for a long time and the cur­rently sta­ble release is 1.2 although there is now a beta ver­sion 2.x.

I use images a lot in my mnemosyne deck espe­cially for learn­ing plants and trees. One of the prob­lems I have is that mnemosyne doesn’t allow full screen view­ing of the images or zoom­ing in and out, although I think that is addressed in the new beta. Fur­ther­more, the 1.x release doesn’t really sup­port the idea of cram­ming, or ad-hoc test­ing, so if I, for exam­ple, want to have a browse through all my tree win­ter ident pho­tos it’s not par­tic­u­larly straightforward.

Most of my pho­tos are pretty well tagged and are cur­rently enjoy­ing a some­what hap­haz­ard jour­ney from f-spot to shotwell, but on the whole they are tagged, with the meta data phys­i­cally writ­ten to the files them­selves. For some time I’ve been mus­ing over a quick and easy way of brows­ing my images based on sim­ple search cri­te­ria but with lim­ited suc­cess. Often I rename images which has the ben­e­fit of mak­ing them rapidly find­able using the linux locate com­mand but this is not with­out its problems.

Ide­ally what I was after was a way of brows­ing images full-screen with the abil­ity to zoom in and out, skip­ping for­ward ran­domly or sequen­tially, and, impor­tantly, when I wanted to, eas­ily view­ing the exif tags writ­ten to the image.

I’m pretty much there, thanks to a shy lit­tle pro­gram called qiv. I don’t know where qiv has been all my life but it’s pretty much every­thing I like about a util­ity. Lean, mean and does what it does well. Using a bit of script­ing and link­ing I get the images I’m inter­ested together and chuck them some­where, such as /jlinks/imagebatch1. Then I invoke qiv with some­thing like:

qiv --autorotate --maxpect --fullscreen --delay=10 --random --no_statusbar --file /tmp/flist

where /tmp/flist con­tains the list of files I want to browse through.

This works pretty well. But there are problems.

If I want to see some infor­ma­tion about the image I’m view­ing, such as its file­name, I can press ‘i’. This dis­plays the sta­tus bar and if you hap­pen to be using mean­ing­ful file­names as I usu­ally do this can be suf­fi­cient to find out the name of the plant, bird, what­ever, you’re look­ing at. The prob­lem is that the text in the sta­tus line is too small for me. I can read it but it’s a bit of an effort. I searched for a solu­tion to this, assum­ing that it would be pos­si­ble to change the text size. If it is I guess it needs a bit of pro­gram­ming as it’s not read­ily obvi­ous if it’s pos­si­ble to recon­fig­ure it in any other way.

What I wanted really was a way to super­im­pose the file­name onto the image itself, in nice big let­ters. As is often the way I spent a lot of hours look­ing for a solu­tion that was star­ing me in the face.

qiv allows you to call an exter­nal com­mand based on cer­tain key­presses. It took me a while to realise that, far from being quite com­pli­cated, it was sim­ply a mat­ter of tak­ing the sam­ple qiv-command script that is shipped with qiv, chuck­ing it into my search path, and then hack­ing it to bits.

I’m still exper­i­ment­ing and for the moments I have a few options in my qiv-command file that dis­play the infor­ma­tion I’m inter­ested in. Most of the time I am inter­ested in the exif key­word tags embed­ded in the image as they reli­ably tell me what it is I’m look­ing at. They are retrieved in no par­tic­u­lar order but that doesn’t mat­ter — it does the job. I also found another util­ity called gnome-osd-client was pretty handy for over­lay­ing the text I wanted.

Here, for exam­ple, is the sec­tion of my qiv-command file for what hap­pens if there is a key­press of 0.

0)
 title=$(exiftool -t -title "${filename}")
 where=$(exiftool -t -Country -State -City -Location "${filename}")
 rating=$(exiftool -T -Rating "${filename}")
 tags=$(exiftool -t -Subject "${filename}")
 gnome-osd-client "${title} ""${tags}"" (Rating=${rating}) ${where}"
 ;;

This uses exiftool to get the infor­ma­tion I’m inter­ested in, then gnome-osd-client to dis­play it. gnome-osd-client isn’t actu­ally nec­es­sary, and other options I have are

 2)
  exiftool -t -title -Subject -Country -State -City -Location -model -Rating "$filename"

and even the brief (pro­duc­ing verbose)

 3)
  exiftool "${filename}"
  ;;

One curios­ity I dis­cov­ered dur­ing all this is that the –T switch on exiftool seems to cause con­ster­na­tion with gnome-osd-client. Unfor­tu­nately I was using this a lot ear­lier on and assumed that it was some­thing I was doing wrong, whereas it just seems to be a quirky clash between the two util­i­ties. If you use –T any­where with exiftool in the gnome-osd-client com­mand you will get an error. e.g.

 4)
  gnome-osd-client "$(exiftool -T -title -Subject -Country -State -City -Location -model -Rating "${filename}")"
  ;;

will fail.

Of course, this doesn’t give you any of the spaced rep­e­ti­tion logic that you’d get from using a sys­tem such as mnemosyne, and per­haps with mnemosyne 2.x this sort of facil­ity might be bui­ilt in any­way. How­ever it’s quite nice to just spec­ify a search key­word and get a slab of brows­able images on the screen.

f-spot, exiftool, exiv2, and exif header weirdness

I decided to revisit an old bug that I logged about a prob­lem I have with f-spot han­dling of exif head­ers. Now I’m more con­fused than ever. I can see what’s hap­pen­ing, but not how or why.

The prob­lem I’m hav­ing is that when I upload some pho­tos to gallery web­sites the han­dling of exif data doesn’t appear con­sis­tent. For exam­ple, have a look at this photo. If you look at the right hand side of the screen where the photo title is shown it also shows the cap­tion. It looks like this:

From Zenfolio gallery

Now have a look at the same photo uploaded to pica­s­aweb (the sizes are slightly dif­fer­ent — I think pica­s­aweb changed them on the fly when I uploaded via google plus). In this case there is no gar­bled text and pica­s­aweb has used the exif descrip­tion field for the photo cap­tion. i.e:

from picasaweb

So what’s hap­pen­ing here? Well, here’s what I think is hap­pen­ing. Pica­s­aweb is extract­ing the cap­tion from the exif field Description, and Zen­fo­lio is extract­ing the cap­tion from the field UserComment. Here’s what I get if I run exiftool on the image file (you might need to click on the image to see it properly):

exiftool -UserComment -Description test1.jpg

As you can see the User­Com­ment field con­tains gar­bled characters.

A lot of my pho­tos have this and the incon­sis­ten­cies can cause me headaches. I decided on a brute-force scan of my photo col­lec­tion to address the issue. I thought, why not just dupli­cate the Descrip­tion field into the User­Com­ment field? That way, what­ever pack­age or gallery reads the image file will prob­a­bly get the cap­tion. So here’s the script I used:

#!/bin/bash

#
#       Process all jpegs and overwrite UserComment field with Description
#       field where they differ.
#
find /jpegs -type f -iname '*.jpg' | while read fname
do
        field_usercomment=$(exiftool -UserComment "${fname}" | sed 's/^.*: //')
        field_description=$(exiftool -Description "${fname}" | sed 's/^.*: //')

        if [[ "${field_usercomment}" != "${field_description}" ]] ; then

                echo "$fname"
                echo "User Comment: ${field_usercomment}"
                echo "Description: ${field_description}"
                echo

                echo "${fname}"
                exiftool -overwrite_original -UserComment="${field_description}" "${fname}"
                echo
        fi
done

After a sat­is­fy­ing hour or two my pho­tos all looked a bit tidier. So now I have a cludge — some­thing that will get round the prob­lem. But I’d really like to treat the cause, and not the symp­tom. So what’s the cause?

My first guess has always been the cam­era. I have a knack­ered old Nikon Coolpix that gives me prob­lems. But I see this prob­lem with other cam­eras too, my Canon DSLR and com­pact cam­era have acquired the gar­bled field in some pic­tures too.

So I turn to f-spot, the photo-management soft­ware I use in Linux Mint. I checked the exiftool out­put from a test file, then imported it into f-spot. I then added a tag so that f-spot would write out the exif data (I have f-spot con­fig­ured to Store Tags and Descrip­tion inside image files where pos­si­ble) then had a look at the image file. Here’s what I got:

exiftool output

The out­put from the first invo­ca­tion of exiftool is on the jpeg before import­ing into f-spot. The sec­ond exam­ple shows the out­put of exiftool run on the file after it has been imported into f-spot. It looks like f-spot does some­thing to the image that man­gles the UserComment field.

At this point I assumed (erro­neously I think) that f-spot must be stor­ing the UserComment and Description fields in its sqlite data­base. Using sqlite3 on the com­mand line I had a look at the struc­ture of the pho­tos table:

dougie@phoenix ~ $ echo '.schema photos' | sqlite3 .config/f-spot/photos.db
CREATE TABLE photos (
    id            INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
    time            INTEGER NOT NULL,
    base_uri        STRING NOT NULL,
    filename        STRING NOT NULL,
    description        TEXT NOT NULL,
    roll_id            INTEGER NOT NULL,
    default_version_id    INTEGER NOT NULL,
    rating            INTEGER NULL
);
dougie@phoenix ~ $

There’s the description field, but no UserComment field. But it looks to me that f-spot is cer­tainly writ­ing to the UserComment field when it updates an image file. Per­haps it’s depen­dent on the type of con­tents of the Description field. It doesn’t, how­ever, make any dif­fer­ence as far as I can tell what the con­tents of the Description field are. In this exam­ple the text ends with an excla­ma­tion mark, but I can’t detect any pat­tern in the text I put in Description fields that might pro­vide a clue.

So if f-spot isn’t stor­ing the UserComment field directly what, when, and why is it writ­ing to the field in the image file? It seems that here we enter the murky world of XMP and I rapidly lose the ten­u­ous grasp I had on the under­ly­ing tech­nol­ogy up to this point.

Back in 2008 there was a dis­cus­sion on the f-spot mail­ing list about how f-spot stores its data in the image file. Re-reading that thread it sounds as if f-spot writes its tags to the XMP meta­data and not all util­i­ties are able to read that. This was 2008 mind, and f-spot has jumped a few ver­sions since then.

Out of the same thread came a hint on using exiv2. This is a tool I use a lot, espe­cially for adjust­ing ‘date taken’ time­stamps, but hadn’t found it any use for extract­ing the UserComment field. It turns out I hadn’t RTFM prop­erly and it is pos­si­ble if you tell exiv2 to look at XMP data. This leads to some inter­est­ing out­put. Here is the exam­ple file again, using both exiv2 and exiftool to exam­ine the field contents:

dougie@phoenix ~ $
dougie@phoenix ~ $ exiftool -UserComment -Description /jpegs/2011/07/17/test1.jpg
User Comment                    : 桷⁹畲污湯⁧桴⁥敢捡⁨桷湥礠畯挠湡挠瑵琠敨挠牯敮ⅲ††††††††††††
Description                     : why run along the beach when you can cut the corner!
dougie@phoenix ~ $
dougie@phoenix ~ $ exiv2 -p a /jpegs/2011/07/17/test1.jpg
Exif.Image.ImageDescription                  Ascii      77  why run along the beach when you can cut the corner!                        
Exif.Image.Software                          Ascii      21  f-spot version 0.8.0
Exif.Image.ExifTag                           Long        1  162
Exif.Photo.DateTimeOriginal                  Ascii      20  2011:07:17 09:37:13
Exif.Photo.UserComment                       Undefined  84  why run along the beach when you can cut the corner!                        
Exif.Image.GPSTag                            Long        1  296
Exif.GPSInfo.GPSVersionID                    Byte        4  2.0.0.0
Exif.GPSInfo.GPSLatitudeRef                  Ascii       2  North
Exif.GPSInfo.GPSLatitude                     Rational    3  55deg 32' 25.410"
Exif.GPSInfo.GPSLongitudeRef                 Ascii       2  West
Exif.GPSInfo.GPSLongitude                    Rational    3  1deg 37' 58.960"
Exif.GPSInfo.GPSAltitudeRef                  Byte        1  Above sea level
Exif.GPSInfo.GPSAltitude                     Rational    1  9.5 m
Exif.GPSInfo.GPSTimeStamp                    SRational   3  09:37:13
Exif.GPSInfo.GPSMapDatum                     Ascii       7  WGS-84
Exif.GPSInfo.GPSDateStamp                    Ascii      11  2011:07:17
Xmp.xmp.CreateDate                           XmpText    19  17/07/2011 09:37:13
Xmp.xmp.Rating                               XmpText     1  0
Xmp.xmp.CreatorTool                          XmpText    20  f-spot version 0.8.0
Xmp.dc.description                           LangAlt     1  lang="x-default" why run along the beach when you can cut the corner!                        
Xmp.dc.subject                               XmpBag      2  Dougie Nisbet, Coastal Run - 2011
Xmp.exif.UserComment                         LangAlt     1  lang="x-default" why run along the beach when you can cut the corner!                        
dougie@phoenix ~ $

Inter­est­ingly, exiv2 is dis­play­ing the UserComment data in clear text, in two places, which I’m guess­ing must be some­thing to do with the dif­fer­ent types of meta­data — XMP and EXIF.

So does this mean this has noth­ing to do with f-spot at all? If exiv2 is able to read the text, per­haps it’s some­thing to do with the util­ity used to exam­ine the image file? If I have a look at the file using gee­qie and open up the EXIF win­dow geeqie seems to under­stand the text too:

geeqie EXIF window

Per­haps this is an unre­lated set­ting I need to have a look at. Lan­guage, Locale, who knows. The issue seems to crop up in dif­fer­ent places so it may very well be unre­lated to f-spot. For the time being I have a fairly straight­for­ward work-around, I just need to remem­ber to run a script to copy the descrip­tion field into the UserComment field for any images I update in f-spot. It’s a bit of a nui­sance but fairly easy to auto­mate, and a lot less time-consuming than try­ing to get to the bot­tom of the mystery!

How to deal with exif stuff in Coolpix images that f-spot doesn’t like

I have a bat­tered and knack­ered old Nikon Coolpix S600 cam­era. The zoom no longer works and it can be quite cranky. It’s not sur­pris­ing as it has a tough time. It often gets car­ried on fell races and road races in, er, ‘hos­tile’ con­di­tions. Its com­pact size and ‘sports’ set­ting makes it handy for fir­ing and for­get­ting. I have a Canon com­pact that gets sim­i­lar treat­ment but on the whole the Canon can’t take the pun­ish­ment that the Nikon can.

The prob­lem I have with the Nikon is that there seems to be issues with the exif data. Whether it’s the cam­era, the camera’s firmware, or the soft­ware I use on the PC to process images, I don’t know. The upshot is the same, though, I have prob­lems writ­ing exif data back to the jpegs from the photo man­age­ment soft­ware f-spot.

I always start f-spot on the com­mand line in debug mode and save the out­put to a file. This way I can get a bet­ter idea of what’s going on. i.e.

f-spot --debug 2>&1 | tee /home/dougie/f-spot.out

(there’s a wrap­per script involved too that takes a backup of the old data­base first).

Once I have the images in f-spot I start apply­ing tags. I have f-spot con­fig­ured so that it writes tags to the image file itself as this gives me greater flex­i­bil­ity if I start copy­ing pho­tos around the place or into other pack­ages. This set­ting is in f-spot under Edit / Pref­er­ences. i.e.

write image data to file

So now I have my pho­tos and I’ve applied some tags to them. But if I have a look at the ter­mi­nal ses­sion where I started f-spot, I can see there are prob­lems. The mes­sages will typ­i­cally look some­thing like this:

[4 Debug 21:39:15.516] open uri = file:///jpegs/2011/06/11/DSCN5936.JPG
[4 Debug 21:39:15.940] Invalid thumbnail, reloading: file:///jpegs/2011/06/11/DSCN5934.JPG
[4 Debug 21:39:15.942] open uri = file:///jpegs/2011/06/11/DSCN5934.JPG
[14 Debug 21:39:15.968] Syncing metadata to file (file:///jpegs/2011/06/11/DSCN5928.JPG)...
[14 Warn 21:39:15.970] Metadata of file file:///jpegs/2011/06/11/DSCN5928.JPG may be corrupt, refusing to write to it, falling back to XMP sidecar.
[4 Debug 21:39:16.359] Invalid thumbnail, reloading: file:///jpegs/2011/06/11/DSCN5931.JPG
[4 Debug 21:39:16.360] open uri = file:///jpegs/2011/06/11/DSCN5931.JPG
[14 Debug 21:39:16.569] Syncing metadata to file (file:///jpegs/2011/06/11/DSCN5924.JPG)...
[14 Warn 21:39:16.571] Metadata of file file:///jpegs/2011/06/11/DSCN5924.JPG may be corrupt, refusing to write to it, falling back to XMP sidecar.
[4 Debug 21:39:16.786] Invalid thumbnail, reloading: file:///jpegs/2011/06/11/DSCN5928.JPG
[4 Debug 21:39:16.787] open uri = file:///jpegs/2011/06/11/DSCN5928.JPG
[14 Debug 21:39:17.153] Syncing metadata to file (file:///jpegs/2011/06/11/DSCN5914.JPG)...
[14 Warn 21:39:17.154] Metadata of file file:///jpegs/2011/06/11/DSCN5914.JPG may be corrupt, refusing to write to it, falling back to XMP sidecar.

The prob­lem for me is two-fold

  1. f-spot has a prob­lem with the meta­data in the jpeg.
  2. It’s cre­at­ing extra .xmp files that I don’t want.

I’ve tried sev­eral avenues to resolve this and I thought the fol­low­ing would do the trick:

jhead -purejpg

This uses the Linux util­ity jhead to rewrite the image header with a stan­dard one. Unfor­tu­nately the prob­lem per­sists. So I took a more bru­tal approach. I used the linux util­ity exiftool to oblit­er­ate all meta data from the image.

At first I’d copy all the images from the mem­ory card into a direc­tory and then run exiftool on all the files there. i.e.

exiftool -all= *

(Note that syn­tax; there’s a space between the equal sign and asterix)

This is fine but unfor­tu­nately it pretty much destroys any use­ful or inter­est­ing extra infor­ma­tion. Most I can live with­out, except the date and time that the photo was taken. It auto­mat­i­cally inher­its the file mod­i­fi­ca­tion time instead.

The solu­tion is to first read the jpegs into f-spot, then, while f-spot is still run­ning, go to the direc­tory where the images have been imported to, then run the exiftool com­mand there. In my setup, I have f-spot con­fig­ured to copy all imported jpegs to /jpegs where they are auto­mat­i­cally arranged in direc­to­ries accord­ing to date and time. So the pro­ce­dure for me is as follows:

  1. Import jpegs into f-spot
  2. With f-spot run­ning, change to des­ti­na­tion direc­tory where jpegs were imported to
  3. Run exiftool -all= *
  4. carry out tag­ging oper­a­tions in f-spot

The advan­tage of this is that despite oblit­er­at­ing the meta data in the files using exiftool, f-spot still knows the data and times of these pho­tos in its own data­base. So the next time you write to them with f-spot, by adding a tag for instance, they will get the date and time from f-spot. You lose pretty much every­thing else, which is a shame, but the date and time are what’s most impor­tant for me.

Typ­i­cally what I tend to do is read all the pho­tos from the mem­ory card into a tem­po­rary folder, e.g. ~dougie/in, where I can carry out a quick pass using some­thing like gee­qie to delete any truly ter­ri­ble pho­tos. Then I import the pho­tos into f-spot. Once that’s done I change to the des­ti­na­tion direc­tory where f-spot has copied the pho­tos and run exi­fool. e.g.

dougie@phoenix /jpegs/2011/06/11 $ exiftool -all= *
60 image files updated
dougie@phoenix /jpegs/2011/06/11 $

Note the syn­tax for the exiftool com­mand. That’s a space after the equal sign and before the asterix. It’s a pow­er­ful com­mand so it’s best to check the man page first to ensure that you know what it’s going to do.