views:

640

answers:

3

I'm currently using Perl Magick http://www.imagemagick.org/script/perl-magick.php, the perl interface to Image Magick http://www.imagemagick.org, to process & convert photos that our site users upload. I'd like to be able to also capture some of the EXIF data attached to these images and I have been able to figure out how to do this using the command line interface to Image Magick with the following command:

/usr/bin/identify -format "%[EXIF:*]" image.jpg

Which returns the following EXIF information for a particular photo:

exif:ApertureValue=29/8
exif:ColorSpace=1
exif:CompressedBitsPerPixel=3/1
exif:CustomRendered=0
exif:DateTime=2002:10:08 19:49:52
exif:DateTimeDigitized=2002:09:29 14:03:55
exif:DateTimeOriginal=2002:09:29 14:03:55
exif:DigitalZoomRatio=1/1
exif:ExifImageLength=307
exif:ExifImageWidth=410
exif:ExifOffset=192
exif:ExifVersion=48, 50, 50, 48
exif:ExposureBiasValue=0/1
exif:ExposureMode=0
exif:ExposureTime=1/1000
exif:Flash=24
exif:FlashPixVersion=48, 49, 48, 48
exif:FNumber=7/2
exif:FocalLength=227/32
exif:FocalPlaneResolutionUnit=2
exif:FocalPlaneXResolution=235741/32
exif:FocalPlaneYResolution=286622/39
exif:Make=Canon
exif:MaxApertureValue=12742/4289
exif:MeteringMode=5
exif:Model=Canon PowerShot S30
exif:ResolutionUnit=2
exif:SceneCaptureType=0
exif:SensingMethod=2
exif:ShutterSpeedValue=319/32
exif:Software=Adobe Photoshop 7.0
exif:WhiteBalance=0
exif:XResolution=180/1
exif:YResolution=180/1

I've tried about 100 ways to get this same result from Perl Magick but can't figure out how pass the same parameters I'm using on the command line to make it work properly. Here are a couple of variations I've tried none of which seems to have worked:

use Image::Magick;
my $image = Image::Magick->new;
my $exif = $image->Identify('image.jpg');
print $exif;

$image->Read('image.jpg');
$exif = $image->Get('format "%[EXIF:*]"');
print $exif;

I know there are other ways to extract EXIF data from an image file in perl but since we already have the Perl Magick module loaded I don't want to waste any more memory by having to load an additional module. I'm hoping someone out there already has this working on their site and can share the solution. Thanks in advance for your help!

A: 

I strongly recommend you to use Phil Harvey's ExifTool. It's comprehensive and well documented. Also, it doesn't read the entire image into memory, and according to the documentation you can get the Exif information from the image just by passing it a file handle to an open image file. So it shouldn't waste a lot of memory.

Kinopiko
@Kinopiko - If I was to go that route, what would you suggest I use to resize the images our users upload instead of Perl Magick? I already have to load Perl Magick and the image to convert the original uploaded photo into a number of different sizes for use on our site. I'm open to other alternatives but want to make sure I'm not loading 5 perl modules and reading the image multiple times when 1 or 2 modules could do the trick with far less memory usage. Thanks!
Russell C.
Oh, sorry, I misunderstood. I thought you meant the memory taken by the module itself rather than the multiple loading of the image. ExifTool is pretty quick at scanning images so I doubt it reads the whole image into memory.
Kinopiko
I checked the documentation and it looks like Exiftool can work even with an open filehandle. I've changed the answer to reflect that.
Kinopiko
+3  A: 
> cat im.pl
use Image::Magick;
my $image = Image::Magick->new();
$image->Read('/home/rjp/2009-02-18/DSC00343.JPG');
my $a = $image->Get('format', '%[EXIF:*]'); # two arguments
my @exif = split(/[\r\n]/, $a);
print join("\n", @exif);
> perl im.pl
exif:ColorSpace=1
exif:ComponentsConfiguration=...
exif:Compression=6
exif:CustomRendered=0
exif:DateTime=2009:02:13 16:18:15
exif:DateTimeDigitized=2009:02:13 16:18:15
...

That seems to work.

Version: ImageMagick 6.3.7 06/04/09 Q16 http://www.imagemagick.org

rjp
+1 Now, why didn't I think of that.
Sinan Ünür
@rjp Thanks! Works like a charm. And in record time too.
Russell C.
A: 

Edit: @rjp showed how to access all of the information rather than individual tags. Here is how to put the data in a hash:

#!/usr/bin/perl

use strict;
use warnings;

use Image::Magick;

my $image = Image::Magick->new;
$image->read('test.jpg');

my %exif = map { s/\s+\z//; $_ }
           map { split /=/, $_  }
           split /exif:/, $image->Get('format', '%[EXIF:*]');

use Data::Dumper;
print Dumper \%exif;
Sinan Ünür
Actually you don't. You can request all tags as a single string by specifying 'EXIF:*'. For me this is preferable since I get easily convert the returned string of all EXIF tags into a hash from which I can use any tag I wish.
Russell C.
@Russel C. Yeah, I know. Note my vote for and comment on @rjp's post.
Sinan Ünür