File Coverage

blib/lib/Image/MetaData/JPEG/parsers/app1_exif.pl
Criterion Covered Total %
statement 141 141 100.0
branch 79 94 84.0
condition 8 14 57.1
subroutine 10 10 100.0
pod 0 6 0.0
total 238 265 89.8


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;