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
|
|
61
|
use Image::MetaData::JPEG::data::Tables qw(:TagsAPP1_Exif); |
|
15
|
|
|
|
|
22
|
|
|
15
|
|
|
|
|
2254
|
|
7
|
15
|
|
|
15
|
|
76
|
no integer; |
|
15
|
|
|
|
|
999
|
|
|
15
|
|
|
|
|
81
|
|
8
|
15
|
|
|
15
|
|
362
|
use strict; |
|
15
|
|
|
|
|
17
|
|
|
15
|
|
|
|
|
332
|
|
9
|
15
|
|
|
15
|
|
48
|
use warnings; |
|
15
|
|
|
|
|
16
|
|
|
15
|
|
|
|
|
18077
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
########################################################### |
12
|
|
|
|
|
|
|
# This method dumps an Exif APP1 segment. Basically, it # |
13
|
|
|
|
|
|
|
# dumps the identifier, the two IFDs and the thumbnail. # |
14
|
|
|
|
|
|
|
########################################################### |
15
|
|
|
|
|
|
|
sub dump_app1_exif { |
16
|
161
|
|
|
161
|
0
|
294
|
my ($this) = @_; |
17
|
|
|
|
|
|
|
# dump the identifier (not part of the TIFF header) |
18
|
161
|
|
|
|
|
394
|
my $identifier = $this->search_record('Identifier')->get(); |
19
|
161
|
|
|
|
|
549
|
$this->set_data($identifier); |
20
|
|
|
|
|
|
|
# dump the TIFF header; note that the offset returned by |
21
|
|
|
|
|
|
|
# dump_TIFF_header is the current position in the newly written |
22
|
|
|
|
|
|
|
# data area AFTER the identifier (i.e., the base is the base |
23
|
|
|
|
|
|
|
# of the TIFF header), so it does not start from zero but from the |
24
|
|
|
|
|
|
|
# value of $ifd0_link. Be aware that its meaning is slightly |
25
|
|
|
|
|
|
|
# different from $offset in the parser. |
26
|
161
|
|
|
|
|
459
|
my ($header, $offset, $endianness) = $this->dump_TIFF_header(); |
27
|
161
|
|
|
|
|
492
|
$this->set_data($header); |
28
|
|
|
|
|
|
|
# locally set the current endianness to what we have found. |
29
|
161
|
|
|
|
|
357
|
local $this->{endianness} = $endianness; |
30
|
|
|
|
|
|
|
# dump all the records of the 0th IFD, and update $offset to |
31
|
|
|
|
|
|
|
# point after the end of the current data area (with respect |
32
|
|
|
|
|
|
|
# to the TIFF header base). This must be done even if the IFD |
33
|
|
|
|
|
|
|
# itself is empty (in order to find the next one). |
34
|
161
|
100
|
|
|
|
399
|
my $ifd1_link = defined $this->search_record('IFD1') ? 0 : 1; |
35
|
161
|
|
|
|
|
529
|
$offset += $this->set_data($this->dump_ifd('IFD0', $offset, $ifd1_link)); |
36
|
|
|
|
|
|
|
# same thing with the 1st IFD. We don't have to worry if this |
37
|
|
|
|
|
|
|
# IFD is not there, because dump_ifd tests for this case. |
38
|
161
|
|
|
|
|
461
|
$offset += $this->set_data($this->dump_ifd('IFD1', $offset, 1)); |
39
|
|
|
|
|
|
|
# if there is thumbnail data in the main directory of this |
40
|
|
|
|
|
|
|
# segment, it is time to dump it. Use the reference, because |
41
|
|
|
|
|
|
|
# this can be quite large (some tens of kilobytes ....) |
42
|
161
|
100
|
|
|
|
481
|
if (my $th_record = $this->search_record('ThumbnailData')) { |
43
|
82
|
|
|
|
|
290
|
(undef, undef, undef, my $tdataref) = $th_record->get(); |
44
|
82
|
|
|
|
|
248
|
$this->set_data($tdataref); } |
45
|
|
|
|
|
|
|
} |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
########################################################### |
48
|
|
|
|
|
|
|
# This method reconstructs a TIFF header and returns a # |
49
|
|
|
|
|
|
|
# list with all the relevant values. Nothing is written # |
50
|
|
|
|
|
|
|
# to the data area. Records are searched for in the # |
51
|
|
|
|
|
|
|
# directory specified by the second argument. # |
52
|
|
|
|
|
|
|
########################################################### |
53
|
|
|
|
|
|
|
sub dump_TIFF_header { |
54
|
162
|
|
|
162
|
0
|
222
|
my ($this, $dirref) = @_; |
55
|
|
|
|
|
|
|
# retrieve the endianness, and signature. It is not worth |
56
|
|
|
|
|
|
|
# setting the temporary segment endianness here, do it later. |
57
|
162
|
|
|
|
|
422
|
my $endianness=$this->search_record('Endianness',$dirref)->get(); |
58
|
162
|
|
|
|
|
455
|
my $signature =$this->search_record('Signature',$dirref)->get($endianness); |
59
|
|
|
|
|
|
|
# create a string containing the TIFF header (we always |
60
|
|
|
|
|
|
|
# choose the offset of the 0th IFD must to be 8 here). |
61
|
162
|
|
|
|
|
230
|
my $ifd0_len = 8; |
62
|
162
|
100
|
|
|
|
625
|
my $ifd0_link = pack $endianness eq $BIG_ENDIAN ? "N" : "V", $ifd0_len; |
63
|
162
|
|
|
|
|
369
|
my $header = $endianness . $signature . $ifd0_link; |
64
|
|
|
|
|
|
|
# return all relevant values in a list |
65
|
162
|
|
|
|
|
495
|
return ($header, $ifd0_len, $endianness); |
66
|
|
|
|
|
|
|
} |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
########################################################### |
69
|
|
|
|
|
|
|
# This is the core of the Exif APP1 dumping method. It # |
70
|
|
|
|
|
|
|
# takes care to dump a whole IFD, including a special # |
71
|
|
|
|
|
|
|
# treatement for thumbnails and makernotes. No action is # |
72
|
|
|
|
|
|
|
# taken unless there is already a directory for this IFD # |
73
|
|
|
|
|
|
|
# in the structured data area of the segment. # |
74
|
|
|
|
|
|
|
# ------------------------------------------------------- # |
75
|
|
|
|
|
|
|
# Special treatement for tags holding an IFD offset (this # |
76
|
|
|
|
|
|
|
# includes makernotes); these tags are regenerated on the # |
77
|
|
|
|
|
|
|
# fly (since they are no more stored) and their value is # |
78
|
|
|
|
|
|
|
# recalculated and written to the raw data area. # |
79
|
|
|
|
|
|
|
# ------------------------------------------------------- # |
80
|
|
|
|
|
|
|
# New argument ($next), which specifies how the next_link # |
81
|
|
|
|
|
|
|
# pointer is to be treated: '0' --> the pointer is dumped # |
82
|
|
|
|
|
|
|
# with a non zero value; '1' --> the pointer is dumped # |
83
|
|
|
|
|
|
|
# with value set to zero; '2' -->: the pointer is ignored # |
84
|
|
|
|
|
|
|
########################################################### |
85
|
|
|
|
|
|
|
sub dump_ifd { |
86
|
630
|
|
|
630
|
0
|
987
|
my ($this, $dirnames, $offset, $next) = @_; |
87
|
|
|
|
|
|
|
# set the next link flag to zero if it is undefined |
88
|
630
|
50
|
|
|
|
1333
|
$next = 0 unless defined $next; |
89
|
|
|
|
|
|
|
# retrieve the appropriate record list (specified by a '@' separated |
90
|
|
|
|
|
|
|
# list of dir names in $dirnames to be interpreted in sequence). If |
91
|
|
|
|
|
|
|
# this fails, return immediately with a reference to an empty string |
92
|
630
|
|
|
|
|
1467
|
my $dirref = $this->search_record_value($dirnames); |
93
|
630
|
100
|
|
|
|
1348
|
return \ (my $ns = '') unless $dirref; |
94
|
|
|
|
|
|
|
# $short and $long are two useful format strings correctly taking |
95
|
|
|
|
|
|
|
# into account the IFD endianness. $format is a format string for |
96
|
|
|
|
|
|
|
# packing an Interoperability array |
97
|
575
|
100
|
|
|
|
1278
|
my $short = $this->{endianness} eq $BIG_ENDIAN ? 'n' : 'v'; |
98
|
575
|
100
|
|
|
|
1059
|
my $long = $this->{endianness} eq $BIG_ENDIAN ? 'N' : 'V'; |
99
|
575
|
|
|
|
|
1593
|
my $format = $short. $short . $long; |
100
|
|
|
|
|
|
|
# retrieve the record list for this IFD, then eliminate the REFERENCE |
101
|
|
|
|
|
|
|
# records (added by the parser routine, they were not in the JPEG file). |
102
|
575
|
|
|
|
|
774
|
my @records = grep { $_->{type} != $REFERENCE } @$dirref; |
|
7246
|
|
|
|
|
10577
|
|
103
|
|
|
|
|
|
|
# for each reference record with a non-undef extra field, regenerate |
104
|
|
|
|
|
|
|
# the corresponding offset record (which can be retraced from the |
105
|
|
|
|
|
|
|
# "extra" field) and insert it into the @records list with a dummy |
106
|
|
|
|
|
|
|
# value (0). We can safely use $LONG as record type (new-style offsets). |
107
|
392
|
|
|
|
|
1355
|
push @records, map { |
108
|
7246
|
100
|
|
|
|
12330
|
my $nt = JPEG_lookup($this->{name}, $dirnames, $_->{extra}); |
109
|
392
|
|
|
|
|
3362
|
new Image::MetaData::JPEG::Record($nt, $LONG, \ pack($long, 0)) } |
110
|
575
|
|
|
|
|
852
|
grep { $_->{type} == $REFERENCE && $_->{extra} } @$dirref; |
111
|
|
|
|
|
|
|
# sort the accumulated records with respect to their tags (numeric). |
112
|
|
|
|
|
|
|
# This is not, strictly speaking mandatory, but the file looks more |
113
|
|
|
|
|
|
|
# polished after this (am I introducing any gratuitous incompatibility?) |
114
|
575
|
|
|
|
|
1721
|
@records = sort { $a->{key} <=> $b->{key} } @records; |
|
10965
|
|
|
|
|
10459
|
|
115
|
|
|
|
|
|
|
# the IFD data area is to be initialised with two bytes specifying |
116
|
|
|
|
|
|
|
# the number of Interoperability arrays. |
117
|
575
|
|
|
|
|
1410
|
my $ifd_content = pack $short, scalar @records; |
118
|
|
|
|
|
|
|
# Data areas too large for the Interop array will be saved in $extra; |
119
|
|
|
|
|
|
|
# $remote should point to its beginning (from TIFF header base), so we |
120
|
|
|
|
|
|
|
# must skip 12 bytes for each Interop. array, 2 bytes for the initial |
121
|
|
|
|
|
|
|
# count (and 4 bytes for the next IFD link, unless $next is two). |
122
|
575
|
|
|
|
|
1294
|
my ($remote, $extra) = ($offset + 2 + 12*@records, ''); |
123
|
575
|
50
|
|
|
|
1140
|
$remote += 4 unless $next == 2; |
124
|
|
|
|
|
|
|
# managing the thumbnail is not trivial. We want to be sure that |
125
|
|
|
|
|
|
|
# its declared size corresponds to the reality and correct if |
126
|
|
|
|
|
|
|
# this is not the case (is this a stupid idea?) |
127
|
575
|
100
|
100
|
|
|
1582
|
if ($dirnames eq 'IFD1' && |
128
|
|
|
|
|
|
|
(my $th_record = $this->search_record('ThumbnailData'))) { |
129
|
82
|
|
|
|
|
248
|
(undef, undef, undef, my $tdataref) = $th_record->get(); |
130
|
82
|
|
|
|
|
248
|
for ($THTIFF_LENGTH, $THJPEG_LENGTH) { |
131
|
164
|
|
|
|
|
417
|
my $th_len = $this->search_record($_, $dirref); |
132
|
164
|
100
|
|
|
|
594
|
$th_len->set_value(length $$tdataref) if $th_len; } } |
133
|
|
|
|
|
|
|
# the following tags can be found only in IFD1 in APP1, and concern |
134
|
|
|
|
|
|
|
# the thumbnail location. They must be dealt with in a special way. |
135
|
575
|
|
|
|
|
1709
|
my %th_tags = ($THTIFF_OFFSET => undef, $THJPEG_OFFSET => undef); |
136
|
|
|
|
|
|
|
# determine weather this IFD can have subidrectories or not; if so, |
137
|
|
|
|
|
|
|
# get a special mapping table from %IFD_SUBDIRS (avoid autovivification) |
138
|
575
|
|
|
|
|
1254
|
my $path = join '@', $this->{name}, $dirnames; |
139
|
575
|
100
|
|
|
|
1574
|
my $mapping = exists $IFD_SUBDIRS{$path} ? $IFD_SUBDIRS{$path} : undef; |
140
|
|
|
|
|
|
|
# loop on all selected records and dump them |
141
|
575
|
|
|
|
|
805
|
for my $record (@records) { |
142
|
|
|
|
|
|
|
# extract all necessary information about this |
143
|
|
|
|
|
|
|
# Interoperability array, with the correct endianness. |
144
|
7243
|
|
|
|
|
14722
|
my ($tag, $type, $count, $dataref) = $record->get($this->{endianness}); |
145
|
|
|
|
|
|
|
# calculate the length of the array data, and correct $count |
146
|
|
|
|
|
|
|
# for string-like records (it had been set to 1 during the |
147
|
|
|
|
|
|
|
# parsing, it must be the data length in this case). |
148
|
7243
|
|
|
|
|
7759
|
my $length = length $$dataref; |
149
|
7243
|
100
|
|
|
|
12198
|
$count = $length if $record->get_category() eq 'S'; |
150
|
|
|
|
|
|
|
# the last four bytes in an interoperability array are either |
151
|
|
|
|
|
|
|
# data or an address; prepare a variable for holding this value |
152
|
7243
|
|
|
|
|
6349
|
my $record_end = ''; |
153
|
|
|
|
|
|
|
# if this IFD1 record specifies the thumbnail location, it needs |
154
|
|
|
|
|
|
|
# a special treatment, since we cannot yet know where the thumbnail |
155
|
|
|
|
|
|
|
# will be located. Write a bogus offset now and overwrite it later. |
156
|
7243
|
100
|
100
|
|
|
34975
|
if ($dirnames eq 'IFD1' && exists $th_tags{$tag}) { |
|
|
100
|
100
|
|
|
|
|
|
|
100
|
|
|
|
|
|
157
|
72
|
|
|
|
|
131
|
$th_tags{$tag} = 8 + length $ifd_content; |
158
|
72
|
|
|
|
|
95
|
$record_end = "\000\000\000\000"; } |
159
|
|
|
|
|
|
|
# if this Interop array is known to correspond to a subdirectory |
160
|
|
|
|
|
|
|
# (use %$mapping for this), the subdirectory content is calculated |
161
|
|
|
|
|
|
|
# on the fly, and stored in this IFD's remote data area. Its offset |
162
|
|
|
|
|
|
|
# instead is saved at the end of the Interoperability array. |
163
|
|
|
|
|
|
|
elsif ($mapping && exists $$mapping{$tag}) { |
164
|
392
|
|
|
|
|
1325
|
my $is_makernote = ($tag =~ $MAKERNOTE_TAG); |
165
|
392
|
|
|
|
|
818
|
my $extended_dirnames = $dirnames.'@'.$$mapping{$tag}; |
166
|
|
|
|
|
|
|
# MakerNotes require a special treatment, including rewriting |
167
|
|
|
|
|
|
|
# type and count (one LONG is really many UNDEF bytes); other |
168
|
|
|
|
|
|
|
# subIFD's are written by a recursive dump_ifd (next link is 0). |
169
|
392
|
100
|
|
|
|
1413
|
my $subifd = $is_makernote ? |
170
|
|
|
|
|
|
|
$this->dump_makernote($extended_dirnames, $remote) : |
171
|
|
|
|
|
|
|
$this->dump_ifd($extended_dirnames, $remote, 1); |
172
|
392
|
100
|
|
|
|
879
|
$type = $UNDEF, $count = length($$subifd) if $is_makernote; |
173
|
392
|
|
|
|
|
722
|
$record_end = pack $long, $remote; |
174
|
392
|
|
|
|
|
581
|
$extra .= $$subifd; $remote += length $$subifd; } |
|
392
|
|
|
|
|
662
|
|
175
|
|
|
|
|
|
|
# if the data length is not larger than four bytes, we are ok. |
176
|
|
|
|
|
|
|
# $$dataref is simply appended (with padding up to 4 bytes, |
177
|
|
|
|
|
|
|
# AFTER $$dataref, independently of the IFD endianness). |
178
|
3485
|
|
|
|
|
5219
|
elsif ($length <= 4) { $record_end = $$dataref . "\000"x(4-$length); } |
179
|
|
|
|
|
|
|
# if $$dataref is too big, it must be packed in the $extra |
180
|
|
|
|
|
|
|
# section, and its pointer appended here. Remember to update |
181
|
|
|
|
|
|
|
# $remote for the next record of this type. |
182
|
3294
|
|
|
|
|
4312
|
else { $record_end = pack $long, $remote; |
183
|
3294
|
|
|
|
|
2804
|
$remote += $length; $extra .= $$dataref; } |
|
3294
|
|
|
|
|
3400
|
|
184
|
|
|
|
|
|
|
# the interoperability array starts with tag, type and count, |
185
|
|
|
|
|
|
|
# followed by $record_end (4 bytes): dump into the ifd data area |
186
|
7243
|
|
|
|
|
16392
|
$ifd_content .= (pack $format, $tag, $type, $count) . $record_end; } |
187
|
|
|
|
|
|
|
# after the Interop. arrays there can be a link to the next IFD |
188
|
|
|
|
|
|
|
# (this takes 4 bytes). $next = 0 --> write the next IFD offset, |
189
|
|
|
|
|
|
|
# = 1 --> write zero, 2 --> do not write these four bytes. |
190
|
575
|
100
|
|
|
|
1096
|
$ifd_content .= pack $long, $remote if $next == 0; |
191
|
575
|
100
|
|
|
|
1241
|
$ifd_content .= pack $long, 0 if $next == 1; |
192
|
|
|
|
|
|
|
# then, we save the remote data area |
193
|
575
|
|
|
|
|
2034
|
$ifd_content .= $extra; |
194
|
|
|
|
|
|
|
# if the thumbnail offset tags were found during the scan, we |
195
|
|
|
|
|
|
|
# need to overwrite their values with a meaningful offset now. |
196
|
575
|
|
|
|
|
1318
|
for (keys %th_tags) { |
197
|
1150
|
100
|
|
|
|
2354
|
next unless my $overwrite = $th_tags{$_}; |
198
|
72
|
|
|
|
|
244
|
my $tag_record = $this->search_record($_, $dirref); |
199
|
72
|
|
|
|
|
187
|
$tag_record->set_value($remote); |
200
|
72
|
|
|
|
|
218
|
my $new_offset = $tag_record->get($this->{endianness}); |
201
|
72
|
|
|
|
|
262
|
substr($ifd_content, $overwrite, length $new_offset) = $new_offset; } |
202
|
|
|
|
|
|
|
# return a reference to the scalar which holds the binary dump |
203
|
|
|
|
|
|
|
# of this IFD (to be saved in the caller routine, I think). |
204
|
575
|
|
|
|
|
3067
|
return \$ifd_content; |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
|
207
|
|
|
|
|
|
|
########################################################### |
208
|
|
|
|
|
|
|
# This routine dumps all kinds of makernotes. Have a look # |
209
|
|
|
|
|
|
|
# at parse_makernote() for further details. # |
210
|
|
|
|
|
|
|
########################################################### |
211
|
|
|
|
|
|
|
sub dump_makernote { |
212
|
87
|
|
|
87
|
0
|
154
|
my ($this, $dirnames, $offset) = @_; |
213
|
|
|
|
|
|
|
# look for a MakerNote subdirectory beginning with $dirnames: the |
214
|
|
|
|
|
|
|
# actual name has the format appended, e.g., MakerNoteData_Canon. |
215
|
87
|
|
|
|
|
757
|
$dirnames =~ s/(.*@|)([^@]*)/$1/; |
216
|
87
|
|
|
|
|
266
|
my $dirref = $this->search_record_value($dirnames); |
217
|
2201
|
|
|
|
|
4861
|
$dirnames .= $_->{key}, $dirref = $_->get_value(), last |
218
|
87
|
|
|
|
|
184
|
for (grep{$_->{key}=~/^$2/} @$dirref); |
219
|
|
|
|
|
|
|
# Also look for the subdir with special information. |
220
|
87
|
|
|
|
|
336
|
my $spcref = $this->search_record_value($dirnames.'@special'); |
221
|
|
|
|
|
|
|
# entering here without the dir and its subdir being present is an error |
222
|
87
|
50
|
33
|
|
|
463
|
$this->die('MakerNote subdirs not found') unless $dirref && $spcref; |
223
|
|
|
|
|
|
|
# read all MakerNote special values (added by the parser routine) |
224
|
435
|
|
|
|
|
849
|
my ($data, $signature, $endianness, $format, $error) = |
225
|
87
|
|
|
|
|
198
|
map { $this->search_record_value($_, $spcref) } |
226
|
|
|
|
|
|
|
('ORIGINAL', 'SIGNATURE', 'ENDIANNESS', 'FORMAT', 'ERROR'); |
227
|
|
|
|
|
|
|
# die and debug if the format record is not present |
228
|
87
|
50
|
|
|
|
256
|
$this->die('FORMAT not found') unless $format; |
229
|
|
|
|
|
|
|
# if the format is unknown or there was an error at parse time, it |
230
|
|
|
|
|
|
|
# is wiser to return the original, unparsed content of the MakerNote |
231
|
87
|
100
|
100
|
|
|
478
|
if ($format =~ /unknown/ || defined $error) { |
232
|
2
|
50
|
|
|
|
6
|
$this->die('ORIGINAL data not found') unless $data; return \$data; }; |
|
2
|
|
|
|
|
5
|
|
233
|
|
|
|
|
|
|
# also extract the property table for this MakerNote format |
234
|
85
|
|
|
|
|
256
|
my $hash = $$HASH_MAKERNOTES{$format}; |
235
|
|
|
|
|
|
|
# now, die if the signature or endianness is still undefined |
236
|
85
|
50
|
33
|
|
|
398
|
$this->die('Properties not found')unless defined $signature && $endianness; |
237
|
|
|
|
|
|
|
# in general, the MakerNote's next-IFD link is zero, but some |
238
|
|
|
|
|
|
|
# MakerNotes do not even have these four bytes: prepare the flag |
239
|
85
|
50
|
|
|
|
259
|
my $next_flag = exists $$hash{nonext} ? 2 : 1; |
240
|
|
|
|
|
|
|
# in general, MakerNote's offsets are computed from the APP1 segment |
241
|
|
|
|
|
|
|
# TIFF base; however, some formats compute offsets from the beginning |
242
|
|
|
|
|
|
|
# of the MakerNote itself: setup the offset base as required. |
243
|
85
|
100
|
|
|
|
263
|
$offset = length($signature) + (exists $$hash{mkntstart} ? 0 : $offset); |
244
|
|
|
|
|
|
|
# initialise the data area with the detected signature |
245
|
85
|
|
|
|
|
131
|
$data = $signature; |
246
|
|
|
|
|
|
|
# some MakerNotes have a TIFF header on their own, freeing them |
247
|
|
|
|
|
|
|
# from the relocation problem; values from this header overwrite |
248
|
|
|
|
|
|
|
# the previously assigned values; records are saved in $mknt_dir. |
249
|
85
|
100
|
|
|
|
274
|
if (exists $$hash{mkntTIFF}) { |
250
|
1
|
|
|
|
|
3
|
my ($TIFF_header, $TIFF_offset, $TIFF_endianness) |
251
|
|
|
|
|
|
|
= $this->dump_TIFF_header($spcref); |
252
|
1
|
50
|
|
|
|
4
|
$this->die('Endianness mismatch') if $endianness ne $TIFF_endianness; |
253
|
1
|
|
|
|
|
2
|
$data .= $TIFF_header; $offset = $TIFF_offset; } |
|
1
|
|
|
|
|
1
|
|
254
|
|
|
|
|
|
|
# Unstructured case: the content of the MakerNote is simply |
255
|
|
|
|
|
|
|
# a sequence of bytes, which must be encoded using $$hash{tags} |
256
|
85
|
100
|
|
|
|
240
|
if (exists $$hash{nonIFD}) { |
257
|
3608
|
|
|
|
|
4488
|
$data .= $this->search_record($$_[0], $dirref)->get($endianness) |
258
|
82
|
|
|
|
|
121
|
for map {$$hash{tags}{$_}} sort {$a <=> $b} keys %{$$hash{tags}}; } |
|
15335
|
|
|
|
|
11384
|
|
|
82
|
|
|
|
|
1120
|
|
259
|
|
|
|
|
|
|
# Structured case: the content of the MakerNote can be dumped |
260
|
|
|
|
|
|
|
# with dump_ifd (change locally the endianness value). |
261
|
3
|
|
|
|
|
7
|
else { local $this->{endianness} = $endianness; |
262
|
3
|
|
|
|
|
5
|
$data .= ${$this->dump_ifd($dirnames, $offset, $next_flag)} }; |
|
3
|
|
|
|
|
12
|
|
263
|
|
|
|
|
|
|
# return the MakerNote as a binary object |
264
|
85
|
|
|
|
|
959
|
return \$data; |
265
|
|
|
|
|
|
|
} |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
# successful load |
268
|
|
|
|
|
|
|
1; |