line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
2
|
|
|
|
|
|
|
# File: HP.pm |
3
|
|
|
|
|
|
|
# |
4
|
|
|
|
|
|
|
# Description: Hewlett-Packard maker notes tags |
5
|
|
|
|
|
|
|
# |
6
|
|
|
|
|
|
|
# Revisions: 2007-05-03 - P. Harvey Created |
7
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
package Image::ExifTool::HP; |
10
|
|
|
|
|
|
|
|
11
|
26
|
|
|
26
|
|
260
|
use strict; |
|
26
|
|
|
|
|
87
|
|
|
26
|
|
|
|
|
873
|
|
12
|
26
|
|
|
26
|
|
169
|
use vars qw($VERSION); |
|
26
|
|
|
|
|
91
|
|
|
26
|
|
|
|
|
1073
|
|
13
|
26
|
|
|
26
|
|
175
|
use Image::ExifTool qw(:DataAccess :Utils); |
|
26
|
|
|
|
|
69
|
|
|
26
|
|
|
|
|
30187
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
$VERSION = '1.04'; |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
sub ProcessHP($$$); |
18
|
|
|
|
|
|
|
sub ProcessTDHD($$$); |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
# HP EXIF-format maker notes (or is it Vivitar?) |
21
|
|
|
|
|
|
|
%Image::ExifTool::HP::Main = ( |
22
|
|
|
|
|
|
|
GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, |
23
|
|
|
|
|
|
|
NOTES => q{ |
24
|
|
|
|
|
|
|
These tables list tags found in the maker notes of some Hewlett-Packard |
25
|
|
|
|
|
|
|
camera models. |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
The first table lists tags found in the EXIF-format maker notes of the |
28
|
|
|
|
|
|
|
PhotoSmart 720 (also used by the Vivitar ViviCam 3705, 3705B and 3715). |
29
|
|
|
|
|
|
|
}, |
30
|
|
|
|
|
|
|
0x0e00 => { |
31
|
|
|
|
|
|
|
Name => 'PrintIM', |
32
|
|
|
|
|
|
|
Description => 'Print Image Matching', |
33
|
|
|
|
|
|
|
SubDirectory => { |
34
|
|
|
|
|
|
|
TagTable => 'Image::ExifTool::PrintIM::Main', |
35
|
|
|
|
|
|
|
}, |
36
|
|
|
|
|
|
|
}, |
37
|
|
|
|
|
|
|
); |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# other types of HP maker notes |
40
|
|
|
|
|
|
|
%Image::ExifTool::HP::Type2 = ( |
41
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessHP, |
42
|
|
|
|
|
|
|
GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, |
43
|
|
|
|
|
|
|
NOTES => 'These tags are used by the PhotoSmart E427.', |
44
|
|
|
|
|
|
|
'PreviewImage' => { |
45
|
|
|
|
|
|
|
Name => 'PreviewImage', |
46
|
|
|
|
|
|
|
Groups => { 2 => 'Preview' }, |
47
|
|
|
|
|
|
|
RawConv => '$self->ValidateImage(\$val,$tag)', |
48
|
|
|
|
|
|
|
}, |
49
|
|
|
|
|
|
|
'Serial Number' => 'SerialNumber', |
50
|
|
|
|
|
|
|
'Lens Shading' => 'LensShading', |
51
|
|
|
|
|
|
|
); |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
%Image::ExifTool::HP::Type4 = ( |
54
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
55
|
|
|
|
|
|
|
GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, |
56
|
|
|
|
|
|
|
NOTES => 'These tags are used by the PhotoSmart M627.', |
57
|
|
|
|
|
|
|
0x0c => { |
58
|
|
|
|
|
|
|
Name => 'MaxAperture', |
59
|
|
|
|
|
|
|
Format => 'int16u', |
60
|
|
|
|
|
|
|
ValueConv => '$val / 10', |
61
|
|
|
|
|
|
|
}, |
62
|
|
|
|
|
|
|
0x10 => { |
63
|
|
|
|
|
|
|
Name => 'ExposureTime', |
64
|
|
|
|
|
|
|
Format => 'int32u', |
65
|
|
|
|
|
|
|
ValueConv => '$val / 1e6', |
66
|
|
|
|
|
|
|
PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', |
67
|
|
|
|
|
|
|
}, |
68
|
|
|
|
|
|
|
0x14 => { |
69
|
|
|
|
|
|
|
Name => 'CameraDateTime', |
70
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
71
|
|
|
|
|
|
|
Format => 'string[20]', |
72
|
|
|
|
|
|
|
}, |
73
|
|
|
|
|
|
|
0x34 => { |
74
|
|
|
|
|
|
|
Name => 'ISO', |
75
|
|
|
|
|
|
|
Format => 'int16u', |
76
|
|
|
|
|
|
|
}, |
77
|
|
|
|
|
|
|
0x5c => { |
78
|
|
|
|
|
|
|
Name => 'SerialNumber', |
79
|
|
|
|
|
|
|
Format => 'string[26]', |
80
|
|
|
|
|
|
|
RawConv => '$val =~ s/^SERIAL NUMBER:// ? $val : undef', |
81
|
|
|
|
|
|
|
}, |
82
|
|
|
|
|
|
|
); |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
%Image::ExifTool::HP::Type6 = ( |
85
|
|
|
|
|
|
|
PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, |
86
|
|
|
|
|
|
|
GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, |
87
|
|
|
|
|
|
|
NOTES => 'These tags are used by the PhotoSmart M425, M525 and M527.', |
88
|
|
|
|
|
|
|
0x0c => { |
89
|
|
|
|
|
|
|
Name => 'FNumber', |
90
|
|
|
|
|
|
|
Format => 'int16u', |
91
|
|
|
|
|
|
|
ValueConv => '$val / 10', |
92
|
|
|
|
|
|
|
}, |
93
|
|
|
|
|
|
|
0x10 => { |
94
|
|
|
|
|
|
|
Name => 'ExposureTime', |
95
|
|
|
|
|
|
|
Format => 'int32u', |
96
|
|
|
|
|
|
|
ValueConv => '$val / 1e6', |
97
|
|
|
|
|
|
|
PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', |
98
|
|
|
|
|
|
|
}, |
99
|
|
|
|
|
|
|
0x14 => { |
100
|
|
|
|
|
|
|
Name => 'CameraDateTime', |
101
|
|
|
|
|
|
|
Groups => { 2 => 'Time' }, |
102
|
|
|
|
|
|
|
Format => 'string[20]', |
103
|
|
|
|
|
|
|
}, |
104
|
|
|
|
|
|
|
0x34 => { |
105
|
|
|
|
|
|
|
Name => 'ISO', |
106
|
|
|
|
|
|
|
Format => 'int16u', |
107
|
|
|
|
|
|
|
}, |
108
|
|
|
|
|
|
|
0x58 => { |
109
|
|
|
|
|
|
|
Name => 'SerialNumber', |
110
|
|
|
|
|
|
|
Format => 'string[26]', |
111
|
|
|
|
|
|
|
RawConv => '$val =~ s/^SERIAL NUMBER:// ? $val : undef', |
112
|
|
|
|
|
|
|
}, |
113
|
|
|
|
|
|
|
); |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
# proprietary format TDHD data written by Photosmart R837 (ref PH) |
116
|
|
|
|
|
|
|
%Image::ExifTool::HP::TDHD = ( |
117
|
|
|
|
|
|
|
PROCESS_PROC => \&ProcessTDHD, |
118
|
|
|
|
|
|
|
GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, |
119
|
|
|
|
|
|
|
NOTES => q{ |
120
|
|
|
|
|
|
|
These tags are extracted from the APP6 "TDHD" segment of Photosmart R837 |
121
|
|
|
|
|
|
|
JPEG images. Many other unknown tags exist in is data, and can be seen with |
122
|
|
|
|
|
|
|
the L (-u) option. |
123
|
|
|
|
|
|
|
}, |
124
|
|
|
|
|
|
|
# (all subdirectories except TDHD and LSLV are automatically recognized |
125
|
|
|
|
|
|
|
# by their "type" word of 0x10001) |
126
|
|
|
|
|
|
|
TDHD => { |
127
|
|
|
|
|
|
|
Name => 'TDHD', |
128
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::HP::TDHD' }, |
129
|
|
|
|
|
|
|
}, |
130
|
|
|
|
|
|
|
LSLV => { |
131
|
|
|
|
|
|
|
Name => 'LSLV', |
132
|
|
|
|
|
|
|
SubDirectory => { TagTable => 'Image::ExifTool::HP::TDHD' }, |
133
|
|
|
|
|
|
|
}, |
134
|
|
|
|
|
|
|
FWRV => 'FirmwareVersion', |
135
|
|
|
|
|
|
|
CMSN => 'SerialNumber', # (unverified) |
136
|
|
|
|
|
|
|
# LTEM - some temperature? |
137
|
|
|
|
|
|
|
); |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
140
|
|
|
|
|
|
|
# Process HP APP6 TDHD metadata (ref PH) |
141
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref |
142
|
|
|
|
|
|
|
# Returns: 1 on success |
143
|
|
|
|
|
|
|
sub ProcessTDHD($$$) |
144
|
|
|
|
|
|
|
{ |
145
|
0
|
|
|
0
|
0
|
|
my ($et, $dirInfo, $tagTablePtr) = @_; |
146
|
0
|
|
|
|
|
|
my $dataPt = $$dirInfo{DataPt}; |
147
|
0
|
|
|
|
|
|
my $dataPos = $$dirInfo{DataPos}; |
148
|
0
|
|
|
|
|
|
my $pos = $$dirInfo{DirStart}; |
149
|
0
|
|
|
|
|
|
my $dirEnd = $pos + $$dirInfo{DirLen}; |
150
|
0
|
|
0
|
|
|
|
my $unknown = $et->Options('Unknown') || $et->Options('Verbose'); |
151
|
0
|
|
|
|
|
|
$et->VerboseDir('TDHD', undef, $$dirInfo{DirLen}); |
152
|
0
|
|
|
|
|
|
SetByteOrder('II'); |
153
|
0
|
|
|
|
|
|
while ($pos + 12 < $dirEnd) { |
154
|
0
|
|
|
|
|
|
my $tag = substr($$dataPt, $pos, 4); |
155
|
0
|
|
|
|
|
|
my $type = Get32u($dataPt, $pos + 4); |
156
|
0
|
|
|
|
|
|
my $size = Get32u($dataPt, $pos + 8); |
157
|
0
|
|
|
|
|
|
$pos += 12; |
158
|
0
|
0
|
0
|
|
|
|
last if $size < 0 or $pos + $size > $dirEnd; |
159
|
0
|
0
|
|
|
|
|
if ($type == 0x10001) { |
160
|
|
|
|
|
|
|
# this is a subdirectory containing more tags |
161
|
0
|
|
|
|
|
|
my %dirInfo = ( |
162
|
|
|
|
|
|
|
DataPt => $dataPt, |
163
|
|
|
|
|
|
|
DataPos => $dataPos, |
164
|
|
|
|
|
|
|
DirStart => $pos, |
165
|
|
|
|
|
|
|
DirLen => $size, |
166
|
|
|
|
|
|
|
); |
167
|
0
|
|
|
|
|
|
$et->ProcessDirectory(\%dirInfo, $tagTablePtr); |
168
|
|
|
|
|
|
|
} else { |
169
|
0
|
0
|
0
|
|
|
|
if (not $$tagTablePtr{$tag} and $unknown) { |
170
|
0
|
|
|
|
|
|
my $name = $tag; |
171
|
0
|
|
|
|
|
|
$name =~ tr/-_A-Za-z0-9//dc; # remove invalid characters |
172
|
0
|
|
|
|
|
|
my %tagInfo = ( |
173
|
|
|
|
|
|
|
Name => "HP_TDHD_$name", |
174
|
|
|
|
|
|
|
Unknown => 1, |
175
|
|
|
|
|
|
|
); |
176
|
|
|
|
|
|
|
# guess format based on data size |
177
|
0
|
0
|
|
|
|
|
if ($size == 1) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
178
|
0
|
|
|
|
|
|
$tagInfo{Format} = 'int8u'; |
179
|
|
|
|
|
|
|
} elsif ($size == 2) { |
180
|
0
|
|
|
|
|
|
$tagInfo{Format} = 'int16u'; |
181
|
|
|
|
|
|
|
} elsif ($size == 4) { |
182
|
0
|
|
|
|
|
|
$tagInfo{Format} = 'int32s'; |
183
|
|
|
|
|
|
|
} elsif ($size > 80) { |
184
|
0
|
|
|
|
|
|
$tagInfo{Binary} = 1; |
185
|
|
|
|
|
|
|
} |
186
|
0
|
|
|
|
|
|
AddTagToTable($tagTablePtr, $tag, \%tagInfo); |
187
|
|
|
|
|
|
|
} |
188
|
0
|
|
|
|
|
|
$et->HandleTag($tagTablePtr, $tag, undef, |
189
|
|
|
|
|
|
|
DataPt => $dataPt, |
190
|
|
|
|
|
|
|
DataPos => $dataPos, |
191
|
|
|
|
|
|
|
Start => $pos, |
192
|
|
|
|
|
|
|
Size => $size, |
193
|
|
|
|
|
|
|
); |
194
|
|
|
|
|
|
|
} |
195
|
0
|
|
|
|
|
|
$pos += $size; |
196
|
|
|
|
|
|
|
} |
197
|
0
|
|
|
|
|
|
return 1; |
198
|
|
|
|
|
|
|
} |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
#------------------------------------------------------------------------------ |
201
|
|
|
|
|
|
|
# Process HP maker notes |
202
|
|
|
|
|
|
|
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref |
203
|
|
|
|
|
|
|
# Returns: 1 on success, otherwise returns 0 and sets a Warning |
204
|
|
|
|
|
|
|
sub ProcessHP($$$) |
205
|
|
|
|
|
|
|
{ |
206
|
0
|
|
|
0
|
0
|
|
my ($et, $dirInfo, $tagTablePtr) = @_; |
207
|
0
|
|
|
|
|
|
my $dataPt = $$dirInfo{DataPt}; |
208
|
0
|
|
|
|
|
|
my $dataLen = $$dirInfo{DataLen}; |
209
|
0
|
|
0
|
|
|
|
my $dirStart = $$dirInfo{DirStart} || 0; |
210
|
0
|
|
0
|
|
|
|
my $dirLen = $$dirInfo{DirLen} || $dataLen - $dirStart; |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
# look for known text-type tags |
213
|
0
|
0
|
0
|
|
|
|
if ($dirStart or $dirLen != length($$dataPt)) { |
214
|
0
|
|
|
|
|
|
my $buff = substr($$dataPt, $dirStart, $dirLen); |
215
|
0
|
|
|
|
|
|
$dataPt = \$buff; |
216
|
|
|
|
|
|
|
} |
217
|
0
|
|
|
|
|
|
my $tagID; |
218
|
|
|
|
|
|
|
# brute-force scan for PreviewImage |
219
|
0
|
0
|
0
|
|
|
|
if ($$tagTablePtr{PreviewImage} and $$dataPt =~ /(\xff\xd8\xff\xdb.*\xff\xd9)/gs) { |
220
|
0
|
|
|
|
|
|
$et->HandleTag($tagTablePtr, 'PreviewImage', $1); |
221
|
|
|
|
|
|
|
# truncate preview to speed subsequent tag scans |
222
|
0
|
|
|
|
|
|
my $buff = substr($$dataPt, 0, pos($$dataPt)-length($1)); |
223
|
0
|
|
|
|
|
|
$dataPt = \$buff; |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
# scan for other tag ID's |
226
|
0
|
|
|
|
|
|
foreach $tagID (sort(TagTableKeys($tagTablePtr))) { |
227
|
0
|
0
|
|
|
|
|
next if $tagID eq 'PreviewImage'; |
228
|
0
|
0
|
|
|
|
|
next unless $$dataPt =~ /$tagID:\s*([\x20-\x7f]+)/i; |
229
|
0
|
|
|
|
|
|
$et->HandleTag($tagTablePtr, $tagID, $1); |
230
|
|
|
|
|
|
|
} |
231
|
0
|
|
|
|
|
|
return 1; |
232
|
|
|
|
|
|
|
} |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
1; # end |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
__END__ |