source: gsdl/trunk/perllib/cpan/Image/ExifTool/Sony.pm@ 16842

Last change on this file since 16842 was 16842, checked in by davidb, 16 years ago

ExifTool added to cpan area to support metadata extraction from files such as JPEG. Primarily targetted as Image files (hence the Image folder name decided upon by the ExifTool author) it also can handle video such as flash and audio such as Wav

File size: 13.2 KB
Line 
1#------------------------------------------------------------------------------
2# File: Sony.pm
3#
4# Description: Sony EXIF Maker Notes tags
5#
6# Revisions: 04/06/2004 - P. Harvey Created
7#
8# References: 1) http://www.cybercom.net/~dcoffin/dcraw/
9# 2) http://homepage3.nifty.com/kamisaka/makernote/makernote_sony.htm
10# 3) Thomas Bodenmann private communication
11#------------------------------------------------------------------------------
12
13package Image::ExifTool::Sony;
14
15use strict;
16use vars qw($VERSION);
17use Image::ExifTool qw(:DataAccess :Utils);
18use Image::ExifTool::Exif;
19use Image::ExifTool::Minolta;
20
21$VERSION = '1.10';
22
23sub ProcessSRF($$$);
24sub ProcessSR2($$$);
25
26my %sonyLensIDs; # filled in based on Minolta LensID's
27
28%Image::ExifTool::Sony::Main = (
29 WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
30 CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
31 GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
32 0x0e00 => {
33 Name => 'PrintIM',
34 Description => 'Print Image Matching',
35 SubDirectory => {
36 TagTable => 'Image::ExifTool::PrintIM::Main',
37 },
38 },
39 # 0xb020 string with observed values "Standard", "None" and "Real"
40 0xb021 => { #2
41 Name => 'ColorTemperature',
42 PrintConv => '$val ? $val : "Auto"',
43 },
44 0xb023 => { #PH (A100)
45 Name => 'SceneMode',
46 PrintConv => {
47 0 => 'Manual (P,A,S or M)',
48 1 => 'Portrait',
49 4 => 'Sunset',
50 5 => 'Sports',
51 6 => 'Landscape',
52 8 => 'Macro',
53 16 => 'Auto',
54 17 => 'Night Portrait',
55 },
56 },
57 0xb024 => { #PH (A100)
58 Name => 'ZoneMatching',
59 PrintConv => {
60 0 => 'ISO Setting Used',
61 1 => 'High Key',
62 2 => 'Low Key',
63 },
64 },
65 0xb025 => { #PH (A100)
66 Name => 'DynamicRangeOptimizer',
67 PrintConv => {
68 0 => 'Off',
69 1 => 'Standard',
70 2 => 'Advanced',
71 },
72 },
73 0xb026 => { #PH (A100)
74 Name => 'ImageStabilization',
75 PrintConv => { 0 => 'Off', 1 => 'On' },
76 },
77 0xb027 => { #2
78 Name => 'LensID',
79 PrintConv => \%sonyLensIDs,
80 },
81 0xb028 => { #2
82 # (used by the DSLR-A100)
83 Name => 'MinoltaMakerNote',
84 Flags => 'SubIFD',
85 SubDirectory => {
86 TagTable => 'Image::ExifTool::Minolta::Main',
87 Start => '$val',
88 },
89 },
90 0xb029 => { #2
91 Name => 'ColorMode',
92 Writable => 'int32u',
93 PrintConv => {
94 0 => 'Standard',
95 1 => 'Vivid',
96 2 => 'Portrait',
97 3 => 'Landscape',
98 4 => 'Sunset',
99 5 => 'Night Scene',
100 6 => 'B&W',
101 7 => 'Adobe RGB',
102 },
103 },
104 0xb040 => { #2
105 Name => 'Macro',
106 PrintConv => { 0 => 'Off', 1 => 'On' },
107 },
108 0xb041 => { #2
109 Name => 'ExposureMode',
110 PrintConv => {
111 0 => 'Auto',
112 5 => 'Landscape',
113 6 => 'Program',
114 7 => 'Aperture Priority',
115 8 => 'Shutter Priority',
116 9 => 'Night Scene',
117 15 => 'Manual',
118 },
119 },
120 0xb047 => { #2
121 Name => 'Quality',
122 PrintConv => {
123 0 => 'Normal',
124 1 => 'Fine',
125 },
126 },
127 0xb04e => { #2
128 Name => 'LongExposureNoiseReduction',
129 PrintConv => { 0 => 'Off', 1 => 'On' },
130 },
131);
132
133# tag table for Sony RAW Format
134%Image::ExifTool::Sony::SRF = (
135 PROCESS_PROC => \&ProcessSRF,
136 GROUPS => { 0 => 'MakerNotes', 1 => 'SRF#', 2 => 'Camera' },
137 NOTES => q{
138 The maker notes in SRF (Sony Raw Format) images contain 7 IFD's (with family
139 1 group names SRF0 through SRF6). SRF0 through SRF5 use these Sony tags,
140 while SRF6 uses standard EXIF tags. All information other than SRF0 is
141 encrypted, but thanks to Dave Coffin the decryption algorithm is known.
142 },
143 0 => {
144 Name => 'SRF2_Key',
145 Notes => 'key to decrypt maker notes from the start of SRF2',
146 RawConv => '$self->{SRF2_Key} = $val',
147 },
148 1 => {
149 Name => 'DataKey',
150 Notes => 'key to decrypt the rest of the file from the end of the maker notes',
151 RawConv => '$self->{SRFDataKey} = $val',
152 },
153);
154
155# tag table for Sony RAW 2 Format Private IFD (ref 1)
156%Image::ExifTool::Sony::SR2Private = (
157 PROCESS_PROC => \&ProcessSR2,
158 GROUPS => { 0 => 'MakerNotes', 1 => 'SR2', 2 => 'Camera' },
159 NOTES => q{
160 The SR2 format uses the DNGPrivateData tag to reference a private IFD
161 containing these tags.
162 },
163 0x7200 => {
164 Name => 'SR2SubIFDOffset',
165 # (adjusting offset messes up calculations for AdobeSR2 in DNG images)
166 # Flags => 'IsOffset',
167 OffsetPair => 0x7201,
168 RawConv => '$self->{SR2SubIFDOffset} = $val',
169 },
170 0x7201 => {
171 Name => 'SR2SubIFDLength',
172 OffsetPair => 0x7200,
173 RawConv => '$self->{SR2SubIFDLength} = $val',
174 },
175 0x7221 => {
176 Name => 'SR2SubIFDKey',
177 Format => 'int32u',
178 Notes => 'key to decrypt SR2SubIFD',
179 RawConv => '$self->{SR2SubIFDKey} = $val',
180 },
181);
182
183%Image::ExifTool::Sony::SR2SubIFD = (
184 GROUPS => { 0 => 'MakerNotes', 1 => 'SR2', 2 => 'Camera' },
185 NOTES => 'Tags in the encrypted SR2SubIFD',
186 0x7303 => 'WB_GRBGLevels', #1
187 0x74c0 => { #PH
188 Name => 'SR2DataIFD',
189 Flags => 'SubIFD',
190 SubDirectory => {
191 TagTable => 'Image::ExifTool::Sony::SR2DataIFD',
192 Start => '$val',
193 MaxSubdirs => 6,
194 },
195 },
196 0x74a0 => 'MaxApertureAtMaxFocal', #PH
197 0x74a1 => 'MaxApertureAtMinFocal', #PH
198);
199
200%Image::ExifTool::Sony::SR2DataIFD = (
201 GROUPS => { 0 => 'MakerNotes', 1 => 'SR2', 2 => 'Camera' },
202 0x7770 => 'ColorMode', #PH
203);
204
205# fill in Sony LensID lookup based on Minolta values
206{
207 my $id;
208 foreach $id (keys %Image::ExifTool::Minolta::minoltaLensIDs) {
209 # higher numbered lenses are missing last digit of ID
210 my $sonyID = ($id < 10000) ? $id : int($id / 10);
211 $sonyLensIDs{$sonyID} = $Image::ExifTool::Minolta::minoltaLensIDs{$id};
212 }
213}
214
215#------------------------------------------------------------------------------
216# decrypt Sony data (ref 1)
217# Inputs: 0) data reference, 1) start offset, 2) data length, 3) decryption key
218# Returns: nothing (original data buffer is updated with decrypted data)
219sub Decrypt($$$$)
220{
221 my ($dataPt, $start, $len, $key) = @_;
222 my ($i, $j, @pad);
223 my $words = $len / 4;
224
225 for ($i=0; $i<4; ++$i) {
226 my $lo = ($key & 0xffff) * 0x0edd + 1;
227 my $hi = ($key >> 16) * 0x0edd + ($key & 0xffff) * 0x02e9 + ($lo >> 16);
228 $pad[$i] = $key = (($hi & 0xffff) << 16) + ($lo & 0xffff);
229 }
230 $pad[3] = ($pad[3] << 1 | ($pad[0]^$pad[2]) >> 31) & 0xffffffff;
231 for ($i=4; $i<0x7f; ++$i) {
232 $pad[$i] = (($pad[$i-4]^$pad[$i-2]) << 1 |
233 ($pad[$i-3]^$pad[$i-1]) >> 31) & 0xffffffff;
234 }
235 my @data = unpack("x$start N$words", $$dataPt);
236 for ($i=0x7f,$j=0; $j<$words; ++$i,++$j) {
237 $data[$j] ^= $pad[$i & 0x7f] = $pad[($i+1) & 0x7f] ^ $pad[($i+65) & 0x7f];
238 }
239 substr($$dataPt, $start, $words*4) = pack('N*', @data);
240}
241
242#------------------------------------------------------------------------------
243# Process SRF maker notes
244# Inputs: 0) ExifTool object reference, 1) reference to directory information
245# 2) pointer to tag table
246# Returns: 1 on success
247sub ProcessSRF($$$)
248{
249 my ($exifTool, $dirInfo, $tagTablePtr) = @_;
250 my $dataPt = $$dirInfo{DataPt};
251 my $dirLen = $$dirInfo{DirLen};
252 my $start = $$dirInfo{DirStart};
253 my $verbose = $exifTool->Options('Verbose');
254
255 # process IFD chain
256 my ($ifd, $success);
257 for ($ifd=0; ; ) {
258 my $srf = $$dirInfo{DirName} = "SRF$ifd";
259 my $srfTable = $tagTablePtr;
260 # SRF6 uses standard EXIF tags
261 $srfTable = GetTagTable('Image::ExifTool::Exif::Main') if $ifd == 6;
262 $exifTool->{SET_GROUP1} = $srf;
263 $success = Image::ExifTool::Exif::ProcessExif($exifTool, $dirInfo, $srfTable);
264 delete $exifTool->{SET_GROUP1};
265 last unless $success;
266#
267# get pointer to next IFD
268#
269 my $count = Get16u($dataPt, $$dirInfo{DirStart});
270 my $dirEnd = $$dirInfo{DirStart} + 2 + $count * 12;
271 last if $dirEnd + 4 > length($$dataPt);
272 my $nextIFD = Get32u($dataPt, $dirEnd);
273 last unless $nextIFD;
274 $nextIFD -= $$dirInfo{DataPos}; # adjust for position of makernotes data
275 $$dirInfo{DirStart} = $nextIFD;
276#
277# decrypt next IFD data if necessary
278#
279 ++$ifd;
280 my ($key, $len);
281 if ($ifd == 1) {
282 # get the key to decrypt IFD1
283 my $cp = $start + 0x8ddc; # why?
284 my $ip = $cp + 4 * unpack("x$cp C", $$dataPt);
285 $key = unpack("x$ip N", $$dataPt);
286 $len = $cp + $nextIFD; # decrypt up to $cp
287 } elsif ($ifd == 2) {
288 # get the key to decrypt IFD2
289 $key = $exifTool->{SRF2_Key};
290 $len = length($$dataPt) - $nextIFD; # decrypt rest of maker notes
291 } else {
292 next; # no decryption needed
293 }
294 # decrypt data
295 Decrypt($dataPt, $nextIFD, $len, $key) if defined $key;
296 next unless $verbose > 2;
297 # display decrypted data in verbose mode
298 $exifTool->VerboseDir("Decrypted SRF$ifd", 0, $nextIFD + $len);
299 my %parms = (
300 Prefix => "$exifTool->{INDENT} ",
301 Start => $nextIFD,
302 DataPos => $$dirInfo{DataPos},
303 Out => $exifTool->Options('TextOut'),
304 );
305 $parms{MaxLen} = 96 unless $verbose > 3;
306 Image::ExifTool::HexDump($dataPt, $len, %parms);
307 }
308}
309
310#------------------------------------------------------------------------------
311# Process SR2 data
312# Inputs: 0) ExifTool object reference, 1) reference to directory information
313# 2) pointer to tag table
314# Returns: 1 on success
315sub ProcessSR2($$$)
316{
317 my ($exifTool, $dirInfo, $tagTablePtr) = @_;
318 my $dataPt = $$dirInfo{DataPt};
319 my $dataPos = $$dirInfo{DataPos};
320 my $dataLen = $$dirInfo{DataLen} || length $$dataPt;
321 my $dirLen = $$dirInfo{DirLen};
322 my $verbose = $exifTool->Options('Verbose');
323 my $result = Image::ExifTool::Exif::ProcessExif($exifTool, $dirInfo, $tagTablePtr);
324 return $result unless $result;
325 my $offset = $exifTool->{SR2SubIFDOffset};
326 my $length = $exifTool->{SR2SubIFDLength};
327 my $key = $exifTool->{SR2SubIFDKey};
328 my $raf = $$dirInfo{RAF};
329 my $base = $$dirInfo{Base} || 0;
330 if ($offset and $length and defined $key) {
331 my $buff;
332 # read encrypted SR2SubIFD from file
333 if (($raf and $raf->Seek($offset+$base, 0) and
334 $raf->Read($buff, $length) == $length) or
335 # or read from data (when processing Adobe DNGPrivateData)
336 ($offset - $dataPos >= 0 and $offset - $dataPos + $length < $dataLen and
337 ($buff = substr($$dataPt, $offset - $dataPos, $length))))
338 {
339 Decrypt(\$buff, 0, $length, $key);
340 # display decrypted data in verbose mode
341 if ($verbose > 2) {
342 $exifTool->VerboseDir("Decrypted SR2SubIFD", 0, $length);
343 my %parms = (
344 Out => $exifTool->{OPTIONS}->{TextOut},
345 Prefix => $exifTool->{INDENT},
346 Addr => $offset + $base,
347 );
348 $parms{MaxLen} = 96 unless $verbose > 3;
349 Image::ExifTool::HexDump(\$buff, $length, %parms);
350 }
351 my %dirInfo = (
352 Base => $base,
353 DataPt => \$buff,
354 DataLen => length $buff,
355 DirStart => 0,
356 DirName => 'SR2SubIFD',
357 DataPos => $offset,
358 );
359 my $subTable = Image::ExifTool::GetTagTable('Image::ExifTool::Sony::SR2SubIFD');
360 $result = $exifTool->ProcessDirectory(\%dirInfo, $subTable);
361
362 } else {
363 $exifTool->Warn('Error reading SR2 data');
364 }
365 }
366 delete $exifTool->{SR2SubIFDOffset};
367 delete $exifTool->{SR2SubIFDLength};
368 delete $exifTool->{SR2SubIFDKey};
369 return $result;
370}
371
3721; # end
373
374__END__
375
376=head1 NAME
377
378Image::ExifTool::Sony - Sony EXIF maker notes tags
379
380=head1 SYNOPSIS
381
382This module is loaded automatically by Image::ExifTool when required.
383
384=head1 DESCRIPTION
385
386This module contains definitions required by Image::ExifTool to
387interpret Sony maker notes EXIF meta information.
388
389=head1 NOTES
390
391The Sony maker notes use the standard EXIF IFD structure, but unfortunately
392the entries are large blocks of binary data for which I can find no
393documentation. You can use "exiftool -v3" to dump these blocks in hex.
394
395=head1 AUTHOR
396
397Copyright 2003-2007, Phil Harvey (phil at owl.phy.queensu.ca)
398
399This library is free software; you can redistribute it and/or modify it
400under the same terms as Perl itself.
401
402=head1 REFERENCES
403
404=over 4
405
406=item L<http://www.cybercom.net/~dcoffin/dcraw/>
407
408=item L<http://homepage3.nifty.com/kamisaka/makernote/makernote_sony.htm>
409
410=back
411
412=head1 ACKNOWLEDGEMENTS
413
414Thanks to Thomas Bodenmann for providing information about the LensID's.
415
416=head1 SEE ALSO
417
418L<Image::ExifTool::TagNames/Sony Tags>,
419L<Image::ExifTool(3pm)|Image::ExifTool>
420
421=cut
Note: See TracBrowser for help on using the repository browser.