source: main/trunk/greenstone2/perllib/cpan/Image/ExifTool/APP12.pm@ 24107

Last change on this file since 24107 was 24107, checked in by sjm84, 13 years ago

Updating the ExifTool perl modules

File size: 10.6 KB
Line 
1#------------------------------------------------------------------------------
2# File: APP12.pm
3#
4# Description: Read APP12 meta information
5#
6# Revisions: 10/18/2005 - P. Harvey Created
7#
8# References: 1) Heinrich Giesen private communication
9#------------------------------------------------------------------------------
10
11package Image::ExifTool::APP12;
12
13use strict;
14use vars qw($VERSION);
15use Image::ExifTool qw(:DataAccess);
16
17$VERSION = '1.08';
18
19sub ProcessAPP12($$$);
20sub ProcessDucky($$$);
21sub WriteDucky($$$);
22
23# APP12 tags (ref PH)
24%Image::ExifTool::APP12::PictureInfo = (
25 PROCESS_PROC => \&ProcessAPP12,
26 GROUPS => { 0 => 'APP12', 1 => 'PictureInfo', 2 => 'Image' },
27 NOTES => q{
28 The JPEG APP12 "Picture Info" segment was used by some older cameras, and
29 contains ASCII-based meta information. Below are some tags which have been
30 observed Agfa and Polaroid images, however ExifTool will extract information
31 from any tags found in this segment.
32 },
33 FNumber => {
34 ValueConv => '$val=~s/^[A-Za-z ]*//;$val', # Agfa leads with an 'F'
35 PrintConv => 'sprintf("%.1f",$val)',
36 },
37 Aperture => {
38 PrintConv => 'sprintf("%.1f",$val)',
39 },
40 TimeDate => {
41 Name => 'DateTimeOriginal',
42 Description => 'Date/Time Original',
43 Groups => { 2 => 'Time' },
44 ValueConv => '$val=~/^\d+$/ ? ConvertUnixTime($val) : $val',
45 PrintConv => '$self->ConvertDateTime($val)',
46 },
47 Shutter => {
48 Name => 'ExposureTime',
49 ValueConv => '$val * 1e-6',
50 PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
51 },
52 shtr => {
53 Name => 'ExposureTime',
54 ValueConv => '$val * 1e-6',
55 PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
56 },
57 'Serial#' => {
58 Name => 'SerialNumber',
59 Groups => { 2 => 'Camera' },
60 },
61 Flash => { PrintConv => { 0 => 'Off', 1 => 'On' } },
62 Macro => { PrintConv => { 0 => 'Off', 1 => 'On' } },
63 StrobeTime => { },
64 Ytarget => { Name => 'YTarget' },
65 ylevel => { Name => 'YLevel' },
66 FocusPos => { },
67 FocusMode => { },
68 Quality => { },
69 ExpBias => 'ExposureCompensation',
70 FWare => 'FirmwareVersion',
71 StrobeTime => { },
72 Resolution => { },
73 Protect => { },
74 ConTake => { },
75 ImageSize => { PrintConv => '$val=~tr/-/x/;$val' },
76 ColorMode => { },
77 Zoom => { },
78 ZoomPos => { },
79 LightS => { },
80 Type => {
81 Name => 'CameraType',
82 Groups => { 2 => 'Camera' },
83 DataMember => 'CameraType',
84 RawConv => '$self->{CameraType} = $val',
85 },
86 Version => { Groups => { 2 => 'Camera' } },
87 ID => { Groups => { 2 => 'Camera' } },
88);
89
90# APP12 segment written in Photoshop "Save For Web" images
91# (from tests with Photoshop 7 files - PH/1)
92%Image::ExifTool::APP12::Ducky = (
93 PROCESS_PROC => \&ProcessDucky,
94 WRITE_PROC => \&WriteDucky,
95 GROUPS => { 0 => 'Ducky', 1 => 'Ducky', 2 => 'Image' },
96 WRITABLE => 'string',
97 NOTES => q{
98 Photoshop uses the JPEG APP12 "Ducky" segment to store some information in
99 "Save for Web" images.
100 },
101 1 => { #PH
102 Name => 'Quality',
103 Priority => 0,
104 Avoid => 1,
105 Writable => 'int32u',
106 ValueConv => 'unpack("N",$val)', # 4-byte integer
107 ValueConvInv => 'pack("N",$val)',
108 PrintConv => '"$val%"',
109 PrintConvInv => '$val=~/(\d+)/ ? $1 : undef',
110 },
111 2 => { #1
112 Name => 'Comment',
113 Priority => 0,
114 Avoid => 1,
115 # (ignore 4-byte character count at start of value)
116 ValueConv => '$self->Decode(substr($val,4),"UCS2","MM")',
117 ValueConvInv => 'pack("N",length $val) . $self->Encode($val,"UCS2","MM")',
118 },
119 3 => { #PH
120 Name => 'Copyright',
121 Priority => 0,
122 Avoid => 1,
123 Groups => { 2 => 'Author' },
124 # (ignore 4-byte character count at start of value)
125 ValueConv => '$self->Decode(substr($val,4),"UCS2","MM")',
126 ValueConvInv => 'pack("N",length $val) . $self->Encode($val,"UCS2","MM")',
127 },
128);
129
130#------------------------------------------------------------------------------
131# Write APP12 Ducky segment
132# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
133# Returns: New directory data or undefined on error
134sub WriteDucky($$$)
135{
136 my ($exifTool, $dirInfo, $tagTablePtr) = @_;
137 $exifTool or return 1; # allow dummy access to autoload this package
138 my $dataPt = $$dirInfo{DataPt};
139 my $pos = $$dirInfo{DirStart};
140 my $newTags = $exifTool->GetNewTagInfoHash($tagTablePtr);
141 my @addTags = sort { $a <=> $b } keys(%$newTags);
142 my ($dirEnd, %doneTags);
143 if ($dataPt) {
144 $dirEnd = $pos + $$dirInfo{DirLen};
145 } else {
146 my $tmp = '';
147 $dataPt = \$tmp;
148 $pos = $dirEnd = 0;
149 }
150 my $newData = '';
151 SetByteOrder('MM');
152 # process all data blocks in Ducky segment
153 for (;;) {
154 my ($tag, $len, $val);
155 if ($pos + 4 <= $dirEnd) {
156 $tag = Get16u($dataPt, $pos);
157 $len = Get16u($dataPt, $pos + 2);
158 $pos += 4;
159 if ($pos + $len > $dirEnd) {
160 $exifTool->Warn('Invalid Ducky block length');
161 return undef;
162 }
163 $val = substr($$dataPt, $pos, $len);
164 $pos += $len;
165 } else {
166 last unless @addTags;
167 $tag = pop @addTags;
168 next if $doneTags{$tag};
169 }
170 $doneTags{$tag} = 1;
171 my $tagInfo = $$newTags{$tag};
172 if ($tagInfo) {
173 my $nvHash = $exifTool->GetNewValueHash($tagInfo);
174 my $isNew;
175 if (defined $val) {
176 if (Image::ExifTool::IsOverwriting($nvHash, $val)) {
177 $exifTool->VerboseValue("- Ducky:$$tagInfo{Name}", $val);
178 $isNew = 1;
179 }
180 } else {
181 next unless Image::ExifTool::IsCreating($nvHash);
182 $isNew = 1;
183 }
184 if ($isNew) {
185 $val = Image::ExifTool::GetNewValues($nvHash);
186 ++$exifTool->{CHANGED};
187 next unless defined $val; # next if tag is being deleted
188 $exifTool->VerboseValue("+ Ducky:$$tagInfo{Name}", $val);
189 }
190 }
191 $newData .= pack('nn', $tag, length $val) . $val;
192 }
193 $newData .= "\0\0" if length $newData;
194 return $newData;
195}
196
197#------------------------------------------------------------------------------
198# Process APP12 Ducky segment (ref PH)
199# Inputs: 0) ExifTool object reference, 1) Directory information ref, 2) tag table ref
200# Returns: 1 on success, 0 if this wasn't a recognized Ducky segment
201# Notes: This segment has the following format:
202# 1) 5 bytes: "Ducky"
203# 2) multiple data blocks (all integers are big endian):
204# a) 2 bytes: block type (0=end, 1=Quality, 2=Comment, 3=Copyright)
205# b) 2 bytes: block length (N)
206# c) N bytes: block data
207sub ProcessDucky($$$)
208{
209 my ($exifTool, $dirInfo, $tagTablePtr) = @_;
210 my $dataPt = $$dirInfo{DataPt};
211 my $pos = $$dirInfo{DirStart};
212 my $dirEnd = $pos + $$dirInfo{DirLen};
213 SetByteOrder('MM');
214 # process all data blocks in Ducky segment
215 for (;;) {
216 last if $pos + 4 > $dirEnd;
217 my $tag = Get16u($dataPt, $pos);
218 my $len = Get16u($dataPt, $pos + 2);
219 $pos += 4;
220 if ($pos + $len > $dirEnd) {
221 $exifTool->Warn('Invalid Ducky block length');
222 last;
223 }
224 my $val = substr($$dataPt, $pos, $len);
225 $exifTool->HandleTag($tagTablePtr, $tag, $val,
226 DataPt => $dataPt,
227 DataPos => $$dirInfo{DataPos},
228 Start => $pos,
229 Size => $len,
230 );
231 $pos += $len;
232 }
233 return 1;
234}
235
236#------------------------------------------------------------------------------
237# Process APP12 Picture Info segment (ref PH)
238# Inputs: 0) ExifTool object reference, 1) Directory information ref, 2) tag table ref
239# Returns: 1 on success, 0 if this wasn't a recognized APP12
240sub ProcessAPP12($$$)
241{
242 my ($exifTool, $dirInfo, $tagTablePtr) = @_;
243 my $dataPt = $$dirInfo{DataPt};
244 my $dirStart = $$dirInfo{DirStart} || 0;
245 my $dirLen = $$dirInfo{DirLen} || (length($$dataPt) - $dirStart);
246 if ($dirLen != $dirStart + length($$dataPt)) {
247 my $buff = substr($$dataPt, $dirStart, $dirLen);
248 $dataPt = \$buff;
249 } else {
250 pos($$dataPt) = $$dirInfo{DirStart};
251 }
252 my $verbose = $exifTool->Options('Verbose');
253 my $success = 0;
254 my $section = '';
255 pos($$dataPt) = 0;
256
257 # this regular expression is a bit complex, but basically we are looking for
258 # section headers (ie. "[Camera Info]") and tag/value pairs (ie. "tag=value",
259 # where "value" may contain white space), separated by spaces or CR/LF.
260 # (APP12 uses CR/LF, but Olympus TextualInfo is similar and uses spaces)
261 while ($$dataPt =~ /(\[.*?\]|[\w#-]+=[\x20-\x7e]+?(?=\s*([\n\r\0]|[\w#-]+=|\[|$)))/g) {
262 my $token = $1;
263 # was this a section name?
264 if ($token =~ /^\[(.*)\]/) {
265 $exifTool->VerboseDir($1) if $verbose;
266 $section = ($token =~ /\[(\S+) ?Info\]/i) ? $1 : '';
267 $success = 1;
268 next;
269 }
270 $exifTool->VerboseDir($$dirInfo{DirName}) if $verbose and not $success;
271 $success = 1;
272 my ($tag, $val) = ($token =~ /(\S+)=(.+)/);
273 my $tagInfo = $exifTool->GetTagInfo($tagTablePtr, $tag);
274 $verbose and $exifTool->VerboseInfo($tag, $tagInfo, Value => $val);
275 unless ($tagInfo) {
276 # add new tag to table
277 $tagInfo = { Name => ucfirst $tag };
278 # put in Camera group if information in "Camera" section
279 $$tagInfo{Groups} = { 2 => 'Camera' } if $section =~ /camera/i;
280 Image::ExifTool::AddTagToTable($tagTablePtr, $tag, $tagInfo);
281 }
282 $exifTool->FoundTag($tagInfo, $val);
283 }
284 return $success;
285}
286
287
2881; #end
289
290__END__
291
292=head1 NAME
293
294Image::ExifTool::APP12 - Read APP12 meta information
295
296=head1 SYNOPSIS
297
298This module is loaded automatically by Image::ExifTool when required.
299
300=head1 DESCRIPTION
301
302This module contains definitions required by Image::ExifTool to interpret
303APP12 meta information.
304
305=head1 AUTHOR
306
307Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca)
308
309This library is free software; you can redistribute it and/or modify it
310under the same terms as Perl itself.
311
312=head1 ACKNOWLEDGEMENTS
313
314Thanks to Heinrich Giesen for his help decoding APP12 "Ducky" information.
315
316=head1 SEE ALSO
317
318L<Image::ExifTool::TagNames/APP12 Tags>,
319L<Image::ExifTool(3pm)|Image::ExifTool>
320
321=cut
Note: See TracBrowser for help on using the repository browser.