Wednesday 4 March 2009

Perl script to run ExifTool on a web server

This morning I took some more flower photos, then I calibrated my monitor. Unfortunately the spyder kept falling off the screen even though I stuck it on as hard as I could. So I had to sit looking at the screen for a few minutes while the spyder did its job, then hold it in place when the top sucker came unstuck. It was still really hard to unstick after it was done though. Possibly it falling off may be because I cleaned the screen before attaching it, though I would have thought this should make it stick better.

After that I updated yesterday's blog post with some links to the stuff I was on about as I didn't have time to do that when I wrote it last night. In searching for the stuff I was on about I came across this nice article at Sitepoint: Open Source Image Archiving: Exif, IPTC, XMP and all that.

Then I restarted my PC as it had finished downloading some Windows updates. Next I started trying to get a perl script to run in my local web development environment. I was following the tutorial at and just copy and pasted the example there to make sure it works. Unfortunately it didn't, and after quite a bit fo testing and searching I found I needed AddHandler cgi-script .cgi .pl to my site config file. Thanks to How to Add Perl CGI Script Support to Your Apache 1.x Web Server on Windows for this info (It's the same for Linux and Apache2).

I had already added directory info to the site config


AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all



and changed the permissions on the .cgi file so that it could be executed.

After lunch I went on Animal, the after that I got my perl script working with EXIFtool to print the metadata, seperated by tag name. The script is quite slow, I think probably because I call the ExifTool->ImageInfo() function for each tag. it would be better to just call it once getting all metadata, and then seperate it out into the tag 'families'. Unfortunately I don't know enough about ExifTool or Perl to do this. Anyway, the script looks like this:

#!/usr/bin/perl -T

use 5.010;
use CGI;

use strict;
use warnings;

my $q = CGI->new();
say $q->header(), $q->start_html();

say "

Parameters

";
my $file = '../_DSC9229sRGB.jpg';
$file = '../Bitteswell Church _DSC4883.jpg';
use Image::ExifTool qw(:Public);
my $exifTool = new Image::ExifTool;
my @metaTags = qw(JPEG EXIF IPTC XMP GPS GeoTiff ICC_Profile PrintIM Photoshop Canon CanonCustom Casio FujiFilm HP JVC Kodak Leaf Minolta Nikon NikonCapture Olympus Panasonic Pentax Ricoh Sanyo Sigma Sony Unknown DNG CanonRaw KyoceraRaw MinoltaRaw SigmaRaw JFIF FlashPix APP12 AFCP CanonVRD FotoStation PhotoMechanic MIE Jpeg2000 BMP PICT PNG MNG MIFF PDF PostScript ID3 ITC Vorbis FLAC APE MPC MPEG QuickTime Flash Real RIFF AIFF ASF DICOM DjVu HTML EXE Rawzor ZIP Extra Composite Shortcuts);
my $info;
my $tag;
foreach $tag (@metaTags)
{
print "

$tag

";
$info = $exifTool->ImageInfo($file, "$tag:*");
foreach(keys %$info)
{print "$_ => $$info{$_}
\n";}
}
say $q->end_html();


The tags array is just a list of all available tags from ExifTool Tag Names.

After that I tried to get the script to work on the web server. The first problem I had was that it was just saying access forbidden. It said to check the site error logs, but there weren't any (other than a PHP error log and an access log).

I thought maybe it was the same problem that I had when I first running a cgi script in my local environment this morning - that is that the site config lists a script alias for /cgi-bin that points somewhere like /usr/bin/cgi-bin, so if you have a cgi-bin folder on your site it's pointless as /cgi-bin doesn't point there.

So I made a new folder called 'cgi' and added an .htaccess file to it so cgi scripts could be executed in that folder. It took me quite a while to get that working, mainly because I just copied the block to do with cgi from the site config and pasted it into an .htaccess file. Eventually I found out that <directory> directives can't be placed in .htaccess files.

After getting that working, the script was still giving a forbidden error. So I checked the web server directory structure for error logs again, but still couldn't find one. I also tried setting the errorLog directive in an .htaccess file, but the errorLog directive can't be set in .htaccess files either. Then I thought to try the site's cpanel, and indeed there was an error log option on there, which displays the last 300 errors.

There I could see what the error was - my script was requiring Perl 5.10.0, but my host only had version 5.8.8. Unfortunately I can't copy the exact error message now as the errorlog seems to have been wiped. I guess cpanel clears the log after you've looked at it or sumat stupid.

Anyway, I found out how to change what perl version you reuqire. I wrote the version in the form v5.8.8 since this seemed to work okay on both my localhost and the web server.

Then I got an error message something like
Can't locate xxx.pm in @INC (@INC contains...


I did some googling and read this useful article: What to do when Perl modules
aren't in their normal locations
. I changed my script by commenting out (Comment Out a Block of perl Code) all the exif stuff. Then I added the follwing to my perl script:

my $loc;
print '

@INC

';
foreach $loc (@INC)
{print "$loc
\n";}


So that prints a nice easy to read list of where perl is looking for modules. Using that I found out where the ExifTool module(s) were saved (it was /usr/local/share/perl/5.10.0/Image). I then copied the Image folder, and placed it in a folder called 'perlModules', which I created in my home folder below the site root. Then in the perl script I added use lib '/home/username/perlModules';.

I uploaded it all to the web server, and got a different error about 'RandomAccess.pm' not being found. I found that in the same directory as where the Image::ExifTool module was located, so copied that across to my perlModules folder, uploaded it to the web server, and now the script worked. Woohoo.

I'm not sure if I will use ExifTool for my photo site, but it's certainly nice to have it available.

After getting that working I started checking my email, then it was dinner time.

After dinner I checked my email a bit more, then watched Flight of the Chonchords s02e07. After that I finished checking my email. Then I checked dpreview where there had been quite a few announcements from PMA on the front page. In the canon lens forums a few people had responded to my question about shooting butterflies, and said that 1/200s should be high enough shutter speed to get them without motion blur. I guess I just need to practice my hand holding technique to avoid camera shake.
In the process of reading some threads in the dpreview fora, I followed a link through to Flickr. So I checked my own Flickr, and they said that you could now create as many sets as you want. So I created some sets and moved the appropriate images into them.

The weather was nice and sunny with a blue sky in the morning, then as the morning went on large textured clouds rolled in. It was a mainly cloudy blue sky (but still sunny) for the rest of the day.

Food
Breakfast: Lemon marmalade toast sandwich; cup o' tea.
Lunch: Cicken Tikka Sandwich spread with sweet & crunchy salad sandwich; clementine; mince pie; Chocolate Waver bar; cup o' tea; piece of Sainsbury's caramel chocolate.
Afternoon Snack: Cadbury's hot chocolate drink with Dooleys; hobnob; milk chocolate digestive.
Dinner: Beef burger with grated cheese, tomato ketchup and sweet & crunchy salad in a cob. Baked beans; Roast potato. Pudding was a peach & passion fruit creamy yoghurt. Coffee; piece of Cadbury's Dairy Milk Turkish.

5 comments:

Pepper said...
This comment has been removed by the author.
Pepper said...

You can speed this up by calling ImageInfo() once with just the filename, then calling GetInfo() repeatedly to return information about the specific tags.

Pepper said...

Also, you may want to look at the sample code in the GetGroups() documentation since it is very similar to what you are doing:

http://owl.phy.queensu.ca/~phil/exiftool/ExifTool.html#GetGroups

Rusty said...

Thanks for the info!

Dave

Unknown said...

I find that the more I call ImageInfo in a program, the slower it goes... and it can c-r-a-w-l along at about a call per second after the first dozen or so calls return as fast as anything! It seems to be better to get a perl script called for each file (or handful of files) that need their tags looked at, etc, even with the overheads associated with that, than to have one script process all the images from (maybe) 30+ images. Not sure why.