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 Image::MetaData::JPEG::data::Tables qw(); |
7
|
15
|
|
|
15
|
|
66
|
no integer; |
|
15
|
|
|
|
|
22
|
|
|
15
|
|
|
|
|
63
|
|
8
|
15
|
|
|
15
|
|
368
|
use strict; |
|
15
|
|
|
|
|
22
|
|
|
15
|
|
|
|
|
331
|
|
9
|
15
|
|
|
15
|
|
56
|
use warnings; |
|
15
|
|
|
|
|
15
|
|
|
15
|
|
|
|
|
5204
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
########################################################### |
12
|
|
|
|
|
|
|
# This method parses an APP12 segment; this segment was # |
13
|
|
|
|
|
|
|
# used around 1998 by at least Olympus, Agfa and Epson # |
14
|
|
|
|
|
|
|
# as a non standard replacement for EXIF. Information is # |
15
|
|
|
|
|
|
|
# semi-readeable (mainly ascii text), but the format is # |
16
|
|
|
|
|
|
|
# undocument (let me know if you have any documentation!) # |
17
|
|
|
|
|
|
|
#=========================================================# |
18
|
|
|
|
|
|
|
# From the few examples I was able to find, my interpre- # |
19
|
|
|
|
|
|
|
# tation of the APP12 format is the following: # |
20
|
|
|
|
|
|
|
#---------------------------------------------------------# |
21
|
|
|
|
|
|
|
# 1 line identification (maker info?) # |
22
|
|
|
|
|
|
|
#----- multiple times ------------------------------------# |
23
|
|
|
|
|
|
|
# 1 line group (a string in square brackets) # |
24
|
|
|
|
|
|
|
# multiple lines records (key-value separated by '=') # |
25
|
|
|
|
|
|
|
#----- multiple times ------------------------------------# |
26
|
|
|
|
|
|
|
# characters group (a string in square brackets) # |
27
|
|
|
|
|
|
|
# characters unintelligible data # |
28
|
|
|
|
|
|
|
#=========================================================# |
29
|
|
|
|
|
|
|
# Well, this description looks a mess, I know. It means # |
30
|
|
|
|
|
|
|
# that after the identification line, there is some plain # |
31
|
|
|
|
|
|
|
# ascii information (divided in groups, each group starts # |
32
|
|
|
|
|
|
|
# with a line like "[picture info]", each key-value pair # |
33
|
|
|
|
|
|
|
# span one line) followed by groups containing binary # |
34
|
|
|
|
|
|
|
# data (so that splitting on line ends does not work!). # |
35
|
|
|
|
|
|
|
# Line terminations are marked by '\r\n' = 0x0d0a. # |
36
|
|
|
|
|
|
|
#=========================================================# |
37
|
|
|
|
|
|
|
# Ref: ... ??? # |
38
|
|
|
|
|
|
|
########################################################### |
39
|
|
|
|
|
|
|
sub parse_app12 { |
40
|
2
|
|
|
2
|
0
|
3
|
my ($this) = @_; |
41
|
|
|
|
|
|
|
# compile once and for all the following regular expression, |
42
|
|
|
|
|
|
|
# which captures a [groupname]; the name can contain alphanumeric |
43
|
|
|
|
|
|
|
# characters, underscores and spaces (this is a guess ...) |
44
|
2
|
|
|
|
|
7
|
my $groupname = qr/^\[([ \w]*)\]/; |
45
|
|
|
|
|
|
|
# search the string "[user]" in the data area; it seems to |
46
|
|
|
|
|
|
|
# separate the ascii data area from the binary data area. |
47
|
|
|
|
|
|
|
# If the string is not there ($limit = -1), convert this value |
48
|
|
|
|
|
|
|
# to the past-the-end character. |
49
|
2
|
|
|
|
|
5
|
my $limit = index $this->data(0, $this->size()), "[user]"; |
50
|
2
|
100
|
|
|
|
8
|
$limit = $this->size() if $limit == -1; |
51
|
|
|
|
|
|
|
# get all segment data up to the $limit and split in lines |
52
|
|
|
|
|
|
|
# (each line is terminated by carriage-return + line-feed) |
53
|
2
|
|
|
|
|
5
|
my @lines = split /\r\n/, $this->data(0, $limit); |
54
|
|
|
|
|
|
|
# extract the first line out of @lines, because it must be |
55
|
|
|
|
|
|
|
# treated differently. It seems that this line contains some |
56
|
|
|
|
|
|
|
# null characters, but I don't want to split it further ... |
57
|
2
|
|
|
|
|
3
|
my $preamble = shift @lines; |
58
|
2
|
|
|
|
|
7
|
$this->store_record('MakerInfo', $ASCII, \ $preamble, length $preamble); |
59
|
|
|
|
|
|
|
# each group will be written to a different subdirectory |
60
|
2
|
|
|
|
|
3
|
my $dirref = undef; |
61
|
|
|
|
|
|
|
# for each line in the ascii data area, except the first ... |
62
|
2
|
|
|
|
|
4
|
for (@lines) { |
63
|
|
|
|
|
|
|
# if the line is like "[groupname]", extract the group name |
64
|
|
|
|
|
|
|
# from the square brackets and create a new subdirectory |
65
|
25
|
100
|
|
|
|
114
|
if (/^$groupname$/) { $dirref = $this->provide_subdirectory($1); } |
|
3
|
|
|
|
|
8
|
|
66
|
|
|
|
|
|
|
# otherwise, split the line on "="; on the left we find the |
67
|
|
|
|
|
|
|
# tag name, on the right the ascii value(s). Store, in the |
68
|
|
|
|
|
|
|
# appropriate subdirectory, a non-numeric record. |
69
|
22
|
|
|
|
|
41
|
else { my ($tag, $vals) = split /=/, $_; |
70
|
22
|
|
|
|
|
51
|
$this->store_record($dirref,$tag,$ASCII,\$vals,length $vals); } |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
# it's time to take care of the binary data area. We can't rely |
73
|
|
|
|
|
|
|
# on line terminations here, so a different strategy is necessary. |
74
|
|
|
|
|
|
|
# First, the remainig of the data area is copied in a variable ... |
75
|
2
|
|
|
|
|
5
|
my $binary = $this->data($limit, $this->size() - $limit); |
76
|
|
|
|
|
|
|
# ... then this variable is slowly consumed |
77
|
2
|
|
|
|
|
8
|
while (0 != length $binary) { |
78
|
|
|
|
|
|
|
# match the [groupname] string. It must be at the beginning |
79
|
|
|
|
|
|
|
# of $$binary_ref, otherwise something is going wrong ... |
80
|
1
|
|
|
|
|
5
|
$binary =~ /$groupname/; |
81
|
1
|
50
|
|
|
|
6
|
$this->die('Error while decoding binary data') if $-[0] != 0; |
82
|
|
|
|
|
|
|
# the subgroup matches the groupname (without the square |
83
|
|
|
|
|
|
|
# brackets); assume the rest, up to the end, is the value |
84
|
1
|
|
|
|
|
3
|
my $tag = $1; |
85
|
1
|
|
|
|
|
2
|
my $val = substr $binary, $+[0]; |
86
|
|
|
|
|
|
|
# but if we find another [groupname], |
87
|
|
|
|
|
|
|
# we change our mind on where the value ends |
88
|
1
|
50
|
|
|
|
11
|
$val = substr($val, 0, $-[0]) if $val =~ /$groupname/; |
89
|
|
|
|
|
|
|
# take out the group name and the value from binary, then |
90
|
|
|
|
|
|
|
# save them in a non-numeric record as undefined bytes (add |
91
|
|
|
|
|
|
|
# 2 to the length sum, this counts the two square brackets) |
92
|
1
|
|
|
|
|
4
|
$binary = substr($binary, length($tag) + length($val) + 2); |
93
|
1
|
|
|
|
|
4
|
$this->store_record($tag, $UNDEF, \$val, length $val); |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
} |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
# successful load |
98
|
|
|
|
|
|
|
1; |