| 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
|
15
|
|
|
15
|
|
60
|
use Image::MetaData::JPEG::data::Tables qw(:TagsAPP1_Exif); |
|
|
15
|
|
|
|
|
18
|
|
|
|
15
|
|
|
|
|
2136
|
|
|
7
|
15
|
|
|
15
|
|
127
|
no integer; |
|
|
15
|
|
|
|
|
23
|
|
|
|
15
|
|
|
|
|
64
|
|
|
8
|
15
|
|
|
15
|
|
258
|
use strict; |
|
|
15
|
|
|
|
|
19
|
|
|
|
15
|
|
|
|
|
302
|
|
|
9
|
15
|
|
|
15
|
|
55
|
use warnings; |
|
|
15
|
|
|
|
|
27
|
|
|
|
15
|
|
|
|
|
22989
|
|
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
########################################################### |
|
12
|
|
|
|
|
|
|
# This method parses a standard (Exif) APP1 segment. Such # |
|
13
|
|
|
|
|
|
|
# an application segment is used by Exif JPEG files to # |
|
14
|
|
|
|
|
|
|
# store metadata, so that they do not conflict with those # |
|
15
|
|
|
|
|
|
|
# of the JFIF format (which uses the APP0 segment). # |
|
16
|
|
|
|
|
|
|
# The structure of an Exif APP1 segment is as follows: # |
|
17
|
|
|
|
|
|
|
#---------------------------------------------------------# |
|
18
|
|
|
|
|
|
|
# 6 bytes identifier ('Exif\000\000' = 0x457869660000) # |
|
19
|
|
|
|
|
|
|
# 2 bytes TIFF header endianness ('II' or 'MM') # |
|
20
|
|
|
|
|
|
|
# 2 bytes TIFF header signature (a fixed value = 42) # |
|
21
|
|
|
|
|
|
|
# 4 bytes TIFF header: offset of 0th IFD # |
|
22
|
|
|
|
|
|
|
# ...IFD... 0th IFD (main image) # |
|
23
|
|
|
|
|
|
|
# ...IFD... SubIFD (EXIF private tags) linked by IFD0 # |
|
24
|
|
|
|
|
|
|
# ...IFD... Interoperability IFD, linked by SubIFD # |
|
25
|
|
|
|
|
|
|
# ...IFD... GPS IFD (optional) linked by IFD0 # |
|
26
|
|
|
|
|
|
|
# ...IFD... 1st IFD (thumbnail) linked by IFD0 # |
|
27
|
|
|
|
|
|
|
# ...IFD... Thumbnail image (0xffd8.....ffd9) # |
|
28
|
|
|
|
|
|
|
#=========================================================# |
|
29
|
|
|
|
|
|
|
# The offset of the 0th IFD in the TIFF header, as well # |
|
30
|
|
|
|
|
|
|
# as IFD links in the IFDs, is given with respect to the # |
|
31
|
|
|
|
|
|
|
# beginning of the TIFF header (i.e. the address of the # |
|
32
|
|
|
|
|
|
|
# 'MM' or 'II' pair). This means that if the 0th IFD be- # |
|
33
|
|
|
|
|
|
|
# gins (as usual) immediately after the end of the TIFF # |
|
34
|
|
|
|
|
|
|
# header, the offset value is 8. # |
|
35
|
|
|
|
|
|
|
#=========================================================# |
|
36
|
|
|
|
|
|
|
# An Exif file can contain a thumbnail, usually located # |
|
37
|
|
|
|
|
|
|
# next to the 1st IFD. There are 3 possible formats: JPEG # |
|
38
|
|
|
|
|
|
|
# (only this is compressed), RGB TIFF, and YCbCr TIFF. It # |
|
39
|
|
|
|
|
|
|
# seems that JPEG and 160x120 pixels are recommended for # |
|
40
|
|
|
|
|
|
|
# Exif ver. 2.1 or higher (mandatory for DCF files). # |
|
41
|
|
|
|
|
|
|
# Since the segment size for APP1 is recorded in 2 bytes, # |
|
42
|
|
|
|
|
|
|
# the thumbnail are limited to 64KB minus something. # |
|
43
|
|
|
|
|
|
|
#---------------------------------------------------------# |
|
44
|
|
|
|
|
|
|
# A JPEG thumbnail is selected by Compression(0x0103) = 6.# |
|
45
|
|
|
|
|
|
|
# In this case, one can get the thumbnail offset from the # |
|
46
|
|
|
|
|
|
|
# JPEGInterchangeFormat(0x0201) tag, and the thumbnail # |
|
47
|
|
|
|
|
|
|
# length from the JPEGInterchangeFormatLength(0x0202) tag.# |
|
48
|
|
|
|
|
|
|
#---------------------------------------------------------# |
|
49
|
|
|
|
|
|
|
# An uncompressed (TIFF image) thumbnail is selected by # |
|
50
|
|
|
|
|
|
|
# Compression(0x0103) = 1. The thumbnail offset and size # |
|
51
|
|
|
|
|
|
|
# are to be read from StripOffset(0x0111) and (the sum of)# |
|
52
|
|
|
|
|
|
|
# StripByteCounts(0x0117). For uncompressed thumbnails, # |
|
53
|
|
|
|
|
|
|
# PhotometricInterpretation(0x0106) = 2 means RGB format, # |
|
54
|
|
|
|
|
|
|
# while = 6 means YCbCr format. # |
|
55
|
|
|
|
|
|
|
#=========================================================# |
|
56
|
|
|
|
|
|
|
# Ref: http://park2.wakwak.com/ # |
|
57
|
|
|
|
|
|
|
# ~tsuruzoh/Computer/Digicams/exif-e.html # |
|
58
|
|
|
|
|
|
|
# and "Exchangeable image file format for digital still # |
|
59
|
|
|
|
|
|
|
# cameras: Exif Version 2.2", JEITA CP-3451, Apr2002 # |
|
60
|
|
|
|
|
|
|
# Japan Electronic Industry Development Assoc. (JEIDA) # |
|
61
|
|
|
|
|
|
|
########################################################### |
|
62
|
|
|
|
|
|
|
sub parse_app1_exif { |
|
63
|
63
|
|
|
63
|
0
|
108
|
my ($this) = @_; |
|
64
|
|
|
|
|
|
|
# decode and save the identifier (it should be 'Exif\000\000' |
|
65
|
|
|
|
|
|
|
# for an APP1 segment) and die if it is not correct. |
|
66
|
63
|
|
|
|
|
277
|
my $identifier = $this->store_record |
|
67
|
|
|
|
|
|
|
('Identifier', $ASCII, 0, length $APP1_EXIF_TAG)->get_value(); |
|
68
|
63
|
50
|
|
|
|
174
|
$this->die("Incorrect identifier ($identifier)") |
|
69
|
|
|
|
|
|
|
if $identifier ne $APP1_EXIF_TAG; |
|
70
|
|
|
|
|
|
|
# decode the TIFF header (records added automatically in root); |
|
71
|
|
|
|
|
|
|
# it should be located immediately after the identifier |
|
72
|
63
|
|
|
|
|
253
|
my ($tiff_base, $ifd0_link, $endianness) = |
|
73
|
|
|
|
|
|
|
$this->parse_TIFF_header(length $identifier); |
|
74
|
|
|
|
|
|
|
# Remember to convert the ifd0 offset with the TIFF header base. |
|
75
|
63
|
|
|
|
|
133
|
my $ifd0_offset = $tiff_base + $ifd0_link; |
|
76
|
|
|
|
|
|
|
# locally set the current endianness to what we have found |
|
77
|
63
|
|
|
|
|
157
|
local $this->{endianness} = $endianness; |
|
78
|
|
|
|
|
|
|
# parse all records in the 0th IFD. Inside it, there might be a link |
|
79
|
|
|
|
|
|
|
# to the EXIF private tag block (SubIFD), which contains all you want |
|
80
|
|
|
|
|
|
|
# to know about how the shot was shot. Perversely enough, the SubIFD |
|
81
|
|
|
|
|
|
|
# can nest two other IFDs, namely the "Interoperabiliy IFD" and the |
|
82
|
|
|
|
|
|
|
# "MakerNote IFD". Decoding the Maker Note is likely to fail, because |
|
83
|
|
|
|
|
|
|
# most vendors do not publish their MakerNote format. However, if the |
|
84
|
|
|
|
|
|
|
# note is decoded, the findings are written in a new subdirectory. |
|
85
|
63
|
|
|
|
|
223
|
my $ifd1_link = $this->parse_ifd('IFD0', $ifd0_offset, $tiff_base); |
|
86
|
|
|
|
|
|
|
# Remember to convert the ifd1 offset with the TIFF header base |
|
87
|
|
|
|
|
|
|
# (if $ifd1_link is zero, there is no next IFD, set to undef) |
|
88
|
63
|
100
|
|
|
|
214
|
my $ifd1_offset = $ifd1_link ? $tiff_base + $ifd1_link : undef; |
|
89
|
|
|
|
|
|
|
# same thing for the 1st IFD. In this case the test is not on next_link |
|
90
|
|
|
|
|
|
|
# being defined, but on it being zero or not. The returned values is |
|
91
|
|
|
|
|
|
|
# forced to be zero (this is the meaning of the final '1' in parse_ifd) |
|
92
|
63
|
100
|
|
|
|
231
|
$this->parse_ifd('IFD1', $ifd1_offset, $tiff_base, 1) if $ifd1_offset; |
|
93
|
|
|
|
|
|
|
# look for the compression tag (thumbnail type record). If it is |
|
94
|
|
|
|
|
|
|
# present, we definitely need to look for the thumbnail (boring) |
|
95
|
63
|
|
|
|
|
249
|
my $th_type = $this->search_record_value('IFD1', $APP1_TH_TYPE); |
|
96
|
63
|
100
|
|
|
|
321
|
if (defined $th_type) { |
|
97
|
|
|
|
|
|
|
# thumbnail type should be either TIFF or JPEG. Die if not known |
|
98
|
32
|
50
|
33
|
|
|
231
|
$this->die("Unknown thumbnail type ($th_type)") |
|
99
|
|
|
|
|
|
|
if $th_type != $APP1_TH_TIFF && $th_type != $APP1_TH_JPEG; |
|
100
|
|
|
|
|
|
|
# calculate the thumbnail location and size |
|
101
|
64
|
|
|
|
|
249
|
my ($thumb_link, $thumb_size) = |
|
102
|
32
|
50
|
|
|
|
119
|
map { $this->search_record_value('IFD1', $_) } |
|
103
|
|
|
|
|
|
|
$th_type == $APP1_TH_TIFF |
|
104
|
|
|
|
|
|
|
? ($THTIFF_OFFSET, $THTIFF_LENGTH) |
|
105
|
|
|
|
|
|
|
: ($THJPEG_OFFSET, $THJPEG_LENGTH); |
|
106
|
|
|
|
|
|
|
# Some pictures declare they have a thumbnail, but there is |
|
107
|
|
|
|
|
|
|
# no thumbnail link for it (maybe this is due to some program |
|
108
|
|
|
|
|
|
|
# which strips the thumbnail out without completely removing |
|
109
|
|
|
|
|
|
|
# the 1st IFD). Treat this case as if $th_type was undefined. |
|
110
|
32
|
50
|
|
|
|
112
|
goto END_THUMBNAIL unless defined $thumb_link; |
|
111
|
|
|
|
|
|
|
# point the current offset to the thumbnail |
|
112
|
32
|
|
|
|
|
69
|
my $offset = $tiff_base + $thumb_link; |
|
113
|
|
|
|
|
|
|
# sometimes, we have broken pictures with an actual size shorter |
|
114
|
|
|
|
|
|
|
# than $thumb_size; nonetheless, the thumbnail is often valid, so |
|
115
|
|
|
|
|
|
|
# this case deserves only a warning if the difference is not too |
|
116
|
|
|
|
|
|
|
# large (currently, 10 bytes), but $thumb_size must be updated. |
|
117
|
32
|
|
|
|
|
98
|
my $remaining = $this->size() - $offset; |
|
118
|
32
|
100
|
|
|
|
893
|
if ($thumb_size > $remaining) { |
|
119
|
1
|
50
|
|
|
|
5
|
$this->die("Large mismatch ($remaining instead of $thumb_size) ", |
|
120
|
|
|
|
|
|
|
"in thumbnail size") if $thumb_size - $remaining > 10; |
|
121
|
1
|
|
|
|
|
9
|
$this->warn("Predicted thumbnail size ($thumb_size) larger than " |
|
122
|
|
|
|
|
|
|
. "available data size ($remaining). Correcting ..."); |
|
123
|
1
|
|
|
|
|
6
|
$thumb_size = $remaining; } |
|
124
|
|
|
|
|
|
|
# store the thumbnail (if present) |
|
125
|
32
|
50
|
|
|
|
167
|
$this->store_record('ThumbnailData', $UNDEF, $offset, $thumb_size) |
|
126
|
|
|
|
|
|
|
if $thumb_size > 0; |
|
127
|
|
|
|
|
|
|
END_THUMBNAIL: |
|
128
|
32
|
|
|
|
|
217
|
} |
|
129
|
|
|
|
|
|
|
} |
|
130
|
|
|
|
|
|
|
|
|
131
|
|
|
|
|
|
|
########################################################### |
|
132
|
|
|
|
|
|
|
# This method parses a TIFF header, which can be found, # |
|
133
|
|
|
|
|
|
|
# for instance, in APP1/APP3 segments. The first argument # |
|
134
|
|
|
|
|
|
|
# is the start address of the TIFF header; the second one # |
|
135
|
|
|
|
|
|
|
# (optional) is the record subdirectory where parsed # |
|
136
|
|
|
|
|
|
|
# records should be saved (defaulting to the root dir). # |
|
137
|
|
|
|
|
|
|
# The structure is as follows: # |
|
138
|
|
|
|
|
|
|
#---------------------------------------------------------# |
|
139
|
|
|
|
|
|
|
# 2 bytes TIFF header endianness ('II' or 'MM') # |
|
140
|
|
|
|
|
|
|
# 2 bytes TIFF header signature (a fixed value = 42) # |
|
141
|
|
|
|
|
|
|
# 4 bytes TIFF header: offset of 0th IFD # |
|
142
|
|
|
|
|
|
|
#---------------------------------------------------------# |
|
143
|
|
|
|
|
|
|
# The returned values are: the offset of the TIFF header # |
|
144
|
|
|
|
|
|
|
# start (this is usually a base for many other offsets), # |
|
145
|
|
|
|
|
|
|
# the offset of the 0-th IFD with respect to the TIFF # |
|
146
|
|
|
|
|
|
|
# header start, and the endianness. # |
|
147
|
|
|
|
|
|
|
#=========================================================# |
|
148
|
|
|
|
|
|
|
# The first two bytes of the TIFF header give the byte # |
|
149
|
|
|
|
|
|
|
# alignement (endianness): either 0x4949='II' for "Intel" # |
|
150
|
|
|
|
|
|
|
# type alignement (small endian) or 0x4d4d='MM' for "Mo- # |
|
151
|
|
|
|
|
|
|
# torola" type alignement (big endian). An EXIF block is # |
|
152
|
|
|
|
|
|
|
# the only part of a JPEG file whose endianness is not # |
|
153
|
|
|
|
|
|
|
# fixed to big endian (sigh!) # |
|
154
|
|
|
|
|
|
|
#=========================================================# |
|
155
|
|
|
|
|
|
|
# and "Exchangeable image file format for digital still # |
|
156
|
|
|
|
|
|
|
# cameras: Exif Version 2.2", JEITA CP-3451, Apr2002 # |
|
157
|
|
|
|
|
|
|
# Japan Electronic Industry Development Assoc. (JEIDA) # |
|
158
|
|
|
|
|
|
|
########################################################### |
|
159
|
|
|
|
|
|
|
sub parse_TIFF_header { |
|
160
|
67
|
|
|
67
|
0
|
129
|
my ($this, $offset, $dirref) = @_; |
|
161
|
|
|
|
|
|
|
# die if the $offset is undefined |
|
162
|
67
|
50
|
|
|
|
181
|
$this->die('Undefined offset') unless defined $offset; |
|
163
|
|
|
|
|
|
|
# set the subdir reference to the root if it is undefined |
|
164
|
67
|
100
|
|
|
|
202
|
$dirref = $this->{records} unless defined $dirref; |
|
165
|
|
|
|
|
|
|
# at least 8 bytes for the TIFF header (remember you |
|
166
|
|
|
|
|
|
|
# should count them starting from $offset) |
|
167
|
67
|
|
|
|
|
288
|
$this->test_size($offset + 8, "not enough space for the TIFF header"); |
|
168
|
|
|
|
|
|
|
# save the current offset for later use (TIFF header starts here) |
|
169
|
67
|
|
|
|
|
99
|
my $tiff_base = $offset; |
|
170
|
|
|
|
|
|
|
# decode the endianness (either 'II' or 'MM', 2 bytes); this is |
|
171
|
|
|
|
|
|
|
# not an $ASCII string (no terminating null character), so it is |
|
172
|
|
|
|
|
|
|
# better to use the $UNDEF type; die if it is unknown |
|
173
|
67
|
|
|
|
|
206
|
my $endianness = $this->store_record |
|
174
|
|
|
|
|
|
|
($dirref, 'Endianness', $UNDEF, $offset, 2)->get_value(); |
|
175
|
67
|
50
|
66
|
|
|
275
|
$this->die("Unknown endianness ($endianness)") |
|
176
|
|
|
|
|
|
|
if $endianness ne $BIG_ENDIAN && $endianness ne $LITTLE_ENDIAN; |
|
177
|
|
|
|
|
|
|
# change (locally) the endianness value |
|
178
|
67
|
|
|
|
|
151
|
local $this->{endianness} = $endianness; |
|
179
|
|
|
|
|
|
|
# decode the signature (42, i.e. 0x002a), die if it is unknown |
|
180
|
67
|
|
|
|
|
208
|
my $signature = $this->store_record |
|
181
|
|
|
|
|
|
|
($dirref, 'Signature', $SHORT, $offset)->get_value(); |
|
182
|
67
|
50
|
|
|
|
206
|
$this->die("Incorrect signature ($signature)") |
|
183
|
|
|
|
|
|
|
if $signature != $APP1_TIFF_SIG; |
|
184
|
|
|
|
|
|
|
# decode the offset of the 0th IFD: this is usually 8, but we are |
|
185
|
|
|
|
|
|
|
# not going to assume it. Do not store the record (it is uninteresting) |
|
186
|
67
|
|
|
|
|
256
|
my $ifd0_link = $this->read_record($LONG, $offset); |
|
187
|
|
|
|
|
|
|
# return all relevant values in a list |
|
188
|
67
|
|
|
|
|
415
|
return ($tiff_base, $ifd0_link, $endianness); |
|
189
|
|
|
|
|
|
|
} |
|
190
|
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
########################################################### |
|
192
|
|
|
|
|
|
|
# This method parses an IFD block, like those found in # |
|
193
|
|
|
|
|
|
|
# the APP1 or APP3 segments. The arguments are: the name # |
|
194
|
|
|
|
|
|
|
# of the block, the absolute address of the start of the # |
|
195
|
|
|
|
|
|
|
# block (in the segment's data area) and the value of the # |
|
196
|
|
|
|
|
|
|
# offset base (i.e., the address which all other offsets # |
|
197
|
|
|
|
|
|
|
# found in the interoperability arrays are relative to; # |
|
198
|
|
|
|
|
|
|
# normally, a TIFF header base). The following arguments # |
|
199
|
|
|
|
|
|
|
# are optional: the first one specifies how the next_link # |
|
200
|
|
|
|
|
|
|
# pointer is to be treated ('0': the pointer is read; # |
|
201
|
|
|
|
|
|
|
# '1': the pointer is read and a warning is issued if it # |
|
202
|
|
|
|
|
|
|
# is non-zero; '2': the pointer is not read), and the # |
|
203
|
|
|
|
|
|
|
# second one whether the prediction mechanism for intero- # |
|
204
|
|
|
|
|
|
|
# perability offsets should be used or not. The return # |
|
205
|
|
|
|
|
|
|
# value is the next_link pointer. # |
|
206
|
|
|
|
|
|
|
# ------------------------------------------------------- # |
|
207
|
|
|
|
|
|
|
# structure of an IFD: # |
|
208
|
|
|
|
|
|
|
# 2 bytes Number n of Interoperability arrays # |
|
209
|
|
|
|
|
|
|
# 12n bytes the n arrays (12 bytes each) # |
|
210
|
|
|
|
|
|
|
# 4 bytes link to next IFD (can be zero) # |
|
211
|
|
|
|
|
|
|
# ....... additional data area # |
|
212
|
|
|
|
|
|
|
# ======================================================= # |
|
213
|
|
|
|
|
|
|
# The block name is indeed a '@' separated list of names, # |
|
214
|
|
|
|
|
|
|
# which are to be interpreted in sequence; for instance # |
|
215
|
|
|
|
|
|
|
# "IFD0@SubIFD" means that in $this->{records} there is a # |
|
216
|
|
|
|
|
|
|
# REFERENCE record with key "IFD" and value $dirref; then # |
|
217
|
|
|
|
|
|
|
# in $$dirref there is a REFERENCE record with key equal # |
|
218
|
|
|
|
|
|
|
# to "SubIFD" and so on ... # |
|
219
|
|
|
|
|
|
|
# ------------------------------------------------------- # |
|
220
|
|
|
|
|
|
|
# After the execution of this routine, a new REFERENCE # |
|
221
|
|
|
|
|
|
|
# record will be present, whose value is a reference to # |
|
222
|
|
|
|
|
|
|
# a list of all the entries in the IFD. If $offset is un- # |
|
223
|
|
|
|
|
|
|
# defined, this routine returns immediately (in this way # |
|
224
|
|
|
|
|
|
|
# you do not need to test it before). No next_link's are # |
|
225
|
|
|
|
|
|
|
# tolerated in the underlying subdirectories. Deeper # |
|
226
|
|
|
|
|
|
|
# IFD's are analysed by parse_ifd_children. # |
|
227
|
|
|
|
|
|
|
# ------------------------------------------------------- # |
|
228
|
|
|
|
|
|
|
# There is now a prediction and correction mechanism for # |
|
229
|
|
|
|
|
|
|
# the offsets in the interoperability arrays. The simple # |
|
230
|
|
|
|
|
|
|
# assumption is that the absolute value of offsets can be # |
|
231
|
|
|
|
|
|
|
# wrong, but their difference is always right, so, if you # |
|
232
|
|
|
|
|
|
|
# get the first one right ... a good bet is the address # |
|
233
|
|
|
|
|
|
|
# of the byte immediately following the next_IFD link. # |
|
234
|
|
|
|
|
|
|
# The @$prediction array is used to exchange information # |
|
235
|
|
|
|
|
|
|
# with parse_interop(): [0] = use predictions to rewrite # |
|
236
|
|
|
|
|
|
|
# addresses (if set); [1] = value for next address pre- # |
|
237
|
|
|
|
|
|
|
# diction; [2] = old interoperability array address. # |
|
238
|
|
|
|
|
|
|
########################################################### |
|
239
|
|
|
|
|
|
|
sub parse_ifd { |
|
240
|
239
|
|
|
239
|
0
|
395
|
my ($this, $dirnames, $offset, $base, $next, $use_prediction) = @_; |
|
241
|
|
|
|
|
|
|
# if $offset is undefined, return immediately |
|
242
|
239
|
50
|
|
|
|
519
|
return unless defined $offset; |
|
243
|
|
|
|
|
|
|
# if next is undefined, set it to zero |
|
244
|
239
|
100
|
|
|
|
437
|
$next = 0 unless defined $next; |
|
245
|
|
|
|
|
|
|
# the first two bytes give the number of Interoperability arrays. |
|
246
|
|
|
|
|
|
|
# Don't insert this value into the record list, just read it. |
|
247
|
239
|
|
|
|
|
590
|
my $records = $this->read_record($SHORT, $offset); |
|
248
|
|
|
|
|
|
|
# create/retrieve the appropriate record list and save its |
|
249
|
|
|
|
|
|
|
# reference. The list is specified by a '@' separated list |
|
250
|
|
|
|
|
|
|
# of dir names in $dirnames (to be interpreted in sequence) |
|
251
|
239
|
|
|
|
|
928
|
my $dirref = $this->provide_subdirectory($dirnames); |
|
252
|
|
|
|
|
|
|
# initialise the structure for address prediction (note that the 4 |
|
253
|
|
|
|
|
|
|
# bytes of the "next link" must be added only if $next is < 2) |
|
254
|
239
|
100
|
|
|
|
436
|
my $remote = $offset + 12*$records; $remote += 4 if $next < 2; |
|
|
239
|
|
|
|
|
512
|
|
|
255
|
239
|
|
|
|
|
426
|
my $prediction = [$use_prediction, $remote, undef]; |
|
256
|
|
|
|
|
|
|
# parse all the records in the IFD; additional data might be referenced |
|
257
|
|
|
|
|
|
|
# through offsets relative to the address base (usually, the tiff header |
|
258
|
|
|
|
|
|
|
# base). This populates the $$dirref list with IFD records. |
|
259
|
|
|
|
|
|
|
$offset = $this->parse_interop |
|
260
|
239
|
|
|
|
|
814
|
($offset, $base, $dirref, $prediction) for (1..$records); |
|
261
|
|
|
|
|
|
|
# after the IFD records there can be a link to the next IFD; this |
|
262
|
|
|
|
|
|
|
# is an unsigned long, i.e. 4 bytes. If there is no next IFD, these |
|
263
|
|
|
|
|
|
|
# bytes are 0x00000000. If $next is 2, these four bytes are absent. |
|
264
|
232
|
50
|
|
|
|
922
|
my $next_link = ($next > 1) ? undef : $this->read_record($LONG, $offset); |
|
265
|
|
|
|
|
|
|
# if $next is true and we have a non-zero "next link", complain |
|
266
|
232
|
50
|
66
|
|
|
1184
|
$this->warn("next link not zero") if $next && $next_link; |
|
267
|
|
|
|
|
|
|
# take care of possible subdirectories |
|
268
|
232
|
|
|
|
|
886
|
$this->parse_ifd_children($dirnames, $base, $offset); |
|
269
|
|
|
|
|
|
|
# return the next IFD link |
|
270
|
232
|
|
|
|
|
638
|
return $next_link; |
|
271
|
|
|
|
|
|
|
} |
|
272
|
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
########################################################### |
|
274
|
|
|
|
|
|
|
# This method analyses the subdirectories of an IFD, once # |
|
275
|
|
|
|
|
|
|
# the basic IFD analysis is complete. The arguments are: # |
|
276
|
|
|
|
|
|
|
# the name of the "parent" IFD, the value of the offset # |
|
277
|
|
|
|
|
|
|
# base and the address of the 1st byte after the next_IFD # |
|
278
|
|
|
|
|
|
|
# link in the parent IFD (this is used only to warn if # |
|
279
|
|
|
|
|
|
|
# smaller addresses are found, which is usually an indi- # |
|
280
|
|
|
|
|
|
|
# cation of data corruption). See parse_ifd for further # |
|
281
|
|
|
|
|
|
|
# details on these arguments and the IFD structure. # |
|
282
|
|
|
|
|
|
|
# ------------------------------------------------------- # |
|
283
|
|
|
|
|
|
|
# Deeper IFD's are searched for and inserted. A subdir is # |
|
284
|
|
|
|
|
|
|
# indicated by a $LONG record whose tag is present in # |
|
285
|
|
|
|
|
|
|
# %IFD_SUBDIRS. The goal of this routine is to create a # |
|
286
|
|
|
|
|
|
|
# $REFERENCE record and parse the subdir into the array # |
|
287
|
|
|
|
|
|
|
# pointed by it; the originating offset record is removed # |
|
288
|
|
|
|
|
|
|
# since it contains very fragile info now (its name is # |
|
289
|
|
|
|
|
|
|
# saved in the "extra" field of the $REFERENCE). # |
|
290
|
|
|
|
|
|
|
# ------------------------------------------------------- # |
|
291
|
|
|
|
|
|
|
# Treatment of MakerNotes is triggered here: the approach # |
|
292
|
|
|
|
|
|
|
# is almost identical to that for deeper IFD's, but the # |
|
293
|
|
|
|
|
|
|
# recursive call to parse_ifd is replaced by a call to # |
|
294
|
|
|
|
|
|
|
# parse_makernote (with some arguments differing). # |
|
295
|
|
|
|
|
|
|
########################################################### |
|
296
|
|
|
|
|
|
|
sub parse_ifd_children { |
|
297
|
232
|
|
|
232
|
0
|
367
|
my ($this, $dirnames, $base, $old_offset) = @_; |
|
298
|
|
|
|
|
|
|
# retrieve the record list of the "parent" IFD |
|
299
|
232
|
|
|
|
|
704
|
my $dirref = $this->search_record_value($dirnames); |
|
300
|
|
|
|
|
|
|
# take care of possible subdirectories. First, create a |
|
301
|
|
|
|
|
|
|
# string with the current IFD or sub-IFD path name. |
|
302
|
232
|
|
|
|
|
654
|
my $path = join '@', $this->{name}, $dirnames; |
|
303
|
|
|
|
|
|
|
# Now look into %IFD_SUBDIRS to see if this path is a valid key; if |
|
304
|
|
|
|
|
|
|
# it is (i.e. subdirs are possible), inspect the relevant mapping hash |
|
305
|
232
|
100
|
|
|
|
708
|
if (exists $IFD_SUBDIRS{$path}) { |
|
306
|
226
|
|
|
|
|
380
|
my $mapping = $IFD_SUBDIRS{$path}; |
|
307
|
|
|
|
|
|
|
# $tag is a numerical value, not a string |
|
308
|
226
|
|
|
|
|
1396
|
foreach my $tag (sort keys %$mapping) { |
|
309
|
|
|
|
|
|
|
# don't parse if there is no such subdirectory |
|
310
|
680
|
100
|
|
|
|
1452
|
next unless (my $record = $this->search_record($tag, $dirref)); |
|
311
|
|
|
|
|
|
|
# get the name and location of this secondary IFD |
|
312
|
170
|
|
|
|
|
535
|
my $new_dirnames = join '@', $dirnames, $$mapping{$tag}; |
|
313
|
170
|
|
|
|
|
432
|
my $new_offset = $base + $record->get_value(); |
|
314
|
|
|
|
|
|
|
# although there is no prescription I know about forbidding to |
|
315
|
|
|
|
|
|
|
# jump back, this situation usually indicates a corrupted file |
|
316
|
170
|
50
|
|
|
|
396
|
$this->die('Jumping back') if $new_offset < $old_offset; |
|
317
|
|
|
|
|
|
|
# parse the new IFD (MakerNote records are analysed here, with a |
|
318
|
|
|
|
|
|
|
# special routine; the data size is contained in the extra field). |
|
319
|
170
|
|
|
|
|
362
|
my @common = ($new_dirnames, $new_offset, $base); |
|
320
|
170
|
100
|
|
|
|
1084
|
$tag == $MAKERNOTE_TAG |
|
321
|
|
|
|
|
|
|
? $this->parse_makernote(@common, $record->{extra}) |
|
322
|
|
|
|
|
|
|
: $this->parse_ifd (@common, 1); |
|
323
|
|
|
|
|
|
|
# mark the record containing the offset to the newly created |
|
324
|
|
|
|
|
|
|
# IFD by setting its "extra" field. This record isn't any more |
|
325
|
|
|
|
|
|
|
# interesting after we have used it, and should be recalculated |
|
326
|
|
|
|
|
|
|
# every time we change the Exif data area. |
|
327
|
170
|
|
|
|
|
405
|
$record->{extra} = "deleteme"; |
|
328
|
|
|
|
|
|
|
# Look for the new IFD referece (it should be the last record |
|
329
|
|
|
|
|
|
|
# in the current subdirectory) and set its "extra" field to |
|
330
|
|
|
|
|
|
|
# the tag name of $record, just for reference |
|
331
|
170
|
|
|
|
|
527
|
$this->search_record('LAST_RECORD', $dirref)->{extra} = |
|
332
|
|
|
|
|
|
|
JPEG_lookup($path, $tag); } } |
|
333
|
|
|
|
|
|
|
# remove all records marked for deletion in the current subdirectory |
|
334
|
|
|
|
|
|
|
# (remember that "extra" is most of the time undefined). |
|
335
|
232
|
100
|
|
|
|
417
|
@$dirref = grep { ! $_->{extra} || $_->{extra} ne "deleteme" } @$dirref; |
|
|
2749
|
|
|
|
|
5567
|
|
|
336
|
|
|
|
|
|
|
} |
|
337
|
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
########################################################### |
|
339
|
|
|
|
|
|
|
# This method parses an IFD Interoperability array. # |
|
340
|
|
|
|
|
|
|
#=========================================================# |
|
341
|
|
|
|
|
|
|
# Each Interoperability array consists of four elements: # |
|
342
|
|
|
|
|
|
|
# bytes 0-1 Tag (a unique 2-byte number) # |
|
343
|
|
|
|
|
|
|
# bytes 2-3 Type (one out of 12 types) # |
|
344
|
|
|
|
|
|
|
# bytes 4-7 Count (the number of values) # |
|
345
|
|
|
|
|
|
|
# bytes 8-11 Value Offset (value or offset) # |
|
346
|
|
|
|
|
|
|
# # |
|
347
|
|
|
|
|
|
|
# Types are the same as for the Record class. The "value # |
|
348
|
|
|
|
|
|
|
# offset" contains an offset from the address base where # |
|
349
|
|
|
|
|
|
|
# the value is recorded (the TIFF header base usually). # |
|
350
|
|
|
|
|
|
|
# It contains the actual value if it is not larger than # |
|
351
|
|
|
|
|
|
|
# 4 bytes. If the value is shorter than 4 bytes, it is # |
|
352
|
|
|
|
|
|
|
# recorded in the lower end of the 4-byte area (smaller # |
|
353
|
|
|
|
|
|
|
# offsets). This method returns the offset value summed # |
|
354
|
|
|
|
|
|
|
# to the number of bytes which were read ($offset + 12). # |
|
355
|
|
|
|
|
|
|
# ------------------------------------------------------- # |
|
356
|
|
|
|
|
|
|
# The MakerNote Interoperability array is now intercepted # |
|
357
|
|
|
|
|
|
|
# and stored as one $LONG (instead of many $UNDEF bytes); # |
|
358
|
|
|
|
|
|
|
# the MakerNote content is supposed to be processed at a # |
|
359
|
|
|
|
|
|
|
# later time, and this record is supposed to be temporary.# |
|
360
|
|
|
|
|
|
|
# The data area size is saved in the extra field. # |
|
361
|
|
|
|
|
|
|
# ------------------------------------------------------- # |
|
362
|
|
|
|
|
|
|
# New "prediction" structure to help detecting corrupted # |
|
363
|
|
|
|
|
|
|
# MakerNotes: [0] = use predictions to rewrite addresses # |
|
364
|
|
|
|
|
|
|
# (if set); [1] = the prediction for the next data area # |
|
365
|
|
|
|
|
|
|
# (for size > 4); [2] = this element is updated with the # |
|
366
|
|
|
|
|
|
|
# address found in the interoperability array. # |
|
367
|
|
|
|
|
|
|
########################################################### |
|
368
|
|
|
|
|
|
|
sub parse_interop { |
|
369
|
2652
|
|
|
2652
|
0
|
2900
|
my ($this, $offset, $offset_base, $dirref, $pred) = @_; |
|
370
|
|
|
|
|
|
|
# the data area must be at least 12 bytes wide |
|
371
|
2652
|
|
|
|
|
4751
|
$this->test_size(12, "initial bytes check"); |
|
372
|
|
|
|
|
|
|
# read the content of the four fields of the Interoperability array, |
|
373
|
|
|
|
|
|
|
# without inserting them in any record list. Interpret the last field |
|
374
|
|
|
|
|
|
|
# as an unsigned long integer, even if this is not the case |
|
375
|
2652
|
|
|
|
|
5019
|
my $tag = $this->read_record($SHORT, $offset); |
|
376
|
2652
|
|
|
|
|
8444
|
my $type = $this->read_record($SHORT, $offset); |
|
377
|
2652
|
|
|
|
|
7869
|
my $count = $this->read_record($LONG , $offset); |
|
378
|
2652
|
|
|
|
|
8104
|
my $doffset = $this->read_record($LONG , $offset); |
|
379
|
|
|
|
|
|
|
# the MakerNote tag should have been designed as a 'LONG' (offset), |
|
380
|
|
|
|
|
|
|
# not as 'UNDEFINED' data. "Correct" it and leave parsing for other |
|
381
|
|
|
|
|
|
|
# routines; ($count is saved in the "extra field, for later reference) |
|
382
|
2652
|
100
|
|
|
|
6807
|
$this->store_record($dirref, $tag, $LONG, $offset-4, 1)->{extra} = |
|
383
|
|
|
|
|
|
|
$count, goto PARSE_END if $tag == $MAKERNOTE_TAG; |
|
384
|
|
|
|
|
|
|
# ask the record class to calculate the number of bytes necessary |
|
385
|
|
|
|
|
|
|
# to store the value (the type size times the number of items). |
|
386
|
2608
|
|
|
|
|
5734
|
my $size = Image::MetaData::JPEG::Record->get_size($type, $count); |
|
387
|
|
|
|
|
|
|
# if $size is zero, it means that the Record type is variable-length; |
|
388
|
|
|
|
|
|
|
# in this case, $size should be given by $count |
|
389
|
2602
|
100
|
|
|
|
3895
|
$size = $count if $size == 0; |
|
390
|
|
|
|
|
|
|
# If $size is larger than 4, calculate the real data area offset |
|
391
|
|
|
|
|
|
|
# ($doffset) in the file by adding the offset base; however, if |
|
392
|
|
|
|
|
|
|
# $size is less or equal to 4 we must point it to its own 4 bytes. |
|
393
|
2602
|
100
|
|
|
|
4231
|
$doffset = ($size < 5) ? ($offset - 4) : ($offset_base + $doffset); |
|
394
|
|
|
|
|
|
|
# if there is a remote data area, and the prediction mechanism is |
|
395
|
|
|
|
|
|
|
# enabled, use the prediction structure to set the value of $doffset |
|
396
|
|
|
|
|
|
|
# (then, update the structure); if the mechanism is disabled, check |
|
397
|
|
|
|
|
|
|
# that $doffset does not point before the first prediction (this is |
|
398
|
|
|
|
|
|
|
# very likely an address corruption). |
|
399
|
2602
|
100
|
|
|
|
3956
|
if ($size > 4) { |
|
400
|
1119
|
100
|
|
|
|
1623
|
if ($$pred[0]) { |
|
401
|
17
|
100
|
|
|
|
50
|
my $jump = defined $$pred[2] ? ($doffset - $$pred[2]) : 0; |
|
402
|
17
|
|
|
|
|
20
|
$$pred[1]+=$jump; ($$pred[2], $doffset) = ($doffset, $$pred[1]); } |
|
|
17
|
|
|
|
|
27
|
|
|
403
|
1102
|
100
|
|
|
|
1948
|
else { $this->die('Corrupted address') if $doffset < $$pred[1] } } |
|
404
|
|
|
|
|
|
|
# Check that the data area exists and has the correct size (this |
|
405
|
|
|
|
|
|
|
# avoids trying to read it if $doffset points out of the segment). |
|
406
|
2601
|
|
|
|
|
5877
|
$this->test_size($doffset + $size, 'Interop. array data area not found'); |
|
407
|
|
|
|
|
|
|
# insert the Interoperability array value into its sub-directory |
|
408
|
2601
|
|
|
|
|
5438
|
$this->store_record($dirref, $tag, $type, $doffset, $count); |
|
409
|
|
|
|
|
|
|
# return the updated $offset |
|
410
|
2645
|
|
|
|
|
6878
|
PARSE_END: return $offset; |
|
411
|
|
|
|
|
|
|
} |
|
412
|
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
########################################################### |
|
414
|
|
|
|
|
|
|
# This method tries to parse a MakerNote block. The first # |
|
415
|
|
|
|
|
|
|
# argument is the beginning of the name of a MakerNote # |
|
416
|
|
|
|
|
|
|
# subdirectory to be completed with the actual format, # |
|
417
|
|
|
|
|
|
|
# e.g. '_Nikon_2'. The other arguments are: the absolute # |
|
418
|
|
|
|
|
|
|
# address of the MakerNote block start, the address base # |
|
419
|
|
|
|
|
|
|
# of the SubIFD (this should be the TIFF header base) and # |
|
420
|
|
|
|
|
|
|
# the size of the MakerNote block. # |
|
421
|
|
|
|
|
|
|
# ======================================================= # |
|
422
|
|
|
|
|
|
|
# The MakerNote tag is read by a call to parse_interop in # |
|
423
|
|
|
|
|
|
|
# the IFD0@SubIFD; however, only the offset and size of # |
|
424
|
|
|
|
|
|
|
# the MakerNote data area is read there -- the real pro- # |
|
425
|
|
|
|
|
|
|
# cessing is done here (this method is called during the # |
|
426
|
|
|
|
|
|
|
# analysis of IFD subdirectories in parse_ifd). # |
|
427
|
|
|
|
|
|
|
########################################################### |
|
428
|
|
|
|
|
|
|
sub parse_makernote { |
|
429
|
44
|
|
|
44
|
0
|
91
|
my ($this, $dirnames, $mknt_offset, $base, $mknt_size) = @_; |
|
430
|
|
|
|
|
|
|
# A MakerNote is always in APP1@IFD0@SubIFD; stop immediately |
|
431
|
|
|
|
|
|
|
# if $dirnames disagrees with this assumption. |
|
432
|
44
|
50
|
|
|
|
403
|
$this->die("Invalid \$dirnames ($dirnames)") |
|
433
|
|
|
|
|
|
|
unless $dirnames =~ '^IFD0@SubIFD@[^@]*$'; |
|
434
|
|
|
|
|
|
|
# get the primary IFD reference and try to extract the maker |
|
435
|
|
|
|
|
|
|
# (setup a fake string if this field is not found) |
|
436
|
44
|
|
|
|
|
141
|
my $ifd0 = $this->search_record_value('IFD0'); |
|
437
|
44
|
|
50
|
|
|
229
|
my $mknt_maker = $this->search_record_value |
|
438
|
|
|
|
|
|
|
(JPEG_lookup('APP1@IFD0@Make'), $ifd0) || 'Unknown Maker'; |
|
439
|
|
|
|
|
|
|
# try all possible MakerNote formats (+ catch-all rule) |
|
440
|
44
|
|
|
|
|
295
|
my $mknt_found = undef; |
|
441
|
44
|
|
|
|
|
729
|
for my $format (sort keys %$HASH_MAKERNOTES) { |
|
442
|
|
|
|
|
|
|
# this quest must stop at the first positive match |
|
443
|
1276
|
100
|
|
|
|
1805
|
next if $mknt_found; |
|
444
|
|
|
|
|
|
|
# extract the property table for this MakerNote format |
|
445
|
|
|
|
|
|
|
# (and skip it if it is only a temporary placeholder) |
|
446
|
514
|
|
|
|
|
668
|
my $hash = $$HASH_MAKERNOTES{$format}; |
|
447
|
514
|
100
|
|
|
|
999
|
next if exists $$hash{ignore}; |
|
448
|
|
|
|
|
|
|
# get the maker and signature for this format |
|
449
|
443
|
|
|
|
|
547
|
my $format_signature = $$hash{signature}; |
|
450
|
443
|
|
|
|
|
512
|
my $format_maker = $$hash{maker}; |
|
451
|
|
|
|
|
|
|
# skip if the maker or the signature is incompatible (the |
|
452
|
|
|
|
|
|
|
# signature test is the initial part of the data area against |
|
453
|
|
|
|
|
|
|
# a regular expression: save the match for later reference) |
|
454
|
443
|
100
|
|
|
|
650
|
my $incipit_size = $mknt_size < 50 ? $mknt_size : 50; |
|
455
|
443
|
|
|
|
|
1109
|
my $incipit = $this->read_record($UNDEF, 0+$mknt_offset,$incipit_size); |
|
456
|
443
|
100
|
|
|
|
4688
|
next unless $mknt_maker =~ /$format_maker/; |
|
457
|
49
|
100
|
|
|
|
731
|
next unless $incipit =~ /$format_signature/; |
|
458
|
44
|
|
|
|
|
193
|
my $signature = $1; my $skip = length $signature; |
|
|
44
|
|
|
|
|
77
|
|
|
459
|
|
|
|
|
|
|
# OK, we opted for this format |
|
460
|
44
|
|
|
|
|
58
|
$mknt_found = 1; |
|
461
|
|
|
|
|
|
|
# if the previous tests pass, it is time to fix the format and |
|
462
|
|
|
|
|
|
|
# to create an appropriate subdirectory for the MakerNote records |
|
463
|
44
|
|
|
|
|
109
|
my $mknt_dirname = $dirnames.'_'.$format; |
|
464
|
44
|
|
|
|
|
199
|
my $mknt_dir = $this->provide_subdirectory($mknt_dirname); |
|
465
|
|
|
|
|
|
|
# prepare also a special subdirectory for pseudofields |
|
466
|
44
|
|
|
|
|
145
|
my $mknt_spcname = $mknt_dirname.'@special'; |
|
467
|
44
|
|
|
|
|
124
|
my $mknt_spc = $this->provide_subdirectory($mknt_spcname); |
|
468
|
|
|
|
|
|
|
# the MakerNote's endianness can be different from that of the IFD; |
|
469
|
|
|
|
|
|
|
# if a value is specified for this format, set it; otherwise, try to |
|
470
|
|
|
|
|
|
|
# detect it by testing the first byte after the signature (preferred). |
|
471
|
44
|
|
|
|
|
187
|
my $it_looks_big_endian = $this->data($mknt_offset+$skip, 1) eq "\000"; |
|
472
|
44
|
100
|
|
|
|
201
|
my $mknt_endianness = exists $$hash{endianness} ? $$hash{endianness} : |
|
|
|
100
|
|
|
|
|
|
|
473
|
|
|
|
|
|
|
$it_looks_big_endian ? $BIG_ENDIAN : $LITTLE_ENDIAN; |
|
474
|
|
|
|
|
|
|
# in general, the MakerNote's next-IFD link is zero, but some |
|
475
|
|
|
|
|
|
|
# MakerNotes do not even have these four bytes: prepare the flag |
|
476
|
44
|
100
|
|
|
|
139
|
my $next_flag = exists $$hash{nonext} ? 2 : 1; |
|
477
|
|
|
|
|
|
|
# in general, MakerNote's offsets are computed from the APP1 segment |
|
478
|
|
|
|
|
|
|
# TIFF base; however, some formats compute offsets from the beginning |
|
479
|
|
|
|
|
|
|
# of the MakerNote itself: prepare an alternative base if necessary |
|
480
|
44
|
100
|
|
|
|
117
|
my $mknt_base = exists $$hash{mkntstart} ? $mknt_offset : $base; |
|
481
|
|
|
|
|
|
|
# some MakerNotes have a TIFF header on their own, freeing them |
|
482
|
|
|
|
|
|
|
# from the relocation problem; values from this header overwrite |
|
483
|
|
|
|
|
|
|
# the previously assigned values; records are saved in $mknt_dir. |
|
484
|
44
|
100
|
|
|
|
143
|
if (exists $$hash{mkntTIFF}) { |
|
485
|
2
|
|
|
|
|
10
|
($mknt_base, my $ifd_link, $mknt_endianness) |
|
486
|
|
|
|
|
|
|
= $this->parse_TIFF_header($mknt_offset + $skip, $mknt_spc); |
|
487
|
|
|
|
|
|
|
# update $skip to point to the beginning of the IFD |
|
488
|
2
|
|
|
|
|
5
|
$skip += $ifd_link; } |
|
489
|
|
|
|
|
|
|
# calculate the address of the beginning of the IFD (both with |
|
490
|
|
|
|
|
|
|
# and without a TIFF header) or of an unstructured data area. |
|
491
|
44
|
|
|
|
|
73
|
my $data_offset = $mknt_offset + $skip; |
|
492
|
|
|
|
|
|
|
# Store the special MakerNote information in a special subdirectory |
|
493
|
|
|
|
|
|
|
# (for instance, the raw MakerNote image, so that the block can at |
|
494
|
|
|
|
|
|
|
# least be dumped to disk again in case its structure is unknown) |
|
495
|
|
|
|
|
|
|
$this->store_record($mknt_spc, shift @$_, $UNDEF, @$_) |
|
496
|
44
|
|
|
|
|
359
|
for (['ORIGINAL' , $mknt_offset, $mknt_size], |
|
497
|
|
|
|
|
|
|
['SIGNATURE' , \$signature], |
|
498
|
|
|
|
|
|
|
['ENDIANNESS', \$mknt_endianness], |
|
499
|
|
|
|
|
|
|
['FORMAT' , \$format]); |
|
500
|
|
|
|
|
|
|
# change locally the endianness value |
|
501
|
44
|
|
|
|
|
146
|
local $this->{endianness} = $mknt_endianness; |
|
502
|
|
|
|
|
|
|
# Unstructured case: the content of the MakerNote is simply |
|
503
|
|
|
|
|
|
|
# a sequence of bytes, which must be decoded using $$hash{tags}; |
|
504
|
|
|
|
|
|
|
# execute inside an eval, to confine errors inside MakerNotes |
|
505
|
44
|
100
|
|
|
|
141
|
if (exists $$hash{nonIFD}) { eval { |
|
|
36
|
|
|
|
|
55
|
|
|
506
|
36
|
|
|
|
|
93
|
my $p = $$hash{tags}; |
|
507
|
1452
|
|
|
|
|
1685
|
$this->store_record($mknt_dir, @$_[0,1], $data_offset, $$_[2]) |
|
508
|
36
|
|
|
|
|
546
|
for map { $$p{$_} } sort { $a <=> $b } keys %$p; |
|
|
6197
|
|
|
|
|
4435
|
|
|
509
|
36
|
50
|
66
|
|
|
432
|
$this->die('MakerNote size mismatch') |
|
510
|
|
|
|
|
|
|
unless $format =~ /unknown/ || |
|
511
|
|
|
|
|
|
|
$data_offset == $mknt_offset + $mknt_size; } } |
|
512
|
|
|
|
|
|
|
# Structured case: the content of the MakerNote is approximately |
|
513
|
|
|
|
|
|
|
# a standard IFD, so parse_ifd is sufficient: it is called a se- |
|
514
|
|
|
|
|
|
|
# cond time if an error occurs (+ cleanup of unreliable findings), |
|
515
|
|
|
|
|
|
|
# but if this doesn't solve the problem, one reverts to 1st case. |
|
516
|
|
|
|
|
|
|
else { |
|
517
|
8
|
|
|
|
|
20
|
my $args = [$mknt_dirname, $data_offset, $mknt_base, $next_flag]; |
|
518
|
8
|
|
|
|
|
14
|
my $code = '@$mknt_dir=@$copy; $this->parse_ifd(@$args'; |
|
519
|
8
|
|
|
|
|
15
|
my $copy = [@$mknt_dir]; eval "$code)"; |
|
|
8
|
|
|
|
|
1017
|
|
|
520
|
8
|
100
|
|
|
|
116
|
$this->warn('Using predictions'), eval "$code,1)" if $@; |
|
521
|
8
|
100
|
|
|
|
92
|
$this->warn('Predictions failed'), eval "$code)" if $@; |
|
522
|
|
|
|
|
|
|
}; |
|
523
|
|
|
|
|
|
|
# If any errors occured during the real MakerNote parsing, |
|
524
|
|
|
|
|
|
|
# and additional special record is saved with the error message |
|
525
|
|
|
|
|
|
|
# (this will be the last record in the MakerNote subdirectory) |
|
526
|
44
|
100
|
|
|
|
280
|
$this->store_record($mknt_spc, 'ERROR',$ASCII,\$@) if $@; |
|
527
|
|
|
|
|
|
|
# print "MESSAGE FROM MAKERNOTE:\n$@\n" if $@; |
|
528
|
|
|
|
|
|
|
} |
|
529
|
|
|
|
|
|
|
} |
|
530
|
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
# successful load |
|
532
|
|
|
|
|
|
|
1; |