The family album has been growing and coping with the volume of images, stored under Ubuntu is becoming a problem. With the attitude – “waste time to save time” – started exploring the options for some kind of digital workflow to automate whatever I can or at least keep mouse clicks to a minimum.
One particular problem is adding comments to images; most archiving software (like gthumb) has you store stuff seperately from the images, maintaining their own databases (in the case of gthumb, under ~/.gnome2/gthumb). But I’d rather have comments stay with the image (e.g. using Exif – there are other ways but Exif wins on being widely supported).
Scripting Nautilus
By chance ran into g-scripts and the notion that you can extend Nautilus (the Ubuntu file manager GUI) with your own scripts. In fact there’s a short tutorial here. The examples on g-scripts use bash scripts but figured this was a good opportunity to mis-use PHP.
Zenity
In addition to extending Nautilus, also took advantage of Zenity (I’m running Ubuntu as in Gnome, not Kbuntu), which allows you to pop dialogs out of shell scripts. For example if you run $ zenity --question --text "Feeling OK?", up pops a dialog like…

There’s more on Zenity here. In fact it is a bad idea to use PHP for this given that Perl has this nailed with UI::Dialog, which supports multiple backends including Zenity and KDialog (meaning your scripts could then also work under Kbuntu) but for fun will continue with PHP here.
Tips
Anyway – some quick tips (which is pretty much covered in above tutorials) then the code.
- You store you scripts under
~/.gnome2/nautilus-scripts - Make sure you’ve got the php5-cli package installed (
$ sudo apt-get install php5-cli) - You need to add the PHP shebang line at the top of your script (I omitted the .php extension) e.g.
#!/usr/bin/php - Make sure you make them executable (
$ chmod +x ~/.gnome2/nautilus-scripts/myscript) - To activate the scripts, you need to point Nautilus at the scripts directory (menu: Go > Location). You may need to reload if you create additional scripts
- To run the scripts, right click on a file and select the scripts menu
Exif Manipulation
Anyway – succeeded in throwing together two scripts, one to view Exif comments (for which it was easiest just to use the exif_read_data() function) in a Zenity info dialog and another to edit comments using a Zenity text entry dialog. For the second I used Martin Geisler’s excellent PEL library, which has an example that I could pretty much copy and paste, replacing the command line interface with Zenity (side note: PEL 0.9 isn’t quite stable it seems – if you get error messages about redefining constants, edit the script and comment the second constant assignment). So now right clicking on an image and selecting my exif_comment_edit script I get a dialog like…

The code…
exif_view_comment
#!/usr/bin/php
<?php
function ohDearMe($msg) {
`zenity --error --text="$msg" --title="Exif Info Error"`;
exit(1);
}
if ( !isset($argv[1]) ) {
ohDearMe("Image filename required");
exit(1);
}
$file = getcwd().'/'.$argv[1];
if (!is_readable($file)) {
ohDearMe(sprintf("Unable to read: %s", $file));
exit(1);
}
$title = 'Exif Info for '.addslashes(basename($file));
$data = exif_read_data($file);
if ( !$data ) {
ohDearMe('Unrecognized image format!');
}
if ( !isset($data['ImageDescription']) || trim($data['ImageDescription']) == '' ) {
ohDearMe('Image contains no comment');
}
$out = $data['ImageDescription'];
`zenity --info --text="$out" --title="$title"`;
exif_edit_comment
#!/usr/bin/php
<?php
require_once('pel/PelDataWindow.php');
require_once('pel/PelJpeg.php');
require_once('pel/PelTiff.php');
function ohDearMe($msg) {
`zenity --error --text="$msg" --title="Exif Info Error"`;
exit(1);
}
if ( !isset($argv[1]) ) {
ohDearMe("Image filename required");
exit(1);
}
$in = getcwd().'/'.$argv[1];
if (!is_readable($in)) {
ohDearMe(sprintf("Unable to read: %s", $in));
exit(1);
}
$title = 'Exif Info for '.addslashes(basename($in));
$data = new PelDataWindow(file_get_contents($in));
if (PelJpeg::isValid($data)) {
$jpeg = $file = new PelJpeg();
$jpeg->load($data);
$app1 = $jpeg->getSection(PelJpegMarker::APP1);
if ($app1 == null) {
$app1 = new PelExif();
$jpeg->insertSection(PelJpegMarker::APP1, $app1, 2);
$tiff = new PelTiff();
$app1->setTiff($tiff);
} else {
$tiff = $app1->getTiff();
}
} elseif (PelTiff::isValid($data)) {
$tiff = $file = new PelTiff();
$tiff->load($data);
} else {
ohDearMe('Unrecognized image format!');
}
$ifd0 = $tiff->getIfd();
if ($ifd0 == null) {
$ifd0 = new PelIfd();
$tiff->setIfd($ifd0);
}
$desc = $ifd0->getEntry(PelTag::IMAGE_DESCRIPTION);
if ($desc == null) {
$description = exec(
'zenity --entry --title="Exif New Comment" --text="Enter comment" --width=800 2>&1'
);
$desc = new PelEntryAscii(PelTag::IMAGE_DESCRIPTION, $description);
$ifd0->addEntry($desc);
} else {
$entry_text = addslashes($desc->getValue());
$description = exec('zenity --entry --title="Exif Existing Comment" --entry-text="'.
$entry_text.'" --text="Enter comment" --width=800 2>&1');
$desc->setValue($description);
}
file_put_contents($in, $file->getBytes());
It goes without saying but will say anyway – use at your own risk!
Related posts:
- Announcing Updates to our Popular Add-ons for Firefox 3.5 If you've recently installed Firefox 3.5 you're probably itching to...
- 13 Firefox Add-ons For Web Development Are you a web developer? Do you use Firefox? There...
- 19 Firefox Add-ons For Designers Are you a web designer who wishes you could do...
- Mozilla Jetpack: An Interview With Nick Nguyen, Add-Ons Director Craig interviews Nick Nguyen, the Mozilla Add-ons team leader, to...
- How to Install PHP 5.3 on Windows PHP 5.3 is the most significant update since version 5.0....







But you have to pay for it so i can use the time for you.
September 14th, 2006 at 9:50 pm
Hey Harry,
Thanks for the inspiration.
Thinking there must be a nicer way than to it then through nautilus-scripts I discovered Nautilus Actions. Look for “Nautilus Actions Configuration” under system->preferences.
By going that route you can have a menu-item show up in the main menu based on filename or mimetype
dv
December 8th, 2006 at 10:10 am
Very useful technology to find the most effective way of imaging.
Thanks for this wonderful post.
June 21st, 2008 at 8:18 pm