| 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 |  | 90 | use Image::MetaData::JPEG::data::Tables qw(:TagsAPP1_Exif); | 
|  | 15 |  |  |  |  | 36 |  | 
|  | 15 |  |  |  |  | 2884 |  | 
| 7 | 15 |  |  | 15 |  | 102 | no  integer; | 
|  | 15 |  |  |  |  | 43 |  | 
|  | 15 |  |  |  |  | 140 |  | 
| 8 | 15 |  |  | 15 |  | 381 | use strict; | 
|  | 15 |  |  |  |  | 32 |  | 
|  | 15 |  |  |  |  | 429 |  | 
| 9 | 15 |  |  | 15 |  | 116 | use warnings; | 
|  | 15 |  |  |  |  | 33 |  | 
|  | 15 |  |  |  |  | 37873 |  | 
| 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 | 135 | 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 |  |  |  |  | 395 | my $identifier = $this->store_record | 
| 67 |  |  |  |  |  |  | ('Identifier', $ASCII, 0, length $APP1_EXIF_TAG)->get_value(); | 
| 68 | 63 | 50 |  |  |  | 240 | $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 |  |  |  |  | 314 | 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 |  |  |  |  | 163 | my $ifd0_offset = $tiff_base + $ifd0_link; | 
| 76 |  |  |  |  |  |  | # locally set the current endianness to what we have found | 
| 77 | 63 |  |  |  |  | 200 | 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 |  |  |  |  | 340 | 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 |  |  |  | 304 | 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 |  |  |  | 333 | $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 |  |  |  |  | 321 | my $th_type = $this->search_record_value('IFD1', $APP1_TH_TYPE); | 
| 96 | 63 | 100 |  |  |  | 863 | if (defined $th_type) { | 
| 97 |  |  |  |  |  |  | # thumbnail type should be either TIFF or JPEG. Die if not known | 
| 98 | 32 | 50 | 33 |  |  | 302 | $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 |  |  |  |  | 394 | my ($thumb_link, $thumb_size) = | 
| 102 | 32 | 50 |  |  |  | 153 | 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 |  |  |  | 132 | goto END_THUMBNAIL unless defined $thumb_link; | 
| 111 |  |  |  |  |  |  | # point the current offset to the thumbnail | 
| 112 | 32 |  |  |  |  | 84 | 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 |  |  |  |  | 133 | my $remaining = $this->size() - $offset; | 
| 118 | 32 | 100 |  |  |  | 149 | 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 |  |  |  |  | 18 | $this->warn("Predicted thumbnail size ($thumb_size) larger than " | 
| 122 |  |  |  |  |  |  | . "available data size ($remaining). Correcting ..."); | 
| 123 | 1 |  |  |  |  | 13 | $thumb_size = $remaining; } | 
| 124 |  |  |  |  |  |  | # store the thumbnail (if present) | 
| 125 | 32 | 50 |  |  |  | 220 | $this->store_record('ThumbnailData', $UNDEF, $offset, $thumb_size) | 
| 126 |  |  |  |  |  |  | if $thumb_size > 0; | 
| 127 |  |  |  |  |  |  | END_THUMBNAIL: | 
| 128 | 32 |  |  |  |  | 269 | } | 
| 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 | 188 | my ($this, $offset, $dirref) = @_; | 
| 161 |  |  |  |  |  |  | # die if the $offset is undefined | 
| 162 | 67 | 50 |  |  |  | 279 | $this->die('Undefined offset') unless defined $offset; | 
| 163 |  |  |  |  |  |  | # set the subdir reference to the root if it is undefined | 
| 164 | 67 | 100 |  |  |  | 259 | $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 |  |  |  |  | 328 | $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 |  |  |  |  | 174 | 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 |  |  |  |  | 310 | my $endianness = $this->store_record | 
| 174 |  |  |  |  |  |  | ($dirref, 'Endianness', $UNDEF, $offset, 2)->get_value(); | 
| 175 | 67 | 50 | 66 |  |  | 376 | $this->die("Unknown endianness ($endianness)") | 
| 176 |  |  |  |  |  |  | if $endianness ne $BIG_ENDIAN && $endianness ne $LITTLE_ENDIAN; | 
| 177 |  |  |  |  |  |  | # change (locally) the endianness value | 
| 178 | 67 |  |  |  |  | 345 | local $this->{endianness} = $endianness; | 
| 179 |  |  |  |  |  |  | # decode the signature (42, i.e. 0x002a), die if it is unknown | 
| 180 | 67 |  |  |  |  | 287 | my $signature = $this->store_record | 
| 181 |  |  |  |  |  |  | ($dirref, 'Signature', $SHORT, $offset)->get_value(); | 
| 182 | 67 | 50 |  |  |  | 267 | $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 |  |  |  |  | 364 | my $ifd0_link = $this->read_record($LONG, $offset); | 
| 187 |  |  |  |  |  |  | # return all relevant values in a list | 
| 188 | 67 |  |  |  |  | 549 | 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 | 1619 | my ($this, $dirnames, $offset, $base, $next, $use_prediction) = @_; | 
| 241 |  |  |  |  |  |  | # if $offset is undefined, return immediately | 
| 242 | 239 | 50 |  |  |  | 754 | return unless defined $offset; | 
| 243 |  |  |  |  |  |  | # if next is undefined, set it to zero | 
| 244 | 239 | 100 |  |  |  | 668 | $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 |  |  |  |  | 945 | 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 |  |  |  |  | 1574 | 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 |  |  |  | 694 | my $remote = $offset + 12*$records; $remote += 4 if $next < 2; | 
|  | 239 |  |  |  |  | 624 |  | 
| 255 | 239 |  |  |  |  | 580 | 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 |  |  |  |  | 3254 | ($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 |  |  |  | 1932 | 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 |  |  | 2076 | $this->warn("next link not zero") if $next && $next_link; | 
| 267 |  |  |  |  |  |  | # take care of possible subdirectories | 
| 268 | 232 |  |  |  |  | 1450 | $this->parse_ifd_children($dirnames, $base, $offset); | 
| 269 |  |  |  |  |  |  | # return the next IFD link | 
| 270 | 232 |  |  |  |  | 991 | 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 | 607 | my ($this, $dirnames, $base, $old_offset) = @_; | 
| 298 |  |  |  |  |  |  | # retrieve the record list of the "parent" IFD | 
| 299 | 232 |  |  |  |  | 1115 | 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 |  |  |  |  | 1231 | 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 |  |  |  | 1028 | if (exists $IFD_SUBDIRS{$path}) { | 
| 306 | 226 |  |  |  |  | 758 | my $mapping = $IFD_SUBDIRS{$path}; | 
| 307 |  |  |  |  |  |  | # $tag is a numerical value, not a string | 
| 308 | 226 |  |  |  |  | 1824 | foreach my $tag (sort keys %$mapping) { | 
| 309 |  |  |  |  |  |  | # don't parse if there is no such subdirectory | 
| 310 | 680 | 100 |  |  |  | 2362 | next unless (my $record = $this->search_record($tag, $dirref)); | 
| 311 |  |  |  |  |  |  | # get the name and location of this secondary IFD | 
| 312 | 170 |  |  |  |  | 828 | my $new_dirnames = join '@', $dirnames, $$mapping{$tag}; | 
| 313 | 170 |  |  |  |  | 858 | 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 |  |  |  | 597 | $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 |  |  |  |  | 3000 | my @common = ($new_dirnames, $new_offset, $base); | 
| 320 | 170 | 100 |  |  |  | 1740 | $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 |  |  |  |  | 746 | $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 |  |  |  |  | 844 | $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 |  |  |  | 660 | @$dirref = grep { ! $_->{extra} || $_->{extra} ne "deleteme" } @$dirref; | 
|  | 2749 |  |  |  |  | 9112 |  | 
| 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 | 5162 | my ($this, $offset, $offset_base, $dirref, $pred) = @_; | 
| 370 |  |  |  |  |  |  | # the data area must be at least 12 bytes wide | 
| 371 | 2652 |  |  |  |  | 7897 | $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 |  |  |  |  | 8385 | my $tag     = $this->read_record($SHORT, $offset); | 
| 376 | 2652 |  |  |  |  | 12587 | my $type    = $this->read_record($SHORT, $offset); | 
| 377 | 2652 |  |  |  |  | 18300 | my $count   = $this->read_record($LONG , $offset); | 
| 378 | 2652 |  |  |  |  | 12302 | 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 |  |  |  | 10186 | $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 |  |  |  |  | 9150 | 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 |  |  |  | 5506 | $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 |  |  |  | 5691 | $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 |  |  |  | 5035 | if ($size > 4) { | 
| 400 | 1119 | 100 |  |  |  | 2317 | if ($$pred[0]) { | 
| 401 | 17 | 100 |  |  |  | 50 | my $jump = defined $$pred[2] ? ($doffset - $$pred[2]) : 0; | 
| 402 | 17 |  |  |  |  | 25 | $$pred[1]+=$jump; ($$pred[2], $doffset) = ($doffset, $$pred[1]); } | 
|  | 17 |  |  |  |  | 41 |  | 
| 403 | 1102 | 100 |  |  |  | 2786 | 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 |  |  |  |  | 10145 | $this->test_size($doffset + $size, 'Interop. array data area not found'); | 
| 407 |  |  |  |  |  |  | # insert the Interoperability array value into its sub-directory | 
| 408 | 2601 |  |  |  |  | 9917 | $this->store_record($dirref, $tag, $type, $doffset, $count); | 
| 409 |  |  |  |  |  |  | # return the updated $offset | 
| 410 | 2645 |  |  |  |  | 14081 | 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 | 143 | 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 |  |  |  | 501 | $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 |  |  |  |  | 326 | my $ifd0 = $this->search_record_value('IFD0'); | 
| 437 | 44 |  | 50 |  |  | 311 | 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 |  |  |  |  | 439 | my $mknt_found = undef; | 
| 441 | 44 |  |  |  |  | 885 | for my $format (sort keys %$HASH_MAKERNOTES) { | 
| 442 |  |  |  |  |  |  | # this quest must stop at the first positive match | 
| 443 | 1276 | 100 |  |  |  | 2571 | 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 |  |  |  |  | 1011 | my $hash = $$HASH_MAKERNOTES{$format}; | 
| 447 | 514 | 100 |  |  |  | 1337 | next if exists $$hash{ignore}; | 
| 448 |  |  |  |  |  |  | # get the maker and signature for this format | 
| 449 | 443 |  |  |  |  | 965 | my $format_signature = $$hash{signature}; | 
| 450 | 443 |  |  |  |  | 735 | 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 |  |  |  | 850 | my $incipit_size = $mknt_size < 50 ? $mknt_size : 50; | 
| 455 | 443 |  |  |  |  | 1743 | my $incipit = $this->read_record($UNDEF, 0+$mknt_offset,$incipit_size); | 
| 456 | 443 | 100 |  |  |  | 6557 | next unless $mknt_maker =~ /$format_maker/; | 
| 457 | 49 | 100 |  |  |  | 985 | next unless $incipit =~ /$format_signature/; | 
| 458 | 44 |  |  |  |  | 219 | my $signature = $1; my $skip = length $signature; | 
|  | 44 |  |  |  |  | 131 |  | 
| 459 |  |  |  |  |  |  | # OK, we opted for this format | 
| 460 | 44 |  |  |  |  | 105 | $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 |  |  |  |  | 264 | my $mknt_dirname = $dirnames.'_'.$format; | 
| 464 | 44 |  |  |  |  | 279 | my $mknt_dir     = $this->provide_subdirectory($mknt_dirname); | 
| 465 |  |  |  |  |  |  | # prepare also a special subdirectory for pseudofields | 
| 466 | 44 |  |  |  |  | 198 | my $mknt_spcname = $mknt_dirname.'@special'; | 
| 467 | 44 |  |  |  |  | 177 | 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 |  |  |  |  | 240 | my $it_looks_big_endian = $this->data($mknt_offset+$skip, 1) eq "\000"; | 
| 472 | 44 | 100 |  |  |  | 270 | 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 |  |  |  | 215 | 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 |  |  |  | 182 | 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 |  |  |  | 174 | if (exists $$hash{mkntTIFF}) { | 
| 485 | 2 |  |  |  |  | 13 | ($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 |  |  |  |  | 6 | $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 |  |  |  |  | 125 | 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 |  |  |  |  | 482 | for (['ORIGINAL'  , $mknt_offset, $mknt_size], | 
| 497 |  |  |  |  |  |  | ['SIGNATURE' , \$signature], | 
| 498 |  |  |  |  |  |  | ['ENDIANNESS', \$mknt_endianness], | 
| 499 |  |  |  |  |  |  | ['FORMAT'    , \$format]); | 
| 500 |  |  |  |  |  |  | # change locally the endianness value | 
| 501 | 44 |  |  |  |  | 229 | 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 |  |  |  | 201 | if (exists $$hash{nonIFD}) { eval { | 
|  | 36 |  |  |  |  | 78 |  | 
| 506 | 36 |  |  |  |  | 103 | my $p = $$hash{tags}; | 
| 507 | 1452 |  |  |  |  | 3034 | $this->store_record($mknt_dir, @$_[0,1], $data_offset, $$_[2]) | 
| 508 | 36 |  |  |  |  | 806 | for map { $$p{$_} } sort { $a <=> $b } keys %$p; | 
|  | 6303 |  |  |  |  | 10559 |  | 
| 509 | 36 | 50 | 66 |  |  | 1103 | $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 |  |  |  |  | 21 | my $args = [$mknt_dirname, $data_offset, $mknt_base, $next_flag]; | 
| 518 | 8 |  |  |  |  | 16 | my $code = '@$mknt_dir=@$copy; $this->parse_ifd(@$args'; | 
| 519 | 8 |  |  |  |  | 23 | my $copy = [@$mknt_dir]; eval "$code)"; | 
|  | 8 |  |  |  |  | 1383 |  | 
| 520 | 8 | 100 |  |  |  | 169 | $this->warn('Using predictions'), eval "$code,1)" if $@; | 
| 521 | 8 | 100 |  |  |  | 154 | $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 |  |  |  | 742 | $this->store_record($mknt_spc, 'ERROR',$ASCII,\$@) if $@; | 
| 527 |  |  |  |  |  |  | # print "MESSAGE FROM MAKERNOTE:\n$@\n" if $@; | 
| 528 |  |  |  |  |  |  | } | 
| 529 |  |  |  |  |  |  | } | 
| 530 |  |  |  |  |  |  |  | 
| 531 |  |  |  |  |  |  | # successful load | 
| 532 |  |  |  |  |  |  | 1; |