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
|
|
|
|
|
|
|
#use 5.008; |
7
|
|
|
|
|
|
|
package Image::MetaData::JPEG; |
8
|
14
|
|
|
14
|
|
124961
|
use Image::MetaData::JPEG::data::Tables qw(:JPEGgrammar); |
|
14
|
|
|
|
|
32
|
|
|
14
|
|
|
|
|
2698
|
|
9
|
14
|
|
|
14
|
|
5483
|
use Image::MetaData::JPEG::Backtrace; |
|
14
|
|
|
|
|
21
|
|
|
14
|
|
|
|
|
371
|
|
10
|
14
|
|
|
14
|
|
5974
|
use Image::MetaData::JPEG::Segment; |
|
14
|
|
|
|
|
36
|
|
|
14
|
|
|
|
|
422
|
|
11
|
14
|
|
|
14
|
|
65
|
no integer; |
|
14
|
|
|
|
|
13
|
|
|
14
|
|
|
|
|
44
|
|
12
|
14
|
|
|
14
|
|
214
|
use strict; |
|
14
|
|
|
|
|
18
|
|
|
14
|
|
|
|
|
276
|
|
13
|
14
|
|
|
14
|
|
44
|
use warnings; |
|
14
|
|
|
|
|
16
|
|
|
14
|
|
|
|
|
25698
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
our $VERSION = '0.159'; |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
########################################################### |
18
|
|
|
|
|
|
|
# These simple methods should be used instead of standard # |
19
|
|
|
|
|
|
|
# "warn" and "die" in this package; they print a much # |
20
|
|
|
|
|
|
|
# more elaborated error message (including a stack trace).# |
21
|
|
|
|
|
|
|
# Warnings can be turned off altogether simply by setting # |
22
|
|
|
|
|
|
|
# Image::MetaData::JPEG::show_warnings to false. # |
23
|
|
|
|
|
|
|
########################################################### |
24
|
5
|
|
|
5
|
0
|
7
|
sub warn { my ($this, $message) = @_; |
25
|
5
|
100
|
|
|
|
20
|
warn Image::MetaData::JPEG::Backtrace::backtrace |
26
|
|
|
|
|
|
|
($message, "Warning" . $this->info(), $this) |
27
|
|
|
|
|
|
|
if $Image::MetaData::JPEG::show_warnings; } |
28
|
17
|
|
|
17
|
0
|
22
|
sub die { my ($this, $message) = @_; |
29
|
17
|
|
|
|
|
41
|
die Image::MetaData::JPEG::Backtrace::backtrace |
30
|
|
|
|
|
|
|
($message, "Fatal error" . $this->info(), $this); } |
31
|
21
|
|
|
21
|
0
|
23
|
sub info { my ($this) = @_; |
32
|
21
|
|
100
|
|
|
50
|
my $filename = $this->{filename} || ''; |
33
|
21
|
|
|
|
|
105
|
return " [file $filename]"; } |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
########################################################### |
36
|
|
|
|
|
|
|
# Constructor for a JPEG file structure object, accepting # |
37
|
|
|
|
|
|
|
# a "JPEG stream". It parses the file stream and stores # |
38
|
|
|
|
|
|
|
# its sections internally. An optional parameter can ex- # |
39
|
|
|
|
|
|
|
# clude parsing and even storing for some segments. The # |
40
|
|
|
|
|
|
|
# stream can be specified in two ways: # |
41
|
|
|
|
|
|
|
# - [a scalar] interpreted as a file name to be opened; # |
42
|
|
|
|
|
|
|
# - [a scalar reference] interpreted as a pointer to an # |
43
|
|
|
|
|
|
|
# in-memory buffer containing a JPEG stream; # |
44
|
|
|
|
|
|
|
# ------------------------------------------------------- # |
45
|
|
|
|
|
|
|
# There is now a second argument, $regex. This string is # |
46
|
|
|
|
|
|
|
# matched against segment names, and only those segments # |
47
|
|
|
|
|
|
|
# with a positive match are parsed. This allows for some # |
48
|
|
|
|
|
|
|
# speed-up if you just need partial information. For # |
49
|
|
|
|
|
|
|
# instance, if you just want to manipulate the comments, # |
50
|
|
|
|
|
|
|
# you could use $regex equal to 'COM'. If $regex is unde- # |
51
|
|
|
|
|
|
|
# fined, all segments are matched. # |
52
|
|
|
|
|
|
|
# ------------------------------------------------------- # |
53
|
|
|
|
|
|
|
# There is now a third optional argument, $options. If it # |
54
|
|
|
|
|
|
|
# matches the string 'FASTREADONLY', only those segments # |
55
|
|
|
|
|
|
|
# matching $regex are actually stored; also, everything # |
56
|
|
|
|
|
|
|
# which is found after a Start Of Scan is completely # |
57
|
|
|
|
|
|
|
# neglected. This allows for very large speed-ups, but, # |
58
|
|
|
|
|
|
|
# obviously, you cannot rebuild the file afterwards, so # |
59
|
|
|
|
|
|
|
# this is only for getting information fast (e.g., when # |
60
|
|
|
|
|
|
|
# doing a directory scan). # |
61
|
|
|
|
|
|
|
# ------------------------------------------------------- # |
62
|
|
|
|
|
|
|
# If an unrecoverable error occurs during the execution # |
63
|
|
|
|
|
|
|
# of the constructor, the undefined value is returned # |
64
|
|
|
|
|
|
|
# instead of the object reference, and a meaningful error # |
65
|
|
|
|
|
|
|
# message is set up (read it with Error()). # |
66
|
|
|
|
|
|
|
########################################################### |
67
|
|
|
|
|
|
|
sub new { |
68
|
71
|
|
|
71
|
1
|
117493
|
my ($pkg, $file_input, $regex, $options) = @_; |
69
|
71
|
|
|
|
|
477
|
my $this = bless { |
70
|
|
|
|
|
|
|
filename => undef, # private |
71
|
|
|
|
|
|
|
handle => undef, # private |
72
|
|
|
|
|
|
|
read_only => undef, # private |
73
|
|
|
|
|
|
|
segments => [], |
74
|
|
|
|
|
|
|
}, $pkg; |
75
|
|
|
|
|
|
|
# remember to unset the ctor error message |
76
|
71
|
|
|
|
|
237
|
$pkg->SetError(undef); |
77
|
|
|
|
|
|
|
# set the read-only flag if $options matches FASTREADONLY |
78
|
71
|
100
|
|
|
|
215
|
$this->{read_only} = $options =~ m/FASTREADONLY/ if $options; |
79
|
|
|
|
|
|
|
# execute the following subroutines in an eval block so that |
80
|
|
|
|
|
|
|
# errors can be treated without shutting down the caller. |
81
|
71
|
|
|
|
|
120
|
my $status = eval { $this->open_input($file_input); |
|
71
|
|
|
|
|
235
|
|
82
|
69
|
|
|
|
|
309
|
$this->parse_segments($regex) ; }; |
83
|
|
|
|
|
|
|
# close the file handle, if open |
84
|
71
|
|
|
|
|
372
|
$this->close_input(); |
85
|
|
|
|
|
|
|
# If an error was found (and it triggered a die call) |
86
|
|
|
|
|
|
|
# we must set the appropriate error variable here |
87
|
71
|
50
|
|
|
|
621
|
$pkg->SetError($@) unless $status; |
88
|
|
|
|
|
|
|
# return the object reference (undef if an error occurred) |
89
|
71
|
100
|
|
|
|
219
|
return $this->Error() ? undef : $this; |
90
|
|
|
|
|
|
|
} |
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
########################################################### |
93
|
|
|
|
|
|
|
# This block declares a private variable containing a # |
94
|
|
|
|
|
|
|
# meaningful error message for problems during the class # |
95
|
|
|
|
|
|
|
# constructor. The two following methods allow reading # |
96
|
|
|
|
|
|
|
# and setting the value of this variable. # |
97
|
|
|
|
|
|
|
########################################################### |
98
|
|
|
|
|
|
|
{ my $ctor_error_message = undef; |
99
|
75
|
|
100
|
75
|
1
|
72789
|
sub Error { return $ctor_error_message || undef; } |
100
|
142
|
|
|
142
|
0
|
299
|
sub SetError { $ctor_error_message = $_[1]; } |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
########################################################### |
104
|
|
|
|
|
|
|
# This method writes the data area of each segment in the # |
105
|
|
|
|
|
|
|
# current object to a disk file or a variable in memory. # |
106
|
|
|
|
|
|
|
# A disk file is written if $filename is a scalar with a # |
107
|
|
|
|
|
|
|
# valid file name; memory is instead used if $filename is # |
108
|
|
|
|
|
|
|
# a scalar reference. If $filename is undef, it defaults # |
109
|
|
|
|
|
|
|
# to the file originally used to create the current JPEG # |
110
|
|
|
|
|
|
|
# structure object. This method returns "true" (1) if it # |
111
|
|
|
|
|
|
|
# works, "false" (undef) otherwise. This call fails if # |
112
|
|
|
|
|
|
|
# the "read_only" member is set. # |
113
|
|
|
|
|
|
|
# ------------------------------------------------------- # |
114
|
|
|
|
|
|
|
# Remember that if you make changes to any segment, you # |
115
|
|
|
|
|
|
|
# should call update() for that particular segment before # |
116
|
|
|
|
|
|
|
# calling this method, otherwise the changes remain confi-# |
117
|
|
|
|
|
|
|
# ned to the internal structures of the segment (update() # |
118
|
|
|
|
|
|
|
# dumps them into the data area). Note that "high level" # |
119
|
|
|
|
|
|
|
# methods, like those in the JPEG_.pl files,# |
120
|
|
|
|
|
|
|
# are supposed to call update() on their own. # |
121
|
|
|
|
|
|
|
########################################################### |
122
|
|
|
|
|
|
|
sub save { |
123
|
26
|
|
|
26
|
1
|
7112
|
my ($this, $filename) = @_; |
124
|
|
|
|
|
|
|
# fail immediately if "read_only" is set |
125
|
26
|
100
|
|
|
|
129
|
return undef if $this->{read_only}; |
126
|
|
|
|
|
|
|
# if $filename is undefined, it defaults to the original name |
127
|
25
|
50
|
|
|
|
73
|
$filename = $this->{filename} unless defined $filename; |
128
|
|
|
|
|
|
|
# Open an IO handler for output on a file named $filename |
129
|
|
|
|
|
|
|
# or on an in-memory variable pointed to by $filename. |
130
|
|
|
|
|
|
|
# Use an indirect handler, which is closed authomatically |
131
|
|
|
|
|
|
|
# when it goes out of scope (so, no need to call close()). |
132
|
|
|
|
|
|
|
# If open fails, it returns false and sets the special |
133
|
|
|
|
|
|
|
# variable $! to reflect the system error. |
134
|
9
|
50
|
|
9
|
|
83
|
open(my $out, '>', $filename) || return undef; |
|
9
|
|
|
|
|
13
|
|
|
9
|
|
|
|
|
59
|
|
|
25
|
|
|
|
|
1782
|
|
135
|
|
|
|
|
|
|
# Legacy systems might need an explicit binary open. |
136
|
25
|
|
|
|
|
9148
|
binmode($out); |
137
|
|
|
|
|
|
|
# For each segment in the segment list, write the content of |
138
|
|
|
|
|
|
|
# the data area (including the preamble when needed) to the |
139
|
|
|
|
|
|
|
# IO handler. Save the results of each output for later testing. |
140
|
25
|
|
|
|
|
44
|
my @results = map { $_->output_segment_data($out) } @{$this->{segments}}; |
|
276
|
|
|
|
|
576
|
|
|
25
|
|
|
|
|
133
|
|
141
|
|
|
|
|
|
|
# return undef if any print failed, true otherwise |
142
|
25
|
50
|
|
|
|
66
|
return (scalar grep { ! $_ } @results) ? undef : 1; |
|
276
|
|
|
|
|
1043
|
|
143
|
|
|
|
|
|
|
} |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
########################################################### |
146
|
|
|
|
|
|
|
# This method takes care to open a file handle pointing # |
147
|
|
|
|
|
|
|
# to the JPEG object specified by $file_input. If the # |
148
|
|
|
|
|
|
|
# "file name" is a scalar reference instead, it is saved # |
149
|
|
|
|
|
|
|
# in the "handle" member (and it must be treated accor- # |
150
|
|
|
|
|
|
|
# dingly in the following). Nothing is actually read now; # |
151
|
|
|
|
|
|
|
# if opening fails, the routine dies with a message. # |
152
|
|
|
|
|
|
|
########################################################### |
153
|
|
|
|
|
|
|
sub open_input { |
154
|
71
|
|
|
71
|
0
|
119
|
my ($this, $file_input) = @_; |
155
|
|
|
|
|
|
|
# protect against undefined values |
156
|
71
|
100
|
|
|
|
239
|
$this->die('Undefined input') unless defined $file_input; |
157
|
|
|
|
|
|
|
# scalar references: save the reference in $this->{handle} |
158
|
|
|
|
|
|
|
# and save a self-explicatory string as file name |
159
|
70
|
100
|
|
|
|
234
|
if (ref $file_input eq 'SCALAR') { |
160
|
26
|
|
|
|
|
57
|
$this->{handle} = $file_input; |
161
|
26
|
|
|
|
|
61
|
$this->{filename} = '[in-memory JPEG stream]'; } |
162
|
|
|
|
|
|
|
# real file: we need to open the file and complain if this is |
163
|
|
|
|
|
|
|
# not possible (legacy systems might need an explicity binary |
164
|
|
|
|
|
|
|
# open); then, the file name of the original file is saved. |
165
|
|
|
|
|
|
|
else { |
166
|
44
|
100
|
|
|
|
2324
|
open($this->{handle}, '<', $file_input) || |
167
|
|
|
|
|
|
|
$this->die("Open error on $file_input: $!"); |
168
|
43
|
|
|
|
|
153
|
binmode($this->{handle}); |
169
|
43
|
|
|
|
|
187
|
$this->{filename} = $file_input; } |
170
|
|
|
|
|
|
|
} |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
########################################################### |
173
|
|
|
|
|
|
|
# This method is the counterpart of "open". Actually, it # |
174
|
|
|
|
|
|
|
# does something only for real files (because we do not # |
175
|
|
|
|
|
|
|
# want to close in-memory scalars ....). # |
176
|
|
|
|
|
|
|
########################################################### |
177
|
|
|
|
|
|
|
sub close_input { |
178
|
71
|
|
|
71
|
0
|
121
|
my ($this) = @_; |
179
|
|
|
|
|
|
|
# $this->{handle} should really be a reference to something |
180
|
71
|
100
|
|
|
|
247
|
return unless ref $this->{handle}; |
181
|
|
|
|
|
|
|
# a ref to a scalar: we do not want to close in-memory scalars |
182
|
70
|
100
|
|
|
|
252
|
return if ref $this->{handle} eq 'SCALAR'; |
183
|
|
|
|
|
|
|
# the default action corresponds to closing the filehandle |
184
|
44
|
|
|
|
|
2507
|
close $this->{handle}; |
185
|
|
|
|
|
|
|
} |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
########################################################### |
188
|
|
|
|
|
|
|
# This method returns a portion of the input file (speci- # |
189
|
|
|
|
|
|
|
# fied by $offset and $length). It is necessary to mask # |
190
|
|
|
|
|
|
|
# how data reading is actually implemented. As usual, it # |
191
|
|
|
|
|
|
|
# dies on errors (but this is trapped in the constructor).# |
192
|
|
|
|
|
|
|
# This method returns a scalar reference; if $offset is # |
193
|
|
|
|
|
|
|
# just "LENGTH", the input length is returned instead. # |
194
|
|
|
|
|
|
|
# A length <= 0 is ignored (ref to empty string). # |
195
|
|
|
|
|
|
|
########################################################### |
196
|
|
|
|
|
|
|
sub get_data { |
197
|
4229
|
|
|
4229
|
0
|
3763
|
my ($this, $offset, $length) = @_; |
198
|
|
|
|
|
|
|
# a shorter name for the file handle |
199
|
4229
|
|
|
|
|
3814
|
my $handle = $this->{handle}; |
200
|
|
|
|
|
|
|
# understand if this is a file or a scalar reference |
201
|
4229
|
|
|
|
|
4205
|
my $is_file = ref $handle eq 'GLOB'; |
202
|
|
|
|
|
|
|
# if the first argument is just the string 'LENGTH', |
203
|
|
|
|
|
|
|
# return the input length instead |
204
|
4229
|
100
|
|
|
|
11345
|
return ($is_file ? -s $handle : length $$handle) if $offset eq 'LENGTH'; |
|
|
100
|
|
|
|
|
|
205
|
|
|
|
|
|
|
# this is the buffer to be returned at the end |
206
|
3401
|
|
|
|
|
3046
|
my $data = ''; |
207
|
|
|
|
|
|
|
# if length is <= zero return a reference to an empty string |
208
|
3401
|
100
|
|
|
|
5242
|
return \ $data if $length <= 0; |
209
|
|
|
|
|
|
|
# if we are dealing with a real file, we need to seek to the |
210
|
|
|
|
|
|
|
# requested position, then read the appropriate amount of data |
211
|
|
|
|
|
|
|
# (and throw an error if reading failed). |
212
|
3281
|
100
|
|
|
|
3425
|
if ($is_file) { |
213
|
2184
|
50
|
|
|
|
5420
|
seek($handle, $offset, 0) || |
214
|
|
|
|
|
|
|
$this->die("Error while seeking in $this->{filename}"); |
215
|
2184
|
|
|
|
|
10090
|
my $read = read $handle, $data, $length; |
216
|
2184
|
50
|
33
|
|
|
7449
|
$this->die("Read error in $this->{filename}") |
217
|
|
|
|
|
|
|
if ! defined $read || $read < $length; } |
218
|
|
|
|
|
|
|
# otherwise, we are dealing with a scalar reference, and |
219
|
|
|
|
|
|
|
# everything is much simpler (this can't fail, right?) |
220
|
1097
|
|
|
|
|
1978
|
else { $data = substr $$handle, $offset, $length; } |
221
|
|
|
|
|
|
|
# return a reference to read data |
222
|
3281
|
|
|
|
|
8200
|
return \ $data; |
223
|
|
|
|
|
|
|
} |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
########################################################### |
226
|
|
|
|
|
|
|
# This method searches for segments in the input JPEG. # |
227
|
|
|
|
|
|
|
# When a segment is found, the corresponding data area is # |
228
|
|
|
|
|
|
|
# read and used to create a segment object (the ctor of # |
229
|
|
|
|
|
|
|
# this object takes care to decode the relevant data). # |
230
|
|
|
|
|
|
|
# The object is then inserted into the "segments" hash, # |
231
|
|
|
|
|
|
|
# with a code-related key. Raw (compressed) image data # |
232
|
|
|
|
|
|
|
# are stored in "fake" segments, just for simplicity. # |
233
|
|
|
|
|
|
|
# ------------------------------------------------------- # |
234
|
|
|
|
|
|
|
# There is now an argument, set equal to the second argu- # |
235
|
|
|
|
|
|
|
# ment of the constructor. If it is defined, only match- # |
236
|
|
|
|
|
|
|
# ing segments are parsed. Also, if read_only is set, # |
237
|
|
|
|
|
|
|
# only "interesting" segments are saved and everything # |
238
|
|
|
|
|
|
|
# after the Start Of Scan is neglected. # |
239
|
|
|
|
|
|
|
#=========================================================# |
240
|
|
|
|
|
|
|
# Structure of a generic segment: # |
241
|
|
|
|
|
|
|
# 2 bytes segment marker (the first byte is always 0xff) # |
242
|
|
|
|
|
|
|
# 2 bytes segment_length (it doesn't include the marker) # |
243
|
|
|
|
|
|
|
# .... data (segment_length - 2 bytes) # |
244
|
|
|
|
|
|
|
#=========================================================# |
245
|
|
|
|
|
|
|
# The segment length (2 bytes) has a "Motorola" (big end- # |
246
|
|
|
|
|
|
|
# ian) endianness (byte alignement), that is it starts # |
247
|
|
|
|
|
|
|
# with the most significant digit. Note that the segment # |
248
|
|
|
|
|
|
|
# length marker counts its own length (i.e., after it # |
249
|
|
|
|
|
|
|
# there are only segment_length-2 bytes). # |
250
|
|
|
|
|
|
|
#=========================================================# |
251
|
|
|
|
|
|
|
# Some segments do not have data after them (not even the # |
252
|
|
|
|
|
|
|
# length field, they are pure markers): SOI, EOI and the # |
253
|
|
|
|
|
|
|
# RST? restart segments. Scans (started by a SOS segment) # |
254
|
|
|
|
|
|
|
# are followed by compressed data, with possibly inter- # |
255
|
|
|
|
|
|
|
# leaved RST segments: raw data must be searched with a # |
256
|
|
|
|
|
|
|
# dedicated routine because they are not envelopped. # |
257
|
|
|
|
|
|
|
#=========================================================# |
258
|
|
|
|
|
|
|
# Ref: "Digital compression and coding of continuous-tone # |
259
|
|
|
|
|
|
|
# still images: requirements and guidelines", # |
260
|
|
|
|
|
|
|
# CCITT, 09/1992, sec. B.1.1.4, pag. 33. # |
261
|
|
|
|
|
|
|
########################################################### |
262
|
|
|
|
|
|
|
sub parse_segments { |
263
|
69
|
|
|
69
|
0
|
122
|
my ($this, $regex) = @_; |
264
|
|
|
|
|
|
|
# prepare another hash to reverse the JPEG markers lookup |
265
|
69
|
|
|
|
|
12324
|
my %JPEG_MARKER_BY_CODE = reverse %JPEG_MARKER; |
266
|
|
|
|
|
|
|
# an offset in the input object, and a variable with its size |
267
|
69
|
|
|
|
|
613
|
my $offset = 0; |
268
|
69
|
|
|
|
|
230
|
my $isize = $this->get_data('LENGTH'); |
269
|
|
|
|
|
|
|
# don't claim empty files are valid JPEG pictures |
270
|
69
|
100
|
|
|
|
184
|
$this->die('Empty file') unless $isize; |
271
|
|
|
|
|
|
|
# loop on input data and find all of its segment |
272
|
68
|
|
|
|
|
237
|
while ($offset < $isize) { |
273
|
|
|
|
|
|
|
# search for the next JPEG marker, giving the segment type |
274
|
696
|
|
|
|
|
1429
|
(my $marker, $offset) = $this->get_next_marker($offset); |
275
|
|
|
|
|
|
|
# Die on unknown markers |
276
|
693
|
50
|
|
|
|
1560
|
$this->die(sprintf 'Unknown marker found: 0x%02x (offset $offset)', |
277
|
|
|
|
|
|
|
$marker) unless exists $JPEG_MARKER_BY_CODE{$marker}; |
278
|
|
|
|
|
|
|
# save the current offset (beginning of data) |
279
|
693
|
|
|
|
|
682
|
my $start = $offset; |
280
|
|
|
|
|
|
|
# calculate the name of the marker |
281
|
693
|
|
|
|
|
841
|
my $name = $JPEG_MARKER_BY_CODE{$marker}; |
282
|
|
|
|
|
|
|
# determine the parse flag |
283
|
693
|
100
|
100
|
|
|
2465
|
my $flag = ($regex && $name !~ /$regex/) ? 'NOPARSE' : undef; |
284
|
|
|
|
|
|
|
# SOI, EOI and ReSTart are dataless segments |
285
|
693
|
100
|
|
|
|
592
|
my $length = 0; goto DECODE_LENGTH_END if $name =~ /^RST|EOI|SOI/; |
|
693
|
|
|
|
|
2798
|
|
286
|
568
|
50
|
|
|
|
1051
|
DECODE_LENGTH_START: |
287
|
|
|
|
|
|
|
# we need at least two bytes here |
288
|
|
|
|
|
|
|
$this->die('Segment size not found') unless $isize > $offset + 2; |
289
|
|
|
|
|
|
|
# decode the length of this application block (2 bytes). |
290
|
|
|
|
|
|
|
# This is always in big endian ("Motorola") style, that |
291
|
|
|
|
|
|
|
# is the first byte is the most significant one. |
292
|
568
|
|
|
|
|
507
|
$length = unpack 'n', ${$this->get_data($offset, 2)}; |
|
568
|
|
|
|
|
818
|
|
293
|
|
|
|
|
|
|
# the segment length includes the two aforementioned |
294
|
|
|
|
|
|
|
# bytes, so the length must be at least two |
295
|
568
|
50
|
|
|
|
1113
|
$this->die('JPEG segment too small') if $length < 2; |
296
|
693
|
100
|
|
|
|
1228
|
DECODE_LENGTH_END: |
297
|
|
|
|
|
|
|
# we need at least $length bytes here |
298
|
|
|
|
|
|
|
$this->die('Segment data not found') unless $isize >= $offset+$length; |
299
|
|
|
|
|
|
|
# pass the data to a segment object and store it, unless |
300
|
|
|
|
|
|
|
# the "read_only" member is set and $flag is "NOPARSE". |
301
|
|
|
|
|
|
|
# (don't pass $flag to dataless segments, it is just silly). |
302
|
692
|
100
|
100
|
|
|
1685
|
push @{$this->{segments}}, new Image::MetaData::JPEG::Segment |
|
633
|
100
|
|
|
|
1598
|
|
303
|
|
|
|
|
|
|
($name, $this->get_data($start + 2, $length - 2), |
304
|
|
|
|
|
|
|
$length ? $flag : undef) unless $this->{read_only} && $flag; |
305
|
|
|
|
|
|
|
# update offset |
306
|
692
|
|
|
|
|
920
|
$offset += $length; |
307
|
|
|
|
|
|
|
# When you find a SOS marker or a RST marker there is a special |
308
|
|
|
|
|
|
|
# treatement; if "read_only" is set, we neglect the rest of the |
309
|
|
|
|
|
|
|
# input. Otherwise, we need a special routine |
310
|
692
|
100
|
|
|
|
2283
|
if ($name =~ /SOS|^RST/) { |
311
|
69
|
100
|
|
|
|
661
|
$offset = $isize, next if $this->{read_only}; |
312
|
63
|
|
|
|
|
189
|
$offset = $this->parse_ecs($offset); } |
313
|
|
|
|
|
|
|
DECODE_PAST_EOI_GARBAGE: |
314
|
|
|
|
|
|
|
# Try to intercept underground data stored after the EOI segment; |
315
|
|
|
|
|
|
|
# I have found images which store multiple reduced versions of |
316
|
|
|
|
|
|
|
# itself after the EOI segment, as well as undocumented binary |
317
|
|
|
|
|
|
|
# and ascii data. Save them in a pseudo-segment, so that they |
318
|
|
|
|
|
|
|
# can be restored (take "read_only" into account). |
319
|
686
|
100
|
100
|
|
|
4135
|
if ($name eq 'EOI' && $offset < $isize) { |
320
|
38
|
|
|
|
|
69
|
my $len = $isize - $offset; |
321
|
38
|
50
|
|
|
|
110
|
push @{$this->{segments}}, new Image::MetaData::JPEG::Segment |
|
38
|
|
|
|
|
112
|
|
322
|
|
|
|
|
|
|
('Post-EOI', $this->get_data($offset, $len), 'NOPARSE') |
323
|
|
|
|
|
|
|
unless $this->{read_only}; |
324
|
38
|
|
|
|
|
3055
|
$offset += $len; |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
} |
327
|
|
|
|
|
|
|
} |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
########################################################### |
330
|
|
|
|
|
|
|
# This method searches for the next JPEG marker in the # |
331
|
|
|
|
|
|
|
# stream being parsed. A marker is always assigned a two # |
332
|
|
|
|
|
|
|
# byte code: an 0xff byte followed by a byte which is not # |
333
|
|
|
|
|
|
|
# 0x00 nor 0xff. Any marker may optionally be preceeded # |
334
|
|
|
|
|
|
|
# by any number of fill bytes (padding of the previous # |
335
|
|
|
|
|
|
|
# segment, I suppose), set to 0xff. Most markers start # |
336
|
|
|
|
|
|
|
# marker segments containing a related group of parame- # |
337
|
|
|
|
|
|
|
# ters; some markers stand alone. The return value is a # |
338
|
|
|
|
|
|
|
# list containing the numeric value of the second marker # |
339
|
|
|
|
|
|
|
# byte and an offset pointing just after it. # |
340
|
|
|
|
|
|
|
# ------------------------------------------------------- # |
341
|
|
|
|
|
|
|
# An old version of "Arles Image Web Page Creator" had a # |
342
|
|
|
|
|
|
|
# bug which caused the application to generate JPEG's # |
343
|
|
|
|
|
|
|
# with illegal comment segments, reportedly due to a bug # |
344
|
|
|
|
|
|
|
# in the Intel JPEG library the developers used at that # |
345
|
|
|
|
|
|
|
# time (these segments had to 0x00 bytes appended). It is # |
346
|
|
|
|
|
|
|
# true that a JPEG file with garbage between segments is # |
347
|
|
|
|
|
|
|
# to be considered invalid, but some libraries like IJG's # |
348
|
|
|
|
|
|
|
# try to forgive, so we try to forgive too, if the amount # |
349
|
|
|
|
|
|
|
# of garbage is not too large ... # |
350
|
|
|
|
|
|
|
#=========================================================# |
351
|
|
|
|
|
|
|
# Ref: "Digital compression and coding of continuous-tone # |
352
|
|
|
|
|
|
|
# still images: requirements and guidelines", # |
353
|
|
|
|
|
|
|
# CCITT, 09/1992, sec. B.1.1.2, pag. 31. # |
354
|
|
|
|
|
|
|
#=========================================================# |
355
|
|
|
|
|
|
|
sub get_next_marker { |
356
|
696
|
|
|
696
|
0
|
748
|
my ($this, $offset) = @_; |
357
|
696
|
|
|
|
|
981
|
my $punctuation = chr $JPEG_PUNCTUATION; my $garbage = 0; |
|
696
|
|
|
|
|
646
|
|
358
|
|
|
|
|
|
|
# this is the upper limit to $offset |
359
|
696
|
|
|
|
|
1139
|
my $length = $this->get_data('LENGTH'); |
360
|
|
|
|
|
|
|
# $offset should point at the beginning of a new segment, |
361
|
|
|
|
|
|
|
# so the next byte should be 0xff. However, sometimes garbage |
362
|
|
|
|
|
|
|
# slips in ... Forgive this bug if garbage is not too much |
363
|
|
|
|
|
|
|
$offset < $length && ${$this->get_data($offset, 1)} eq $punctuation |
364
|
696
|
100
|
100
|
|
|
1934
|
? last : (++$garbage, ++$offset) for (0..10); |
365
|
696
|
100
|
|
|
|
1573
|
$this->die('Next marker not found') unless $length - $offset > 1; |
366
|
|
|
|
|
|
|
# it is assumed that we are now at the beginning of |
367
|
|
|
|
|
|
|
# a new segment, so the next byte must be 0xff. |
368
|
694
|
|
|
|
|
588
|
my $marker_byte = ${$this->get_data($offset++, 1)}; |
|
694
|
|
|
|
|
1190
|
|
369
|
694
|
100
|
|
|
|
1284
|
$this->die(sprintf 'Unknown punctuation (0x%02x) at offset 0x%x', |
370
|
|
|
|
|
|
|
ord($marker_byte), $offset) if $marker_byte ne $punctuation; |
371
|
|
|
|
|
|
|
# report about garbage, unless we died |
372
|
693
|
100
|
|
|
|
1065
|
$this->warn("Skipping $garbage garbage bytes") if $garbage; |
373
|
|
|
|
|
|
|
# next byte can be either the marker type or a padding |
374
|
|
|
|
|
|
|
# byte equal to 0xff (skip it if it's a padding byte) |
375
|
693
|
|
|
|
|
1184
|
$marker_byte = ${$this->get_data($offset++, 1)} |
|
693
|
|
|
|
|
1061
|
|
376
|
|
|
|
|
|
|
while $marker_byte eq $punctuation; |
377
|
|
|
|
|
|
|
# return the marker we have found (no check on its validity), |
378
|
|
|
|
|
|
|
# as well as the offset to the next byte in the JPEG stream |
379
|
693
|
|
|
|
|
1163
|
return (ord($marker_byte), $offset); |
380
|
|
|
|
|
|
|
} |
381
|
|
|
|
|
|
|
|
382
|
|
|
|
|
|
|
########################################################### |
383
|
|
|
|
|
|
|
# This method reads in a compressed (entropy coded) data # |
384
|
|
|
|
|
|
|
# segment (ECS) and saves it as a "pseudo" segment. The # |
385
|
|
|
|
|
|
|
# argument is the current offset in the in-memory JPEG # |
386
|
|
|
|
|
|
|
# stream, the result is the updated offset. These pseudo # |
387
|
|
|
|
|
|
|
# segments can be found after a Start-Of-Scan segment, # |
388
|
|
|
|
|
|
|
# and, if restart is enabled, they can be interleaved # |
389
|
|
|
|
|
|
|
# with restart segments (RST). Indeed, an ECS is not a # |
390
|
|
|
|
|
|
|
# real segment, because it does not start with a marker # |
391
|
|
|
|
|
|
|
# and its length is not known a priori. However, it is # |
392
|
|
|
|
|
|
|
# easy to detect its end since a regular marker cannot # |
393
|
|
|
|
|
|
|
# appear inside it. In practice, data in an ECS are coded # |
394
|
|
|
|
|
|
|
# in such a way that a 0xff byte can only be followed by # |
395
|
|
|
|
|
|
|
# 0x00 (invalid marker) or 0xff (padding). # |
396
|
|
|
|
|
|
|
#=========================================================# |
397
|
|
|
|
|
|
|
# WARNING: when restart is enabled, usually the file con- # |
398
|
|
|
|
|
|
|
# tains a lot of ECS and RST. In order not to be too slow # |
399
|
|
|
|
|
|
|
# we keep the restart marker embedded in row data here. # |
400
|
|
|
|
|
|
|
#=========================================================# |
401
|
|
|
|
|
|
|
# Ref: "Digital compression and coding of continuous-tone # |
402
|
|
|
|
|
|
|
# still images: requirements and guidelines", # |
403
|
|
|
|
|
|
|
# CCITT, 09/1992, sec. B.1.1.5, pag. 33. # |
404
|
|
|
|
|
|
|
########################################################### |
405
|
|
|
|
|
|
|
sub parse_ecs { |
406
|
63
|
|
|
63
|
0
|
95
|
my ($this, $offset) = @_; |
407
|
|
|
|
|
|
|
# A title for a raw data block ('ECS' must be there) |
408
|
63
|
|
|
|
|
94
|
my $ecs_name = 'ECS (Raw data)'; |
409
|
|
|
|
|
|
|
# transform the JPEG punctuation value into a string |
410
|
63
|
|
|
|
|
112
|
my $punctuation = chr $JPEG_PUNCTUATION; |
411
|
|
|
|
|
|
|
# create a string containing the character which can follow a |
412
|
|
|
|
|
|
|
# punctuations mark without causing the ECS to be considered |
413
|
|
|
|
|
|
|
# terminated. This string must contain at least the null byte and |
414
|
|
|
|
|
|
|
# the punctuation mark itself. But, for efficiency reasons, we are |
415
|
|
|
|
|
|
|
# going to include also the restart markers here. |
416
|
63
|
|
|
|
|
105
|
my $skipstring = $punctuation . chr 0x00; |
417
|
63
|
|
|
|
|
369
|
$skipstring .= chr $_ for ($JPEG_MARKER{RST0} .. $JPEG_MARKER{RST7}); |
418
|
|
|
|
|
|
|
# read in everything till the end of the input |
419
|
63
|
|
|
|
|
153
|
my $length = $this->get_data('LENGTH'); |
420
|
63
|
|
|
|
|
164
|
my $buffer = $this->get_data($offset, $length - $offset); |
421
|
|
|
|
|
|
|
# find the next 0xff byte not followed by a character of $skipstring |
422
|
|
|
|
|
|
|
# from $offset on. It is better to use pos() instead of taking a |
423
|
|
|
|
|
|
|
# substring of $$buffer, because this copy takes a lot of space. In |
424
|
|
|
|
|
|
|
# order to honour the position set by pos(), it is necessary to use |
425
|
|
|
|
|
|
|
# "g" in scalar context. My benchmarks say this is almost as fast as C. |
426
|
63
|
|
|
|
|
297
|
pos($$buffer) = 0; scalar $$buffer =~ /$punctuation[^$skipstring]/g; |
|
63
|
|
|
|
|
1762
|
|
427
|
|
|
|
|
|
|
# trim the $buffer at the byte before the punctuation mark; the |
428
|
|
|
|
|
|
|
# position of the last match can be accessed through pos(); if no |
429
|
|
|
|
|
|
|
# match is found, complain but do not fail (similar behaviour to that |
430
|
|
|
|
|
|
|
# of the 'xv' program); the file is however corrupt and unusable. |
431
|
63
|
50
|
|
|
|
1011
|
pos($$buffer) ? substr($$buffer, pos($$buffer) - 2) = '' |
432
|
|
|
|
|
|
|
: $this->warn('Premature end of JPEG stream'); |
433
|
|
|
|
|
|
|
# push a pseudo segment among the regular ones (do not parse it) |
434
|
63
|
|
|
|
|
94
|
push @{$this->{segments}}, new Image::MetaData::JPEG::Segment |
|
63
|
|
|
|
|
290
|
|
435
|
|
|
|
|
|
|
($ecs_name, $buffer, 'NOPARSE'); |
436
|
|
|
|
|
|
|
# return the updated offset |
437
|
63
|
|
|
|
|
172
|
return $offset + length $$buffer; |
438
|
|
|
|
|
|
|
} |
439
|
|
|
|
|
|
|
|
440
|
|
|
|
|
|
|
########################################################### |
441
|
|
|
|
|
|
|
# This method creates a list containing the references # |
442
|
|
|
|
|
|
|
# (or their indexes in the segment references list, if # |
443
|
|
|
|
|
|
|
# the second argument is 'INDEXES') of those segments # |
444
|
|
|
|
|
|
|
# whose name matches a given regular expression. # |
445
|
|
|
|
|
|
|
# The output can be invalid after adding/removing any # |
446
|
|
|
|
|
|
|
# segment. If $regex is undefined or evaluates to the # |
447
|
|
|
|
|
|
|
# empty string, this method returns all indexes. # |
448
|
|
|
|
|
|
|
########################################################### |
449
|
|
|
|
|
|
|
sub get_segments { |
450
|
678
|
|
|
678
|
1
|
15512
|
my ($this, $regex, $do_indexes) = @_; |
451
|
|
|
|
|
|
|
# fix the regular expression to '.' if undefined or set to the |
452
|
|
|
|
|
|
|
# empty string. I do this because I want to avoid the stupid |
453
|
|
|
|
|
|
|
# behaviour of m//; from `man perlop`: if the pattern evaluates |
454
|
|
|
|
|
|
|
# to the empty string, the last successfully matched regular |
455
|
|
|
|
|
|
|
# expression is used instead; if no match has previously succeeded, |
456
|
|
|
|
|
|
|
# this will (silently) act instead as a genuine empty pattern |
457
|
678
|
100
|
100
|
|
|
2741
|
$regex = '.' unless defined $regex && length $regex > 0; |
458
|
|
|
|
|
|
|
# get the list of segment references in this file |
459
|
678
|
|
|
|
|
993
|
my $segments = $this->{segments}; |
460
|
|
|
|
|
|
|
# return the list of matched segments |
461
|
1539
|
|
|
|
|
3125
|
return (defined $do_indexes && $do_indexes eq 'INDEXES') ? |
462
|
6580
|
|
|
|
|
14590
|
grep { $$segments[$_]->{name} =~ /$regex/ } 0..$#$segments : |
463
|
678
|
100
|
66
|
|
|
2370
|
grep { $_->{name} =~ /$regex/ } @$segments; |
464
|
|
|
|
|
|
|
} |
465
|
|
|
|
|
|
|
|
466
|
|
|
|
|
|
|
########################################################### |
467
|
|
|
|
|
|
|
# This method erases from the internal segment list all # |
468
|
|
|
|
|
|
|
# segments matching the $regex regular expression. If # |
469
|
|
|
|
|
|
|
# $regex is undefined or evaluates to the empty string, # |
470
|
|
|
|
|
|
|
# this method throws an exception, because I don't want # |
471
|
|
|
|
|
|
|
# the user to erase the whole file just because he/she # |
472
|
|
|
|
|
|
|
# did not understand what he was doing. The apocalyptic # |
473
|
|
|
|
|
|
|
# behaviour can be forced by setting $regex = '.'. One # |
474
|
|
|
|
|
|
|
# must remember that it is not wise to drop non-metadata # |
475
|
|
|
|
|
|
|
# segments, because this in general invalidates the file. # |
476
|
|
|
|
|
|
|
# As a special case, if $regex == 'METADATA', all APP* # |
477
|
|
|
|
|
|
|
# and COM segments are erased. # |
478
|
|
|
|
|
|
|
########################################################### |
479
|
|
|
|
|
|
|
sub drop_segments { |
480
|
30
|
|
|
30
|
1
|
3427
|
my ($this, $regex) = @_; |
481
|
|
|
|
|
|
|
# refuse to work with empty or undefined regular expressions |
482
|
30
|
100
|
100
|
|
|
179
|
$this->die('regular expression not specified') |
483
|
|
|
|
|
|
|
unless defined $regex && length $regex > 0; |
484
|
|
|
|
|
|
|
# if $regex is 'METADATA', convert it |
485
|
26
|
100
|
|
|
|
79
|
$regex = '^(APP\d{1,2}|COM)$' if $regex eq 'METADATA'; |
486
|
|
|
|
|
|
|
# rewrite the segment list keeping only segments not matching |
487
|
|
|
|
|
|
|
# $regex (see get_segments for further considerations). |
488
|
26
|
|
|
|
|
706
|
@{$this->{segments}} = |
|
354
|
|
|
|
|
764
|
|
489
|
26
|
|
|
|
|
43
|
grep { $_->{name} !~ /$regex/ } @{$this->{segments}}; |
|
26
|
|
|
|
|
103
|
|
490
|
|
|
|
|
|
|
} |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
########################################################### |
493
|
|
|
|
|
|
|
# This method inserts the segments referenced by $segref # |
494
|
|
|
|
|
|
|
# into the current list of segments at position $pos. If # |
495
|
|
|
|
|
|
|
# $segref is undefined, the method fails silently. If # |
496
|
|
|
|
|
|
|
# $pos is undefined, the position is chosen automatically # |
497
|
|
|
|
|
|
|
# (using find_new_app_segment_position); if $pos is out # |
498
|
|
|
|
|
|
|
# of bound, an exception is thrown; this happens also if # |
499
|
|
|
|
|
|
|
# $pos points to the first segment, and it is SOI. # |
500
|
|
|
|
|
|
|
# $segref may be a reference to a single segment or a # |
501
|
|
|
|
|
|
|
# reference to a list of segment references; everything # |
502
|
|
|
|
|
|
|
# else throws an exception. If overwrite is defined, it # |
503
|
|
|
|
|
|
|
# must be the number of segs to overwrite during splice. # |
504
|
|
|
|
|
|
|
########################################################### |
505
|
|
|
|
|
|
|
sub insert_segments { |
506
|
56
|
|
|
56
|
1
|
5076
|
my ($this, $segref, $pos, $overwrite) = @_; |
507
|
|
|
|
|
|
|
# do nothing if $segref is undefined or is not a reference |
508
|
56
|
100
|
|
|
|
141
|
return unless ref $segref; |
509
|
|
|
|
|
|
|
# segref may be a reference to a segment or a reference |
510
|
|
|
|
|
|
|
# to a list; we must turn it into a reference to a list |
511
|
55
|
100
|
|
|
|
179
|
$segref = [ $segref ] unless ref $segref eq 'ARRAY'; |
512
|
|
|
|
|
|
|
# check that all elements in the list are segment references |
513
|
|
|
|
|
|
|
ref $_ eq 'Image::MetaData::JPEG::Segment' || |
514
|
55
|
|
33
|
|
|
188
|
$this->die('$segref is not a reference') for @$segref; |
515
|
|
|
|
|
|
|
# calculate a convenient position if the user neglects to; |
516
|
|
|
|
|
|
|
# remember to pass the new segment name as an argument |
517
|
55
|
50
|
|
|
|
166
|
$pos = $this->find_new_app_segment_position |
|
|
100
|
|
|
|
|
|
518
|
|
|
|
|
|
|
(exists $$segref[0] ? $$segref[0]->{name} : undef) unless defined $pos; |
519
|
55
|
|
|
|
|
100
|
my $max_pos = -1 + $this->get_segments(); |
520
|
|
|
|
|
|
|
# fail if $pos is negative or out-of-bound; |
521
|
55
|
100
|
66
|
|
|
296
|
$this->die("out-of-bound position $pos [0, $max_pos]") |
522
|
|
|
|
|
|
|
if $pos < 0 || $pos > $max_pos; |
523
|
|
|
|
|
|
|
# fail if $pos points to the first segment and it is SOI |
524
|
54
|
100
|
100
|
|
|
162
|
$this->die('inserting on start-of-image is forbidden') |
525
|
|
|
|
|
|
|
if $pos == 0 && $this->{segments}->[0]->{name} eq 'SOI'; |
526
|
|
|
|
|
|
|
# do the actual insertion (one or multiple segments); |
527
|
|
|
|
|
|
|
# if overwrite is defined, it must be the number of |
528
|
|
|
|
|
|
|
# segments to overwrite during the splice. |
529
|
53
|
100
|
|
|
|
105
|
$overwrite = 0 unless defined $overwrite; |
530
|
53
|
|
|
|
|
63
|
splice @{$this->{segments}}, $pos, $overwrite, @$segref; |
|
53
|
|
|
|
|
234
|
|
531
|
|
|
|
|
|
|
} |
532
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
########################################################### |
534
|
|
|
|
|
|
|
# This method finds a position for a new application or # |
535
|
|
|
|
|
|
|
# comment segment to be placed in the file. The algorithm # |
536
|
|
|
|
|
|
|
# is the following: the position is chosen immediately # |
537
|
|
|
|
|
|
|
# before the first (or after the last) element of some # |
538
|
|
|
|
|
|
|
# list, provided that the list is not empty, otherwise # |
539
|
|
|
|
|
|
|
# the next list is taken into account: # |
540
|
|
|
|
|
|
|
# -) [for COM segments only] try after 'COM' segments; # |
541
|
|
|
|
|
|
|
# otherwise try after all APP segments; # |
542
|
|
|
|
|
|
|
# -) [for APPx segments only] try after the last element # |
543
|
|
|
|
|
|
|
# of the list of APPy's (with y = x..0, in sequence); # |
544
|
|
|
|
|
|
|
# otherwise try before the first element of the list # |
545
|
|
|
|
|
|
|
# of APPy's (with y = x+1..15, in sequence); # |
546
|
|
|
|
|
|
|
# -) try before the first DHP segment # |
547
|
|
|
|
|
|
|
# -) try before the first SOF segment # |
548
|
|
|
|
|
|
|
# If all these approaches fail, this method returns the # |
549
|
|
|
|
|
|
|
# position immediately after the SOI segment (i.e., 1). # |
550
|
|
|
|
|
|
|
# ------------------------------------------------------- # |
551
|
|
|
|
|
|
|
# The argument must be the name of the segment to be # |
552
|
|
|
|
|
|
|
# inserted (it defaults to 'COM', producing a warning). # |
553
|
|
|
|
|
|
|
########################################################### |
554
|
|
|
|
|
|
|
sub find_new_app_segment_position { |
555
|
32
|
|
|
32
|
1
|
2263
|
my ($this, $name) = @_; |
556
|
|
|
|
|
|
|
# if name is not specified, issue a warning and set 'COM' |
557
|
32
|
100
|
|
|
|
79
|
$this->warn('Segment name not specified: using COM'), $name = 'COM' |
558
|
|
|
|
|
|
|
unless $name; |
559
|
|
|
|
|
|
|
# setting $name to something else than 'COM' or 'APPx' is an error |
560
|
32
|
50
|
|
|
|
176
|
$this->die("Unknown segment name ($name)") |
561
|
|
|
|
|
|
|
unless $name =~ /^(COM|APP([0-9]|1[0-5]))$/; |
562
|
|
|
|
|
|
|
# just in order to avoid a warning for half-read files |
563
|
|
|
|
|
|
|
# with an incomplete set of segments, let us make sure |
564
|
|
|
|
|
|
|
# that no position is past the segment array end |
565
|
32
|
|
|
|
|
72
|
my $last_segment = -1 + $this->get_segments(); |
566
|
32
|
100
|
|
32
|
|
124
|
my $safe = sub { ($last_segment < $_[0]) ? $last_segment : $_[0] }; |
|
32
|
|
|
|
|
249
|
|
567
|
|
|
|
|
|
|
# this private function returns a list containing the |
568
|
|
|
|
|
|
|
# indexes of the segments whose name matches the argument |
569
|
32
|
|
|
105
|
|
109
|
my $list = sub { $this->get_segments('^'.$_[0].'$', 'INDEXES') }; |
|
105
|
|
|
|
|
214
|
|
570
|
|
|
|
|
|
|
# if there are already some 'COM' segments, let us put the new COM |
571
|
|
|
|
|
|
|
# segment immediately after them; otherwise try after all APP segments |
572
|
32
|
100
|
|
|
|
108
|
if ($name =~ /^COM/) { |
573
|
12
|
|
|
|
|
21
|
return &$safe(1+$_) for reverse &$list('COM'); |
574
|
7
|
|
|
|
|
18
|
return &$safe(1+$_) for reverse &$list('APP.*'); } |
575
|
|
|
|
|
|
|
# if $name is APPx, try after the last element of the list of APPy's |
576
|
|
|
|
|
|
|
# (with y = x .. 0, in sequence); if all these fail, try before the |
577
|
|
|
|
|
|
|
# first element of the list of APPy's (with y = x+1..15, in sequence) |
578
|
22
|
100
|
|
|
|
143
|
if ($name =~ /^APP(.*)$/) { |
579
|
20
|
|
|
|
|
133
|
for (reverse 0..$1) {return &$safe(1+$_) for reverse &$list("APP$_");}; |
|
76
|
|
|
|
|
158
|
|
580
|
2
|
|
|
|
|
9
|
for (1+$1..15) { return &$safe($_) for &$list("APP$_"); }; } |
|
4
|
|
|
|
|
9
|
|
581
|
|
|
|
|
|
|
# if all specific tests failed, try with the |
582
|
|
|
|
|
|
|
# first DHP segment or the first SOF segment |
583
|
3
|
|
|
|
|
14
|
return &$safe($_) for &$list('DHP'); |
584
|
3
|
|
|
|
|
8
|
return &$safe($_) for &$list('SOF'); |
585
|
|
|
|
|
|
|
# if even this fails, try after start-of-image (just in order |
586
|
|
|
|
|
|
|
# to avoid a warning for half-read files with not even two |
587
|
|
|
|
|
|
|
# segments (they cannot be saved), return 0 if necessary) |
588
|
3
|
|
|
|
|
9
|
return &$safe(1); |
589
|
|
|
|
|
|
|
} |
590
|
|
|
|
|
|
|
|
591
|
|
|
|
|
|
|
########################################################### |
592
|
|
|
|
|
|
|
# Load other parts for this package. In order to avoid # |
593
|
|
|
|
|
|
|
# that this file becomes too large, only general interest # |
594
|
|
|
|
|
|
|
# methods are written here. # |
595
|
|
|
|
|
|
|
########################################################### |
596
|
|
|
|
|
|
|
require 'Image/MetaData/JPEG/access/various.pl'; |
597
|
|
|
|
|
|
|
require 'Image/MetaData/JPEG/access/comments.pl'; |
598
|
|
|
|
|
|
|
require 'Image/MetaData/JPEG/access/app1_exif.pl'; |
599
|
|
|
|
|
|
|
require 'Image/MetaData/JPEG/access/app13.pl'; |
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
# successful package load |
602
|
|
|
|
|
|
|
1; |