line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
########################################################### |
2
|
|
|
|
|
|
|
# A Perl package for showing/modifying JPEG (meta)data. # |
3
|
|
|
|
|
|
|
# Copyright (C) 2004,2005,2006 Stefano Bettelli # |
4
|
|
|
|
|
|
|
# See the COPYING and LICENSE files for license terms. # |
5
|
|
|
|
|
|
|
########################################################### |
6
|
|
|
|
|
|
|
package Image::MetaData::JPEG::data::Tables; |
7
|
16
|
|
|
16
|
|
170655
|
use Exporter 'import'; |
|
16
|
|
|
|
|
28
|
|
|
16
|
|
|
|
|
544
|
|
8
|
16
|
|
|
16
|
|
64
|
use strict; |
|
16
|
|
|
|
|
26
|
|
|
16
|
|
|
|
|
380
|
|
9
|
16
|
|
|
16
|
|
60
|
use warnings; |
|
16
|
|
|
|
|
22
|
|
|
16
|
|
|
|
|
424
|
|
10
|
16
|
|
|
16
|
|
8021
|
no integer; |
|
16
|
|
|
|
|
135
|
|
|
16
|
|
|
|
|
55
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
#============================================================================# |
13
|
|
|
|
|
|
|
#============================================================================# |
14
|
|
|
|
|
|
|
#============================================================================# |
15
|
|
|
|
|
|
|
# This section defines the export policy of this module; no variable or # |
16
|
|
|
|
|
|
|
# method is exported by default. Everything is exportable via %EXPORT_TAGS. # |
17
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
18
|
|
|
|
|
|
|
our @ISA = qw(Exporter); # |
19
|
|
|
|
|
|
|
our @EXPORT = qw(); # |
20
|
|
|
|
|
|
|
our @EXPORT_OK = qw(); # |
21
|
|
|
|
|
|
|
our %EXPORT_TAGS = # |
22
|
|
|
|
|
|
|
(RecordTypes => [qw($NIBBLES $BYTE $ASCII $SHORT $LONG $RATIONAL), # |
23
|
|
|
|
|
|
|
qw($SBYTE $UNDEF $SSHORT $SLONG $SRATIONAL $FLOAT), # |
24
|
|
|
|
|
|
|
qw($DOUBLE $REFERENCE)], # |
25
|
|
|
|
|
|
|
RecordProps => [qw(@JPEG_RECORD_TYPE_NAME @JPEG_RECORD_TYPE_LENGTH), # |
26
|
|
|
|
|
|
|
qw(@JPEG_RECORD_TYPE_CATEGORY @JPEG_RECORD_TYPE_SIGN)], # |
27
|
|
|
|
|
|
|
Endianness => [qw($NATIVE_ENDIANNESS $BIG_ENDIAN $LITTLE_ENDIAN)], # |
28
|
|
|
|
|
|
|
JPEGgrammar => [qw($JPEG_PUNCTUATION %JPEG_MARKER $JPEG_SEG_MAX_LEN)], # |
29
|
|
|
|
|
|
|
TagsAPP0 => [qw($APP0_JFIF_TAG $APP0_JFXX_TAG $APP0_JFXX_JPG), # |
30
|
|
|
|
|
|
|
qw($APP0_JFXX_1B $APP0_JFXX_3B $APP0_JFXX_PAL)], # |
31
|
|
|
|
|
|
|
TagsAPP1_Exif=>[qw($APP1_TH_JPEG $APP1_TH_TIFF $APP1_TH_TYPE), # |
32
|
|
|
|
|
|
|
qw($APP1_EXIF_TAG $THJPEG_OFFSET $THJPEG_LENGTH), # |
33
|
|
|
|
|
|
|
qw($APP1_TIFF_SIG $THTIFF_OFFSET $THTIFF_LENGTH), # |
34
|
|
|
|
|
|
|
qw(%IFD_SUBDIRS $HASH_MAKERNOTES $MAKERNOTE_TAG)], # |
35
|
|
|
|
|
|
|
TagsAPP1_XMP=> [qw($APP1_XMP_TAG $APP1_XMP_XPACKET_BEGIN), # |
36
|
|
|
|
|
|
|
qw($APP1_XMP_XPACKET_ID $APP1_XMP_META_NS), # |
37
|
|
|
|
|
|
|
qw($APP1_XMP_OUTER_RDF_NS)], # |
38
|
|
|
|
|
|
|
TagsAPP2 => [qw($APP2_FPXR_TAG $APP2_ICC_TAG)], # |
39
|
|
|
|
|
|
|
TagsAPP3 => [qw($APP3_EXIF_TAG %IFD_SUBDIRS)], # |
40
|
|
|
|
|
|
|
TagsAPP13 => [qw($APP13_PHOTOSHOP_IPTC $APP13_PHOTOSHOP_IDS), # |
41
|
|
|
|
|
|
|
qw($APP13_PHOTOSHOP_TYPE $APP13_IPTC_TAGMARKER), # |
42
|
|
|
|
|
|
|
qw($APP13_PHOTOSHOP_DIRNAME $APP13_IPTC_DIRNAME)], # |
43
|
|
|
|
|
|
|
TagsAPP14 => [qw($APP14_PHOTOSHOP_IDENTIFIER)], # |
44
|
|
|
|
|
|
|
Lookups => [qw(&JPEG_lookup)], ); # |
45
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
46
|
|
|
|
|
|
|
Exporter::export_ok_tags( # |
47
|
|
|
|
|
|
|
qw(RecordTypes RecordProps Endianness JPEGgrammar), # |
48
|
|
|
|
|
|
|
qw(TagsAPP0 TagsAPP1_Exif TagsAPP1_XMP), # |
49
|
|
|
|
|
|
|
qw(TagsAPP2 TagsAPP3 TagsAPP13 TagsAPP14 Lookups)); # |
50
|
|
|
|
|
|
|
#============================================================================# |
51
|
|
|
|
|
|
|
#============================================================================# |
52
|
|
|
|
|
|
|
#============================================================================# |
53
|
|
|
|
|
|
|
# Constants for the grammar of a JPEG files. You can find here everything # |
54
|
|
|
|
|
|
|
# about segment markers as well as the JPEG puncutation mark. The maximum # |
55
|
|
|
|
|
|
|
# length of the data area of a standard JPEG segment is determined by the # |
56
|
|
|
|
|
|
|
# fact that the segment lenght must be written to a two bytes field (inclu- # |
57
|
|
|
|
|
|
|
# ding the two bytes themselves (so, it is 2^16 - 3). # |
58
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
59
|
|
|
|
|
|
|
our $JPEG_SEG_MAX_LEN = 2**16 - 3; # data area max length for a std segment # |
60
|
|
|
|
|
|
|
our $JPEG_PUNCTUATION = 0xff; # constant prefixed to every JPEG marker # |
61
|
|
|
|
|
|
|
our %JPEG_MARKER = # non-repetitive JPEG markers # |
62
|
|
|
|
|
|
|
(TEM => 0x01, # for TEMporary private use in arithmetic coding # |
63
|
|
|
|
|
|
|
DHT => 0xc4, # Define Huffman Table(s) # |
64
|
|
|
|
|
|
|
JPG => 0xc8, # reserved for JPEG extensions # |
65
|
|
|
|
|
|
|
DAC => 0xcc, # Define Arithmetic Coding Conditioning(s) # |
66
|
|
|
|
|
|
|
SOI => 0xd8, # Start Of Image # |
67
|
|
|
|
|
|
|
EOI => 0xd9, # End Of Image # |
68
|
|
|
|
|
|
|
SOS => 0xda, # Start Of Scan # |
69
|
|
|
|
|
|
|
DQT => 0xdb, # Define Quantization Table(s) # |
70
|
|
|
|
|
|
|
DNL => 0xdc, # Define Number of Lines # |
71
|
|
|
|
|
|
|
DRI => 0xdd, # Define Restart Interval # |
72
|
|
|
|
|
|
|
DHP => 0xde, # Define Hierarchical Progression # |
73
|
|
|
|
|
|
|
EXP => 0xdf, # EXPand reference component(s) # |
74
|
|
|
|
|
|
|
COM => 0xfe); # COMment block # |
75
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
76
|
|
|
|
|
|
|
# markers 0x02 --> 0xbf are REServed for future uses # |
77
|
|
|
|
|
|
|
for (0x02..0xbf) { $JPEG_MARKER{sprintf "res%02x", $_} = $_; } # |
78
|
|
|
|
|
|
|
# some markers in 0xc0 --> 0xcf correspond to Start-Of-Frame typologies # |
79
|
|
|
|
|
|
|
for (0xc0..0xc3, 0xc5..0xc7, 0xc9..0xcb, # |
80
|
|
|
|
|
|
|
0xcd..0xcf) { $JPEG_MARKER{sprintf "SOF_%d", $_ - 0xc0} = $_; } # |
81
|
|
|
|
|
|
|
# markers 0xd0 --> 0xd7 correspond to ReSTart with module 8 count # |
82
|
|
|
|
|
|
|
for (0xd0..0xd7) { $JPEG_MARKER{sprintf "RST%d", $_ - 0xd0} = $_; } # |
83
|
|
|
|
|
|
|
# markers 0xe0 --> 0xef are the APPlication markers # |
84
|
|
|
|
|
|
|
for (0xe0..0xef) { $JPEG_MARKER{sprintf "APP%d", $_ - 0xe0} = $_; } # |
85
|
|
|
|
|
|
|
# markers 0xf0 --> 0xfd are reserved for JPEG extensions # |
86
|
|
|
|
|
|
|
for (0xf0..0xfd) { $JPEG_MARKER{sprintf "JPG%d", $_ - 0xf0} = $_; } # |
87
|
|
|
|
|
|
|
#============================================================================# |
88
|
|
|
|
|
|
|
#============================================================================# |
89
|
|
|
|
|
|
|
#============================================================================# |
90
|
|
|
|
|
|
|
# Functions for generating arrays (arg0=hashref, arg1=index) or references # |
91
|
|
|
|
|
|
|
# to lookup tables [hashes] (arg0=hashref,arg1=index) from hashes; it is # |
92
|
|
|
|
|
|
|
# assumed that the general hash they work on has array references as values. # |
93
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
94
|
608
|
|
|
608
|
0
|
476
|
sub generate_lookup { my %a=map { $_ => $_[0]{$_}[$_[1]] } keys %{$_[0]}; \%a}; |
|
43840
|
|
|
|
|
67902
|
|
|
608
|
|
|
|
|
5065
|
|
|
608
|
|
|
|
|
5884
|
|
95
|
64
|
|
|
64
|
0
|
100
|
sub generate_array { map { $_[0]{$_}[$_[1]] } (0..(-1+scalar keys %{$_[0]}))}; |
|
896
|
|
|
|
|
1200
|
|
|
64
|
|
|
|
|
154
|
|
96
|
|
|
|
|
|
|
#============================================================================# |
97
|
|
|
|
|
|
|
#============================================================================# |
98
|
|
|
|
|
|
|
#============================================================================# |
99
|
|
|
|
|
|
|
# Various lists for JPEG record names, lengths, categories and signs; see # |
100
|
|
|
|
|
|
|
# Image::MetaData::JPEG::Record class for further details. The general hash # |
101
|
|
|
|
|
|
|
# is private to this file, the other arrays are exported if so requested. # |
102
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
103
|
|
|
|
|
|
|
# I gave up trying to calculate the length of a reference. This is probably # |
104
|
|
|
|
|
|
|
# allocation dependent ... I use 0 here, meaning the length is variable. # |
105
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
106
|
|
|
|
|
|
|
my $RECORD_TYPE_GENERAL = # |
107
|
|
|
|
|
|
|
{(our $NIBBLES = 0) => [ 'NIBBLES' , 1, 'I', 'N' ], # |
108
|
|
|
|
|
|
|
(our $BYTE = 1) => [ 'BYTE' , 1, 'I', 'N' ], # |
109
|
|
|
|
|
|
|
(our $ASCII = 2) => [ 'ASCII' , 0, 'S', 'N' ], # |
110
|
|
|
|
|
|
|
(our $SHORT = 3) => [ 'SHORT' , 2, 'I', 'N' ], # |
111
|
|
|
|
|
|
|
(our $LONG = 4) => [ 'LONG' , 4, 'I', 'N' ], # |
112
|
|
|
|
|
|
|
(our $RATIONAL = 5) => [ 'RATIONAL' , 8, 'R', 'N' ], # |
113
|
|
|
|
|
|
|
(our $SBYTE = 6) => [ 'SBYTE' , 1, 'I', 'Y' ], # |
114
|
|
|
|
|
|
|
(our $UNDEF = 7) => [ 'UNDEF' , 0, 'S', 'N' ], # |
115
|
|
|
|
|
|
|
(our $SSHORT = 8) => [ 'SSHORT' , 2, 'I', 'Y' ], # |
116
|
|
|
|
|
|
|
(our $SLONG = 9) => [ 'SLONG' , 4, 'I', 'Y' ], # |
117
|
|
|
|
|
|
|
(our $SRATIONAL = 10) => [ 'SRATIONAL' , 8, 'R', 'Y' ], # |
118
|
|
|
|
|
|
|
(our $FLOAT = 11) => [ 'FLOAT' , 4, 'F', 'N' ], # |
119
|
|
|
|
|
|
|
(our $DOUBLE = 12) => [ 'DOUBLE' , 8, 'F', 'N' ], # |
120
|
|
|
|
|
|
|
(our $REFERENCE = 13) => [ 'REFERENCE' , 0, 'p', 'N' ], }; # |
121
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
122
|
|
|
|
|
|
|
our @JPEG_RECORD_TYPE_NAME = generate_array($RECORD_TYPE_GENERAL, 0); # |
123
|
|
|
|
|
|
|
our @JPEG_RECORD_TYPE_LENGTH = generate_array($RECORD_TYPE_GENERAL, 1); # |
124
|
|
|
|
|
|
|
our @JPEG_RECORD_TYPE_CATEGORY = generate_array($RECORD_TYPE_GENERAL, 2); # |
125
|
|
|
|
|
|
|
our @JPEG_RECORD_TYPE_SIGN = generate_array($RECORD_TYPE_GENERAL, 3); # |
126
|
|
|
|
|
|
|
#============================================================================# |
127
|
|
|
|
|
|
|
#============================================================================# |
128
|
|
|
|
|
|
|
#============================================================================# |
129
|
|
|
|
|
|
|
# These tags are related to endianness. The endianness of the current # |
130
|
|
|
|
|
|
|
# machine is detected every time with a simple procedure. # |
131
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
132
|
|
|
|
|
|
|
my ($__short, $__byte1, $__byte2) = unpack "SCC", "\111\333" x 2; # |
133
|
|
|
|
|
|
|
our $BIG_ENDIAN = 'MM'; # |
134
|
|
|
|
|
|
|
our $LITTLE_ENDIAN = 'II'; # |
135
|
|
|
|
|
|
|
our $NATIVE_ENDIANNESS = $__byte2 + ($__byte1<<8) == $__short ? $BIG_ENDIAN # |
136
|
|
|
|
|
|
|
: $__byte1 + ($__byte2<<8) == $__short ? $LITTLE_ENDIAN : undef; # |
137
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
138
|
|
|
|
|
|
|
# various interesting constants which are not tags (mostly record values); # |
139
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
140
|
|
|
|
|
|
|
our $APP0_JFIF_TAG = "JFIF\000"; # |
141
|
|
|
|
|
|
|
our $APP0_JFXX_TAG = "JFXX\000"; # |
142
|
|
|
|
|
|
|
our $APP0_JFXX_JPG = 0x10; # |
143
|
|
|
|
|
|
|
our $APP0_JFXX_1B = 0x11; # |
144
|
|
|
|
|
|
|
our $APP0_JFXX_3B = 0x13; # |
145
|
|
|
|
|
|
|
our $APP0_JFXX_PAL = 768; # |
146
|
|
|
|
|
|
|
our $APP1_EXIF_TAG = "Exif\000\000"; # |
147
|
|
|
|
|
|
|
our $APP1_XMP_TAG = "http://ns.adobe.com/xap/1.0/\000"; # |
148
|
|
|
|
|
|
|
our $APP1_XMP_XPACKET_ID = 'W5M0MpCehiHzreSzNTczkc9d'; # |
149
|
|
|
|
|
|
|
our $APP1_XMP_XPACKET_BEGIN = "\x{FEFF}"; # |
150
|
|
|
|
|
|
|
our $APP1_XMP_META_NS = 'adobe:ns:meta/'; # |
151
|
|
|
|
|
|
|
our $APP1_XMP_OUTER_RDF_NS ='http://www.w3.org/1999/02/22-rdf-syntax-ns#'; |
152
|
|
|
|
|
|
|
our $APP1_TIFF_SIG = 42; # |
153
|
|
|
|
|
|
|
our $APP1_TH_TIFF = 1; # |
154
|
|
|
|
|
|
|
our $APP1_TH_JPEG = 6; # |
155
|
|
|
|
|
|
|
our $APP2_FPXR_TAG = "FPXR\000"; # |
156
|
|
|
|
|
|
|
our $APP2_ICC_TAG = "ICC_PROFILE\000"; # |
157
|
|
|
|
|
|
|
our $APP3_EXIF_TAG = "Meta\000\000"; # |
158
|
|
|
|
|
|
|
our $APP13_PHOTOSHOP_IDS = ["Photoshop 3.0\000",'Adobe_Photoshop2.5:']; |
159
|
|
|
|
|
|
|
our $APP13_PHOTOSHOP_TYPE = ['8BIM', '8BPS', 'PHUT']; # |
160
|
|
|
|
|
|
|
our $APP13_PHOTOSHOP_IPTC = 0x0404; # |
161
|
|
|
|
|
|
|
our $APP13_PHOTOSHOP_DIRNAME = 'Photoshop_RECORDS'; # |
162
|
|
|
|
|
|
|
our $APP13_IPTC_TAGMARKER = 0x1c; # |
163
|
|
|
|
|
|
|
our $APP13_IPTC_DIRNAME = 'IPTC_RECORD'; # |
164
|
|
|
|
|
|
|
our $APP14_PHOTOSHOP_IDENTIFIER = 'Adobe'; # |
165
|
|
|
|
|
|
|
#============================================================================# |
166
|
|
|
|
|
|
|
#============================================================================# |
167
|
|
|
|
|
|
|
#============================================================================# |
168
|
|
|
|
|
|
|
# The following lines contain a list of general-purpose regular expressions, # |
169
|
|
|
|
|
|
|
# which are used by the IFD, GPS ... and other sections. The only reason for # |
170
|
|
|
|
|
|
|
# them being here is to avoid to do errors more than once ... # |
171
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
172
|
|
|
|
|
|
|
my $re_integer = '\d+'; # a generic integer number # |
173
|
|
|
|
|
|
|
my $re_signed = join('', '-?', $re_integer); # a generic signed integer num # |
174
|
|
|
|
|
|
|
my $re_float = '[+-]?\d+(|.\d+)'; # a generic floating point # |
175
|
|
|
|
|
|
|
my $re_Cstring = '.*\000'; # a null-terminated string # |
176
|
|
|
|
|
|
|
my $re_yr18 = '(18|19|20)\d\d'; # YYYY (from 1800AD only ...) # |
177
|
|
|
|
|
|
|
my $re_year = '\d{4}'; # YYYY (from 0AD on) # |
178
|
|
|
|
|
|
|
my $re_month = '(0[1-9]|1[0-2])'; # MM (month in 1-12) # |
179
|
|
|
|
|
|
|
my $re_day = '(0[1-9]|[12]\d|3[01])'; # DD (day in 1-31) # |
180
|
|
|
|
|
|
|
my $re_hour = '([01]\d|2[0-3])'; # HH (hour in 0-23) # |
181
|
|
|
|
|
|
|
my $re_minute = '[0-5]\d'; # MM (minute in 0-59) # |
182
|
|
|
|
|
|
|
my $re_second = $re_minute; # SS (seconds like minutes) # |
183
|
|
|
|
|
|
|
my $re_zone = join('', $re_hour, $re_minute); # HHMM # |
184
|
|
|
|
|
|
|
my $re_dt18 = join('', $re_yr18, $re_month, $re_day); # YYYYMMDD # |
185
|
|
|
|
|
|
|
my $re_date = join('', $re_year, $re_month, $re_day); # YYYYMMDD # |
186
|
|
|
|
|
|
|
my $re_time = join('', $re_hour, $re_minute, $re_second); # HHMMSS # |
187
|
|
|
|
|
|
|
my $re_dt18_cl = join(':', $re_yr18, $re_month, $re_day); # YYYY:MM:DD # |
188
|
|
|
|
|
|
|
my $re_date_cl = join(':', $re_year, $re_month, $re_day); # YYYY:MM:DD # |
189
|
|
|
|
|
|
|
my $re_time_cl = join(':', $re_hour, $re_minute, $re_second); # HH:MM:SS # |
190
|
|
|
|
|
|
|
#============================================================================# |
191
|
|
|
|
|
|
|
#============================================================================# |
192
|
|
|
|
|
|
|
#============================================================================# |
193
|
|
|
|
|
|
|
# Root level records for an Exif APP1 segment; we could avoid writing them # |
194
|
|
|
|
|
|
|
# down here, but this makes syntax checks easier. Also, mandatory tags are # |
195
|
|
|
|
|
|
|
# here just for reference, since I think they are already present, hence # |
196
|
|
|
|
|
|
|
# never used. See the tables for IFD0 and IFD1 for further details. # |
197
|
|
|
|
|
|
|
#--- Mandatory records for IFD0 and IFD1 (not calculated) -------------------# |
198
|
|
|
|
|
|
|
my $HASH_APP1_ROOT_MANDATORY = {'Identifier' => $APP1_EXIF_TAG, # |
199
|
|
|
|
|
|
|
'Endianness' => $BIG_ENDIAN, # |
200
|
|
|
|
|
|
|
'Signature' => $APP1_TIFF_SIG, }; # |
201
|
|
|
|
|
|
|
#--- Legal records' list ----------------------------------------------------# |
202
|
|
|
|
|
|
|
my $HASH_APP1_ROOT_GENERAL = # |
203
|
|
|
|
|
|
|
{'Identifier' => ['Idx-1', $ASCII, 6, $APP1_EXIF_TAG, 'B' ], # |
204
|
|
|
|
|
|
|
'Endianness' => ['Idx-2', $UNDEF, 2, "($BIG_ENDIAN|$LITTLE_ENDIAN)" ], # |
205
|
|
|
|
|
|
|
'Signature' => ['Idx-3', $SHORT, 1, $APP1_TIFF_SIG, 'B' ], # |
206
|
|
|
|
|
|
|
'ThumbnailData' => ['Idx-4', $UNDEF, undef, '.*', 'T' ], }; # |
207
|
|
|
|
|
|
|
#============================================================================# |
208
|
|
|
|
|
|
|
#============================================================================# |
209
|
|
|
|
|
|
|
#============================================================================# |
210
|
|
|
|
|
|
|
# Most tags in the following three lists are the same for IFD0 and IFD1, # |
211
|
|
|
|
|
|
|
# only the support level changes (some of them, indeed, must be present in # |
212
|
|
|
|
|
|
|
# both directories). See the relevant sections in the Image::MetaData::JPEG # |
213
|
|
|
|
|
|
|
# module perldoc page for further details on the %$HASH_APP1_IFD01_* hashes: # |
214
|
|
|
|
|
|
|
# MAIN --> "Canonical Exif 2.2 and TIFF 6.0 tags for IFD0 and IFD1"; # |
215
|
|
|
|
|
|
|
# ADDITIONAL --> "Additional TIFF 6.0 tags not in Exif 2.2 for IFD0"; # |
216
|
|
|
|
|
|
|
# COMPANIES --> "Exif tags assigned to companies for IFD0 and IFD1". # |
217
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
218
|
|
|
|
|
|
|
# The meaning of pseudo-regular-expressions is the following: # |
219
|
|
|
|
|
|
|
# - 'calculated': these tags must not be set by the final user (they are # |
220
|
|
|
|
|
|
|
# created, if necessary, by the module itself [this is more reliable]). # |
221
|
|
|
|
|
|
|
# - 'obsoleted': this means that the corresponding tag is no more allowed. # |
222
|
|
|
|
|
|
|
# Some tags do not have a fixed type (for instance, they can be $SHORT or # |
223
|
|
|
|
|
|
|
# $LONG): in these cases, the most general type was chosen. Remember that # |
224
|
|
|
|
|
|
|
# some tags in the main hash table are mandatory. # |
225
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
226
|
|
|
|
|
|
|
# Hash keys are numeric tags, here written in hexadecimal base. # |
227
|
|
|
|
|
|
|
# Fields: 0 -> name, 1 -> type, 2 -> count, 3 -> matching regular expression # |
228
|
|
|
|
|
|
|
# 4 -> (optional) this tag can be set only together with the thumbnail # |
229
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
230
|
|
|
|
|
|
|
my $IFD_integer = $re_integer; # a generic integer number # |
231
|
|
|
|
|
|
|
my $IFD_signed = $re_signed; # a generic signed integer num # |
232
|
|
|
|
|
|
|
my $IFD_float = $re_float; # a generic floating point # |
233
|
|
|
|
|
|
|
my $IFD_Cstring = $re_Cstring; # a null-terminated string # |
234
|
|
|
|
|
|
|
my $IFD_dt_full = $re_dt18_cl.' '.$re_time_cl; # YYYY:MM:DD HH:MM:SS # |
235
|
|
|
|
|
|
|
my $IFD_datetime = '('.$IFD_dt_full.'| : : : : |\s{19})\000'; # |
236
|
|
|
|
|
|
|
#--- Special screen rules for IFD0 and IFD1 ---------------------------------# |
237
|
|
|
|
|
|
|
# a YCbCrSubSampling tag indicates the ratio of chrominance components. Its # |
238
|
|
|
|
|
|
|
# value can be only [2,1] (for YCbCr 4:2:2) or [2,2] (for YCbCr 4:2:0). # |
239
|
|
|
|
|
|
|
my $SSR_YCCsampl = sub { die unless $_[0] == 2 && $_[1] =~ /1|2/; }; # |
240
|
|
|
|
|
|
|
#--- Mandatory records for IFD0 and IFD1 (not calculated) -------------------# |
241
|
|
|
|
|
|
|
my $HASH_APP1_IFD01_MANDATORY = {'XResolution' => [72, 1], # |
242
|
|
|
|
|
|
|
'YResolution' => [72, 1], # |
243
|
|
|
|
|
|
|
'ResolutionUnit' => 2, }; # |
244
|
|
|
|
|
|
|
my $HASH_APP1_IFD0_MANDATORY = {%$HASH_APP1_IFD01_MANDATORY, # |
245
|
|
|
|
|
|
|
'YCbCrPositioning' => 1, }; # |
246
|
|
|
|
|
|
|
my $HASH_APP1_IFD1_MANDATORY = {%$HASH_APP1_IFD01_MANDATORY, # |
247
|
|
|
|
|
|
|
'YCbCrSubSampling' => [2, 1], # |
248
|
|
|
|
|
|
|
'PhotometricInterpretation' => 2, # |
249
|
|
|
|
|
|
|
'PlanarConfiguration' => 1, }; # |
250
|
|
|
|
|
|
|
#--- Legal records' list ----------------------------------------------------# |
251
|
|
|
|
|
|
|
my $HASH_APP1_IFD01_MAIN = # |
252
|
|
|
|
|
|
|
{0x0100 => ['ImageWidth', $LONG, 1, $IFD_integer, 'T'], # |
253
|
|
|
|
|
|
|
0x0101 => ['ImageLength', $LONG, 1, $IFD_integer, 'T'], # |
254
|
|
|
|
|
|
|
0x0102 => ['BitsPerSample', $SHORT, 3, '8', 'T'], # |
255
|
|
|
|
|
|
|
0x0103 => ['Compression', $SHORT, 1, '[16]', 'T'], # |
256
|
|
|
|
|
|
|
0x0106 => ['PhotometricInterpretation', $SHORT, 1, '[26]', ], # |
257
|
|
|
|
|
|
|
0x010e => ['ImageDescription', $ASCII, undef, $IFD_Cstring ], # |
258
|
|
|
|
|
|
|
0x010f => ['Make', $ASCII, undef, $IFD_Cstring ], # |
259
|
|
|
|
|
|
|
0x0110 => ['Model', $ASCII, undef, $IFD_Cstring ], # |
260
|
|
|
|
|
|
|
0x0111 => ['StripOffsets', $LONG, undef, 'calculated' ], # |
261
|
|
|
|
|
|
|
0x0112 => ['Orientation', $SHORT, 1, '[1-8]' ], # |
262
|
|
|
|
|
|
|
0x0115 => ['SamplesPerPixel', $SHORT, 1, '3', 'T'], # |
263
|
|
|
|
|
|
|
0x0116 => ['RowsPerStrip', $LONG, 1, $IFD_integer, 'T'], # |
264
|
|
|
|
|
|
|
0x0117 => ['StripByteCounts', $LONG, undef, $IFD_integer, 'T'], # |
265
|
|
|
|
|
|
|
0x011a => ['XResolution', $RATIONAL, 1, $IFD_integer ], # |
266
|
|
|
|
|
|
|
0x011b => ['YResolution', $RATIONAL, 1, $IFD_integer ], # |
267
|
|
|
|
|
|
|
0x011c => ['PlanarConfiguration', $SHORT, 1, '[12]' ], # |
268
|
|
|
|
|
|
|
0x0128 => ['ResolutionUnit', $SHORT, 1, '[23]' ], # |
269
|
|
|
|
|
|
|
0x012d => ['TransferFunction', $SHORT, 768, $IFD_integer ], # |
270
|
|
|
|
|
|
|
0x0131 => ['Software', $ASCII, undef, $IFD_Cstring ], # |
271
|
|
|
|
|
|
|
0x0132 => ['DateTime', $ASCII, 20, $IFD_datetime ], # |
272
|
|
|
|
|
|
|
0x013b => ['Artist', $ASCII, undef, $IFD_Cstring ], # |
273
|
|
|
|
|
|
|
0x013e => ['WhitePoint', $RATIONAL, 2, $IFD_integer ], # |
274
|
|
|
|
|
|
|
0x013f => ['PrimaryChromaticities', $RATIONAL, 6, $IFD_integer ], # |
275
|
|
|
|
|
|
|
0x0201 => ['JPEGInterchangeFormat', $LONG, 1, 'calculated' ], # |
276
|
|
|
|
|
|
|
0x0202 => ['JPEGInterchangeFormatLength',$LONG, 1, $IFD_integer, 'T'], # |
277
|
|
|
|
|
|
|
0x0211 => ['YCbCrCoefficients', $RATIONAL, 3, $IFD_integer ], # |
278
|
|
|
|
|
|
|
0x0212 => ['YCbCrSubSampling', $SHORT, 2, $SSR_YCCsampl ], # |
279
|
|
|
|
|
|
|
0x0213 => ['YCbCrPositioning', $SHORT, 1, '[12]' ], # |
280
|
|
|
|
|
|
|
0x0214 => ['ReferenceBlackWhite', $RATIONAL, 6, $IFD_integer ], # |
281
|
|
|
|
|
|
|
0x8298 => ['Copyright', $ASCII, undef, $IFD_Cstring ], # |
282
|
|
|
|
|
|
|
0x8769 => ['ExifOffset', $LONG, 1, 'calculated' ], # |
283
|
|
|
|
|
|
|
0x8825 => ['GPSInfo', $LONG, 1, 'calculated' ], }; # |
284
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
285
|
|
|
|
|
|
|
my $HASH_APP1_IFD01_ADDITIONAL = # |
286
|
|
|
|
|
|
|
{0x00fe => ['NewSubfileType', $LONG, 1, $IFD_integer ], # |
287
|
|
|
|
|
|
|
0x00ff => ['SubFileType', $SHORT, 1, $IFD_integer ], # |
288
|
|
|
|
|
|
|
0x0107 => ['Thresholding', $SHORT, 1, $IFD_integer ], # |
289
|
|
|
|
|
|
|
0x0108 => ['CellWidth', $SHORT, 1, $IFD_integer ], # |
290
|
|
|
|
|
|
|
0x0109 => ['CellLength', $SHORT, 1, $IFD_integer ], # |
291
|
|
|
|
|
|
|
0x010a => ['FillOrder', $SHORT, 1, $IFD_integer ], # |
292
|
|
|
|
|
|
|
0x010d => ['DocumentName', $ASCII, undef, $IFD_Cstring ], # |
293
|
|
|
|
|
|
|
0x0118 => ['MinSampleValue', $SHORT, undef, $IFD_integer ], # |
294
|
|
|
|
|
|
|
0x0119 => ['MaxSampleValue', $SHORT, undef, $IFD_integer ], # |
295
|
|
|
|
|
|
|
0x011d => ['PageName', $ASCII, undef, $IFD_Cstring ], # |
296
|
|
|
|
|
|
|
0x011e => ['XPosition', $RATIONAL, 1, $IFD_integer ], # |
297
|
|
|
|
|
|
|
0x011f => ['YPosition', $RATIONAL, 1, $IFD_integer ], # |
298
|
|
|
|
|
|
|
0x0120 => ['FreeOffsets', $LONG, undef, $IFD_integer ], # |
299
|
|
|
|
|
|
|
0x0121 => ['FreeByteCounts', $LONG, undef, $IFD_integer ], # |
300
|
|
|
|
|
|
|
0x0122 => ['GrayResponseUnit', $SHORT, 1, $IFD_integer ], # |
301
|
|
|
|
|
|
|
0x0123 => ['GrayResponseCurve', $SHORT, undef, $IFD_integer ], # |
302
|
|
|
|
|
|
|
0x0124 => ['T4Options', $LONG, 1, $IFD_integer ], # |
303
|
|
|
|
|
|
|
0x0125 => ['T6Options', $LONG, 1, $IFD_integer ], # |
304
|
|
|
|
|
|
|
0x0129 => ['PageNumber', $SHORT, 2, $IFD_integer ], # |
305
|
|
|
|
|
|
|
0x012c => ['ColorResponseUnit', $SHORT, 1, 'invalid' ], # |
306
|
|
|
|
|
|
|
0x013c => ['HostComputer', $ASCII, undef, $IFD_Cstring ], # |
307
|
|
|
|
|
|
|
0x013d => ['Predictor', $SHORT, 1, $IFD_integer ], # |
308
|
|
|
|
|
|
|
0x0140 => ['Colormap', $SHORT, undef, $IFD_integer ], # |
309
|
|
|
|
|
|
|
0x0141 => ['HalftoneHints', $SHORT, 2, $IFD_integer ], # |
310
|
|
|
|
|
|
|
0x0142 => ['TileWidth', $LONG, 1, $IFD_integer ], # |
311
|
|
|
|
|
|
|
0x0143 => ['TileLength', $LONG, 1, $IFD_integer ], # |
312
|
|
|
|
|
|
|
0x0144 => ['TileOffsets', $LONG, undef, $IFD_integer ], # |
313
|
|
|
|
|
|
|
0x0145 => ['TileByteCounts', $LONG, undef, $IFD_integer ], # |
314
|
|
|
|
|
|
|
0x0146 => ['BadFaxLines', $LONG, 1, $IFD_integer ], # |
315
|
|
|
|
|
|
|
0x0147 => ['CleanFaxData', $SHORT, 1, $IFD_integer ], # |
316
|
|
|
|
|
|
|
0x0148 => ['ConsecutiveBadFaxLines', $LONG, 1, $IFD_integer ], # |
317
|
|
|
|
|
|
|
0x014a => ['SubIFD', $LONG, undef, $IFD_integer ], # |
318
|
|
|
|
|
|
|
0x014c => ['InkSet', $SHORT, 1, $IFD_integer ], # |
319
|
|
|
|
|
|
|
0x014d => ['InkNames', $ASCII, undef, $IFD_Cstring ], # |
320
|
|
|
|
|
|
|
0x014e => ['NumberOfInks', $SHORT, 1, $IFD_integer ], # |
321
|
|
|
|
|
|
|
0x0150 => ['DotRange', $SHORT, undef, $IFD_integer ], # |
322
|
|
|
|
|
|
|
0x0151 => ['TargetPrinter', $ASCII, undef, $IFD_Cstring ], # |
323
|
|
|
|
|
|
|
0x0152 => ['ExtraSamples', $SHORT, undef, $IFD_integer ], # |
324
|
|
|
|
|
|
|
0x0153 => ['SampleFormats', $SHORT, undef, $IFD_integer ], # |
325
|
|
|
|
|
|
|
0x0154 => ['SMinSampleValue', $UNDEF, undef, '.*' ], # |
326
|
|
|
|
|
|
|
0x0155 => ['SMaxSampleValue', $UNDEF, undef, '.*' ], # |
327
|
|
|
|
|
|
|
0x0156 => ['TransferRange', $SHORT, 6, $IFD_integer ], # |
328
|
|
|
|
|
|
|
0x0157 => ['ClipPath', $BYTE, undef, $IFD_integer ], # |
329
|
|
|
|
|
|
|
0x0158 => ['XClipPathUnits', $DOUBLE, 1, $IFD_float ], # |
330
|
|
|
|
|
|
|
0x0159 => ['YClipPathUnits', $DOUBLE, 1, $IFD_float ], # |
331
|
|
|
|
|
|
|
0x015a => ['Indexed', $SHORT, 1, $IFD_integer ], # |
332
|
|
|
|
|
|
|
0x015b => ['JPEGTables', undef, undef, 'invalid' ], # |
333
|
|
|
|
|
|
|
0x015f => ['OPIProxy', $SHORT, 1, $IFD_integer ], # |
334
|
|
|
|
|
|
|
0x0200 => ['JPEGProc', $SHORT, 1, 'invalid' ], # |
335
|
|
|
|
|
|
|
0x0203 => ['JPEGRestartInterval', $SHORT, 1, 'invalid' ], # |
336
|
|
|
|
|
|
|
0x0205 => ['JPEGLosslessPredictors', $SHORT, undef, 'invalid' ], # |
337
|
|
|
|
|
|
|
0x0206 => ['JPEGPointTransforms', $SHORT, undef, 'invalid' ], # |
338
|
|
|
|
|
|
|
0x0207 => ['JPEGQTables', $LONG, undef, 'invalid' ], # |
339
|
|
|
|
|
|
|
0x0208 => ['JPEGDCTables', $LONG, undef, 'invalid' ], # |
340
|
|
|
|
|
|
|
0x0209 => ['JPEGACTables', $LONG, undef, 'invalid' ], # |
341
|
|
|
|
|
|
|
0x02bc => ['XML_Packet', $BYTE, undef, $IFD_integer ], }; # |
342
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
343
|
|
|
|
|
|
|
# The following company-related fields are marked as invalid because they # |
344
|
|
|
|
|
|
|
# are present also in the SubIFD section (with different numerical values) # |
345
|
|
|
|
|
|
|
# and I don't want the two entries to collide when setting IMAGE_DATA: # |
346
|
|
|
|
|
|
|
# 'FlashEnergy', 'SpatialFrequencyResponse', FocalPlane[XY]Resolution', # |
347
|
|
|
|
|
|
|
# 'FocalPlaneResolutionUnit', 'ExposureIndex', 'SensingMethod', 'CFAPattern' # |
348
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
349
|
|
|
|
|
|
|
my $HASH_APP1_IFD01_COMPANIES = # |
350
|
|
|
|
|
|
|
{0x800d => ['ImageID', $ASCII, undef, $IFD_Cstring ], # |
351
|
|
|
|
|
|
|
0x80b9 => ['RefPts', undef, undef, 'invalid' ], # |
352
|
|
|
|
|
|
|
0x80ba => ['RegionTackPoint', undef, undef, 'invalid' ], # |
353
|
|
|
|
|
|
|
0x80bb => ['RegionWarpCorners', undef, undef, 'invalid' ], # |
354
|
|
|
|
|
|
|
0x80bc => ['RegionAffine', undef, undef, 'invalid' ], # |
355
|
|
|
|
|
|
|
0x80e3 => ['Matteing', $SHORT, 1, 'obsoleted' ], # |
356
|
|
|
|
|
|
|
0x80e4 => ['DataType', $SHORT, 1, 'obsoleted' ], # |
357
|
|
|
|
|
|
|
0x80e5 => ['ImageDepth', $LONG, 1, $IFD_integer ], # |
358
|
|
|
|
|
|
|
0x80e6 => ['TileDepth', $LONG, 1, $IFD_integer ], # |
359
|
|
|
|
|
|
|
0x8214 => ['ImageFullWidth', $LONG, 1, $IFD_integer ], # |
360
|
|
|
|
|
|
|
0x8215 => ['ImageFullLength', $LONG, 1, $IFD_integer ], # |
361
|
|
|
|
|
|
|
0x8216 => ['TextureFormat', $ASCII, undef, $IFD_Cstring ], # |
362
|
|
|
|
|
|
|
0x8217 => ['WrapModes', $ASCII, undef, $IFD_Cstring ], # |
363
|
|
|
|
|
|
|
0x8218 => ['FovCot', $FLOAT, 1, $IFD_float ], # |
364
|
|
|
|
|
|
|
0x8219 => ['MatrixWorldToScreen', $FLOAT, 16, $IFD_float ], # |
365
|
|
|
|
|
|
|
0x821a => ['MatrixWorldToCamera', $FLOAT, 16, $IFD_float ], # |
366
|
|
|
|
|
|
|
0x827d => ['WriterSerialNumber', undef, undef, 'invalid' ], # |
367
|
|
|
|
|
|
|
0x828d => ['CFARepeatPatternDim', $SHORT, 2, $IFD_integer ], # |
368
|
|
|
|
|
|
|
0x828e => ['CFAPattern', $BYTE, undef, 'invalid' ], # |
369
|
|
|
|
|
|
|
0x828f => ['BatteryLevel', $ASCII, undef, $IFD_Cstring ], # |
370
|
|
|
|
|
|
|
0x830e => ['ModelPixelScaleTag', $DOUBLE, 3, $IFD_float ], # |
371
|
|
|
|
|
|
|
0x83bb => ['IPTC/NAA', $ASCII, undef, $IFD_Cstring ], # |
372
|
|
|
|
|
|
|
0x8480 => ['IntergraphMatrixTag', $DOUBLE, 16, 'obsoleted' ], # |
373
|
|
|
|
|
|
|
0x8482 => ['ModelTiepointTag', $DOUBLE,undef, $IFD_float ], # |
374
|
|
|
|
|
|
|
0x84e0 => ['Site', $ASCII, undef, $IFD_Cstring ], # |
375
|
|
|
|
|
|
|
0x84e1 => ['ColorSequence', $ASCII, undef, $IFD_Cstring ], # |
376
|
|
|
|
|
|
|
0x84e2 => ['IT8Header', $ASCII, undef, $IFD_Cstring ], # |
377
|
|
|
|
|
|
|
0x84e3 => ['RasterPadding', $SHORT, 1, $IFD_integer ], # |
378
|
|
|
|
|
|
|
0x84e4 => ['BitsPerRunLength', $SHORT, 1, $IFD_integer ], # |
379
|
|
|
|
|
|
|
0x84e5 => ['BitsPerExtendedRunLength', $SHORT, 1, $IFD_integer ], # |
380
|
|
|
|
|
|
|
0x84e6 => ['ColorTable', $BYTE, undef, $IFD_integer ], # |
381
|
|
|
|
|
|
|
0x84e7 => ['ImageColorIndicator', $BYTE, 1, $IFD_integer ], # |
382
|
|
|
|
|
|
|
0x84e8 => ['BackgroundColorIndicator', $BYTE, 1, $IFD_integer ], # |
383
|
|
|
|
|
|
|
0x84e9 => ['ImageColorValue', $BYTE, 1, $IFD_integer ], # |
384
|
|
|
|
|
|
|
0x84ea => ['BackgroundColorValue', $BYTE, 1, $IFD_integer ], # |
385
|
|
|
|
|
|
|
0x84eb => ['PixelIntensityRange', $BYTE, 2, $IFD_integer ], # |
386
|
|
|
|
|
|
|
0x84ec => ['TransparencyIndicator', $BYTE, 1, $IFD_integer ], # |
387
|
|
|
|
|
|
|
0x84ed => ['ColorCharacterization', $ASCII, undef, $IFD_Cstring ], # |
388
|
|
|
|
|
|
|
0x84ee => ['HCUsage', $LONG, 1, $IFD_integer ], # |
389
|
|
|
|
|
|
|
0x84ef => ['TrapIndicator', $BYTE, 1, $IFD_integer ], # |
390
|
|
|
|
|
|
|
0x84f0 => ['CMYKEquivalent', $SHORT, undef, $IFD_integer ], # |
391
|
|
|
|
|
|
|
0x84f1 => ['Reserved_TIFF_IT_1', undef, undef, 'invalid' ], # |
392
|
|
|
|
|
|
|
0x84f2 => ['Reserved_TIFF_IT_2', undef, undef, 'invalid' ], # |
393
|
|
|
|
|
|
|
0x84f3 => ['Reserved_TIFF_IT_3', undef, undef, 'invalid' ], # |
394
|
|
|
|
|
|
|
0x85b8 => ['FrameCount', $LONG, 1, $IFD_integer ], # |
395
|
|
|
|
|
|
|
0x85d8 => ['ModelTransformationTag', $DOUBLE, 16, $IFD_float ], # |
396
|
|
|
|
|
|
|
0x8649 => ['PhotoshopImageResources', $BYTE, undef, $IFD_integer ], # |
397
|
|
|
|
|
|
|
0x8773 => ['ICCProfile', undef, undef, 'invalid' ], # |
398
|
|
|
|
|
|
|
0x87af => ['GeoKeyDirectoryTag', $SHORT, undef, $IFD_integer ], # |
399
|
|
|
|
|
|
|
0x87b0 => ['GeoDoubleParamsTag', $DOUBLE,undef, $IFD_float ], # |
400
|
|
|
|
|
|
|
0x87b1 => ['GeoAsciiParamsTag', $ASCII, undef, $IFD_Cstring ], # |
401
|
|
|
|
|
|
|
0x87be => ['JBIG_Options', undef, undef, 'invalid' ], # |
402
|
|
|
|
|
|
|
0x8829 => ['Interlace', $SHORT, 1, $IFD_integer ], # |
403
|
|
|
|
|
|
|
0x882a => ['TimeZoneOffset', $SSHORT,undef, $IFD_signed ], # |
404
|
|
|
|
|
|
|
0x882b => ['SelfTimerMode', $SHORT, 1, $IFD_integer ], # |
405
|
|
|
|
|
|
|
0x885c => ['FaxRecvParams', $LONG, 1, $IFD_integer ], # |
406
|
|
|
|
|
|
|
0x885d => ['FaxSubAddress', $ASCII, undef, $IFD_Cstring ], # |
407
|
|
|
|
|
|
|
0x885e => ['FaxRecvTime', $LONG, 1, $IFD_integer ], # |
408
|
|
|
|
|
|
|
0x8871 => ['FedExEDR', undef, undef, 'invalid' ], # |
409
|
|
|
|
|
|
|
0x920b => ['FlashEnergy', $RATIONAL,undef,'invalid' ], # |
410
|
|
|
|
|
|
|
0x920c => ['SpatialFrequencyResponse', undef, undef, 'invalid' ], # |
411
|
|
|
|
|
|
|
0x920d => ['Noise', undef, undef, 'invalid' ], # |
412
|
|
|
|
|
|
|
0x920e => ['FocalPlaneXResolution', $RATIONAL, 1, 'invalid' ], # |
413
|
|
|
|
|
|
|
0x920f => ['FocalPlaneYResolution', $RATIONAL, 1, 'invalid' ], # |
414
|
|
|
|
|
|
|
0x9210 => ['FocalPlaneResolutionUnit', $SHORT, 1, 'invalid' ], # |
415
|
|
|
|
|
|
|
0x9211 => ['ImageNumber', $LONG, 1, $IFD_integer ], # |
416
|
|
|
|
|
|
|
0x9212 => ['SecurityClassification', $ASCII, undef, $IFD_Cstring ], # |
417
|
|
|
|
|
|
|
0x9213 => ['ImageHistory', $ASCII, undef, $IFD_Cstring ], # |
418
|
|
|
|
|
|
|
0x9215 => ['ExposureIndex', $RATIONAL,undef,'invalid' ], # |
419
|
|
|
|
|
|
|
0x9216 => ['TIFF/EPStandardID', $BYTE, 4, $IFD_integer ], # |
420
|
|
|
|
|
|
|
0x9217 => ['SensingMethod', $SHORT, 1, 'invalid' ], # |
421
|
|
|
|
|
|
|
0x923f => ['StoNits', $DOUBLE, 1, $IFD_float ], # |
422
|
|
|
|
|
|
|
0x935c => ['ImageSourceData', undef, undef, 'invalid' ], # |
423
|
|
|
|
|
|
|
0xc4a5 => ['PrintIM_Data', undef, undef, 'invalid' ], # |
424
|
|
|
|
|
|
|
0xc44f => ['PhotoshopAnnotations', undef, undef, 'invalid' ], # |
425
|
|
|
|
|
|
|
0xffff => ['DCSHueShiftValues', undef, undef, 'invalid' ], }; # |
426
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
427
|
|
|
|
|
|
|
my $HASH_APP1_IFD01_GENERAL = {}; # |
428
|
|
|
|
|
|
|
@$HASH_APP1_IFD01_GENERAL{keys %$_} = # |
429
|
|
|
|
|
|
|
values %$_ for ($HASH_APP1_IFD01_MAIN, # |
430
|
|
|
|
|
|
|
$HASH_APP1_IFD01_ADDITIONAL, # |
431
|
|
|
|
|
|
|
$HASH_APP1_IFD01_COMPANIES); # |
432
|
|
|
|
|
|
|
#============================================================================# |
433
|
|
|
|
|
|
|
#============================================================================# |
434
|
|
|
|
|
|
|
#============================================================================# |
435
|
|
|
|
|
|
|
# See the "Exif tags for the 0th IFD Exif private subdirectory" section in # |
436
|
|
|
|
|
|
|
# the Image::MetaData::JPEG module perldoc page for further details (private # |
437
|
|
|
|
|
|
|
# EXIF region in IFD0, also known as SubIFD). # |
438
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
439
|
|
|
|
|
|
|
# Hash keys are numeric tags, here written in hexadecimal base. # |
440
|
|
|
|
|
|
|
# Fields: 0 -> name, 1 -> type, 2 -> count, 3 -> matching regular # |
441
|
|
|
|
|
|
|
# Mandatory records: ExifVersion, ComponentsConfiguration, FlashpixVersion, # |
442
|
|
|
|
|
|
|
# ColorSpace, PixelXDimension and PixelYDimension. # |
443
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
444
|
|
|
|
|
|
|
my $IFD_subsecs = '\d*\s*\000'; # a fraction of a second # |
445
|
|
|
|
|
|
|
my $IFD_Ustring = '(ASCII\000{3}|JIS\000{5}|Unicode\000|\000{8}).*'; # |
446
|
|
|
|
|
|
|
my $IFD_DOSfile = '\w{8}\.\w{3}\000'; # a DOS filename (8+3) # |
447
|
|
|
|
|
|
|
my $IFD_lightsrc = '([0-49]|1[0-57-9]|2[0-4]|255)'; # possible light sources # |
448
|
|
|
|
|
|
|
my $IFD_flash = '([01579]|1[356]|2[459]|3[12]|6[59]|7[1379]|89|9[35])'; # |
449
|
|
|
|
|
|
|
my $IFD_hexstr = '[0-9a-fA-F]+\000+'; # hexadecimal ASCII str # |
450
|
|
|
|
|
|
|
my $IFD_Exifver = '0(100|110|200|210|220|221)'; # known Exif versions # |
451
|
|
|
|
|
|
|
my $IFD_setdesc = '.{4}(\376\377(.{2})*\000\000)*'; # for DeviceSettingDesc.# |
452
|
|
|
|
|
|
|
my $IFD_compconf = '(\004\005\006|\001\002\003)\000';# for ComponentsConfig. # |
453
|
|
|
|
|
|
|
#--- Special screen rules ---------------------------------------------------# |
454
|
|
|
|
|
|
|
# a SubjectArea tag indicates the location and area of the main subject. The # |
455
|
|
|
|
|
|
|
# tag can contain 2, 3 or 4 integer numbers (see Exif 2.2 for their meaning) # |
456
|
|
|
|
|
|
|
my $SSR_subjectarea = sub { die if scalar @_ < 2 || scalar @_ > 4; # |
457
|
|
|
|
|
|
|
die if grep { ! /^\d+$/ } @_; }; # |
458
|
|
|
|
|
|
|
# a CFAPattern tag indicates a color filter array. The first four bytes are # |
459
|
|
|
|
|
|
|
# two shorts giving the horizontal (m) and vertical (n) repeat pixel units. # |
460
|
|
|
|
|
|
|
# Then, m x n bytes follow, with the actual filter values (in the range 0-6).# |
461
|
|
|
|
|
|
|
my $SSR_cfapattern = sub { my ($x, $y) = unpack 'nn', $_[0]; # |
462
|
|
|
|
|
|
|
die if length $_[0] != 4+$x*$y; # |
463
|
|
|
|
|
|
|
die if $_[0] !~ /^.{4}[0-6]*$/; }; # |
464
|
|
|
|
|
|
|
#--- Mandatory records ------------------------------------------------------# |
465
|
|
|
|
|
|
|
my $HASH_APP1_SUBIFD_MANDATORY = {'ExifVersion' => '0220', # |
466
|
|
|
|
|
|
|
'ComponentsConfiguration' => "\001\002\003\000", # |
467
|
|
|
|
|
|
|
'FlashpixVersion' => '0100', # |
468
|
|
|
|
|
|
|
'ColorSpace' => 1, # |
469
|
|
|
|
|
|
|
'PixelXDimension' => 0, # global info # |
470
|
|
|
|
|
|
|
'PixelYDimension' => 0 }; # needed here! # |
471
|
|
|
|
|
|
|
#--- Legal records' list ----------------------------------------------------# |
472
|
|
|
|
|
|
|
my $HASH_APP1_SUBIFD_GENERAL = # |
473
|
|
|
|
|
|
|
{0x829a => ['ExposureTime', $RATIONAL, 1, $IFD_integer ], # |
474
|
|
|
|
|
|
|
0x829d => ['FNumber', $RATIONAL, 1, $IFD_integer ], # |
475
|
|
|
|
|
|
|
0x8822 => ['ExposureProgram', $SHORT, 1, '[0-8]' ], # |
476
|
|
|
|
|
|
|
0x8824 => ['SpectralSensitivity', $ASCII, undef, $IFD_Cstring ], # |
477
|
|
|
|
|
|
|
0x8827 => ['ISOSpeedRatings', $SHORT, undef, $IFD_integer ], # |
478
|
|
|
|
|
|
|
0x8828 => ['OECF', $UNDEF, undef, '.*' ], # |
479
|
|
|
|
|
|
|
0x9000 => ['ExifVersion', $UNDEF, 4, $IFD_Exifver ], # |
480
|
|
|
|
|
|
|
0x9003 => ['DateTimeOriginal', $ASCII, 20, $IFD_datetime ], # |
481
|
|
|
|
|
|
|
0x9004 => ['DateTimeDigitized', $ASCII, 20, $IFD_datetime ], # |
482
|
|
|
|
|
|
|
0x9101 => ['ComponentsConfiguration', $UNDEF, 4, $IFD_compconf ], # |
483
|
|
|
|
|
|
|
0x9102 => ['CompressedBitsPerPixel', $RATIONAL, 1, $IFD_integer ], # |
484
|
|
|
|
|
|
|
0x9201 => ['ShutterSpeedValue', $SRATIONAL, 1, $IFD_signed ], # |
485
|
|
|
|
|
|
|
0x9202 => ['ApertureValue', $RATIONAL, 1, $IFD_integer ], # |
486
|
|
|
|
|
|
|
0x9203 => ['BrightnessValue', $SRATIONAL, 1, $IFD_signed ], # |
487
|
|
|
|
|
|
|
0x9204 => ['ExposureBiasValue', $SRATIONAL, 1, $IFD_signed ], # |
488
|
|
|
|
|
|
|
0x9205 => ['MaxApertureValue', $RATIONAL, 1, $IFD_integer ], # |
489
|
|
|
|
|
|
|
0x9206 => ['SubjectDistance', $RATIONAL, 1, $IFD_integer ], # |
490
|
|
|
|
|
|
|
0x9207 => ['MeteringMode', $SHORT, 1, '([0-6]|255)' ], # |
491
|
|
|
|
|
|
|
0x9208 => ['LightSource', $SHORT, 1, $IFD_lightsrc ], # |
492
|
|
|
|
|
|
|
0x9209 => ['Flash', $SHORT, 1, $IFD_flash ], # |
493
|
|
|
|
|
|
|
0x920a => ['FocalLength', $RATIONAL, 1, $IFD_integer ], # |
494
|
|
|
|
|
|
|
0x9214 => ['SubjectArea', $SHORT, undef, $SSR_subjectarea], # |
495
|
|
|
|
|
|
|
0x927c => ['MakerNote', $UNDEF, undef, 'invalid' ], # |
496
|
|
|
|
|
|
|
0x9286 => ['UserComment', $UNDEF, undef, $IFD_Ustring ], # |
497
|
|
|
|
|
|
|
0x9290 => ['SubSecTime', $ASCII, undef, $IFD_subsecs ], # |
498
|
|
|
|
|
|
|
0x9291 => ['SubSecTimeOriginal', $ASCII, undef, $IFD_subsecs ], # |
499
|
|
|
|
|
|
|
0x9292 => ['SubSecTimeDigitized', $ASCII, undef, $IFD_subsecs ], # |
500
|
|
|
|
|
|
|
0xa000 => ['FlashpixVersion', $UNDEF, 4, '0100' ], # |
501
|
|
|
|
|
|
|
0xa001 => ['ColorSpace', $SHORT, 1, '(1|65535)' ], # |
502
|
|
|
|
|
|
|
0xa002 => ['PixelXDimension', $LONG, 1, $IFD_integer ], # |
503
|
|
|
|
|
|
|
0xa003 => ['PixelYDimension', $LONG, 1, $IFD_integer ], # |
504
|
|
|
|
|
|
|
0xa004 => ['RelatedSoundFile', $ASCII, 13, $IFD_DOSfile ], # |
505
|
|
|
|
|
|
|
0xa005 => ['InteroperabilityOffset', $LONG, 1, 'calculated' ], # |
506
|
|
|
|
|
|
|
0xa20b => ['FlashEnergy', $RATIONAL, 1, $IFD_integer ], # |
507
|
|
|
|
|
|
|
0xa20c => ['SpatialFrequencyResponse', $UNDEF, undef, '.*' ], # |
508
|
|
|
|
|
|
|
0xa20e => ['FocalPlaneXResolution', $RATIONAL, 1, $IFD_integer ], # |
509
|
|
|
|
|
|
|
0xa20f => ['FocalPlaneYResolution', $RATIONAL, 1, $IFD_integer ], # |
510
|
|
|
|
|
|
|
0xa210 => ['FocalPlaneResolutionUnit', $SHORT, 1, '[23]' ], # |
511
|
|
|
|
|
|
|
0xa214 => ['SubjectLocation', $SHORT, 2, $IFD_integer ], # |
512
|
|
|
|
|
|
|
0xa215 => ['ExposureIndex', $RATIONAL, 1, $IFD_integer ], # |
513
|
|
|
|
|
|
|
0xa217 => ['SensingMethod', $SHORT, 1, '[1-578]' ], # |
514
|
|
|
|
|
|
|
0xa300 => ['FileSource', $UNDEF, 1, '\003' ], # |
515
|
|
|
|
|
|
|
0xa301 => ['SceneType', $UNDEF, 1, '\001' ], # |
516
|
|
|
|
|
|
|
0xa302 => ['CFAPattern', $UNDEF, undef, $SSR_cfapattern ], # |
517
|
|
|
|
|
|
|
0xa401 => ['CustomRendered', $SHORT, 1, '[01]' ], # |
518
|
|
|
|
|
|
|
0xa402 => ['ExposureMode', $SHORT, 1, '[012]' ], # |
519
|
|
|
|
|
|
|
0xa403 => ['WhiteBalance', $SHORT, 1, '[01]' ], # |
520
|
|
|
|
|
|
|
0xa404 => ['DigitalZoomRatio', $RATIONAL, 1, $IFD_integer ], # |
521
|
|
|
|
|
|
|
0xa405 => ['FocalLengthIn35mmFilm', $SHORT, 1, $IFD_integer ], # |
522
|
|
|
|
|
|
|
0xa406 => ['SceneCaptureType', $SHORT, 1, '[0-3]' ], # |
523
|
|
|
|
|
|
|
0xa407 => ['GainControl', $SHORT, 1, '[0-4]' ], # |
524
|
|
|
|
|
|
|
0xa408 => ['Contrast', $SHORT, 1, '[0-2]' ], # |
525
|
|
|
|
|
|
|
0xa409 => ['Saturation', $SHORT, 1, '[0-2]' ], # |
526
|
|
|
|
|
|
|
0xa40a => ['Sharpness', $SHORT, 1, '[0-2]' ], # |
527
|
|
|
|
|
|
|
0xa40b => ['DeviceSettingDescription', $UNDEF, undef, $IFD_setdesc ], # |
528
|
|
|
|
|
|
|
0xa40c => ['SubjectDistanceRange', $SHORT, 1, '[0-3]' ], # |
529
|
|
|
|
|
|
|
0xa420 => ['ImageUniqueID', $ASCII, 33, $IFD_hexstr ], # |
530
|
|
|
|
|
|
|
# --- From Photoshop >= 7.0 treatment of raw camera files (undocumented) --- # |
531
|
|
|
|
|
|
|
0xfde8 => ['_OwnerName', $ASCII, undef, "Owner'".'s Name: .*\000' ], # |
532
|
|
|
|
|
|
|
0xfde9 => ['_SerialNumber', $ASCII, undef, 'Serial Number: .*\000' ], # |
533
|
|
|
|
|
|
|
0xfdea => ['_Lens', $ASCII, undef, 'Lens: .*\000' ], # |
534
|
|
|
|
|
|
|
0xfe4c => ['_RawFile', $ASCII, undef, 'Raw File: .*\000' ], # |
535
|
|
|
|
|
|
|
0xfe4d => ['_Converter', $ASCII, undef, 'Converter: .*\000' ], # |
536
|
|
|
|
|
|
|
0xfe4e => ['_WhiteBalance', $ASCII, undef, 'White Balance: .*\000' ], # |
537
|
|
|
|
|
|
|
0xfe51 => ['_Exposure', $ASCII, undef, 'Exposure: .*\000' ], # |
538
|
|
|
|
|
|
|
0xfe52 => ['_Shadows', $ASCII, undef, 'Shadows: .*\000' ], # |
539
|
|
|
|
|
|
|
0xfe53 => ['_Brightness', $ASCII, undef, 'Brightness: .*\000' ], # |
540
|
|
|
|
|
|
|
0xfe54 => ['_Contrast', $ASCII, undef, 'Contrast: .*\000' ], # |
541
|
|
|
|
|
|
|
0xfe55 => ['_Saturation', $ASCII, undef, 'Saturation: .*\000' ], # |
542
|
|
|
|
|
|
|
0xfe56 => ['_Sharpness', $ASCII, undef, 'Sharpness: .*\000' ], # |
543
|
|
|
|
|
|
|
0xfe57 => ['_Smoothness', $ASCII, undef, 'Smoothness: .*\000' ], # |
544
|
|
|
|
|
|
|
0xfe58 => ['_MoireFilter', $ASCII, undef, 'Moire Filter: .*\000' ], }; # |
545
|
|
|
|
|
|
|
#============================================================================# |
546
|
|
|
|
|
|
|
#============================================================================# |
547
|
|
|
|
|
|
|
#============================================================================# |
548
|
|
|
|
|
|
|
# See the "EXIF tags for the 0th IFD Interoperability subdirectory" section # |
549
|
|
|
|
|
|
|
# in the Image::MetaData::JPEG module perldoc page for further details. # |
550
|
|
|
|
|
|
|
# Mandatory records: InteroperabilityIndex and InteroperabilityVersion # |
551
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
552
|
|
|
|
|
|
|
# Hash keys are numeric tags, here written in hexadecimal base. # |
553
|
|
|
|
|
|
|
# Fields: 0 -> name, 1 -> type, 2 -> count, 3 -> matching regular # |
554
|
|
|
|
|
|
|
#--- Mandatory records ------------------------------------------------------# |
555
|
|
|
|
|
|
|
my $HASH_INTEROP_MANDATORY = {'InteroperabilityVersion' => '0100', # |
556
|
|
|
|
|
|
|
'InteroperabilityIndex' => 'R98' }; # |
557
|
|
|
|
|
|
|
#--- Legal records' list ----------------------------------------------------# |
558
|
|
|
|
|
|
|
my $HASH_INTEROP_GENERAL = # |
559
|
|
|
|
|
|
|
{0x0001 => ['InteroperabilityIndex', $ASCII, 4, 'R98\000' ], # |
560
|
|
|
|
|
|
|
0x0002 => ['InteroperabilityVersion', $UNDEF, 4, '[0-9]{4}' ], # |
561
|
|
|
|
|
|
|
0x1000 => ['RelatedImageFileFormat', $ASCII, undef, $IFD_Cstring ], # |
562
|
|
|
|
|
|
|
0x1001 => ['RelatedImageWidth', $LONG, 1, '[0-9]*' ], # |
563
|
|
|
|
|
|
|
0x1002 => ['RelatedImageLength', $LONG, 1, '[0-9]*' ], }; # |
564
|
|
|
|
|
|
|
#============================================================================# |
565
|
|
|
|
|
|
|
#============================================================================# |
566
|
|
|
|
|
|
|
#============================================================================# |
567
|
|
|
|
|
|
|
# See the "EXIF tags for the 0th IFD GPS subdirectory" section in the # |
568
|
|
|
|
|
|
|
# Image::MetaData::JPEG module perldoc page for further details on GPS data. # |
569
|
|
|
|
|
|
|
# Mandatory records: only GPSVersionID # |
570
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
571
|
|
|
|
|
|
|
# Hash keys are numeric tags, here written in hexadecimal base. # |
572
|
|
|
|
|
|
|
# Fields: 0 -> name, 1 -> type, 2 -> count, 3 -> matching regular # |
573
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
574
|
|
|
|
|
|
|
my $GPS_re_Cstring = $re_Cstring; # a null terminated string # |
575
|
|
|
|
|
|
|
my $GPS_re_date = $re_dt18_cl . '\000'; # YYYY:MM:DD null terminated # |
576
|
|
|
|
|
|
|
my $GPS_re_number = $re_integer; # a generic integer number # |
577
|
|
|
|
|
|
|
my $GPS_re_NS = '[NS]\000'; # latitude reference # |
578
|
|
|
|
|
|
|
my $GPS_re_EW = '[EW]\000'; # longitude reference # |
579
|
|
|
|
|
|
|
my $GPS_re_spdsref = '[KMN]\000'; # speed or distance reference # |
580
|
|
|
|
|
|
|
my $GPS_re_direref = '[TM]\000'; # directin reference # |
581
|
|
|
|
|
|
|
my $GPS_re_string = '[AJU\000].*'; # GPS "undefined" strings # |
582
|
|
|
|
|
|
|
#--- Special screen rules ---------------------------------------------------# |
583
|
|
|
|
|
|
|
# a direction is a rational number in [0.00, 359.99] (we should also test # |
584
|
|
|
|
|
|
|
# explicitely that the numerator and the denominator are not negative). # |
585
|
|
|
|
|
|
|
my $SSR_direction = sub { die if grep { $_ < 0 } @_; # |
586
|
|
|
|
|
|
|
my $dire = $_[0]/$_[1]; die if $dire >= 360; # |
587
|
|
|
|
|
|
|
die unless $dire =~ /^\d+(\.\d{1,2})?$/; }; # |
588
|
|
|
|
|
|
|
# a "triplet" corresponds to three rationals for units, minutes (< 60) and # |
589
|
|
|
|
|
|
|
# seconds (< 60). The 1st argument must be a limit on units (helper rule). # |
590
|
|
|
|
|
|
|
my $SSR_triplet = sub { my $limit = shift; die if grep { $_ < 0 } @_; # |
591
|
|
|
|
|
|
|
my ($dd,$mm,$ss) = map {$_[$_]/$_[1+$_]} (0,2,4); # |
592
|
|
|
|
|
|
|
die unless $mm < 60 && $ss < 60 && $dd <= $limit; # |
593
|
|
|
|
|
|
|
die unless ($dd + $mm /60 + $ss/360) <= $limit;}; # |
594
|
|
|
|
|
|
|
# a latitude or a longitude is stored as a sequence of three rationals nums # |
595
|
|
|
|
|
|
|
# (degrees, minutes and seconds) with degrees<=90 or 180 (see $SSR_triplet). # |
596
|
|
|
|
|
|
|
my $SSR_latitude = sub { &$SSR_triplet( 90, @_); }; # |
597
|
|
|
|
|
|
|
my $SSR_longitude = sub { &$SSR_triplet(180, @_); }; # |
598
|
|
|
|
|
|
|
# a time stamp is stored as three rationals (hours, minutes and seconds); in # |
599
|
|
|
|
|
|
|
# this case hours must be <= 24 (see $SSR_triplet for further details). # |
600
|
|
|
|
|
|
|
my $SSR_stupidtime = sub { &$SSR_triplet(24, @_); }; # |
601
|
|
|
|
|
|
|
#--- Mandatory records ------------------------------------------------------# |
602
|
|
|
|
|
|
|
my $HASH_GPS_MANDATORY = {'GPSVersionID' => [2,2,0,0]}; # |
603
|
|
|
|
|
|
|
#--- Legal records' list ----------------------------------------------------# |
604
|
|
|
|
|
|
|
my $HASH_GPS_GENERAL = # |
605
|
|
|
|
|
|
|
{0x00 => ['GPSVersionID', $BYTE, 4, '.' ], # |
606
|
|
|
|
|
|
|
0x01 => ['GPSLatitudeRef', $ASCII, 2, $GPS_re_NS ], # |
607
|
|
|
|
|
|
|
0x02 => ['GPSLatitude', $RATIONAL, 3, $SSR_latitude ], # |
608
|
|
|
|
|
|
|
0x03 => ['GPSLongitudeRef', $ASCII, 2, $GPS_re_EW ], # |
609
|
|
|
|
|
|
|
0x04 => ['GPSLongitude', $RATIONAL, 3, $SSR_longitude ], # |
610
|
|
|
|
|
|
|
0x05 => ['GPSAltitudeRef', $BYTE, 1, '[01]' ], # |
611
|
|
|
|
|
|
|
0x06 => ['GPSAltitude', $RATIONAL, 1, $GPS_re_number ], # |
612
|
|
|
|
|
|
|
0x07 => ['GPSTimeStamp', $RATIONAL, 3, $SSR_stupidtime ], # |
613
|
|
|
|
|
|
|
0x08 => ['GPSSatellites', $ASCII, undef, $GPS_re_Cstring ], # |
614
|
|
|
|
|
|
|
0x09 => ['GPSStatus', $ASCII, 2, '[AV]\000' ], # |
615
|
|
|
|
|
|
|
0x0a => ['GPSMeasureMode', $ASCII, 2, '[23]\000' ], # |
616
|
|
|
|
|
|
|
0x0b => ['GPSDOP', $RATIONAL, 1, $GPS_re_number ], # |
617
|
|
|
|
|
|
|
0x0c => ['GPSSpeedRef', $ASCII, 2, $GPS_re_spdsref ], # |
618
|
|
|
|
|
|
|
0x0d => ['GPSSpeed', $RATIONAL, 1, $GPS_re_number ], # |
619
|
|
|
|
|
|
|
0x0e => ['GPSTrackRef', $ASCII, 2, $GPS_re_direref ], # |
620
|
|
|
|
|
|
|
0x0f => ['GPSTrack', $RATIONAL, 1, $SSR_direction ], # |
621
|
|
|
|
|
|
|
0x10 => ['GPSImgDirectionRef', $ASCII, 2, $GPS_re_direref ], # |
622
|
|
|
|
|
|
|
0x11 => ['GPSImgDirection', $RATIONAL, 1, $SSR_direction ], # |
623
|
|
|
|
|
|
|
0x12 => ['GPSMapDatum', $ASCII, undef, $GPS_re_Cstring ], # |
624
|
|
|
|
|
|
|
0x13 => ['GPSDestLatitudeRef', $ASCII, 2, $GPS_re_NS ], # |
625
|
|
|
|
|
|
|
0x14 => ['GPSDestLatitude', $RATIONAL, 3, $SSR_latitude ], # |
626
|
|
|
|
|
|
|
0x15 => ['GPSDestLongitudeRef', $ASCII, 2, $GPS_re_EW ], # |
627
|
|
|
|
|
|
|
0x16 => ['GPSDestLongitude', $RATIONAL, 3, $SSR_longitude ], # |
628
|
|
|
|
|
|
|
0x17 => ['GPSDestBearingRef', $ASCII, 2, $GPS_re_direref ], # |
629
|
|
|
|
|
|
|
0x18 => ['GPSDestBearing', $RATIONAL, 1, $SSR_direction ], # |
630
|
|
|
|
|
|
|
0x19 => ['GPSDestDistanceRef', $ASCII, 2, $GPS_re_spdsref ], # |
631
|
|
|
|
|
|
|
0x1a => ['GPSDestDistance', $RATIONAL, 1, $GPS_re_number ], # |
632
|
|
|
|
|
|
|
0x1b => ['GPSProcessingMethod', $UNDEF, undef, $GPS_re_string ], # |
633
|
|
|
|
|
|
|
0x1c => ['GPSAreaInformation', $UNDEF, undef, $GPS_re_string ], # |
634
|
|
|
|
|
|
|
0x1d => ['GPSDateStamp', $ASCII, 11, $GPS_re_date ], # |
635
|
|
|
|
|
|
|
0x1e => ['GPSDifferential', $SHORT, 1, '[01]' ],}; # |
636
|
|
|
|
|
|
|
#============================================================================# |
637
|
|
|
|
|
|
|
|
638
|
|
|
|
|
|
|
# Tags used for ICC data in APP2 (they are 4 bytes strings, so |
639
|
|
|
|
|
|
|
# I prefer to write the string and then convert it). |
640
|
592
|
|
|
592
|
0
|
453
|
sub str2hex { my $z = 0; ($z *= 256) += $_ for unpack "CCCC", $_[0]; $z; } |
|
592
|
|
|
|
|
1382
|
|
|
592
|
|
|
|
|
11447
|
|
641
|
|
|
|
|
|
|
my $HASH_APP2_ICC = |
642
|
|
|
|
|
|
|
{str2hex('A2B0') => 'AT0B0Tag', |
643
|
|
|
|
|
|
|
str2hex('A2B1') => 'AToB1Tag', |
644
|
|
|
|
|
|
|
str2hex('A2B2') => 'AToB2Tag', |
645
|
|
|
|
|
|
|
str2hex('bXYZ') => 'BlueMatrixColumn', |
646
|
|
|
|
|
|
|
str2hex('bTRC') => 'BlueTRC', |
647
|
|
|
|
|
|
|
str2hex('B2A0') => 'BToA0Tag', |
648
|
|
|
|
|
|
|
str2hex('B2A1') => 'BToA1Tag', |
649
|
|
|
|
|
|
|
str2hex('B2A2') => 'BToA2Tag', |
650
|
|
|
|
|
|
|
str2hex('calt') => 'CalibrationDateTime', |
651
|
|
|
|
|
|
|
str2hex('targ') => 'CharTarget', |
652
|
|
|
|
|
|
|
str2hex('chad') => 'ChromaticAdaptation', |
653
|
|
|
|
|
|
|
str2hex('chrm') => 'Chromaticity', |
654
|
|
|
|
|
|
|
str2hex('clro') => 'ColorantOrder', |
655
|
|
|
|
|
|
|
str2hex('clrt') => 'ColorantTable', |
656
|
|
|
|
|
|
|
str2hex('cprt') => 'Copyright', |
657
|
|
|
|
|
|
|
str2hex('dmnd') => 'DeviceMfgDesc', |
658
|
|
|
|
|
|
|
str2hex('dmdd') => 'DeviceModelDesc', |
659
|
|
|
|
|
|
|
str2hex('gamt') => 'Gamut', |
660
|
|
|
|
|
|
|
str2hex('kTRC') => 'GrayTRC', |
661
|
|
|
|
|
|
|
str2hex('gXYZ') => 'GreenMatrixColumn', |
662
|
|
|
|
|
|
|
str2hex('gTRC') => 'GreenTRC', |
663
|
|
|
|
|
|
|
str2hex('lumi') => 'Luminance', |
664
|
|
|
|
|
|
|
str2hex('meas') => 'Measurement', |
665
|
|
|
|
|
|
|
str2hex('bkpt') => 'MediaBlackPoint', |
666
|
|
|
|
|
|
|
str2hex('wtpt') => 'MediaWhitePoint', |
667
|
|
|
|
|
|
|
str2hex('ncl2') => 'NamedColor2', |
668
|
|
|
|
|
|
|
str2hex('resp') => 'OutputResponse', |
669
|
|
|
|
|
|
|
str2hex('pre0') => 'Preview0', |
670
|
|
|
|
|
|
|
str2hex('pre1') => 'Preview1', |
671
|
|
|
|
|
|
|
str2hex('pre2') => 'Preview2', |
672
|
|
|
|
|
|
|
str2hex('desc') => 'ProfileDescription', |
673
|
|
|
|
|
|
|
str2hex('pseq') => 'ProfileSequenceDesc', |
674
|
|
|
|
|
|
|
str2hex('rXYZ') => 'RedMatrixColumn', |
675
|
|
|
|
|
|
|
str2hex('rTRC') => 'RedTRC', |
676
|
|
|
|
|
|
|
str2hex('tech') => 'Technology', |
677
|
|
|
|
|
|
|
str2hex('vued') => 'ViewingCondDesc', |
678
|
|
|
|
|
|
|
str2hex('view') => 'ViewingConditions', }; |
679
|
|
|
|
|
|
|
|
680
|
|
|
|
|
|
|
# Tags used by the 0-th IFD of an APP3 segment (reference ... ?) |
681
|
|
|
|
|
|
|
my $HASH_APP3_IFD = |
682
|
|
|
|
|
|
|
{0xc350 => 'FilmProductCode', |
683
|
|
|
|
|
|
|
0xc351 => 'ImageSource', |
684
|
|
|
|
|
|
|
0xc352 => 'PrintArea', |
685
|
|
|
|
|
|
|
0xc353 => 'CameraOwner', |
686
|
|
|
|
|
|
|
0xc354 => 'CameraSerialNumber', |
687
|
|
|
|
|
|
|
0xc355 => 'GroupCaption', |
688
|
|
|
|
|
|
|
0xc356 => 'DealerID', |
689
|
|
|
|
|
|
|
0xc357 => 'OrderID', |
690
|
|
|
|
|
|
|
0xc358 => 'BagNumber', |
691
|
|
|
|
|
|
|
0xc359 => 'ScanFrameSeqNumber', |
692
|
|
|
|
|
|
|
0xc35a => 'FilmCategory', |
693
|
|
|
|
|
|
|
0xc35b => 'FilmGenCode', |
694
|
|
|
|
|
|
|
0xc35c => 'ScanSoftware', |
695
|
|
|
|
|
|
|
0xc35d => 'FilmSize', |
696
|
|
|
|
|
|
|
0xc35e => 'SBARGBShifts', |
697
|
|
|
|
|
|
|
0xc35f => 'SBAInputColor', |
698
|
|
|
|
|
|
|
0xc360 => 'SBAInputBitDepth', |
699
|
|
|
|
|
|
|
0xc361 => 'SBAExposureRec', |
700
|
|
|
|
|
|
|
0xc362 => 'UserSBARGBShifts', |
701
|
|
|
|
|
|
|
0xc363 => 'ImageRotationStatus', |
702
|
|
|
|
|
|
|
0xc364 => 'RollGUID', |
703
|
|
|
|
|
|
|
0xc365 => 'APP3Version', |
704
|
|
|
|
|
|
|
0xc36e => 'SpecialEffectsIFD', # pointer to an IFD |
705
|
|
|
|
|
|
|
0xc36f => 'BordersIFD', }; # pointer to an IFD |
706
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
my $HASH_APP3_SPECIAL = |
708
|
|
|
|
|
|
|
{0x0000 => 'APP3_SpecialIFD_tag_0', |
709
|
|
|
|
|
|
|
0x0001 => 'APP3_SpecialIFD_tag_1', |
710
|
|
|
|
|
|
|
0x0002 => 'APP3_SpecialIFD_tag_2', }; |
711
|
|
|
|
|
|
|
|
712
|
|
|
|
|
|
|
my $HASH_APP3_BORDERS = |
713
|
|
|
|
|
|
|
{0x0000 => 'APP3_BordersIFD_tag_0', |
714
|
|
|
|
|
|
|
0x0001 => 'APP3_BordersIFD_tag_1', |
715
|
|
|
|
|
|
|
0x0002 => 'APP3_BordersIFD_tag_2', |
716
|
|
|
|
|
|
|
0x0003 => 'APP3_BordersIFD_tag_3', |
717
|
|
|
|
|
|
|
0x0004 => 'APP3_BordersIFD_tag_4', |
718
|
|
|
|
|
|
|
0x0008 => 'APP3_BordersIFD_tag_8', }; |
719
|
|
|
|
|
|
|
|
720
|
|
|
|
|
|
|
#============================================================================# |
721
|
|
|
|
|
|
|
#============================================================================# |
722
|
|
|
|
|
|
|
#============================================================================# |
723
|
|
|
|
|
|
|
# See the "VALID TAGS FOR IPTC DATA" section in the Image::MetaData::JPEG # |
724
|
|
|
|
|
|
|
# module perldoc page for further details on IPTC data. Also 1:xx datasets # |
725
|
|
|
|
|
|
|
# are documented here, although only 2:xx datasets are likely to be found. # |
726
|
|
|
|
|
|
|
# Note: I don't know why the standard says 4 for 'RecordVersion'; it turns # |
727
|
|
|
|
|
|
|
# out that you always find 2 in JPEG files. # |
728
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
729
|
|
|
|
|
|
|
# Hash keys are numeric tags in decimal (the IPTC standard uses base 10...). # |
730
|
|
|
|
|
|
|
# Fields: 0 -> Tag name, 1 -> repeatability ('N' means non-repeatable), # |
731
|
|
|
|
|
|
|
# 2,3 -> min and max length, 4 -> regular expression to match. # |
732
|
|
|
|
|
|
|
# The regular expression for "words" is what they call graphic characters. # |
733
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
734
|
|
|
|
|
|
|
my $IPTC_re_word = '^[^\000-\040\177]*$'; # words # |
735
|
|
|
|
|
|
|
my $IPTC_re_line = '^[^\000-\037\177]*$'; # words + spaces # |
736
|
|
|
|
|
|
|
my $IPTC_re_para = '^[^\000-\011\013\014\016-\037\177]*$'; # line + CR + LF # |
737
|
|
|
|
|
|
|
my $IPTC_re_dt18 = $re_dt18; # CCYYMMDD # |
738
|
|
|
|
|
|
|
my $IPTC_re_date = $re_date; # CCYYMMDD full # |
739
|
|
|
|
|
|
|
my $IPTC_re_dura = $re_time; # HHMMSS # |
740
|
|
|
|
|
|
|
my $IPTC_re_time = $IPTC_re_dura . '[\+-]' . $re_zone; # HHMMSS+/-HHMM # |
741
|
|
|
|
|
|
|
my $vchr = '\040-\051\053-\071\073-\076\100-\176'; # (SubjectRef.) # |
742
|
|
|
|
|
|
|
my $IPTC_re_sure='['.$vchr.']{1,32}?:[01]\d{7}(:['.$vchr.'\s]{0,64}?){3}'; # |
743
|
|
|
|
|
|
|
#--- Mandatory records ------------------------------------------------------# |
744
|
|
|
|
|
|
|
my $HASH_IPTC_MANDATORY_1 = {'ModelVersion' => "\000\004" }; # |
745
|
|
|
|
|
|
|
my $HASH_IPTC_MANDATORY_2 = {'RecordVersion' => "\000\002" }; # |
746
|
|
|
|
|
|
|
#--- Legal records' list ( datasets 1:xx ) ----------------------------------# |
747
|
|
|
|
|
|
|
my $HASH_IPTC_GENERAL_1 = # |
748
|
|
|
|
|
|
|
{0 => ['ModelVersion', 'N', 2, 2, 'binary' ], # |
749
|
|
|
|
|
|
|
5 => ['Destination', ' ',1,1024, $IPTC_re_word ], # |
750
|
|
|
|
|
|
|
20 => ['FileFormat', 'N', 2, 2, 'invalid,binary' ], # |
751
|
|
|
|
|
|
|
22 => ['FileFormatVersion', 'N', 2, 2, 'invalid,binary' ], # |
752
|
|
|
|
|
|
|
30 => ['ServiceIdentifier', 'N', 0, 10, $IPTC_re_word ], # |
753
|
|
|
|
|
|
|
40 => ['EnvelopeNumber', 'N', 8, 8, 'invalid,\d{8}' ], # |
754
|
|
|
|
|
|
|
50 => ['ProductID', ' ', 0, 32, $IPTC_re_word ], # |
755
|
|
|
|
|
|
|
60 => ['EnvelopePriority', 'N', 1, 1, 'invalid,[1-9]' ], # |
756
|
|
|
|
|
|
|
70 => ['DataSent', 'N', 8, 8, 'invalid,date' ], # |
757
|
|
|
|
|
|
|
80 => ['TimeSent', 'N',11, 11, 'invalid,time' ], # |
758
|
|
|
|
|
|
|
90 => ['CodedCharacterSet', 'N', 0, 32, '\033.{1,3}' ], # |
759
|
|
|
|
|
|
|
100 => ['UNO', 'N',14, 80, 'invalid' ], # |
760
|
|
|
|
|
|
|
120 => ['ARMIdentifier', 'N', 2, 2, 'invalid,binary' ], # |
761
|
|
|
|
|
|
|
122 => ['ARMVersion', 'N', 2, 2, 'invalid,binary' ],}; # |
762
|
|
|
|
|
|
|
#--- Legal records' list ( datasets 2:xx ) ----------------------------------# |
763
|
|
|
|
|
|
|
my $HASH_IPTC_GENERAL_2 = # |
764
|
|
|
|
|
|
|
{0 => ['RecordVersion', 'N', 2, 2, 'binary' ], # |
765
|
|
|
|
|
|
|
3 => ['ObjectTypeReference', 'N', 3, 67, '\d{2}:[\w\s]{0,64}?' ], # |
766
|
|
|
|
|
|
|
4 => ['ObjectAttributeReference', ' ', 4, 68, '\d{3}:[\w\s]{0,64}?' ], # |
767
|
|
|
|
|
|
|
5 => ['ObjectName', 'N', 1, 64, $IPTC_re_line ], # |
768
|
|
|
|
|
|
|
7 => ['EditStatus', 'N', 1, 64, $IPTC_re_line ], # |
769
|
|
|
|
|
|
|
8 => ['EditorialUpdate', 'N', 2, 2, '01' ], # |
770
|
|
|
|
|
|
|
10 => ['Urgency', 'N', 1, 1, '[1-8]' ], # |
771
|
|
|
|
|
|
|
12 => ['SubjectReference', ' ',13,236, $IPTC_re_sure ], # |
772
|
|
|
|
|
|
|
15 => ['Category', 'N', 1, 3, '[a-zA-Z]{1,3}?' ], # |
773
|
|
|
|
|
|
|
20 => ['SupplementalCategory', ' ', 1, 32, $IPTC_re_line ], # |
774
|
|
|
|
|
|
|
22 => ['FixtureIdentifier', 'N', 1, 32, $IPTC_re_word ], # |
775
|
|
|
|
|
|
|
25 => ['Keywords', ' ', 1, 64, $IPTC_re_line ], # |
776
|
|
|
|
|
|
|
26 => ['ContentLocationCode', ' ', 3, 3, '[A-Z]{3}' ], # |
777
|
|
|
|
|
|
|
27 => ['ContentLocationName', ' ', 1, 64, $IPTC_re_line ], # |
778
|
|
|
|
|
|
|
30 => ['ReleaseDate', 'N', 8, 8, $IPTC_re_dt18 ], # |
779
|
|
|
|
|
|
|
35 => ['ReleaseTime', 'N',11, 11, $IPTC_re_time ], # |
780
|
|
|
|
|
|
|
37 => ['ExpirationDate', 'N', 8, 8, $IPTC_re_dt18 ], # |
781
|
|
|
|
|
|
|
38 => ['ExpirationTime', 'N',11, 11, $IPTC_re_time ], # |
782
|
|
|
|
|
|
|
40 => ['SpecialInstructions', 'N', 1,256, $IPTC_re_line ], # |
783
|
|
|
|
|
|
|
42 => ['ActionAdvised', 'N', 2, 2, '0[1-4]' ], # |
784
|
|
|
|
|
|
|
45 => ['ReferenceService', ' ',10, 10, 'invalid' ], # |
785
|
|
|
|
|
|
|
47 => ['ReferenceDate', ' ', 8, 8, 'invalid' ], # |
786
|
|
|
|
|
|
|
50 => ['ReferenceNumber', ' ', 8, 8, 'invalid' ], # |
787
|
|
|
|
|
|
|
55 => ['DateCreated', 'N', 8, 8, $IPTC_re_date ], # |
788
|
|
|
|
|
|
|
60 => ['TimeCreated', 'N',11, 11, $IPTC_re_time ], # |
789
|
|
|
|
|
|
|
62 => ['DigitalCreationDate', 'N', 8, 8, $IPTC_re_dt18 ], # |
790
|
|
|
|
|
|
|
63 => ['DigitalCreationTime', 'N',11, 11, $IPTC_re_time ], # |
791
|
|
|
|
|
|
|
65 => ['OriginatingProgram', 'N', 1, 32, $IPTC_re_line ], # |
792
|
|
|
|
|
|
|
70 => ['ProgramVersion', 'N', 1, 10, $IPTC_re_line ], # |
793
|
|
|
|
|
|
|
75 => ['ObjectCycle', 'N', 1, 1, '[apb]' ], # |
794
|
|
|
|
|
|
|
80 => ['ByLine', ' ', 1, 32, $IPTC_re_line ], # |
795
|
|
|
|
|
|
|
85 => ['ByLineTitle', ' ', 1, 32, $IPTC_re_line ], # |
796
|
|
|
|
|
|
|
90 => ['City', 'N', 1, 32, $IPTC_re_line ], # |
797
|
|
|
|
|
|
|
92 => ['SubLocation', 'N', 1, 32, $IPTC_re_line ], # |
798
|
|
|
|
|
|
|
95 => ['Province/State', 'N', 1, 32, $IPTC_re_line ], # |
799
|
|
|
|
|
|
|
100 => ['Country/PrimaryLocationCode', 'N', 3, 3, '[A-Z]{3}' ], # |
800
|
|
|
|
|
|
|
101 => ['Country/PrimaryLocationName', 'N', 1, 64, $IPTC_re_line ], # |
801
|
|
|
|
|
|
|
103 => ['OriginalTransmissionReference','N',1, 32, $IPTC_re_line ], # |
802
|
|
|
|
|
|
|
105 => ['Headline', 'N', 1,256, $IPTC_re_line ], # |
803
|
|
|
|
|
|
|
110 => ['Credit', 'N', 1, 32, $IPTC_re_line ], # |
804
|
|
|
|
|
|
|
115 => ['Source', 'N', 1, 32, $IPTC_re_line ], # |
805
|
|
|
|
|
|
|
116 => ['CopyrightNotice', 'N', 1,128, $IPTC_re_line ], # |
806
|
|
|
|
|
|
|
118 => ['Contact', ' ', 1,128, $IPTC_re_line ], # |
807
|
|
|
|
|
|
|
120 => ['Caption/Abstract', 'N', 1,2000,$IPTC_re_para ], # |
808
|
|
|
|
|
|
|
122 => ['Writer/Editor', ' ', 1, 32, $IPTC_re_line ], # |
809
|
|
|
|
|
|
|
125 => ['RasterizedCaption', 'N',7360,7360,'binary' ], # |
810
|
|
|
|
|
|
|
130 => ['ImageType', 'N', 2, 2,'[0-49][WYMCKRGBTFLPS]'], # |
811
|
|
|
|
|
|
|
131 => ['ImageOrientation', 'N', 1, 1, '[PLS]' ], # |
812
|
|
|
|
|
|
|
135 => ['LanguageIdentifier', 'N', 2, 3, '[a-zA-Z]{2,3}?' ], # |
813
|
|
|
|
|
|
|
150 => ['AudioType', 'N', 2, 2, '[012][ACMQRSTVW]' ], # |
814
|
|
|
|
|
|
|
151 => ['AudioSamplingRate', 'N', 6, 6, '\d{6}' ], # |
815
|
|
|
|
|
|
|
152 => ['AudioSamplingResolution', 'N', 2, 2, '\d{2}' ], # |
816
|
|
|
|
|
|
|
153 => ['AudioDuration', 'N', 6, 6, $IPTC_re_dura ], # |
817
|
|
|
|
|
|
|
154 => ['AudioOutcue', 'N', 1, 64, $IPTC_re_line ], # |
818
|
|
|
|
|
|
|
200 => ['ObjDataPreviewFileFormat', 'N', 2, 2, 'invalid,binary' ], # |
819
|
|
|
|
|
|
|
201 => ['ObjDataPreviewFileFormatVer', 'N', 2, 2, 'invalid,binary' ], # |
820
|
|
|
|
|
|
|
202 => ['ObjDataPreviewData', 'N', 1,256000,'invalid,binary' ],}; # |
821
|
|
|
|
|
|
|
#============================================================================# |
822
|
|
|
|
|
|
|
#============================================================================# |
823
|
|
|
|
|
|
|
#============================================================================# |
824
|
|
|
|
|
|
|
# Esoteric tags for a Photoshop APP13 segment (not IPTC data); # |
825
|
|
|
|
|
|
|
# see the "VALID TAGS FOR PHOTOSHOP-STYLE APP13 DATA" section in the # |
826
|
|
|
|
|
|
|
# Image::MetaData::JPEG module perldoc page for further details. # |
827
|
|
|
|
|
|
|
# [tags 0x07d0 --> 0x0bb6 are reserved for path information] # |
828
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
829
|
|
|
|
|
|
|
# Hash keys are numeric tags, here written in hexadecimal base. # |
830
|
|
|
|
|
|
|
# Fields: 0 -> Tag name, 1 -> repeatability ('N' means non-repeatable), # |
831
|
|
|
|
|
|
|
# 2,3 -> min and max length, 4 -> regular expression to match. # |
832
|
|
|
|
|
|
|
# The syntax specifications are currently just placeholder, but this could # |
833
|
|
|
|
|
|
|
# change in future. The only effect is to inhibit a direct assignement of # |
834
|
|
|
|
|
|
|
# the 'IPTC/NAA' dataset, which must be modified with specialised routines. # |
835
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
836
|
|
|
|
|
|
|
my $HASH_PHOTOSHOP_PATHINFO = # |
837
|
|
|
|
|
|
|
{( map { $_ => [ sprintf("PathInfo_%3x",$_), # |
838
|
|
|
|
|
|
|
' ', 0, 65535, 'binary'] } (0x07d0..0x0bb6) ), # |
839
|
|
|
|
|
|
|
0x0bb7 => ['ClippingPathName', ' ', 0, 65535, 'binary' ], }; # |
840
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
841
|
|
|
|
|
|
|
my $HASH_PHOTOSHOP_GENERAL = # |
842
|
|
|
|
|
|
|
{0x03e8 => ['Photoshop2Info', ' ', 0, 65535, 'binary' ], # |
843
|
|
|
|
|
|
|
0x03e9 => ['MacintoshPrintInfo', ' ', 0, 65535, 'binary' ], # |
844
|
|
|
|
|
|
|
0x03eb => ['Photoshop2ColorTable', ' ', 0, 65535, 'binary' ], # |
845
|
|
|
|
|
|
|
0x03ed => ['ResolutionInfo', ' ', 0, 65535, 'binary' ], # |
846
|
|
|
|
|
|
|
0x03ee => ['AlphaChannelsNames', ' ', 0, 65535, 'binary' ], # |
847
|
|
|
|
|
|
|
0x03ef => ['DisplayInfo', ' ', 0, 65535, 'binary' ], # |
848
|
|
|
|
|
|
|
0x03f0 => ['PStringCaption', ' ', 0, 65535, 'binary' ], # |
849
|
|
|
|
|
|
|
0x03f1 => ['BorderInformation', ' ', 0, 65535, 'binary' ], # |
850
|
|
|
|
|
|
|
0x03f2 => ['BackgroundColor', ' ', 0, 65535, 'binary' ], # |
851
|
|
|
|
|
|
|
0x03f3 => ['PrintFlags', ' ', 0, 65535, 'binary' ], # |
852
|
|
|
|
|
|
|
0x03f4 => ['BWHalftoningInfo', ' ', 0, 65535, 'binary' ], # |
853
|
|
|
|
|
|
|
0x03f5 => ['ColorHalftoningInfo', ' ', 0, 65535, 'binary' ], # |
854
|
|
|
|
|
|
|
0x03f6 => ['DuotoneHalftoningInfo', ' ', 0, 65535, 'binary' ], # |
855
|
|
|
|
|
|
|
0x03f7 => ['BWTransferFunc', ' ', 0, 65535, 'binary' ], # |
856
|
|
|
|
|
|
|
0x03f8 => ['ColorTransferFuncs', ' ', 0, 65535, 'binary' ], # |
857
|
|
|
|
|
|
|
0x03f9 => ['DuotoneTransferFuncs', ' ', 0, 65535, 'binary' ], # |
858
|
|
|
|
|
|
|
0x03fa => ['DuotoneImageInfo', ' ', 0, 65535, 'binary' ], # |
859
|
|
|
|
|
|
|
0x03fb => ['EffectiveBW', ' ', 0, 65535, 'binary' ], # |
860
|
|
|
|
|
|
|
0x03fc => ['ObsoletePhotoshopTag1', ' ', 0, 65535, 'binary' ], # |
861
|
|
|
|
|
|
|
0x03fd => ['EPSOptions', ' ', 0, 65535, 'binary' ], # |
862
|
|
|
|
|
|
|
0x03fe => ['QuickMaskInfo', ' ', 0, 65535, 'binary' ], # |
863
|
|
|
|
|
|
|
0x03ff => ['ObsoletePhotoshopTag2', ' ', 0, 65535, 'binary' ], # |
864
|
|
|
|
|
|
|
0x0400 => ['LayerStateInfo', ' ', 0, 65535, 'binary' ], # |
865
|
|
|
|
|
|
|
0x0401 => ['WorkingPathInfo', ' ', 0, 65535, 'binary' ], # |
866
|
|
|
|
|
|
|
0x0402 => ['LayersGroupInfo', ' ', 0, 65535, 'binary' ], # |
867
|
|
|
|
|
|
|
0x0403 => ['ObsoletePhotoshopTag3', ' ', 0, 65535, 'binary' ], # |
868
|
|
|
|
|
|
|
0x0404 => ['IPTC/NAA', ' ', 0, 65535, 'invalid' ], # |
869
|
|
|
|
|
|
|
0x0405 => ['RawImageMode', ' ', 0, 65535, 'binary' ], # |
870
|
|
|
|
|
|
|
0x0406 => ['JPEGQuality', ' ', 0, 65535, 'binary' ], # |
871
|
|
|
|
|
|
|
0x0408 => ['GridGuidesInfo', ' ', 0, 65535, 'binary' ], # |
872
|
|
|
|
|
|
|
0x0409 => ['ThumbnailResource', ' ', 0, 65535, 'binary' ], # |
873
|
|
|
|
|
|
|
0x040a => ['CopyrightFlag', ' ', 0, 65535, 'binary' ], # |
874
|
|
|
|
|
|
|
0x040b => ['URL', ' ', 0, 65535, 'binary' ], # |
875
|
|
|
|
|
|
|
0x040c => ['ThumbnailResource2', ' ', 0, 65535, 'binary' ], # |
876
|
|
|
|
|
|
|
0x040d => ['GlobalAngle', ' ', 0, 65535, 'binary' ], # |
877
|
|
|
|
|
|
|
0x040e => ['ColorSamplersResource', ' ', 0, 65535, 'binary' ], # |
878
|
|
|
|
|
|
|
0x040f => ['ICCProfile', ' ', 0, 65535, 'binary' ], # |
879
|
|
|
|
|
|
|
0x0410 => ['Watermark', ' ', 0, 65535, 'binary' ], # |
880
|
|
|
|
|
|
|
0x0411 => ['ICCUntagged', ' ', 0, 65535, 'binary' ], # |
881
|
|
|
|
|
|
|
0x0412 => ['EffectsVisible', ' ', 0, 65535, 'binary' ], # |
882
|
|
|
|
|
|
|
0x0413 => ['SpotHalftone', ' ', 0, 65535, 'binary' ], # |
883
|
|
|
|
|
|
|
0x0414 => ['IDsBaseValue', ' ', 0, 65535, 'binary' ], # |
884
|
|
|
|
|
|
|
0x0415 => ['UnicodeAlphaNames', ' ', 0, 65535, 'binary' ], # |
885
|
|
|
|
|
|
|
0x0416 => ['IndexedColourTableCount', ' ', 0, 65535, 'binary' ], # |
886
|
|
|
|
|
|
|
0x0417 => ['TransparentIndex', ' ', 0, 65535, 'binary' ], # |
887
|
|
|
|
|
|
|
0x0419 => ['GlobalAltitude', ' ', 0, 65535, 'binary' ], # |
888
|
|
|
|
|
|
|
0x041a => ['Slices', ' ', 0, 65535, 'binary' ], # |
889
|
|
|
|
|
|
|
0x041b => ['WorkflowURL', ' ', 0, 65535, 'binary' ], # |
890
|
|
|
|
|
|
|
0x041c => ['JumpToXPEP', ' ', 0, 65535, 'binary' ], # |
891
|
|
|
|
|
|
|
0x041d => ['AlphaIdentifiers', ' ', 0, 65535, 'binary' ], # |
892
|
|
|
|
|
|
|
0x041e => ['URLList', ' ', 0, 65535, 'binary' ], # |
893
|
|
|
|
|
|
|
0x0421 => ['VersionInfo', ' ', 0, 65535, 'binary' ], # |
894
|
|
|
|
|
|
|
0x2710 => ['PrintFlagsInfo', ' ', 0, 65535, 'binary' ], }; # |
895
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
896
|
|
|
|
|
|
|
@$HASH_PHOTOSHOP_GENERAL{keys %$HASH_PHOTOSHOP_PATHINFO} = # |
897
|
|
|
|
|
|
|
values %$HASH_PHOTOSHOP_PATHINFO; # |
898
|
|
|
|
|
|
|
#============================================================================# |
899
|
|
|
|
|
|
|
#============================================================================# |
900
|
|
|
|
|
|
|
#============================================================================# |
901
|
|
|
|
|
|
|
# Some scalar-valued hashes, which were once original databases, are now # |
902
|
|
|
|
|
|
|
# generated with "generate_lookup" from more general array-valued hashes # |
903
|
|
|
|
|
|
|
# (in practice, a single column is singled out from a multi-column table). # |
904
|
|
|
|
|
|
|
# %$HASH_APP1_IFD is built by merging the first column of 3 different hashes.# |
905
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
906
|
|
|
|
|
|
|
my $HASH_PHOTOSHOP_TAGS = generate_lookup($HASH_PHOTOSHOP_GENERAL ,0); # |
907
|
|
|
|
|
|
|
my $HASH_PHOTOSHOP_PHUT = generate_lookup($HASH_PHOTOSHOP_PATHINFO ,0); # |
908
|
|
|
|
|
|
|
my $HASH_IPTC_TAGS_1 = generate_lookup($HASH_IPTC_GENERAL_1 ,0); # |
909
|
|
|
|
|
|
|
my $HASH_IPTC_TAGS_2 = generate_lookup($HASH_IPTC_GENERAL_2 ,0); # |
910
|
|
|
|
|
|
|
my $HASH_APP1_ROOT = generate_lookup($HASH_APP1_ROOT_GENERAL ,0); # |
911
|
|
|
|
|
|
|
my $HASH_APP1_GPS = generate_lookup($HASH_GPS_GENERAL ,0); # |
912
|
|
|
|
|
|
|
my $HASH_APP1_INTEROP = generate_lookup($HASH_INTEROP_GENERAL ,0); # |
913
|
|
|
|
|
|
|
my $HASH_APP1_IFD = generate_lookup($HASH_APP1_IFD01_GENERAL ,0); # |
914
|
|
|
|
|
|
|
my $HASH_APP1_SUBIFD = generate_lookup($HASH_APP1_SUBIFD_GENERAL ,0); # |
915
|
|
|
|
|
|
|
#============================================================================# |
916
|
|
|
|
|
|
|
#============================================================================# |
917
|
|
|
|
|
|
|
#============================================================================# |
918
|
|
|
|
|
|
|
# Some segments (APP1 and APP3 currently) have an IFD-like structure, i.e. # |
919
|
|
|
|
|
|
|
# they can have "subdirectories" pointed to by offset tags. These subdirs # |
920
|
|
|
|
|
|
|
# are bifurcation points for the lookup process, and are represented by # |
921
|
|
|
|
|
|
|
# hash references instead of plain strings (scalars). # |
922
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
923
|
|
|
|
|
|
|
$$HASH_APP1_IFD{SubIFD} = $HASH_APP1_SUBIFD; # Exif private tags # |
924
|
|
|
|
|
|
|
$$HASH_APP1_IFD{GPS} = $HASH_APP1_GPS; # GPS tags # |
925
|
|
|
|
|
|
|
$$HASH_APP3_IFD{Special} = $HASH_APP3_SPECIAL; # Special effect tags # |
926
|
|
|
|
|
|
|
$$HASH_APP3_IFD{Borders} = $HASH_APP3_BORDERS; # Border tags # |
927
|
|
|
|
|
|
|
$$HASH_APP1_SUBIFD{Interop} = $HASH_APP1_INTEROP; # Interoperability tags # |
928
|
|
|
|
|
|
|
#============================================================================# |
929
|
|
|
|
|
|
|
#============================================================================# |
930
|
|
|
|
|
|
|
#============================================================================# |
931
|
|
|
|
|
|
|
# MakerNote stuff is stored in a separated file; the return value of this # |
932
|
|
|
|
|
|
|
# inclusion is the $HASH_MAKERNOTES hash reference, containing all relevant # |
933
|
|
|
|
|
|
|
# parameters. We only have to link this new table into $HASH_APP1_SUBIFD. # |
934
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
935
|
|
|
|
|
|
|
our $HASH_MAKERNOTES = require 'Image/MetaData/JPEG/data/Makernotes.pl'; # |
936
|
|
|
|
|
|
|
$$HASH_APP1_SUBIFD{'MakerNoteData_' . $_} = # |
937
|
|
|
|
|
|
|
generate_lookup($$HASH_MAKERNOTES{$_}{tags} ,0) # |
938
|
|
|
|
|
|
|
for keys %$HASH_MAKERNOTES; # |
939
|
|
|
|
|
|
|
#============================================================================# |
940
|
|
|
|
|
|
|
#============================================================================# |
941
|
|
|
|
|
|
|
#============================================================================# |
942
|
|
|
|
|
|
|
# Syntax tables and mandatory records tables for IPTC data are hidden in the # |
943
|
|
|
|
|
|
|
# corresponding tag hashes. Another %IFD_SUBDIRS is overkill here. # |
944
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
945
|
|
|
|
|
|
|
$$HASH_IPTC_TAGS_1{__syntax} = $HASH_IPTC_GENERAL_1; # |
946
|
|
|
|
|
|
|
$$HASH_IPTC_TAGS_1{__mandatory} = $HASH_IPTC_MANDATORY_1; # |
947
|
|
|
|
|
|
|
$$HASH_IPTC_TAGS_2{__syntax} = $HASH_IPTC_GENERAL_2; # |
948
|
|
|
|
|
|
|
$$HASH_IPTC_TAGS_2{__mandatory} = $HASH_IPTC_MANDATORY_2; # |
949
|
|
|
|
|
|
|
$$HASH_PHOTOSHOP_TAGS{__syntax} = $HASH_PHOTOSHOP_GENERAL; # |
950
|
|
|
|
|
|
|
#============================================================================# |
951
|
|
|
|
|
|
|
#============================================================================# |
952
|
|
|
|
|
|
|
#============================================================================# |
953
|
|
|
|
|
|
|
# The following hash is the database for the tag-to-tagname translation; of # |
954
|
|
|
|
|
|
|
# course, records with a textual tag are not listed here. The navigation # |
955
|
|
|
|
|
|
|
# through this structure is best done with the help of the JPEG_lookup # |
956
|
|
|
|
|
|
|
# function, so this hash is not exported (as it was some time ago). # |
957
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
958
|
|
|
|
|
|
|
my $psdirname = sub { $APP13_PHOTOSHOP_DIRNAME . '_' . $_[0] }; # |
959
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
960
|
|
|
|
|
|
|
my $JPEG_RECORD_NAME = # |
961
|
|
|
|
|
|
|
{APP1 => {%$HASH_APP1_ROOT, # APP1 root # |
962
|
|
|
|
|
|
|
IFD0 => $HASH_APP1_IFD, # main image # |
963
|
|
|
|
|
|
|
IFD1 => $HASH_APP1_IFD, }, # thumbnail # |
964
|
|
|
|
|
|
|
APP2 => {TagTable => $HASH_APP2_ICC, }, # ICC data # |
965
|
|
|
|
|
|
|
APP3 => {IFD0 => $HASH_APP3_IFD, }, # main image # |
966
|
|
|
|
|
|
|
APP13 => {&$psdirname('8BIM') => $HASH_PHOTOSHOP_TAGS, # PS:8BIM # |
967
|
|
|
|
|
|
|
&$psdirname('8BPS') => $HASH_PHOTOSHOP_TAGS, # PS: < ver 4 # |
968
|
|
|
|
|
|
|
&$psdirname('PHUT') => $HASH_PHOTOSHOP_PHUT, # PS:PHUT # |
969
|
|
|
|
|
|
|
$APP13_IPTC_DIRNAME.'_1' => $HASH_IPTC_TAGS_1, # PS:IPTC R:1 # |
970
|
|
|
|
|
|
|
$APP13_IPTC_DIRNAME.'_2' => $HASH_IPTC_TAGS_2, }, };# PS:IPTC R:2 # |
971
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
972
|
|
|
|
|
|
|
|
973
|
|
|
|
|
|
|
########################################################### |
974
|
|
|
|
|
|
|
# This helper function returns record data from the # |
975
|
|
|
|
|
|
|
# %$JPEG_RECORD_NAME hash. The arguments are first joined # |
976
|
|
|
|
|
|
|
# with the '@' character, and then splitted on the same # |
977
|
|
|
|
|
|
|
# character to give a list of '@'-free strings (this al- # |
978
|
|
|
|
|
|
|
# lows for greater flexibility at call time); this list # |
979
|
|
|
|
|
|
|
# contains keys for exploring the %$JPEG_RECORD_NAME hash;# |
980
|
|
|
|
|
|
|
# e.g., the arguments ('APP1', 'IFD0@GPS', 0x1e) select # |
981
|
|
|
|
|
|
|
# $JPEG_RECORD_NAME{APP1}{IFD0}{GPS}{0x1e}, i.e. the # |
982
|
|
|
|
|
|
|
# textual name of the GPS record with key = 0x1e in the # |
983
|
|
|
|
|
|
|
# IFD0 in the APP1 segment. If, at some point during the # |
984
|
|
|
|
|
|
|
# search, an argument fails (it is not a valid key) or it # |
985
|
|
|
|
|
|
|
# is not defined, the search is interrupted, and undef is # |
986
|
|
|
|
|
|
|
# returned. Note also that the return value could be a # |
987
|
|
|
|
|
|
|
# string as well as a hash reference, depending on the # |
988
|
|
|
|
|
|
|
# search depth. If the key lookup for the last argument # |
989
|
|
|
|
|
|
|
# fails, a reverse lookup is run (i.e., the key corres- # |
990
|
|
|
|
|
|
|
# ponding to the value equal to the last user argument is # |
991
|
|
|
|
|
|
|
# searched). If even this lookup fails, undef is returned.# |
992
|
|
|
|
|
|
|
########################################################### |
993
|
|
|
|
|
|
|
sub JPEG_lookup { |
994
|
|
|
|
|
|
|
# all searches start from here |
995
|
6417
|
|
|
6417
|
0
|
6917
|
my $lookup = $JPEG_RECORD_NAME; |
996
|
|
|
|
|
|
|
# print a debugging message and return immediately unless |
997
|
|
|
|
|
|
|
# all arguments are scalars (i.e., references are not allowed) |
998
|
6417
|
50
|
|
|
|
7734
|
for (@_) { print "wrong argument(s) in JPEG_lookup call", return if ref; } |
|
16489
|
|
|
|
|
25186
|
|
999
|
|
|
|
|
|
|
# delete all undefined or "false" arguments |
1000
|
6417
|
|
|
|
|
7654
|
@_ = grep { defined $_ } @_; |
|
16489
|
|
|
|
|
23215
|
|
1001
|
|
|
|
|
|
|
# join all remaining arguments |
1002
|
6417
|
|
|
|
|
10528
|
my $keystring = join('@', @_); |
1003
|
|
|
|
|
|
|
# split the resulting string on '@' |
1004
|
6417
|
|
|
|
|
13784
|
my @keylist = split('@', $keystring); |
1005
|
|
|
|
|
|
|
# extract and save the last argument for special treatment |
1006
|
6417
|
|
|
|
|
7131
|
my $last = pop @keylist; |
1007
|
|
|
|
|
|
|
# delete all false arguments |
1008
|
6417
|
|
|
|
|
6089
|
@keylist = grep { $_ } @keylist; |
|
14820
|
|
|
|
|
18933
|
|
1009
|
|
|
|
|
|
|
# refuse to work with $last undefined |
1010
|
6417
|
50
|
|
|
|
10082
|
return unless defined $last; |
1011
|
|
|
|
|
|
|
# consume the list of "normal" arguments: they must be successive |
1012
|
|
|
|
|
|
|
# keys for navigation in a multi-level hash. Interrupt the search |
1013
|
|
|
|
|
|
|
# as soon as an argument is undefined or $lookup is not a hash ref |
1014
|
6417
|
|
|
|
|
6597
|
for (@keylist) { |
1015
|
|
|
|
|
|
|
# return undef as soon as an argument is undefined |
1016
|
14737
|
50
|
|
|
|
18655
|
return undef unless $_; |
1017
|
|
|
|
|
|
|
# go one level deeper in the hash exploration |
1018
|
14737
|
|
|
|
|
14924
|
$lookup = $$lookup{$_}; |
1019
|
|
|
|
|
|
|
# return undef if $lookup is no more a hash reference |
1020
|
14737
|
50
|
|
|
|
24225
|
return undef unless ref $lookup eq 'HASH'; } |
1021
|
|
|
|
|
|
|
# $lookup is a hash reference now. Return the value |
1022
|
|
|
|
|
|
|
# corresponding to $last (used as a key) if it exists. |
1023
|
6417
|
100
|
|
|
|
20396
|
return $$lookup{$last} if exists $$lookup{$last}; |
1024
|
|
|
|
|
|
|
# if we are still here, scan the hash looking for a value equal to |
1025
|
|
|
|
|
|
|
# $last, and return its key. Avoid each %$lookup, since we could |
1026
|
|
|
|
|
|
|
# exit the loop before the end and I don't want to reset the |
1027
|
|
|
|
|
|
|
# iterator in that stupid manner. |
1028
|
2386
|
100
|
|
|
|
36826
|
for (keys %$lookup) { return $_ if $$lookup{$_} eq $last; } |
|
185421
|
|
|
|
|
268553
|
|
1029
|
|
|
|
|
|
|
# if we are still here, we have lost |
1030
|
241
|
|
|
|
|
2422
|
return undef; |
1031
|
|
|
|
|
|
|
}; |
1032
|
|
|
|
|
|
|
|
1033
|
|
|
|
|
|
|
#============================================================================# |
1034
|
|
|
|
|
|
|
#============================================================================# |
1035
|
|
|
|
|
|
|
#============================================================================# |
1036
|
|
|
|
|
|
|
# This hash is needed to overcome some complications due to the APP1/APP3 # |
1037
|
|
|
|
|
|
|
# structure: some IFDs or sub-IFDs can contain offset tags (tags whose value # |
1038
|
|
|
|
|
|
|
# is an offset in the JPEG file), linking to nested structures, which are # |
1039
|
|
|
|
|
|
|
# represented internally as sub-lists pointed to by $REFERENCE records; the # |
1040
|
|
|
|
|
|
|
# sub-lists deserve in general a more significant name than the offset tag # |
1041
|
|
|
|
|
|
|
# name. Each key in the following hash is a path to an IFD or one of its # |
1042
|
|
|
|
|
|
|
# subdirectories; the corresponding value is a hash reference, with the # |
1043
|
|
|
|
|
|
|
# pointed hash mapping offset tag numerical values to subdirectory names. # |
1044
|
|
|
|
|
|
|
# (the [tag names] -> [tag numerical values] translation is done afterwards) # |
1045
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
1046
|
|
|
|
|
|
|
# A sub hash must also own the '__syntax' and '__mandatory' keys, returning # |
1047
|
|
|
|
|
|
|
# a reference to a hash of syntactical properties to be respected by data in # |
1048
|
|
|
|
|
|
|
# the corresponding IFD and a reference to a hash of mandatory records. # |
1049
|
|
|
|
|
|
|
# These special entries are of course treated differently from the others ...# |
1050
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
1051
|
|
|
|
|
|
|
# When the JPEG file is read, offset tag records are not stored; insted, we # |
1052
|
|
|
|
|
|
|
# store a $REFERENCE record with the mapped name (and the name of the origi- # |
1053
|
|
|
|
|
|
|
# nating offset tag saved in the "extra" field). The following hash can then # |
1054
|
|
|
|
|
|
|
# be used in both directions to do data parsing/dumping. # |
1055
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
1056
|
|
|
|
|
|
|
our %IFD_SUBDIRS = # |
1057
|
|
|
|
|
|
|
('APP1' => {'__syntax' => $HASH_APP1_ROOT_GENERAL, # |
1058
|
|
|
|
|
|
|
'__mandatory' => $HASH_APP1_ROOT_MANDATORY }, # |
1059
|
|
|
|
|
|
|
'APP1@IFD0' => {'__syntax' => $HASH_APP1_IFD01_GENERAL, # |
1060
|
|
|
|
|
|
|
'__mandatory' => $HASH_APP1_IFD0_MANDATORY, # |
1061
|
|
|
|
|
|
|
'GPSInfo' => 'GPS', # |
1062
|
|
|
|
|
|
|
'ExifOffset' => 'SubIFD'}, # |
1063
|
|
|
|
|
|
|
'APP1@IFD0@GPS' => {'__syntax' => $HASH_GPS_GENERAL, # |
1064
|
|
|
|
|
|
|
'__mandatory' => $HASH_GPS_MANDATORY }, # |
1065
|
|
|
|
|
|
|
'APP1@IFD0@SubIFD' => {'__syntax' => $HASH_APP1_SUBIFD_GENERAL, # |
1066
|
|
|
|
|
|
|
'__mandatory' => $HASH_APP1_SUBIFD_MANDATORY, # |
1067
|
|
|
|
|
|
|
'MakerNote' => 'MakerNoteData', # |
1068
|
|
|
|
|
|
|
'InteroperabilityOffset' => 'Interop'}, # |
1069
|
|
|
|
|
|
|
'APP1@IFD0@SubIFD@Interop' => {'__syntax' => $HASH_INTEROP_GENERAL, # |
1070
|
|
|
|
|
|
|
'__mandatory'=> $HASH_INTEROP_MANDATORY }, # |
1071
|
|
|
|
|
|
|
'APP1@IFD1' => {'__syntax' => $HASH_APP1_IFD01_GENERAL, # |
1072
|
|
|
|
|
|
|
'__mandatory' => $HASH_APP1_IFD1_MANDATORY }, # |
1073
|
|
|
|
|
|
|
'APP3@IFD0' => {'BordersIFD' => 'Borders', # |
1074
|
|
|
|
|
|
|
'SpecialEffectsIFD' => 'Special'}, ); # |
1075
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
1076
|
|
|
|
|
|
|
while (my ($ifd_path, $ifd_hash) = each %IFD_SUBDIRS) { # |
1077
|
|
|
|
|
|
|
my %h = map { $_ =~ /__syntax|__mandatory/ ? ($_ => $$ifd_hash{$_}) : # |
1078
|
|
|
|
|
|
|
(JPEG_lookup($ifd_path, $_) => $$ifd_hash{$_}) # |
1079
|
|
|
|
|
|
|
} keys %$ifd_hash; # |
1080
|
|
|
|
|
|
|
$IFD_SUBDIRS{$ifd_path} = \ %h; } # |
1081
|
|
|
|
|
|
|
#============================================================================# |
1082
|
|
|
|
|
|
|
#============================================================================# |
1083
|
|
|
|
|
|
|
#============================================================================# |
1084
|
|
|
|
|
|
|
# These parameters must be initialised with JPEG_lookup, because I don't # |
1085
|
|
|
|
|
|
|
# want to have them written explicitely in more than one place. # |
1086
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
1087
|
|
|
|
|
|
|
our $APP1_TH_TYPE = JPEG_lookup('APP1@IFD1@Compression'); # |
1088
|
|
|
|
|
|
|
our $THJPEG_OFFSET = JPEG_lookup('APP1@IFD1@JPEGInterchangeFormat'); # |
1089
|
|
|
|
|
|
|
our $THJPEG_LENGTH = JPEG_lookup('APP1@IFD1@JPEGInterchangeFormatLength'); # |
1090
|
|
|
|
|
|
|
our $THTIFF_OFFSET = JPEG_lookup('APP1@IFD1@StripOffsets'); # |
1091
|
|
|
|
|
|
|
our $THTIFF_LENGTH = JPEG_lookup('APP1@IFD1@StripByteCounts'); # |
1092
|
|
|
|
|
|
|
our $MAKERNOTE_TAG = JPEG_lookup('APP1@IFD0@SubIFD@MakerNote'); # |
1093
|
|
|
|
|
|
|
#----------------------------------------------------------------------------# |
1094
|
|
|
|
|
|
|
|
1095
|
|
|
|
|
|
|
# successful package load |
1096
|
|
|
|
|
|
|
1; |