Exiftool returning more than one Exif Image Width and Exif Image Height tags

Started by binvin, June 03, 2010, 07:31:49 AM

Previous topic - Next topic

binvin

Hi Phil,
I am using Image::ExifTool to fetch image size of an eps file. I am able to get the information using Exif Image Width and Exif Image Height tags. But the problem is I am getting more than one set of those two tags with different values. Ofcourse only one is fetching me the correct value. But I am completely confused about which tag to use in my script to fetch the height and width correctly.

Can you please help me?

Here is my script (taken from the CPAN example only)

use Image::ExifTool;
use Data::Dumper;
    my $exifTool = new Image::ExifTool;
    my $info = $exifTool->ImageInfo("c:\\Remya\\NEWEPS.eps");
   
    my $group = '';
    foreach $tag ($exifTool->GetFoundTags('Group0')) {
    #print "$tag \n";
        if ($group ne $exifTool->GetGroup($tag)) {
            $group = $exifTool->GetGroup($tag);
            print "---- $group ----\n";
        }
        my $val = $info->{$tag};
        if (ref $val eq 'SCALAR') {
            if ($$val =~ /^Binary data/) {
                $val = "($$val)";
            } else {
                my $len = length($$val);
                $val = "(Binary data $len bytes)";
            }
        }
        printf("%-32s : %s\n", $exifTool->GetDescription($tag), $val);
    }


And here is my output (I am pasting only the EXIF data). The first set (2154 and 3508) retruns the correct value.


---- EXIF ----
Subfile Type                     : Full-resolution Image
Image Width                      : 258
Image Height                     : 421
Bits Per Sample                  : 8
Compression                      : Uncompressed
Photometric Interpretation       : BlackIsZero
Strip Offsets                    : 18082
Samples Per Pixel                : 1
Rows Per Strip                   : 421
Strip Byte Counts                : 108618
X Resolution                     : 28.2912
Y Resolution                     : 28.2912
Resolution Unit                  : cm
Software                         : Adobe Photoshop 7.0
Modify Date                      : 2010:05:28 16:40:33
Orientation                      : Horizontal (normal)
X Resolution                     : 235
Y Resolution                     : 235
Resolution Unit                  : cm
Software                         : Adobe Photoshop 7.0
Modify Date                      : 2010:05:28 16:40:33
Color Space                      : Uncalibrated
<b>Exif Image Width                 : 2154
Exif Image Height                : 3508</b>
Compression                      : JPEG (old-style)
X Resolution                     : 72
Y Resolution                     : 72
Resolution Unit                  : inches
Thumbnail Offset                 : 294
Thumbnail Length                 : 0
Color Space                      : Uncalibrated
<b>Exif Image Width                 : 258
Exif Image Height                : 421</b>


Is there any way to identify the correct tag to fetch the height and width of the actual image?

Thanks in advance.

Bindu

Phil Harvey

Interesting.  I haven't seen ExifImageWidth/Height duplicated like this.

Try going to the family 1 group to show the specific location of these tags:

[...]
        if ($group ne $exifTool->GetGroup($tag, 1)) {
            $group = $exifTool->GetGroup($tag, 1);
            print "---- $group ----\n";
        }
[...]


- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

binvin

Hi Phil,
   Thanks a lot for your reply.

I tried it, and here is the output (again I am pasting onlt the old EXIF data):


---- IFD0 ----
Subfile Type                     : Full-resolution Image
Image Width                      : 258
Image Height                     : 421
Bits Per Sample                  : 8
Compression                      : Uncompressed
Photometric Interpretation       : BlackIsZero
Strip Offsets                    : 18082
Samples Per Pixel                : 1
Rows Per Strip                   : 421
Strip Byte Counts                : 108618
X Resolution                     : 28.2912
Y Resolution                     : 28.2912
Resolution Unit                  : cm
Software                         : Adobe Photoshop 7.0
Modify Date                      : 2010:05:28 16:40:33
Orientation                      : Horizontal (normal)
X Resolution                     : 235
Y Resolution                     : 235
Resolution Unit                  : cm
Software                         : Adobe Photoshop 7.0
Modify Date                      : 2010:05:28 16:40:33
---- ExifIFD ----
Color Space                      : Uncalibrated
Exif Image Width                 : 2154
Exif Image Height                : 3508
---- IFD1 ----
Compression                      : JPEG (old-style)
X Resolution                     : 72
Y Resolution                     : 72
Resolution Unit                  : inches
Thumbnail Offset                 : 294
Thumbnail Length                 : 0
---- ExifIFD ----
Color Space                      : Uncalibrated
Exif Image Width                 : 258
Exif Image Height                : 421


So can this be because of the embedded Thumbnail? If so how can I fetch only the first ExifIFD using my script.

Sorry if this is a very basic question and any help regarding this will be great.

Thanks again.

Bindu

Phil Harvey

Hi Bindu,

This is not a basic question.  I have never before seen an ExifIFD inside IFD1.  Very, very odd.

The solution is not trivial because it relies on the details of my implementation, but you can get the first extracted tag value for ExifImageWidth and ExifImageHeight like this:

#!/usr/bin/perl -w
use strict;
BEGIN { push @INC, 'lib', '..'}
use Image::ExifTool;
my $file = shift or die "No file specified\n";
my $exifTool = new Image::ExifTool;
$exifTool->ExtractInfo($file) or die "Error extracting information\n";
foreach my $tag ('ExifImageWidth','ExifImageHeight') {
    my $info = $exifTool->GetInfo($tag);
    next unless %$info;
    my ($key) = reverse sort keys %$info;
    print "$tag = $$info{$key}\n";
}
# end


- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

binvin

Thanks a lot Phil. That was very helpful.

BTW, can I do the samething for other multiple tags also? For example Under Photoshop group I get following values:


---- Photoshop ----
IPTCDigest (1)                   : 00000000000000000000000000000000
XResolution (1)                  : 72
DisplayedUnitsX (1)              : inches
YResolution (1)                  : 72
DisplayedUnitsY (1)              : inches
GlobalAngle (1)                  : 120
GlobalAltitude (1)               : 30
CopyrightFlag (1)                : False
PhotoshopThumbnail (1)           : (Binary data 1014 bytes)
IPTCDigest                       : 00000000000000000000000000000000
XResolution (4)                  : 72
DisplayedUnitsX                  : inches
YResolution (4)                  : 72
DisplayedUnitsY                  : inches
GlobalAngle                      : 120
GlobalAltitude                   : 30
CopyrightFlag                    : False
PhotoshopThumbnail               : (Binary data 1014 bytes)

As you can see we have multiple values for X Resolution , Displayed Units X , Y Resolution and Displayed Units Y  tags.

So is it correct to use the following code if I want to fetch only the first set of values for those 4 tags?


use Image::ExifTool;

my $exifTool = new Image::ExifTool;
$exifTool->ExtractInfo("C:\\eps.eps");

foreach my $tag ('XResolution', 'DisplayedUnitsX', 'YResolution','DisplayedUnitsY') {
    my $info = $exifTool->GetInfo($tag);
    next unless %$info;
    my ($key) = sort keys %$info;
    print "Key is $key \n";
    print "$tag = $$info{$key}\n";
}


I tried it and I got the following output:


Key is XResolution
XResolution = 72

Key is DisplayedUnitsX
DisplayedUnitsX = inches

Key is YResolution
YResolution = 72

Key is DisplayedUnitsY
DisplayedUnitsY = inches


Looks fine to me but just thought of getting it confirmed too :)

Thanks again for all your help.

Bindu

Phil Harvey

Hi Bindu,

Now things start getting more complicated.  In this case your code will do what you want and extract the tag without a copy number in the tag key.  For these tags, exiftool prioritizes the copies that exist in the IFD of the full resolution image, so extracting the prioritized tag (the one without a copy number in the tag key) is what you want.

I had ignored this prioritization in my previous example because most tags don't behave this way. I also realized that my example was not correct for another reason.  As well, I thought of a better way to do this which uses public API functions rather than the implementation-dependent technique I used before.  So if you are really interested in the order of the extracted tags then this is a better way to get the first one:


use Image::ExifTool;
my $file = shift or die "No file specified\n";
my $exifTool = new Image::ExifTool;
$exifTool->ExtractInfo($file) or die "Error extracting information\n";
foreach my $tag ('ExifImageWidth','ExifImageHeight') {
    my $info = $exifTool->GetInfo($tag);
    next unless %$info;
    # sort returned tag keys in the order they were extracted from the file
    my ($key) = $exifTool->GetTagList($info, 'File');
    print "$tag = $$info{$key}\n";
}
# end


However, for tags like X/YResolution you don't always want the first extracted tag.  Usually for these the prioritized tag is what you want, which is what you will get with your last script.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).

binvin

Hi Phil,
Thanks a lot for your reply. I will check this today.

Bindu

binvin

Hi Phil,
   Thanks, both the snippets work fine for me :).

I am using the snippet in your last code for fetching the first extracted Exifimageheight and Exifimagewidth and my snippet above for fetching the prioritized resolution tag.

But what exactly is a prioritized tag? How is it different from other tags? If you can point me to some documentation that should help too.

Thanks a lot.

Bindu

Phil Harvey

Hi Bindu,

The tag priorities are something that I haven't documented very well.  In general as I said the last extracted tag takes priority, but I have facility to tweak priorities in the code if necessary (for instance to take the tag from the full resolution image, or to take the tag which has a more reliable value).  The only documentation for this is in the lib/Image/ExifTool/README file of the full distribution.  Here is the relevant section:

Quote'Priority' - gives the priority of this tag while reading.  If
                  set to zero, this tag will not override the value of previous
                  tags with the same name.  If the priority is greater than
                  zero, this tag won't be overridden by subsequent tags unless
                  their priority is equal to or greater than this priority.  A
                  special feature is that Priority 0 tags are automatically
                  incremented to Priority 1 if they exist in the IFD of the full
                  resolution image (as determined by SubfileType).  If not
                  defined, the priority defaults to 1 for all tags except except
                  tags in IFD1 of JPEG images which default to priority 0.

But the only way to see the details about which tags are prioritized is to look at the source code.

- Phil
...where DIR is the name of a directory/folder containing the images.  On Mac/Linux/PowerShell, use single quotes (') instead of double quotes (") around arguments containing a dollar sign ($).