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 (2006/08/06)
|
---|
10 | # 3) Thomas Bodenmann private communication
|
---|
11 | # 4) Philippe Devaux private communication (A700)
|
---|
12 | # 5) Marcus Holland-Moritz private communication (A700)
|
---|
13 | # 6) Andrey Tverdokhleb private communication
|
---|
14 | # 7) Rudiger Lange private communication (A700)
|
---|
15 | # 8) Igal Milchtaich private communication
|
---|
16 | # 9) Michael Reitinger private communication (DSC-TX7)
|
---|
17 | # 10) http://www.klingebiel.com/tempest/hd/pmp.html
|
---|
18 | # 11 Mike Battilana private communication
|
---|
19 | # JD) Jens Duttke private communication
|
---|
20 | #------------------------------------------------------------------------------
|
---|
21 |
|
---|
22 | package Image::ExifTool::Sony;
|
---|
23 |
|
---|
24 | use strict;
|
---|
25 | use vars qw($VERSION);
|
---|
26 | use Image::ExifTool qw(:DataAccess :Utils);
|
---|
27 | use Image::ExifTool::Exif;
|
---|
28 | use Image::ExifTool::Minolta;
|
---|
29 |
|
---|
30 | $VERSION = '1.50';
|
---|
31 |
|
---|
32 | sub ProcessSRF($$$);
|
---|
33 | sub ProcessSR2($$$);
|
---|
34 | sub WriteSR2($$$);
|
---|
35 |
|
---|
36 | my %sonyLensTypes; # filled in based on Minolta LensType's
|
---|
37 |
|
---|
38 | # ExposureProgram values (ref PH, mainly decoded from A200)
|
---|
39 | my %sonyExposureProgram = (
|
---|
40 | 0 => 'Auto', # (same as 'Program AE'?)
|
---|
41 | 1 => 'Manual',
|
---|
42 | 2 => 'Program AE',
|
---|
43 | 3 => 'Aperture-priority AE',
|
---|
44 | 4 => 'Shutter speed priority AE',
|
---|
45 | 8 => 'Program Shift A', #7
|
---|
46 | 9 => 'Program Shift S', #7
|
---|
47 | 19 => 'Night Portrait', # (A330)
|
---|
48 | 18 => 'Sunset', # (A330)
|
---|
49 | 17 => 'Sports', # (A330)
|
---|
50 | 21 => 'Macro', # (A330)
|
---|
51 | 20 => 'Landscape', # (A330)
|
---|
52 | 16 => 'Portrait', # (A330)
|
---|
53 | 35 => 'Auto No Flash', # (A330)
|
---|
54 | );
|
---|
55 |
|
---|
56 | my %binaryDataAttrs = (
|
---|
57 | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
---|
58 | WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
|
---|
59 | CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
|
---|
60 | WRITABLE => 1,
|
---|
61 | FIRST_ENTRY => 0,
|
---|
62 | );
|
---|
63 |
|
---|
64 | %Image::ExifTool::Sony::Main = (
|
---|
65 | WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
|
---|
66 | CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
|
---|
67 | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
|
---|
68 | 0x0102 => { #5/JD
|
---|
69 | Name => 'Quality',
|
---|
70 | Writable => 'int32u',
|
---|
71 | PrintConv => {
|
---|
72 | 0 => 'RAW',
|
---|
73 | 1 => 'Super Fine',
|
---|
74 | 2 => 'Fine',
|
---|
75 | 3 => 'Standard',
|
---|
76 | 4 => 'Economy',
|
---|
77 | 5 => 'Extra Fine',
|
---|
78 | 6 => 'RAW + JPEG',
|
---|
79 | 7 => 'Compressed RAW',
|
---|
80 | 8 => 'Compressed RAW + JPEG',
|
---|
81 | },
|
---|
82 | },
|
---|
83 | 0x0104 => { #5/JD
|
---|
84 | Name => 'FlashExposureComp',
|
---|
85 | Description => 'Flash Exposure Compensation',
|
---|
86 | Writable => 'rational64s',
|
---|
87 | },
|
---|
88 | 0x0105 => { #5/JD
|
---|
89 | Name => 'Teleconverter',
|
---|
90 | Writable => 'int32u',
|
---|
91 | PrintHex => 1,
|
---|
92 | PrintConv => {
|
---|
93 | 0 => 'None',
|
---|
94 | 72 => 'Minolta AF 2x APO (D)',
|
---|
95 | 80 => 'Minolta AF 2x APO II',
|
---|
96 | 136 => 'Minolta AF 1.4x APO (D)',
|
---|
97 | 144 => 'Minolta AF 1.4x APO II',
|
---|
98 | },
|
---|
99 | },
|
---|
100 | 0x0112 => { #JD
|
---|
101 | Name => 'WhiteBalanceFineTune',
|
---|
102 | Format => 'int32s',
|
---|
103 | Writable => 'int32u',
|
---|
104 | },
|
---|
105 | 0x0114 => [ #PH
|
---|
106 | {
|
---|
107 | Name => 'CameraSettings',
|
---|
108 | Condition => '$$self{Model} =~ /DSLR-A(200|230|300|350|700|850|900)\b/',
|
---|
109 | SubDirectory => {
|
---|
110 | TagTable => 'Image::ExifTool::Sony::CameraSettings',
|
---|
111 | ByteOrder => 'BigEndian',
|
---|
112 | },
|
---|
113 | },
|
---|
114 | {
|
---|
115 | Name => 'CameraSettings2',
|
---|
116 | Condition => '$$self{Model} =~ /DSLR-A(330|380)\b/',
|
---|
117 | SubDirectory => {
|
---|
118 | TagTable => 'Image::ExifTool::Sony::CameraSettings2',
|
---|
119 | ByteOrder => 'BigEndian',
|
---|
120 | },
|
---|
121 | },
|
---|
122 | {
|
---|
123 | Name => 'CameraSettingsUnknown',
|
---|
124 | SubDirectory => {
|
---|
125 | TagTable => 'Image::ExifTool::Sony::CameraSettingsUnknown',
|
---|
126 | ByteOrder => 'BigEndian',
|
---|
127 | },
|
---|
128 | },
|
---|
129 | ],
|
---|
130 | 0x0115 => { #JD
|
---|
131 | Name => 'WhiteBalance',
|
---|
132 | Writable => 'int32u',
|
---|
133 | PrintHex => 1,
|
---|
134 | PrintConv => {
|
---|
135 | 0x00 => 'Auto',
|
---|
136 | 0x01 => 'Color Temperature/Color Filter',
|
---|
137 | 0x10 => 'Daylight',
|
---|
138 | 0x20 => 'Cloudy',
|
---|
139 | 0x30 => 'Shade',
|
---|
140 | 0x40 => 'Tungsten',
|
---|
141 | 0x50 => 'Flash',
|
---|
142 | 0x60 => 'Fluorescent',
|
---|
143 | 0x70 => 'Custom',
|
---|
144 | },
|
---|
145 | },
|
---|
146 | 0x0e00 => {
|
---|
147 | Name => 'PrintIM',
|
---|
148 | Description => 'Print Image Matching',
|
---|
149 | SubDirectory => {
|
---|
150 | TagTable => 'Image::ExifTool::PrintIM::Main',
|
---|
151 | },
|
---|
152 | },
|
---|
153 | # the next 3 tags have a different meaning for some models (with format int32u)
|
---|
154 | 0x1000 => { #9 (F88, multi burst mode only)
|
---|
155 | Name => 'MultiBurstMode',
|
---|
156 | Condition => '$format eq "undef"',
|
---|
157 | Notes => 'MultiBurst tags valid only for models with this feature, like the F88',
|
---|
158 | Writable => 'undef',
|
---|
159 | Format => 'int8u',
|
---|
160 | PrintConv => { 0 => 'Off', 1 => 'On' },
|
---|
161 | },
|
---|
162 | 0x1001 => { #9 (F88, multi burst mode only)
|
---|
163 | Name => 'MultiBurstImageWidth',
|
---|
164 | Condition => '$format eq "int16u"',
|
---|
165 | Writable => 'int16u',
|
---|
166 | },
|
---|
167 | 0x1002 => { #9 (F88, multi burst mode only)
|
---|
168 | Name => 'MultiBurstImageHeight',
|
---|
169 | Condition => '$format eq "int16u"',
|
---|
170 | Writable => 'int16u',
|
---|
171 | },
|
---|
172 | 0x1003 => { #9 (TX7, panorama mode only)
|
---|
173 | Name => 'Panorama',
|
---|
174 | SubDirectory => { TagTable => 'Image::ExifTool::Sony::Panorama' },
|
---|
175 | },
|
---|
176 | 0x2001 => { #PH (JPEG images from all DSLR's except the A100)
|
---|
177 | Name => 'PreviewImage',
|
---|
178 | Writable => 'undef',
|
---|
179 | DataTag => 'PreviewImage',
|
---|
180 | # Note: the preview data starts with a 32-byte proprietary Sony header
|
---|
181 | WriteCheck => 'return $val=~/^(none|.{32}\xff\xd8\xff)/s ? undef : "Not a valid image"',
|
---|
182 | RawConv => q{
|
---|
183 | return \$val if $val =~ /^Binary/;
|
---|
184 | $val = substr($val,0x20) if length($val) > 0x20;
|
---|
185 | return \$val if $val =~ s/^.(\xd8\xff\xdb)/\xff$1/s;
|
---|
186 | $$self{PreviewError} = 1 unless $val eq 'none';
|
---|
187 | return undef;
|
---|
188 | },
|
---|
189 | # must construct 0x20-byte header which contains length, width and height
|
---|
190 | ValueConvInv => q{
|
---|
191 | return 'none' unless $val;
|
---|
192 | my $e = new Image::ExifTool;
|
---|
193 | my $info = $e->ImageInfo(\$val,'ImageWidth','ImageHeight');
|
---|
194 | return undef unless $$info{ImageWidth} and $$info{ImageHeight};
|
---|
195 | my $size = Set32u($$info{ImageWidth}) . Set32u($$info{ImageHeight});
|
---|
196 | return Set32u(length $val) . $size . ("\0" x 8) . $size . ("\0" x 4) . $val;
|
---|
197 | },
|
---|
198 | },
|
---|
199 | # 0x2002 - probably Sharpness (PH guess)
|
---|
200 | 0x2004 => { #PH (NEX-5)
|
---|
201 | Name => 'Contrast',
|
---|
202 | Writable => 'int32s',
|
---|
203 | PrintConv => '$val > 0 ? "+$val" : $val',
|
---|
204 | PrintConvInv => '$val',
|
---|
205 | },
|
---|
206 | 0x2005 => { #PH (NEX-5)
|
---|
207 | Name => 'Saturation',
|
---|
208 | Writable => 'int32s',
|
---|
209 | PrintConv => '$val > 0 ? "+$val" : $val',
|
---|
210 | PrintConvInv => '$val',
|
---|
211 | },
|
---|
212 | 0x2006 => { #PH
|
---|
213 | Name => 'Sharpness',
|
---|
214 | Writable => 'int32s',
|
---|
215 | PrintConv => '$val > 0 ? "+$val" : $val',
|
---|
216 | PrintConvInv => '$val',
|
---|
217 | },
|
---|
218 | 0x2007 => { #PH
|
---|
219 | Name => 'Brightness',
|
---|
220 | Writable => 'int32s',
|
---|
221 | PrintConv => '$val > 0 ? "+$val" : $val',
|
---|
222 | PrintConvInv => '$val',
|
---|
223 | },
|
---|
224 | 0x2008 => { #PH
|
---|
225 | Name => 'LongExposureNoiseReduction',
|
---|
226 | Writable => 'int32u',
|
---|
227 | PrintHex => 1,
|
---|
228 | PrintConv => {
|
---|
229 | 0 => 'Off',
|
---|
230 | 1 => 'On',
|
---|
231 | 0xffff0000 => 'Off 2',
|
---|
232 | 0xffff0001 => 'On 2',
|
---|
233 | 0xffffffff => 'n/a',
|
---|
234 | },
|
---|
235 | },
|
---|
236 | 0x2009 => { #PH
|
---|
237 | Name => 'HighISONoiseReduction',
|
---|
238 | Writable => 'int16u',
|
---|
239 | PrintConv => {
|
---|
240 | 0 => 'Off',
|
---|
241 | 1 => 'Low',
|
---|
242 | 2 => 'Normal',
|
---|
243 | 3 => 'High',
|
---|
244 | 256 => 'Auto',
|
---|
245 | 65535 => 'n/a',
|
---|
246 | },
|
---|
247 | },
|
---|
248 | 0x200a => { #PH (A550)
|
---|
249 | Name => 'HDR',
|
---|
250 | Writable => 'int32u',
|
---|
251 | PrintHex => 1,
|
---|
252 | PrintConv => {
|
---|
253 | 0x0 => 'Off',
|
---|
254 | 0x10001 => 'Auto',
|
---|
255 | 0x10010 => '1.0 EV', # (NEX_5)
|
---|
256 | 0x10011 => '1.5 EV',
|
---|
257 | 0x10012 => '2.0 EV',
|
---|
258 | 0x10013 => '2.5 EV',
|
---|
259 | 0x10014 => '3.0 EV',
|
---|
260 | 0x10015 => '3.5 EV',
|
---|
261 | 0x10016 => '4.0 EV',
|
---|
262 | 0x10017 => '4.5 EV',
|
---|
263 | 0x10018 => '5.0 EV',
|
---|
264 | 0x10019 => '5.5 EV',
|
---|
265 | 0x1001a => '6.0 EV', # (SLT-A55V)
|
---|
266 | },
|
---|
267 | },
|
---|
268 | 0x200b => { #PH
|
---|
269 | Name => 'MultiFrameNoiseReduction',
|
---|
270 | Writable => 'int32u',
|
---|
271 | PrintConv => {
|
---|
272 | 0 => 'Off',
|
---|
273 | 1 => 'On',
|
---|
274 | 255 => 'n/a',
|
---|
275 | },
|
---|
276 | },
|
---|
277 | 0x3000 => {
|
---|
278 | Name => 'ShotInfo',
|
---|
279 | SubDirectory => {
|
---|
280 | TagTable => 'Image::ExifTool::Sony::ShotInfo',
|
---|
281 | },
|
---|
282 | },
|
---|
283 | # 0x3000: data block that includes DateTimeOriginal string
|
---|
284 | 0xb000 => { #8
|
---|
285 | Name => 'FileFormat',
|
---|
286 | Writable => 'int8u',
|
---|
287 | Count => 4,
|
---|
288 | # dynamically set the file type to SR2 because we could have assumed ARW up till now
|
---|
289 | RawConv => q{
|
---|
290 | $self->OverrideFileType($$self{TIFF_TYPE} = 'SR2') if $val eq '1 0 0 0';
|
---|
291 | return $val;
|
---|
292 | },
|
---|
293 | PrintConv => {
|
---|
294 | '0 0 0 2' => 'JPEG',
|
---|
295 | '1 0 0 0' => 'SR2',
|
---|
296 | '2 0 0 0' => 'ARW 1.0',
|
---|
297 | '3 0 0 0' => 'ARW 2.0',
|
---|
298 | '3 1 0 0' => 'ARW 2.1',
|
---|
299 | '3 2 0 0' => 'ARW 2.2', # (NEX-5)
|
---|
300 | # what about cRAW images?
|
---|
301 | },
|
---|
302 | },
|
---|
303 | 0xb001 => { # ref http://forums.dpreview.com/forums/read.asp?forum=1037&message=33609644
|
---|
304 | # (ARW and SR2 images only)
|
---|
305 | Name => 'SonyModelID',
|
---|
306 | Writable => 'int16u',
|
---|
307 | PrintConvColumns => 2,
|
---|
308 | PrintConv => {
|
---|
309 | 2 => 'DSC-R1',
|
---|
310 | 256 => 'DSLR-A100',
|
---|
311 | 257 => 'DSLR-A900',
|
---|
312 | 258 => 'DSLR-A700',
|
---|
313 | 259 => 'DSLR-A200',
|
---|
314 | 260 => 'DSLR-A350',
|
---|
315 | 261 => 'DSLR-A300',
|
---|
316 | 263 => 'DSLR-A380/A390', #PH (A390)
|
---|
317 | 264 => 'DSLR-A330',
|
---|
318 | 265 => 'DSLR-A230',
|
---|
319 | 266 => 'DSLR-A290', #PH
|
---|
320 | 269 => 'DSLR-A850',
|
---|
321 | 273 => 'DSLR-A550',
|
---|
322 | 274 => 'DSLR-A500', #PH
|
---|
323 | 275 => 'DSLR-A450', # (http://dev.exiv2.org/issues/show/0000611)
|
---|
324 | 278 => 'NEX-5', #PH
|
---|
325 | 279 => 'NEX-3', #PH
|
---|
326 | 280 => 'SLT-A33', #PH
|
---|
327 | 281 => 'SLT-A55V', #PH
|
---|
328 | 282 => 'DSLR-A560', #PH
|
---|
329 | 283 => 'DSLR-A580', # (http://u88.n24.queensu.ca/exiftool/forum/index.php/topic,2881.0.html)
|
---|
330 | },
|
---|
331 | },
|
---|
332 | 0xb020 => { #2
|
---|
333 | Name => 'ColorReproduction',
|
---|
334 | # observed values: None, Standard, Vivid, Real, AdobeRGB - PH
|
---|
335 | Writable => 'string',
|
---|
336 | },
|
---|
337 | 0xb021 => { #2
|
---|
338 | Name => 'ColorTemperature',
|
---|
339 | Writable => 'int32u',
|
---|
340 | PrintConv => '$val ? $val : "Auto"',
|
---|
341 | PrintConvInv => '$val=~/Auto/i ? 0 : $val',
|
---|
342 | },
|
---|
343 | 0xb022 => { #7
|
---|
344 | Name => 'ColorCompensationFilter',
|
---|
345 | Format => 'int32s',
|
---|
346 | Writable => 'int32u', # (written incorrectly as unsigned by Sony)
|
---|
347 | Notes => 'negative is green, positive is magenta',
|
---|
348 | },
|
---|
349 | 0xb023 => { #PH (A100) - (set by mode dial)
|
---|
350 | Name => 'SceneMode',
|
---|
351 | Writable => 'int32u',
|
---|
352 | PrintConv => \%Image::ExifTool::Minolta::minoltaSceneMode,
|
---|
353 | },
|
---|
354 | 0xb024 => { #PH (A100)
|
---|
355 | Name => 'ZoneMatching',
|
---|
356 | Writable => 'int32u',
|
---|
357 | PrintConv => {
|
---|
358 | 0 => 'ISO Setting Used',
|
---|
359 | 1 => 'High Key',
|
---|
360 | 2 => 'Low Key',
|
---|
361 | },
|
---|
362 | },
|
---|
363 | 0xb025 => { #PH (A100)
|
---|
364 | Name => 'DynamicRangeOptimizer',
|
---|
365 | Writable => 'int32u',
|
---|
366 | PrintConv => {
|
---|
367 | 0 => 'Off',
|
---|
368 | 1 => 'Standard',
|
---|
369 | 2 => 'Advanced Auto',
|
---|
370 | 3 => 'Auto', # (A550)
|
---|
371 | 8 => 'Advanced Lv1', #JD
|
---|
372 | 9 => 'Advanced Lv2', #JD
|
---|
373 | 10 => 'Advanced Lv3', #JD
|
---|
374 | 11 => 'Advanced Lv4', #JD
|
---|
375 | 12 => 'Advanced Lv5', #JD
|
---|
376 | 16 => 'Lv1', # (NEX_5)
|
---|
377 | 17 => 'Lv2',
|
---|
378 | 18 => 'Lv3',
|
---|
379 | 19 => 'Lv4',
|
---|
380 | 20 => 'Lv5',
|
---|
381 | },
|
---|
382 | },
|
---|
383 | 0xb026 => { #PH (A100)
|
---|
384 | Name => 'ImageStabilization',
|
---|
385 | Writable => 'int32u',
|
---|
386 | PrintConv => { 0 => 'Off', 1 => 'On' },
|
---|
387 | },
|
---|
388 | 0xb027 => { #2
|
---|
389 | Name => 'LensType',
|
---|
390 | Writable => 'int32u',
|
---|
391 | SeparateTable => 1,
|
---|
392 | PrintConv => \%sonyLensTypes,
|
---|
393 | },
|
---|
394 | 0xb028 => { #2
|
---|
395 | # (used by the DSLR-A100)
|
---|
396 | Name => 'MinoltaMakerNote',
|
---|
397 | # must check for zero since apparently a value of zero indicates the IFD doesn't exist
|
---|
398 | # (dumb Sony -- they shouldn't write this tag if the IFD is missing!)
|
---|
399 | Condition => '$$valPt ne "\0\0\0\0"',
|
---|
400 | Flags => 'SubIFD',
|
---|
401 | SubDirectory => {
|
---|
402 | TagTable => 'Image::ExifTool::Minolta::Main',
|
---|
403 | Start => '$val',
|
---|
404 | },
|
---|
405 | },
|
---|
406 | 0xb029 => { #2 (set by creative style menu)
|
---|
407 | Name => 'ColorMode',
|
---|
408 | Writable => 'int32u',
|
---|
409 | PrintConv => \%Image::ExifTool::Minolta::sonyColorMode,
|
---|
410 | },
|
---|
411 | 0xb02b => { #PH (A550 JPEG and A200, A230, A300, A350, A380, A700 and A900 ARW)
|
---|
412 | Name => 'FullImageSize',
|
---|
413 | Writable => 'int32u',
|
---|
414 | Count => 2,
|
---|
415 | # values stored height first, so swap to get "width height"
|
---|
416 | ValueConv => 'join(" ", reverse split(" ", $val))',
|
---|
417 | ValueConvInv => 'join(" ", reverse split(" ", $val))',
|
---|
418 | PrintConv => '$val =~ tr/ /x/; $val',
|
---|
419 | PrintConvInv => '$val =~ tr/x/ /; $val',
|
---|
420 | },
|
---|
421 | 0xb02c => { #PH (A550 JPEG and A200, A230, A300, A350, A380, A700 and A900 ARW)
|
---|
422 | Name => 'PreviewImageSize',
|
---|
423 | Writable => 'int32u',
|
---|
424 | Count => 2,
|
---|
425 | ValueConv => 'join(" ", reverse split(" ", $val))',
|
---|
426 | ValueConvInv => 'join(" ", reverse split(" ", $val))',
|
---|
427 | PrintConv => '$val =~ tr/ /x/; $val',
|
---|
428 | PrintConvInv => '$val =~ tr/x/ /; $val',
|
---|
429 | },
|
---|
430 | 0xb040 => { #2
|
---|
431 | Name => 'Macro',
|
---|
432 | Writable => 'int16u',
|
---|
433 | RawConv => '$val == 65535 ? undef : $val',
|
---|
434 | PrintConv => {
|
---|
435 | 0 => 'Off',
|
---|
436 | 1 => 'On',
|
---|
437 | 2 => 'Close Focus', #9
|
---|
438 | 65535 => 'n/a', #PH (A100)
|
---|
439 | },
|
---|
440 | },
|
---|
441 | 0xb041 => { #2
|
---|
442 | Name => 'ExposureMode',
|
---|
443 | Writable => 'int16u',
|
---|
444 | RawConv => '$val == 65535 ? undef : $val',
|
---|
445 | PrintConv => {
|
---|
446 | 0 => 'Auto',
|
---|
447 | 1 => 'Portrait', #PH (HX1)
|
---|
448 | 2 => 'Beach', #9
|
---|
449 | 4 => 'Snow', #9
|
---|
450 | 5 => 'Landscape',
|
---|
451 | 6 => 'Program',
|
---|
452 | 7 => 'Aperture Priority',
|
---|
453 | 8 => 'Shutter Priority',
|
---|
454 | 9 => 'Night Scene / Twilight',#2/9
|
---|
455 | 10 => 'Hi-Speed Shutter', #9
|
---|
456 | 11 => 'Twilight Portrait', #9
|
---|
457 | 12 => 'Soft Snap', #9
|
---|
458 | 13 => 'Fireworks', #9
|
---|
459 | 14 => 'Smile Shutter', #9 (T200)
|
---|
460 | 15 => 'Manual',
|
---|
461 | 18 => 'High Sensitivity', #9
|
---|
462 | 20 => 'Advanced Sports Shooting', #9
|
---|
463 | 29 => 'Underwater', #9
|
---|
464 | 33 => 'Gourmet', #9
|
---|
465 | 34 => 'Panorama', #PH (HX1)
|
---|
466 | 35 => 'Handheld Twilight', #PH (HX1/TX1)
|
---|
467 | 36 => 'Anti Motion Blur', #PH (TX1)
|
---|
468 | 37 => 'Pet', #9
|
---|
469 | 38 => 'Backlight Correction HDR', #9
|
---|
470 | 65535 => 'n/a', #PH (A100)
|
---|
471 | },
|
---|
472 | },
|
---|
473 | 0xb042 => { #9
|
---|
474 | Name => 'FocusMode',
|
---|
475 | Writable => 'int16u',
|
---|
476 | RawConv => '$val == 65535 ? undef : $val',
|
---|
477 | PrintConv => {
|
---|
478 | 1 => 'AF-S', # (called Single-AF by Sony)
|
---|
479 | 2 => 'AF-C', # (called Monitor-AF by Sony)
|
---|
480 | 4 => 'Permanent-AF', # (TX7)
|
---|
481 | 65535 => 'n/a', #PH (A100)
|
---|
482 | },
|
---|
483 | },
|
---|
484 | 0xb043 => { #9
|
---|
485 | Name => 'AFMode',
|
---|
486 | Writable => 'int16u',
|
---|
487 | RawConv => '$val == 65535 ? undef : $val',
|
---|
488 | PrintConv => {
|
---|
489 | 0 => 'Default', # (takes this value after camera reset, but can't be set back once changed)
|
---|
490 | 1 => 'Multi AF',
|
---|
491 | 2 => 'Center AF',
|
---|
492 | 3 => 'Spot AF',
|
---|
493 | 4 => 'Flexible Spot AF', # (T200)
|
---|
494 | 6 => 'Touch AF',
|
---|
495 | 14 => 'Manual Focus', # (T200)
|
---|
496 | 15 => 'Face Detected', # (not set when in face detect mode and no faces detected)
|
---|
497 | 65535 => 'n/a', #PH (A100)
|
---|
498 | },
|
---|
499 | },
|
---|
500 | 0xb044 => { #9
|
---|
501 | Name => 'AFIlluminator',
|
---|
502 | Writable => 'int16u',
|
---|
503 | RawConv => '$val == 65535 ? undef : $val',
|
---|
504 | PrintConv => {
|
---|
505 | 0 => 'Off',
|
---|
506 | 1 => 'Auto',
|
---|
507 | 65535 => 'n/a', #PH (A100)
|
---|
508 | },
|
---|
509 | },
|
---|
510 | 0xb047 => { #2
|
---|
511 | Name => 'Quality',
|
---|
512 | Writable => 'int16u',
|
---|
513 | RawConv => '$val == 65535 ? undef : $val',
|
---|
514 | PrintConv => {
|
---|
515 | 0 => 'Normal',
|
---|
516 | 1 => 'Fine',
|
---|
517 | 65535 => 'n/a', #PH (A100)
|
---|
518 | },
|
---|
519 | },
|
---|
520 | 0xb048 => { #9
|
---|
521 | Name => 'FlashLevel',
|
---|
522 | Writable => 'int16s',
|
---|
523 | RawConv => '$val == -1 ? undef : $val',
|
---|
524 | PrintConv => {
|
---|
525 | -32768 => 'Low',
|
---|
526 | -1 => 'n/a', #PH (A100)
|
---|
527 | 0 => 'Normal',
|
---|
528 | 32767 => 'High',
|
---|
529 | },
|
---|
530 | },
|
---|
531 | 0xb049 => { #9
|
---|
532 | Name => 'ReleaseMode',
|
---|
533 | Writable => 'int16u',
|
---|
534 | RawConv => '$val == 65535 ? undef : $val',
|
---|
535 | PrintConv => {
|
---|
536 | 0 => 'Normal',
|
---|
537 | 2 => 'Burst',
|
---|
538 | 5 => 'Exposure Bracketing',
|
---|
539 | 6 => 'White Balance Bracketing', # (HX5)
|
---|
540 | 65535 => 'n/a', #PH (A100)
|
---|
541 | },
|
---|
542 | },
|
---|
543 | 0xb04a => { #9
|
---|
544 | Name => 'SequenceNumber',
|
---|
545 | Notes => 'shot number in continuous burst',
|
---|
546 | Writable => 'int16u',
|
---|
547 | RawConv => '$val == 65535 ? undef : $val',
|
---|
548 | PrintConv => {
|
---|
549 | 0 => 'Single',
|
---|
550 | 65535 => 'n/a', #PH (A100)
|
---|
551 | OTHER => sub { shift }, # pass all other numbers straight through
|
---|
552 | },
|
---|
553 | },
|
---|
554 | 0xb04b => { #2/PH
|
---|
555 | Name => 'Anti-Blur',
|
---|
556 | Writable => 'int16u',
|
---|
557 | RawConv => '$val == 65535 ? undef : $val',
|
---|
558 | PrintConv => {
|
---|
559 | 0 => 'Off',
|
---|
560 | 1 => 'On (Continuous)', #PH (NC)
|
---|
561 | 2 => 'On (Shooting)', #PH (NC)
|
---|
562 | 65535 => 'n/a',
|
---|
563 | },
|
---|
564 | },
|
---|
565 | 0xb04e => { #2
|
---|
566 | Name => 'LongExposureNoiseReduction',
|
---|
567 | Writable => 'int16u',
|
---|
568 | RawConv => '$val == 65535 ? undef : $val',
|
---|
569 | PrintConv => {
|
---|
570 | 0 => 'Off',
|
---|
571 | 1 => 'On',
|
---|
572 | 65535 => 'n/a', #PH (A100)
|
---|
573 | },
|
---|
574 | },
|
---|
575 | 0xb04f => { #PH (TX1)
|
---|
576 | Name => 'DynamicRangeOptimizer',
|
---|
577 | Writable => 'int16u',
|
---|
578 | PrintConv => {
|
---|
579 | 0 => 'Off',
|
---|
580 | 1 => 'Standard',
|
---|
581 | 2 => 'Plus',
|
---|
582 | },
|
---|
583 | },
|
---|
584 | 0xb052 => { #PH (TX1)
|
---|
585 | Name => 'IntelligentAuto',
|
---|
586 | Writable => 'int16u',
|
---|
587 | PrintConv => {
|
---|
588 | 0 => 'Off',
|
---|
589 | 1 => 'On',
|
---|
590 | 2 => 'Advanced', #9
|
---|
591 | },
|
---|
592 | },
|
---|
593 | 0xb054 => { #PH (TX1)
|
---|
594 | Name => 'WhiteBalance',
|
---|
595 | Writable => 'int16u',
|
---|
596 | Priority => 0, # (until more values are filled in)
|
---|
597 | PrintConv => {
|
---|
598 | 0 => 'Auto',
|
---|
599 | 4 => 'Manual',
|
---|
600 | 5 => 'Daylight',
|
---|
601 | 6 => 'Cloudy', #9
|
---|
602 | 7 => 'White Flourescent', #9 (Sony "Fluorescent 1 (White)")
|
---|
603 | 8 => 'Cool White Flourescent', #9 (Sony "Fluorescent 2 (Natural White)")
|
---|
604 | 9 => 'Day White Flourescent', #9 (Sony "Fluorescent 3 (Day White)")
|
---|
605 | 14 => 'Incandescent',
|
---|
606 | 15 => 'Flash', #9
|
---|
607 | 17 => 'Underwater 1 (Blue Water)', #9
|
---|
608 | 18 => 'Underwater 2 (Green Water)', #9
|
---|
609 | },
|
---|
610 | },
|
---|
611 | );
|
---|
612 |
|
---|
613 | # "SEMC MS" maker notes
|
---|
614 | %Image::ExifTool::Sony::Ericsson = (
|
---|
615 | WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
|
---|
616 | CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
|
---|
617 | GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
|
---|
618 | NOTES => 'Maker notes found in images from some Sony Ericsson phones.',
|
---|
619 | 0x2000 => {
|
---|
620 | Name => 'MakerNoteVersion',
|
---|
621 | Writable => 'undef',
|
---|
622 | Count => 4,
|
---|
623 | },
|
---|
624 | 0x201 => {
|
---|
625 | Name => 'PreviewImageStart',
|
---|
626 | IsOffset => 1,
|
---|
627 | MakerPreview => 1, # force preview inside maker notes
|
---|
628 | OffsetPair => 0x202,
|
---|
629 | DataTag => 'PreviewImage',
|
---|
630 | Writable => 'int32u',
|
---|
631 | Protected => 2,
|
---|
632 | Notes => 'a small 320x200 preview image',
|
---|
633 | },
|
---|
634 | 0x202 => {
|
---|
635 | Name => 'PreviewImageLength',
|
---|
636 | OffsetPair => 0x201,
|
---|
637 | DataTag => 'PreviewImage',
|
---|
638 | Writable => 'int32u',
|
---|
639 | Protected => 2,
|
---|
640 | },
|
---|
641 | );
|
---|
642 |
|
---|
643 | # Camera settings (ref PH) (decoded mainly from A200)
|
---|
644 | %Image::ExifTool::Sony::CameraSettings = (
|
---|
645 | %binaryDataAttrs,
|
---|
646 | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
|
---|
647 | FORMAT => 'int16u',
|
---|
648 | NOTES => q{
|
---|
649 | Camera settings for the A200, A230, A300, A350, A700, A850 and A900. Some
|
---|
650 | tags are only valid for certain models.
|
---|
651 | },
|
---|
652 | 0x04 => { #7 (A700, not valid for other models)
|
---|
653 | Name => 'DriveMode',
|
---|
654 | Condition => '$$self{Model} =~ /DSLR-A700\b/',
|
---|
655 | Notes => 'A700 only',
|
---|
656 | PrintConv => {
|
---|
657 | 1 => 'Single Frame',
|
---|
658 | 2 => 'Continuous High',
|
---|
659 | 4 => 'Self-timer 10 sec',
|
---|
660 | 5 => 'Self-timer 2 sec',
|
---|
661 | 7 => 'Continuous Bracketing',
|
---|
662 | 12 => 'Continuous Low',
|
---|
663 | 18 => 'White Balance Bracketing Low',
|
---|
664 | 19 => 'D-Range Optimizer Bracketing Low',
|
---|
665 | },
|
---|
666 | },
|
---|
667 | 0x06 => { #7 (A700, not valid for other models)
|
---|
668 | Name => 'WhiteBalanceFineTune',
|
---|
669 | Condition => '$$self{Model} =~ /DSLR-A700\b/',
|
---|
670 | Format => 'int16s',
|
---|
671 | Notes => 'A700 only',
|
---|
672 | },
|
---|
673 | 0x10 => { #7 (A700, not confirmed for other models)
|
---|
674 | Name => 'FocusMode',
|
---|
675 | PrintConv => {
|
---|
676 | 0 => 'Manual',
|
---|
677 | 1 => 'AF-S',
|
---|
678 | 2 => 'AF-C',
|
---|
679 | 3 => 'AF-A',
|
---|
680 | },
|
---|
681 | },
|
---|
682 | 0x11 => { #JD (A700)
|
---|
683 | Name => 'AFAreaMode',
|
---|
684 | PrintConv => {
|
---|
685 | 0 => 'Wide',
|
---|
686 | 1 => 'Local',
|
---|
687 | 2 => 'Spot',
|
---|
688 | },
|
---|
689 | },
|
---|
690 | 0x12 => { #7 (A700, not confirmed for other models)
|
---|
691 | Name => 'LocalAFAreaPoint',
|
---|
692 | Format => 'int16u',
|
---|
693 | Condition => '$$self{Model} !~ /DSLR-A230/',
|
---|
694 | PrintConv => {
|
---|
695 | 1 => 'Center',
|
---|
696 | 2 => 'Top',
|
---|
697 | 3 => 'Top-Right',
|
---|
698 | 4 => 'Right',
|
---|
699 | 5 => 'Bottom-Right',
|
---|
700 | 6 => 'Bottom',
|
---|
701 | 7 => 'Bottom-Left',
|
---|
702 | 8 => 'Left',
|
---|
703 | 9 => 'Top-Left',
|
---|
704 | 10 => 'Far Right',
|
---|
705 | 11 => 'Far Left',
|
---|
706 | # have seen value of 128 for A230, A330, A380 - PH
|
---|
707 | },
|
---|
708 | },
|
---|
709 | 0x15 => { #7
|
---|
710 | Name => 'MeteringMode',
|
---|
711 | Condition => '$$self{Model} !~ /DSLR-A230/',
|
---|
712 | PrintConv => {
|
---|
713 | 1 => 'Multi-segment',
|
---|
714 | 2 => 'Center-weighted Average',
|
---|
715 | 4 => 'Spot',
|
---|
716 | },
|
---|
717 | },
|
---|
718 | 0x16 => {
|
---|
719 | Name => 'ISOSetting',
|
---|
720 | Condition => '$$self{Model} !~ /DSLR-A230/',
|
---|
721 | # 0 indicates 'Auto' (I think)
|
---|
722 | ValueConv => '$val ? exp(($val/8-6)*log(2))*100 : $val',
|
---|
723 | ValueConvInv => '$val ? 8*(log($val/100)/log(2)+6) : $val',
|
---|
724 | PrintConv => '$val ? sprintf("%.0f",$val) : "Auto"',
|
---|
725 | PrintConvInv => '$val =~ /auto/i ? 0 : $val',
|
---|
726 | },
|
---|
727 | 0x18 => { #7
|
---|
728 | Name => 'DynamicRangeOptimizerMode',
|
---|
729 | Condition => '$$self{Model} !~ /DSLR-A230/',
|
---|
730 | PrintConv => {
|
---|
731 | 0 => 'Off',
|
---|
732 | 1 => 'Standard',
|
---|
733 | 2 => 'Advanced Auto',
|
---|
734 | 3 => 'Advanced Level',
|
---|
735 | 4097 => 'Auto', #PH (A550)
|
---|
736 | },
|
---|
737 | },
|
---|
738 | 0x19 => { #7
|
---|
739 | Name => 'DynamicRangeOptimizerLevel',
|
---|
740 | Condition => '$$self{Model} !~ /DSLR-A230/',
|
---|
741 | },
|
---|
742 | 0x1a => { # style actually used (combination of mode dial + creative style menu)
|
---|
743 | Name => 'CreativeStyle',
|
---|
744 | Condition => '$$self{Model} !~ /DSLR-A230/',
|
---|
745 | PrintConv => {
|
---|
746 | 1 => 'Standard',
|
---|
747 | 2 => 'Vivid',
|
---|
748 | 3 => 'Portrait',
|
---|
749 | 4 => 'Landscape',
|
---|
750 | 5 => 'Sunset',
|
---|
751 | 6 => 'Night View/Portrait',
|
---|
752 | 8 => 'B&W',
|
---|
753 | 9 => 'Adobe RGB', # A900
|
---|
754 | 11 => 'Neutral',
|
---|
755 | 12 => 'Clear', #7
|
---|
756 | 13 => 'Deep', #7
|
---|
757 | 14 => 'Light', #7
|
---|
758 | 15 => 'Autumn', #7
|
---|
759 | 16 => 'Sepia', #7
|
---|
760 | },
|
---|
761 | },
|
---|
762 | 0x1c => {
|
---|
763 | Name => 'Sharpness',
|
---|
764 | ValueConv => '$val - 10',
|
---|
765 | ValueConvInv => '$val + 10',
|
---|
766 | PrintConv => '$val > 0 ? "+$val" : $val',
|
---|
767 | PrintConvInv => '$val',
|
---|
768 | },
|
---|
769 | 0x1d => {
|
---|
770 | Name => 'Contrast',
|
---|
771 | ValueConv => '$val - 10',
|
---|
772 | ValueConvInv => '$val + 10',
|
---|
773 | PrintConv => '$val > 0 ? "+$val" : $val',
|
---|
774 | PrintConvInv => '$val',
|
---|
775 | },
|
---|
776 | 0x1e => {
|
---|
777 | Name => 'Saturation',
|
---|
778 | ValueConv => '$val - 10',
|
---|
779 | ValueConvInv => '$val + 10',
|
---|
780 | PrintConv => '$val > 0 ? "+$val" : $val',
|
---|
781 | PrintConvInv => '$val',
|
---|
782 | },
|
---|
783 | 0x1f => { #7
|
---|
784 | Name => 'ZoneMatchingValue',
|
---|
785 | Condition => '$$self{Model} !~ /DSLR-A230/',
|
---|
786 | ValueConv => '$val - 10',
|
---|
787 | ValueConvInv => '$val + 10',
|
---|
788 | PrintConv => '$val > 0 ? "+$val" : $val',
|
---|
789 | PrintConvInv => '$val',
|
---|
790 | },
|
---|
791 | 0x22 => { #7
|
---|
792 | Name => 'Brightness',
|
---|
793 | Condition => '$$self{Model} !~ /DSLR-A230/',
|
---|
794 | ValueConv => '$val - 10',
|
---|
795 | ValueConvInv => '$val + 10',
|
---|
796 | PrintConv => '$val > 0 ? "+$val" : $val',
|
---|
797 | PrintConvInv => '$val',
|
---|
798 | },
|
---|
799 | 0x23 => {
|
---|
800 | Name => 'FlashMode',
|
---|
801 | PrintConv => {
|
---|
802 | 0 => 'ADI',
|
---|
803 | 1 => 'TTL',
|
---|
804 | },
|
---|
805 | },
|
---|
806 | 0x28 => { #7
|
---|
807 | Name => 'PrioritySetupShutterRelease',
|
---|
808 | Condition => '$$self{Model} =~ /DSLR-A700\b/',
|
---|
809 | Notes => 'A700 only',
|
---|
810 | PrintConv => {
|
---|
811 | 0 => 'AF',
|
---|
812 | 1 => 'Release',
|
---|
813 | },
|
---|
814 | },
|
---|
815 | 0x29 => { #7
|
---|
816 | Name => 'AFIlluminator',
|
---|
817 | Condition => '$$self{Model} =~ /DSLR-A700\b/',
|
---|
818 | Notes => 'A700 only',
|
---|
819 | PrintConv => {
|
---|
820 | 0 => 'Auto',
|
---|
821 | 1 => 'Off',
|
---|
822 | },
|
---|
823 | },
|
---|
824 | 0x2a => { #7
|
---|
825 | Name => 'AFWithShutter',
|
---|
826 | Condition => '$$self{Model} =~ /DSLR-A700\b/',
|
---|
827 | Notes => 'A700 only',
|
---|
828 | PrintConv => { 0 => 'On', 1 => 'Off' },
|
---|
829 | },
|
---|
830 | 0x2b => { #7
|
---|
831 | Name => 'LongExposureNoiseReduction',
|
---|
832 | Condition => '$$self{Model} =~ /DSLR-A700\b/',
|
---|
833 | Notes => 'A700 only',
|
---|
834 | PrintConv => { 0 => 'Off', 1 => 'On' },
|
---|
835 | },
|
---|
836 | 0x2c => { #7
|
---|
837 | Name => 'HighISONoiseReduction',
|
---|
838 | Condition => '$$self{Model} =~ /DSLR-A700\b/',
|
---|
839 | Notes => 'A700 only',
|
---|
840 | 0 => 'Normal',
|
---|
841 | 1 => 'Low',
|
---|
842 | 2 => 'High',
|
---|
843 | 3 => 'Off',
|
---|
844 | },
|
---|
845 | 0x2d => { #7
|
---|
846 | Name => 'ImageStyle',
|
---|
847 | Condition => '$$self{Model} =~ /DSLR-A700\b/',
|
---|
848 | Notes => 'A700 only',
|
---|
849 | PrintConv => {
|
---|
850 | 1 => 'Standard',
|
---|
851 | 2 => 'Vivid',
|
---|
852 | 9 => 'Adobe RGB',
|
---|
853 | 11 => 'Neutral',
|
---|
854 | 129 => 'StyleBox1',
|
---|
855 | 130 => 'StyleBox2',
|
---|
856 | 131 => 'StyleBox3',
|
---|
857 | },
|
---|
858 | },
|
---|
859 | # 0x2d - A900:1=?,4=?,129=std,130=vivid,131=neutral,132=portrait,133=landscape,134=b&w
|
---|
860 | 0x3c => {
|
---|
861 | Name => 'ExposureProgram',
|
---|
862 | Priority => 0,
|
---|
863 | PrintConv => \%sonyExposureProgram,
|
---|
864 | },
|
---|
865 | 0x3d => {
|
---|
866 | Name => 'ImageStabilization',
|
---|
867 | PrintConv => { 0 => 'Off', 1 => 'On' },
|
---|
868 | },
|
---|
869 | 0x3f => { # (verified for A330/A380)
|
---|
870 | Name => 'Rotation',
|
---|
871 | PrintConv => {
|
---|
872 | 0 => 'Horizontal (normal)',
|
---|
873 | 1 => 'Rotate 90 CW', #(NC)
|
---|
874 | 2 => 'Rotate 270 CW',
|
---|
875 | },
|
---|
876 | },
|
---|
877 | 0x54 => {
|
---|
878 | Name => 'SonyImageSize',
|
---|
879 | PrintConv => {
|
---|
880 | 1 => 'Large',
|
---|
881 | 2 => 'Medium',
|
---|
882 | 3 => 'Small',
|
---|
883 | },
|
---|
884 | },
|
---|
885 | 0x55 => { #7
|
---|
886 | Name => 'AspectRatio',
|
---|
887 | PrintConv => {
|
---|
888 | 1 => '3:2',
|
---|
889 | 2 => '16:9',
|
---|
890 | },
|
---|
891 | },
|
---|
892 | 0x56 => { #PH/7
|
---|
893 | Name => 'Quality',
|
---|
894 | PrintConv => {
|
---|
895 | 0 => 'RAW',
|
---|
896 | 2 => 'CRAW',
|
---|
897 | 34 => 'RAW + JPEG',
|
---|
898 | 35 => 'CRAW + JPEG',
|
---|
899 | 16 => 'Extra Fine',
|
---|
900 | 32 => 'Fine',
|
---|
901 | 48 => 'Standard',
|
---|
902 | },
|
---|
903 | },
|
---|
904 | 0x58 => { #7
|
---|
905 | Name => 'ExposureLevelIncrements',
|
---|
906 | PrintConv => {
|
---|
907 | 33 => '1/3 EV',
|
---|
908 | 50 => '1/2 EV',
|
---|
909 | },
|
---|
910 | },
|
---|
911 | );
|
---|
912 |
|
---|
913 | # Camera settings (ref PH) (A330 and A380)
|
---|
914 | %Image::ExifTool::Sony::CameraSettings2 = (
|
---|
915 | %binaryDataAttrs,
|
---|
916 | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
|
---|
917 | FORMAT => 'int16u',
|
---|
918 | NOTES => 'Camera settings for the A330 and A380.',
|
---|
919 | 0x10 => { #7 (A700, not confirmed for other models)
|
---|
920 | Name => 'FocusMode',
|
---|
921 | PrintConv => {
|
---|
922 | 0 => 'Manual',
|
---|
923 | 1 => 'AF-S',
|
---|
924 | 2 => 'AF-C',
|
---|
925 | 3 => 'AF-A',
|
---|
926 | },
|
---|
927 | },
|
---|
928 | 0x11 => { #JD (A700)
|
---|
929 | Name => 'AFAreaMode',
|
---|
930 | PrintConv => {
|
---|
931 | 0 => 'Wide',
|
---|
932 | 1 => 'Local',
|
---|
933 | 2 => 'Spot',
|
---|
934 | },
|
---|
935 | },
|
---|
936 | 0x12 => { #7 (A700, not confirmed for other models)
|
---|
937 | Name => 'LocalAFAreaPoint',
|
---|
938 | Format => 'int16u',
|
---|
939 | PrintConv => {
|
---|
940 | 1 => 'Center',
|
---|
941 | 2 => 'Top',
|
---|
942 | 3 => 'Top-Right',
|
---|
943 | 4 => 'Right',
|
---|
944 | 5 => 'Bottom-Right',
|
---|
945 | 6 => 'Bottom',
|
---|
946 | 7 => 'Bottom-Left',
|
---|
947 | 8 => 'Left',
|
---|
948 | 9 => 'Top-Left',
|
---|
949 | 10 => 'Far Right',
|
---|
950 | 11 => 'Far Left',
|
---|
951 | # see value of 128 for some models
|
---|
952 | },
|
---|
953 | },
|
---|
954 | 0x13 => {
|
---|
955 | Name => 'MeteringMode',
|
---|
956 | PrintConv => {
|
---|
957 | 1 => 'Multi-segment',
|
---|
958 | 2 => 'Center-weighted Average',
|
---|
959 | 4 => 'Spot',
|
---|
960 | },
|
---|
961 | },
|
---|
962 | 0x14 => { # A330/A380
|
---|
963 | Name => 'ISOSetting',
|
---|
964 | # 0 indicates 'Auto' (?)
|
---|
965 | ValueConv => '$val ? exp(($val/8-6)*log(2))*100 : $val',
|
---|
966 | ValueConvInv => '$val ? 8*(log($val/100)/log(2)+6) : $val',
|
---|
967 | PrintConv => '$val ? sprintf("%.0f",$val) : "Auto"',
|
---|
968 | PrintConvInv => '$val =~ /auto/i ? 0 : $val',
|
---|
969 | },
|
---|
970 | 0x16 => {
|
---|
971 | Name => 'DynamicRangeOptimizerMode',
|
---|
972 | PrintConv => {
|
---|
973 | 0 => 'Off',
|
---|
974 | 1 => 'Standard',
|
---|
975 | 2 => 'Advanced Auto',
|
---|
976 | 3 => 'Advanced Level',
|
---|
977 | },
|
---|
978 | },
|
---|
979 | 0x17 => {
|
---|
980 | Name => 'DynamicRangeOptimizerLevel',
|
---|
981 | },
|
---|
982 | 0x18 => { # A380
|
---|
983 | Name => 'CreativeStyle',
|
---|
984 | PrintConv => {
|
---|
985 | 1 => 'Standard',
|
---|
986 | 2 => 'Vivid',
|
---|
987 | 3 => 'Portrait',
|
---|
988 | 4 => 'Landscape',
|
---|
989 | 5 => 'Sunset',
|
---|
990 | 6 => 'Night View/Portrait',
|
---|
991 | 8 => 'B&W',
|
---|
992 | 9 => 'Adobe RGB',
|
---|
993 | 11 => 'Neutral',
|
---|
994 | },
|
---|
995 | },
|
---|
996 | 0x19 => {
|
---|
997 | Name => 'Sharpness',
|
---|
998 | ValueConv => '$val - 10',
|
---|
999 | ValueConvInv => '$val + 10',
|
---|
1000 | PrintConv => '$val > 0 ? "+$val" : $val',
|
---|
1001 | PrintConvInv => '$val',
|
---|
1002 | },
|
---|
1003 | 0x1a => {
|
---|
1004 | Name => 'Contrast',
|
---|
1005 | ValueConv => '$val - 10',
|
---|
1006 | ValueConvInv => '$val + 10',
|
---|
1007 | PrintConv => '$val > 0 ? "+$val" : $val',
|
---|
1008 | PrintConvInv => '$val',
|
---|
1009 | },
|
---|
1010 | 0x1b => {
|
---|
1011 | Name => 'Saturation',
|
---|
1012 | ValueConv => '$val - 10',
|
---|
1013 | ValueConvInv => '$val + 10',
|
---|
1014 | PrintConv => '$val > 0 ? "+$val" : $val',
|
---|
1015 | PrintConvInv => '$val',
|
---|
1016 | },
|
---|
1017 | 0x23 => {
|
---|
1018 | Name => 'FlashMode',
|
---|
1019 | PrintConv => {
|
---|
1020 | 0 => 'ADI',
|
---|
1021 | 1 => 'TTL',
|
---|
1022 | },
|
---|
1023 | },
|
---|
1024 | # 0x27 - also related to CreativeStyle:
|
---|
1025 | # A380:1=std,2=vivid,3=portrait,4=landscape,5=sunset,7=night view,8=b&w
|
---|
1026 | 0x3c => {
|
---|
1027 | Name => 'ExposureProgram',
|
---|
1028 | Priority => 0,
|
---|
1029 | PrintConv => \%sonyExposureProgram,
|
---|
1030 | },
|
---|
1031 | 0x3f => { # (verified for A330/A380)
|
---|
1032 | Name => 'Rotation',
|
---|
1033 | PrintConv => {
|
---|
1034 | 0 => 'Horizontal (normal)',
|
---|
1035 | 1 => 'Rotate 90 CW', #(NC)
|
---|
1036 | 2 => 'Rotate 270 CW',
|
---|
1037 | },
|
---|
1038 | },
|
---|
1039 | 0x54 => {
|
---|
1040 | Name => 'SonyImageSize',
|
---|
1041 | PrintConv => {
|
---|
1042 | 1 => 'Large',
|
---|
1043 | 2 => 'Medium',
|
---|
1044 | 3 => 'Small',
|
---|
1045 | },
|
---|
1046 | },
|
---|
1047 | # 0x56 - something to do with JPEG quality?
|
---|
1048 | );
|
---|
1049 |
|
---|
1050 | # Camera settings for other models
|
---|
1051 | %Image::ExifTool::Sony::CameraSettingsUnknown = (
|
---|
1052 | %binaryDataAttrs,
|
---|
1053 | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
|
---|
1054 | FORMAT => 'int16u',
|
---|
1055 | );
|
---|
1056 |
|
---|
1057 | # shot information (ref PH)
|
---|
1058 | %Image::ExifTool::Sony::ShotInfo = (
|
---|
1059 | %binaryDataAttrs,
|
---|
1060 | GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
|
---|
1061 | DATAMEMBER => [ 0x02, 0x30, 0x32 ],
|
---|
1062 | IS_SUBDIR => [ 0x48, 0x5e ],
|
---|
1063 | # 0x00 - byte order 'II'
|
---|
1064 | 0x02 => {
|
---|
1065 | Name => 'FaceInfoOffset',
|
---|
1066 | Format => 'int16u',
|
---|
1067 | DataMember => 'FaceInfoOffset',
|
---|
1068 | Writable => 0,
|
---|
1069 | RawConv => '$$self{FaceInfoOffset} = $val',
|
---|
1070 | },
|
---|
1071 | 0x06 => {
|
---|
1072 | Name => 'SonyDateTime',
|
---|
1073 | Format => 'string[20]',
|
---|
1074 | Groups => { 2 => 'Time' },
|
---|
1075 | Shift => 'Time',
|
---|
1076 | PrintConv => '$self->ConvertDateTime($val)',
|
---|
1077 | PrintConvInv => '$self->InverseDateTime($val,0)',
|
---|
1078 | },
|
---|
1079 | 0x30 => { #Jeffrey Friedl
|
---|
1080 | Name => 'FacesDetected',
|
---|
1081 | DataMember => 'FacesDetected',
|
---|
1082 | Format => 'int16u',
|
---|
1083 | RawConv => '$$self{FacesDetected} = $val',
|
---|
1084 | },
|
---|
1085 | 0x32 => {
|
---|
1086 | Name => 'FaceInfoLength', # length of a single FaceInfo entry
|
---|
1087 | DataMember => 'FaceInfoLength',
|
---|
1088 | Format => 'int16u',
|
---|
1089 | Writable => 0,
|
---|
1090 | RawConv => '$$self{FaceInfoLength} = $val',
|
---|
1091 | },
|
---|
1092 | #0x34 => {
|
---|
1093 | # # values: 'DC5303320222000', 'DC6303320222000' or 'DC7303320222000'
|
---|
1094 | # Name => 'UnknownString',
|
---|
1095 | # Format => 'string[16]',
|
---|
1096 | # Unknown => 1,
|
---|
1097 | #},
|
---|
1098 | 0x48 => { # (most models: DC5303320222000 and DC6303320222000)
|
---|
1099 | Name => 'FaceInfo1',
|
---|
1100 | Condition => q{
|
---|
1101 | $$self{FacesDetected} and
|
---|
1102 | $$self{FaceInfoOffset} == 0x48 and
|
---|
1103 | $$self{FaceInfoLength} == 0x20
|
---|
1104 | },
|
---|
1105 | SubDirectory => { TagTable => 'Image::ExifTool::Sony::FaceInfo1' },
|
---|
1106 | },
|
---|
1107 | 0x5e => { # (HX7V: DC7303320222000)
|
---|
1108 | Name => 'FaceInfo2',
|
---|
1109 | Condition => q{
|
---|
1110 | $$self{FacesDetected} and
|
---|
1111 | $$self{FaceInfoOffset} == 0x5e and
|
---|
1112 | $$self{FaceInfoLength} == 0x25
|
---|
1113 | },
|
---|
1114 | SubDirectory => { TagTable => 'Image::ExifTool::Sony::FaceInfo2' },
|
---|
1115 | },
|
---|
1116 | );
|
---|
1117 |
|
---|
1118 | %Image::ExifTool::Sony::FaceInfo1 = (
|
---|
1119 | %binaryDataAttrs,
|
---|
1120 | GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
|
---|
1121 | 0x00 => {
|
---|
1122 | Name => 'Face1Position',
|
---|
1123 | Format => 'int16u[4]',
|
---|
1124 | RawConv => '$$self{FacesDetected} < 1 ? undef : $val',
|
---|
1125 | Notes => q{
|
---|
1126 | top, left, height and width of detected face. Coordinates are relative to
|
---|
1127 | the full-sized unrotated image, with increasing Y downwards
|
---|
1128 | },
|
---|
1129 | },
|
---|
1130 | 0x20 => {
|
---|
1131 | Name => 'Face2Position',
|
---|
1132 | Format => 'int16u[4]',
|
---|
1133 | RawConv => '$$self{FacesDetected} < 2 ? undef : $val',
|
---|
1134 | },
|
---|
1135 | 0x40 => {
|
---|
1136 | Name => 'Face3Position',
|
---|
1137 | Format => 'int16u[4]',
|
---|
1138 | RawConv => '$$self{FacesDetected} < 3 ? undef : $val',
|
---|
1139 | },
|
---|
1140 | 0x60 => {
|
---|
1141 | Name => 'Face4Position',
|
---|
1142 | Format => 'int16u[4]',
|
---|
1143 | RawConv => '$$self{FacesDetected} < 4 ? undef : $val',
|
---|
1144 | },
|
---|
1145 | 0x80 => {
|
---|
1146 | Name => 'Face5Position',
|
---|
1147 | Format => 'int16u[4]',
|
---|
1148 | RawConv => '$$self{FacesDetected} < 5 ? undef : $val',
|
---|
1149 | },
|
---|
1150 | 0xa0 => {
|
---|
1151 | Name => 'Face6Position',
|
---|
1152 | Format => 'int16u[4]',
|
---|
1153 | RawConv => '$$self{FacesDetected} < 6 ? undef : $val',
|
---|
1154 | },
|
---|
1155 | 0xc0 => {
|
---|
1156 | Name => 'Face7Position',
|
---|
1157 | Format => 'int16u[4]',
|
---|
1158 | RawConv => '$$self{FacesDetected} < 7 ? undef : $val',
|
---|
1159 | },
|
---|
1160 | 0xe0 => {
|
---|
1161 | Name => 'Face8Position',
|
---|
1162 | Format => 'int16u[4]',
|
---|
1163 | RawConv => '$$self{FacesDetected} < 8 ? undef : $val',
|
---|
1164 | },
|
---|
1165 | );
|
---|
1166 |
|
---|
1167 | %Image::ExifTool::Sony::FaceInfo2 = (
|
---|
1168 | %binaryDataAttrs,
|
---|
1169 | GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
|
---|
1170 | 0x00 => {
|
---|
1171 | Name => 'Face1Position',
|
---|
1172 | Format => 'int16u[4]',
|
---|
1173 | RawConv => '$$self{FacesDetected} < 1 ? undef : $val',
|
---|
1174 | Notes => q{
|
---|
1175 | top, left, height and width of detected face. Coordinates are relative to
|
---|
1176 | the full-sized unrotated image, with increasing Y downwards
|
---|
1177 | },
|
---|
1178 | },
|
---|
1179 | 0x25 => {
|
---|
1180 | Name => 'Face2Position',
|
---|
1181 | Format => 'int16u[4]',
|
---|
1182 | RawConv => '$$self{FacesDetected} < 2 ? undef : $val',
|
---|
1183 | },
|
---|
1184 | 0x4a => {
|
---|
1185 | Name => 'Face3Position',
|
---|
1186 | Format => 'int16u[4]',
|
---|
1187 | RawConv => '$$self{FacesDetected} < 3 ? undef : $val',
|
---|
1188 | },
|
---|
1189 | 0x6f => {
|
---|
1190 | Name => 'Face4Position',
|
---|
1191 | Format => 'int16u[4]',
|
---|
1192 | RawConv => '$$self{FacesDetected} < 4 ? undef : $val',
|
---|
1193 | },
|
---|
1194 | 0x94 => {
|
---|
1195 | Name => 'Face5Position',
|
---|
1196 | Format => 'int16u[4]',
|
---|
1197 | RawConv => '$$self{FacesDetected} < 5 ? undef : $val',
|
---|
1198 | },
|
---|
1199 | 0xb9 => {
|
---|
1200 | Name => 'Face6Position',
|
---|
1201 | Format => 'int16u[4]',
|
---|
1202 | RawConv => '$$self{FacesDetected} < 6 ? undef : $val',
|
---|
1203 | },
|
---|
1204 | 0xde => {
|
---|
1205 | Name => 'Face7Position',
|
---|
1206 | Format => 'int16u[4]',
|
---|
1207 | RawConv => '$$self{FacesDetected} < 7 ? undef : $val',
|
---|
1208 | },
|
---|
1209 | 0x103 => {
|
---|
1210 | Name => 'Face8Position',
|
---|
1211 | Format => 'int16u[4]',
|
---|
1212 | RawConv => '$$self{FacesDetected} < 8 ? undef : $val',
|
---|
1213 | },
|
---|
1214 | );
|
---|
1215 |
|
---|
1216 | # panorama info for cameras such as the HX1, HX5, TX7 (ref 9/PH)
|
---|
1217 | %Image::ExifTool::Sony::Panorama = (
|
---|
1218 | %binaryDataAttrs,
|
---|
1219 | GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
|
---|
1220 | FORMAT => 'int32u',
|
---|
1221 | NOTES => q{
|
---|
1222 | Tags found only in panorama images from Sony cameras such as the HX1, HX5
|
---|
1223 | and TX7. The width/height values of these tags are not affected by camera
|
---|
1224 | rotation -- the width is always the longer dimension.
|
---|
1225 | },
|
---|
1226 | # 0: 257
|
---|
1227 | 1 => 'PanoramaFullWidth', # (including black/grey borders)
|
---|
1228 | 2 => 'PanoramaFullHeight',
|
---|
1229 | 3 => {
|
---|
1230 | Name => 'PanoramaDirection',
|
---|
1231 | PrintConv => {
|
---|
1232 | 0 => 'Right to Left',
|
---|
1233 | 1 => 'Left to Right',
|
---|
1234 | },
|
---|
1235 | },
|
---|
1236 | # crop area to remove black/grey borders from full image
|
---|
1237 | 4 => 'PanoramaCropLeft',
|
---|
1238 | 5 => 'PanoramaCropTop', #PH guess (NC)
|
---|
1239 | 6 => 'PanoramaCropRight',
|
---|
1240 | 7 => 'PanoramaCropBottom',
|
---|
1241 | # 8: 1728 (HX1), 1824 (HX5/TX7) (value8/value9 = 16/9)
|
---|
1242 | 8 => 'PanoramaFrameWidth', #PH guess (NC)
|
---|
1243 | # 9: 972 (HX1), 1026 (HX5/TX7)
|
---|
1244 | 9 => 'PanoramaFrameHeight', #PH guess (NC)
|
---|
1245 | # 10: 3200-3800 (HX1), 4000-4900 (HX5/TX7)
|
---|
1246 | 10 => 'PanoramaSourceWidth', #PH guess (NC)
|
---|
1247 | # 11: 800-1800 (larger for taller panoramas)
|
---|
1248 | 11 => 'PanoramaSourceHeight', #PH guess (NC)
|
---|
1249 | # 12-15: 0
|
---|
1250 | );
|
---|
1251 |
|
---|
1252 | # tag table for SRF0 IFD (ref 1)
|
---|
1253 | %Image::ExifTool::Sony::SRF = (
|
---|
1254 | PROCESS_PROC => \&ProcessSRF,
|
---|
1255 | GROUPS => { 0 => 'MakerNotes', 1 => 'SRF#', 2 => 'Camera' },
|
---|
1256 | NOTES => q{
|
---|
1257 | The maker notes in SRF (Sony Raw Format) images contain 7 IFD's with family
|
---|
1258 | 1 group names SRF0 through SRF6. SRF0 and SRF1 use the tags in this table,
|
---|
1259 | while SRF2 through SRF5 use the tags in the next table, and SRF6 uses
|
---|
1260 | standard EXIF tags. All information other than SRF0 is encrypted, but
|
---|
1261 | thanks to Dave Coffin the decryption algorithm is known. SRF images are
|
---|
1262 | written by the Sony DSC-F828 and DSC-V3.
|
---|
1263 | },
|
---|
1264 | # tags 0-1 are used in SRF1
|
---|
1265 | 0 => {
|
---|
1266 | Name => 'SRF2Key',
|
---|
1267 | Notes => 'key to decrypt maker notes from the start of SRF2',
|
---|
1268 | RawConv => '$self->{SRF2Key} = $val',
|
---|
1269 | },
|
---|
1270 | 1 => {
|
---|
1271 | Name => 'DataKey',
|
---|
1272 | Notes => 'key to decrypt the rest of the file from the end of the maker notes',
|
---|
1273 | RawConv => '$self->{SRFDataKey} = $val',
|
---|
1274 | },
|
---|
1275 | # SRF0 contains a single unknown tag with TagID 0x0003
|
---|
1276 | );
|
---|
1277 |
|
---|
1278 | # tag table for Sony RAW Format (ref 1)
|
---|
1279 | %Image::ExifTool::Sony::SRF2 = (
|
---|
1280 | PROCESS_PROC => \&ProcessSRF,
|
---|
1281 | GROUPS => { 0 => 'MakerNotes', 1 => 'SRF#', 2 => 'Camera' },
|
---|
1282 | NOTES => "These tags are found in the SRF2 through SRF5 IFD's.",
|
---|
1283 | # the following tags are used in SRF2-5
|
---|
1284 | 2 => 'SRF6Offset', #PH
|
---|
1285 | # SRFDataOffset references 2220 bytes of unknown data for the DSC-F828 - PH
|
---|
1286 | 3 => { Name => 'SRFDataOffset', Unknown => 1 }, #PH
|
---|
1287 | 4 => { Name => 'RawDataOffset' }, #PH
|
---|
1288 | 5 => { Name => 'RawDataLength' }, #PH
|
---|
1289 | );
|
---|
1290 |
|
---|
1291 | # tag table for Sony RAW 2 Format Private IFD (ref 1)
|
---|
1292 | %Image::ExifTool::Sony::SR2Private = (
|
---|
1293 | PROCESS_PROC => \&ProcessSR2,
|
---|
1294 | WRITE_PROC => \&WriteSR2,
|
---|
1295 | GROUPS => { 0 => 'MakerNotes', 1 => 'SR2', 2 => 'Camera' },
|
---|
1296 | NOTES => q{
|
---|
1297 | The SR2 format uses the DNGPrivateData tag to reference a private IFD
|
---|
1298 | containing these tags. SR2 images are written by the Sony DSC-R1, but
|
---|
1299 | this information is also written to ARW images by other models.
|
---|
1300 | },
|
---|
1301 | 0x7200 => {
|
---|
1302 | Name => 'SR2SubIFDOffset',
|
---|
1303 | # (adjusting offset messes up calculations for AdobeSR2 in DNG images)
|
---|
1304 | # Flags => 'IsOffset',
|
---|
1305 | # (can't set OffsetPair or else DataMember won't be set when writing)
|
---|
1306 | # OffsetPair => 0x7201,
|
---|
1307 | DataMember => 'SR2SubIFDOffset',
|
---|
1308 | RawConv => '$$self{SR2SubIFDOffset} = $val',
|
---|
1309 | },
|
---|
1310 | 0x7201 => {
|
---|
1311 | Name => 'SR2SubIFDLength',
|
---|
1312 | # (can't set OffsetPair or else DataMember won't be set when writing)
|
---|
1313 | # OffsetPair => 0x7200,
|
---|
1314 | DataMember => 'SR2SubIFDLength',
|
---|
1315 | RawConv => '$$self{SR2SubIFDLength} = $val',
|
---|
1316 | },
|
---|
1317 | 0x7221 => {
|
---|
1318 | Name => 'SR2SubIFDKey',
|
---|
1319 | Format => 'int32u',
|
---|
1320 | Notes => 'key to decrypt SR2SubIFD',
|
---|
1321 | DataMember => 'SR2SubIFDKey',
|
---|
1322 | RawConv => '$$self{SR2SubIFDKey} = $val',
|
---|
1323 | PrintConv => 'sprintf("0x%.8x", $val)',
|
---|
1324 | },
|
---|
1325 | 0x7240 => { #PH
|
---|
1326 | Name => 'IDC_IFD',
|
---|
1327 | Groups => { 1 => 'SonyIDC' },
|
---|
1328 | Condition => '$$valPt !~ /^\0\0\0\0/', # (just in case this could be zero)
|
---|
1329 | Flags => 'SubIFD',
|
---|
1330 | SubDirectory => {
|
---|
1331 | DirName => 'SonyIDC',
|
---|
1332 | TagTable => 'Image::ExifTool::SonyIDC::Main',
|
---|
1333 | Start => '$val',
|
---|
1334 | },
|
---|
1335 | },
|
---|
1336 | 0x7241 => { #PH
|
---|
1337 | Name => 'IDC2_IFD',
|
---|
1338 | Groups => { 1 => 'SonyIDC' },
|
---|
1339 | Condition => '$$valPt !~ /^\0\0\0\0/', # may be zero if dir doesn't exist
|
---|
1340 | Flags => 'SubIFD',
|
---|
1341 | SubDirectory => {
|
---|
1342 | DirName => 'SonyIDC2',
|
---|
1343 | TagTable => 'Image::ExifTool::SonyIDC::Main',
|
---|
1344 | Start => '$val',
|
---|
1345 | Base => '$start',
|
---|
1346 | MaxSubdirs => 20, # (A900 has 10 null entries, but IDC writes only 1)
|
---|
1347 | RelativeBase => 1, # needed to write SubIFD with relative offsets
|
---|
1348 | },
|
---|
1349 | },
|
---|
1350 | 0x7250 => { #1
|
---|
1351 | Name => 'MRWInfo',
|
---|
1352 | Condition => '$$valPt !~ /^\0\0\0\0/', # (just in case this could be zero)
|
---|
1353 | SubDirectory => {
|
---|
1354 | TagTable => 'Image::ExifTool::MinoltaRaw::Main',
|
---|
1355 | },
|
---|
1356 | },
|
---|
1357 | );
|
---|
1358 |
|
---|
1359 | %Image::ExifTool::Sony::SR2SubIFD = (
|
---|
1360 | WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
|
---|
1361 | CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
|
---|
1362 | GROUPS => { 0 => 'MakerNotes', 1 => 'SR2SubIFD', 2 => 'Camera' },
|
---|
1363 | SET_GROUP1 => 1, # set group1 name to directory name for all tags in table
|
---|
1364 | NOTES => 'Tags in the encrypted SR2SubIFD',
|
---|
1365 | 0x7303 => 'WB_GRBGLevels', #1
|
---|
1366 | 0x74c0 => { #PH
|
---|
1367 | Name => 'SR2DataIFD',
|
---|
1368 | Groups => { 1 => 'SR2DataIFD' }, # (needed to set SubIFD DirName)
|
---|
1369 | Flags => 'SubIFD',
|
---|
1370 | SubDirectory => {
|
---|
1371 | TagTable => 'Image::ExifTool::Sony::SR2DataIFD',
|
---|
1372 | Start => '$val',
|
---|
1373 | MaxSubdirs => 20, # an A700 ARW has 14 of these! - PH
|
---|
1374 | },
|
---|
1375 | },
|
---|
1376 | 0x7313 => 'WB_RGGBLevels', #6
|
---|
1377 | 0x74a0 => 'MaxApertureAtMaxFocal', #PH
|
---|
1378 | 0x74a1 => 'MaxApertureAtMinFocal', #PH
|
---|
1379 | 0x7820 => 'WB_RGBLevelsDaylight', #6
|
---|
1380 | 0x7821 => 'WB_RGBLevelsCloudy', #6
|
---|
1381 | 0x7822 => 'WB_RGBLevelsTungsten', #6
|
---|
1382 | 0x7825 => 'WB_RGBLevelsShade', #6
|
---|
1383 | 0x7826 => 'WB_RGBLevelsFluorescent', #6
|
---|
1384 | 0x7828 => 'WB_RGBLevelsFlash', #6
|
---|
1385 | );
|
---|
1386 |
|
---|
1387 | %Image::ExifTool::Sony::SR2DataIFD = (
|
---|
1388 | WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
|
---|
1389 | CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
|
---|
1390 | GROUPS => { 0 => 'MakerNotes', 1 => 'SR2DataIFD', 2 => 'Camera' },
|
---|
1391 | SET_GROUP1 => 1, # set group1 name to directory name for all tags in table
|
---|
1392 | # 0x7313 => 'WB_RGGBLevels', (duplicated in all SR2DataIFD's)
|
---|
1393 | 0x7770 => { #PH
|
---|
1394 | Name => 'ColorMode',
|
---|
1395 | Priority => 0,
|
---|
1396 | },
|
---|
1397 | );
|
---|
1398 |
|
---|
1399 | # tags found in DSC-F1 PMP header (ref 10)
|
---|
1400 | %Image::ExifTool::Sony::PMP = (
|
---|
1401 | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
|
---|
1402 | WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
|
---|
1403 | CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
|
---|
1404 | GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
|
---|
1405 | FIRST_ENTRY => 0,
|
---|
1406 | NOTES => q{
|
---|
1407 | These tags are written in the proprietary-format header of PMP images from
|
---|
1408 | the DSC-F1.
|
---|
1409 | },
|
---|
1410 | 8 => { #PH
|
---|
1411 | Name => 'JpgFromRawStart',
|
---|
1412 | Format => 'int32u',
|
---|
1413 | Notes => q{
|
---|
1414 | OK, not really a RAW file, but this mechanism is used to allow extraction of
|
---|
1415 | the JPEG image from a PMP file
|
---|
1416 | },
|
---|
1417 | },
|
---|
1418 | 12 => { Name => 'JpgFromRawLength',Format => 'int32u' },
|
---|
1419 | 22 => { Name => 'SonyImageWidth', Format => 'int16u' },
|
---|
1420 | 24 => { Name => 'SonyImageHeight', Format => 'int16u' },
|
---|
1421 | 27 => {
|
---|
1422 | Name => 'Orientation',
|
---|
1423 | PrintConv => {
|
---|
1424 | 0 => 'Horizontal (normal)',
|
---|
1425 | 1 => 'Rotate 270 CW',#11
|
---|
1426 | 2 => 'Rotate 180',
|
---|
1427 | 3 => 'Rotate 90 CW',#11
|
---|
1428 | },
|
---|
1429 | },
|
---|
1430 | 29 => {
|
---|
1431 | Name => 'ImageQuality',
|
---|
1432 | PrintConv => {
|
---|
1433 | 8 => 'Snap Shot',
|
---|
1434 | 23 => 'Standard',
|
---|
1435 | 51 => 'Fine',
|
---|
1436 | },
|
---|
1437 | },
|
---|
1438 | # 40 => ImageWidth again (int16u)
|
---|
1439 | # 42 => ImageHeight again (int16u)
|
---|
1440 | 52 => { Name => 'Comment', Format => 'string[19]' },
|
---|
1441 | 76 => {
|
---|
1442 | Name => 'DateTimeOriginal',
|
---|
1443 | Description => 'Date/Time Original',
|
---|
1444 | Format => 'int8u[6]',
|
---|
1445 | Groups => { 2 => 'Time' },
|
---|
1446 | ValueConv => q{
|
---|
1447 | my @a = split ' ', $val;
|
---|
1448 | $a[0] += $a[0] < 70 ? 2000 : 1900;
|
---|
1449 | sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d', @a);
|
---|
1450 | },
|
---|
1451 | PrintConv => '$self->ConvertDateTime($val)',
|
---|
1452 | },
|
---|
1453 | 84 => {
|
---|
1454 | Name => 'ModifyDate',
|
---|
1455 | Format => 'int8u[6]',
|
---|
1456 | Groups => { 2 => 'Time' },
|
---|
1457 | ValueConv => q{
|
---|
1458 | my @a = split ' ', $val;
|
---|
1459 | $a[0] += $a[0] < 70 ? 2000 : 1900;
|
---|
1460 | sprintf('%.4d:%.2d:%.2d %.2d:%.2d:%.2d', @a);
|
---|
1461 | },
|
---|
1462 | PrintConv => '$self->ConvertDateTime($val)',
|
---|
1463 | },
|
---|
1464 | 102 => {
|
---|
1465 | Name => 'ExposureTime',
|
---|
1466 | Format => 'int16s',
|
---|
1467 | RawConv => '$val <= 0 ? undef : $val',
|
---|
1468 | ValueConv => '2 ** (-$val / 100)',
|
---|
1469 | PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
|
---|
1470 | },
|
---|
1471 | 106 => { # (NC -- not written by DSC-F1)
|
---|
1472 | Name => 'FNumber',
|
---|
1473 | Format => 'int16s',
|
---|
1474 | RawConv => '$val <= 0 ? undef : $val',
|
---|
1475 | ValueConv => '$val / 100', # (likely wrong)
|
---|
1476 | },
|
---|
1477 | 108 => { # (NC -- not written by DSC-F1)
|
---|
1478 | Name => 'ExposureCompensation',
|
---|
1479 | Format => 'int16s',
|
---|
1480 | RawConv => '($val == -1 or $val == -32768) ? undef : $val',
|
---|
1481 | ValueConv => '$val / 100', # (probably wrong too)
|
---|
1482 | },
|
---|
1483 | 112 => { # (NC -- not written by DSC-F1)
|
---|
1484 | Name => 'FocalLength',
|
---|
1485 | Format => 'int16s',
|
---|
1486 | Groups => { 2 => 'Camera' },
|
---|
1487 | RawConv => '$val <= 0 ? undef : $val',
|
---|
1488 | ValueConv => '$val / 100',
|
---|
1489 | PrintConv => 'sprintf("%.1f mm",$val)',
|
---|
1490 | },
|
---|
1491 | 118 => {
|
---|
1492 | Name => 'Flash',
|
---|
1493 | Groups => { 2 => 'Camera' },
|
---|
1494 | PrintConv => { 0 => 'No Flash', 1 => 'Fired' },
|
---|
1495 | },
|
---|
1496 | );
|
---|
1497 |
|
---|
1498 | # fill in Sony LensType lookup based on Minolta values
|
---|
1499 | {
|
---|
1500 | my $minoltaTypes = \%Image::ExifTool::Minolta::minoltaLensTypes;
|
---|
1501 | %sonyLensTypes = %$minoltaTypes;
|
---|
1502 | my $notes = $$minoltaTypes{Notes};
|
---|
1503 | delete $$minoltaTypes{Notes};
|
---|
1504 | my $id;
|
---|
1505 | foreach $id (sort { $a <=> $b } keys %$minoltaTypes) {
|
---|
1506 | # higher numbered lenses are missing last digit of ID for some Sony models
|
---|
1507 | next if $id < 10000;
|
---|
1508 | my $sid = int($id/10);
|
---|
1509 | my $i;
|
---|
1510 | my $lens = $$minoltaTypes{$id};
|
---|
1511 | if ($sonyLensTypes{$sid}) {
|
---|
1512 | # put lens name with "or" first in list
|
---|
1513 | if ($lens =~ / or /) {
|
---|
1514 | my $tmp = $sonyLensTypes{$sid};
|
---|
1515 | $sonyLensTypes{$sid} = $lens;
|
---|
1516 | $lens = $tmp;
|
---|
1517 | }
|
---|
1518 | for (;;) {
|
---|
1519 | $i = ($i || 0) + 1;
|
---|
1520 | $sid = int($id/10) . ".$i";
|
---|
1521 | last unless $sonyLensTypes{$sid};
|
---|
1522 | }
|
---|
1523 | }
|
---|
1524 | $sonyLensTypes{$sid} = $lens;
|
---|
1525 | }
|
---|
1526 | $$minoltaTypes{Notes} = $sonyLensTypes{Notes} = $notes;
|
---|
1527 | }
|
---|
1528 |
|
---|
1529 | #------------------------------------------------------------------------------
|
---|
1530 | # Read Sony DSC-F1 PMP file
|
---|
1531 | # Inputs: 0) ExifTool object ref, 1) dirInfo ref
|
---|
1532 | # Returns: 1 on success when reading, 0 if this isn't a valid PMP file
|
---|
1533 | sub ProcessPMP($$)
|
---|
1534 | {
|
---|
1535 | my ($exifTool, $dirInfo) = @_;
|
---|
1536 | my $raf = $$dirInfo{RAF};
|
---|
1537 | my $buff;
|
---|
1538 | $raf->Read($buff, 128) == 128 or return 0;
|
---|
1539 | # validate header length (124 bytes)
|
---|
1540 | $buff =~ /^.{8}\0{3}\x7c.{112}\xff\xd8\xff\xdb$/s or return 0;
|
---|
1541 | $exifTool->SetFileType();
|
---|
1542 | SetByteOrder('MM');
|
---|
1543 | $exifTool->FoundTag(Make => 'Sony');
|
---|
1544 | $exifTool->FoundTag(Model => 'DSC-F1');
|
---|
1545 | # extract information from 124-byte header
|
---|
1546 | my $tagTablePtr = GetTagTable('Image::ExifTool::Sony::PMP');
|
---|
1547 | my %dirInfo = ( DataPt => \$buff, DirName => 'PMP' );
|
---|
1548 | $exifTool->ProcessDirectory(\%dirInfo, $tagTablePtr);
|
---|
1549 | # process JPEG image
|
---|
1550 | $raf->Seek(124, 0);
|
---|
1551 | $$dirInfo{Base} = 124;
|
---|
1552 | $exifTool->ProcessJPEG($dirInfo);
|
---|
1553 | return 1;
|
---|
1554 | }
|
---|
1555 |
|
---|
1556 | #------------------------------------------------------------------------------
|
---|
1557 | # Decrypt Sony data (ref 1)
|
---|
1558 | # Inputs: 0) data reference, 1) start offset, 2) data length, 3) decryption key
|
---|
1559 | # Returns: nothing (original data buffer is updated with decrypted data)
|
---|
1560 | # Notes: data length should be a multiple of 4
|
---|
1561 | sub Decrypt($$$$)
|
---|
1562 | {
|
---|
1563 | my ($dataPt, $start, $len, $key) = @_;
|
---|
1564 | my ($i, $j, @pad);
|
---|
1565 | my $words = int ($len / 4);
|
---|
1566 |
|
---|
1567 | for ($i=0; $i<4; ++$i) {
|
---|
1568 | my $lo = ($key & 0xffff) * 0x0edd + 1;
|
---|
1569 | my $hi = ($key >> 16) * 0x0edd + ($key & 0xffff) * 0x02e9 + ($lo >> 16);
|
---|
1570 | $pad[$i] = $key = (($hi & 0xffff) << 16) + ($lo & 0xffff);
|
---|
1571 | }
|
---|
1572 | $pad[3] = ($pad[3] << 1 | ($pad[0]^$pad[2]) >> 31) & 0xffffffff;
|
---|
1573 | for ($i=4; $i<0x7f; ++$i) {
|
---|
1574 | $pad[$i] = (($pad[$i-4]^$pad[$i-2]) << 1 |
|
---|
1575 | ($pad[$i-3]^$pad[$i-1]) >> 31) & 0xffffffff;
|
---|
1576 | }
|
---|
1577 | my @data = unpack("x$start N$words", $$dataPt);
|
---|
1578 | for ($i=0x7f,$j=0; $j<$words; ++$i,++$j) {
|
---|
1579 | $data[$j] ^= $pad[$i & 0x7f] = $pad[($i+1) & 0x7f] ^ $pad[($i+65) & 0x7f];
|
---|
1580 | }
|
---|
1581 | substr($$dataPt, $start, $words*4) = pack('N*', @data);
|
---|
1582 | }
|
---|
1583 |
|
---|
1584 | #------------------------------------------------------------------------------
|
---|
1585 | # Set the ARW file type and decide between SubIFD and A100DataOffset
|
---|
1586 | # Inputs: 0) ExifTool object ref, 1) reference to tag 0x14a raw data
|
---|
1587 | # Returns: true if tag 0x14a is a SubIFD, false otherwise
|
---|
1588 | sub SetARW($$)
|
---|
1589 | {
|
---|
1590 | my ($exifTool, $valPt) = @_;
|
---|
1591 |
|
---|
1592 | # assume ARW for now -- SR2's get identified when FileFormat is parsed
|
---|
1593 | $exifTool->OverrideFileType($$exifTool{TIFF_TYPE} = 'ARW');
|
---|
1594 |
|
---|
1595 | # this should always be a SubIFD for models other than the A100
|
---|
1596 | return 1 unless $$exifTool{Model} eq 'DSLR-A100' and length $$valPt == 4;
|
---|
1597 |
|
---|
1598 | # for the A100, IFD0 tag 0x14a is either a pointer to the raw data if this is
|
---|
1599 | # an original image, or a SubIFD offset if the image was edited by Sony IDC,
|
---|
1600 | # so assume it points to the raw data if it isn't a valid IFD (this assumption
|
---|
1601 | # will be checked later when we try to parse the SR2Private directory)
|
---|
1602 | my %subdir = (
|
---|
1603 | DirStart => Get32u($valPt, 0),
|
---|
1604 | Base => 0,
|
---|
1605 | RAF => $$exifTool{RAF},
|
---|
1606 | AllowOutOfOrderTags => 1, # doh!
|
---|
1607 | );
|
---|
1608 | return Image::ExifTool::Exif::ValidateIFD(\%subdir);
|
---|
1609 | }
|
---|
1610 |
|
---|
1611 | #------------------------------------------------------------------------------
|
---|
1612 | # Finish writing ARW image, patching necessary Sony quirks, etc
|
---|
1613 | # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) EXIF data ref, 3) image data reference
|
---|
1614 | # Returns: undef on success, error string otherwise
|
---|
1615 | # Notes: (it turns that all of this is for the A100 only)
|
---|
1616 | sub FinishARW($$$$)
|
---|
1617 | {
|
---|
1618 | my ($exifTool, $dirInfo, $dataPt, $imageData) = @_;
|
---|
1619 |
|
---|
1620 | # pre-scan IFD0 to get IFD entry offsets for each tag
|
---|
1621 | my $dataLen = length $$dataPt;
|
---|
1622 | return 'Truncated IFD0' if $dataLen < 2;
|
---|
1623 | my $n = Get16u($dataPt, 0);
|
---|
1624 | return 'Truncated IFD0' if $dataLen < 2 + 12 * $n;
|
---|
1625 | my ($i, %entry, $dataBlock, $pad, $dataOffset);
|
---|
1626 | for ($i=0; $i<$n; ++$i) {
|
---|
1627 | my $entry = 2 + $i * 12;
|
---|
1628 | $entry{Get16u($dataPt, $entry)} = $entry;
|
---|
1629 | }
|
---|
1630 | # fix up SR2Private offset and A100DataOffset (A100 only)
|
---|
1631 | if ($entry{0xc634} and $$exifTool{MRWDirData}) {
|
---|
1632 | return 'Unexpected MRW block' unless $$exifTool{Model} eq 'DSLR-A100';
|
---|
1633 | return 'Missing A100DataOffset' unless $entry{0x14a} and $$exifTool{A100DataOffset};
|
---|
1634 | # account for total length of image data
|
---|
1635 | my $totalLen = 8 + $dataLen;
|
---|
1636 | if (ref $imageData) {
|
---|
1637 | foreach $dataBlock (@$imageData) {
|
---|
1638 | my ($pos, $size, $pad) = @$dataBlock;
|
---|
1639 | $totalLen += $size + $pad;
|
---|
1640 | }
|
---|
1641 | }
|
---|
1642 | # align MRW block on an even 4-byte boundary
|
---|
1643 | my $remain = $totalLen & 0x03;
|
---|
1644 | $pad = 4 - $remain and $totalLen += $pad if $remain;
|
---|
1645 | # set offset for the MRW directory data
|
---|
1646 | Set32u($totalLen, $dataPt, $entry{0xc634} + 8);
|
---|
1647 | # also pad MRWDirData data to an even 4 bytes (just to be safe)
|
---|
1648 | $remain = length($$exifTool{MRWDirData}) & 0x03;
|
---|
1649 | $$exifTool{MRWDirData} .= "\0" x (4 - $remain) if $remain;
|
---|
1650 | $totalLen += length $$exifTool{MRWDirData};
|
---|
1651 | # fix up A100DataOffset
|
---|
1652 | $dataOffset = $$exifTool{A100DataOffset};
|
---|
1653 | Set32u($totalLen, $dataPt, $entry{0x14a} + 8);
|
---|
1654 | }
|
---|
1655 | # patch double-referenced and incorrectly-sized A100 PreviewImage
|
---|
1656 | if ($entry{0x201} and $$exifTool{A100PreviewStart} and
|
---|
1657 | $entry{0x202} and $$exifTool{A100PreviewLength})
|
---|
1658 | {
|
---|
1659 | Set32u($$exifTool{A100PreviewStart}, $dataPt, $entry{0x201} + 8);
|
---|
1660 | Set32u($$exifTool{A100PreviewLength}, $dataPt, $entry{0x202} + 8);
|
---|
1661 | }
|
---|
1662 | # write TIFF IFD structure
|
---|
1663 | my $outfile = $$dirInfo{OutFile};
|
---|
1664 | my $header = GetByteOrder() . Set16u(0x2a) . Set32u(8);
|
---|
1665 | Write($outfile, $header, $$dataPt) or return 'Error writing';
|
---|
1666 | # copy over image data
|
---|
1667 | if (ref $imageData) {
|
---|
1668 | $exifTool->CopyImageData($imageData, $outfile) or return 'Error copying image data';
|
---|
1669 | }
|
---|
1670 | # write MRW data if necessary
|
---|
1671 | if ($$exifTool{MRWDirData}) {
|
---|
1672 | Write($outfile, "\0" x $pad) if $pad; # write padding if necessary
|
---|
1673 | Write($outfile, $$exifTool{MRWDirData});
|
---|
1674 | delete $$exifTool{MRWDirData};
|
---|
1675 | # set TIFF_END to copy over the MRW image data
|
---|
1676 | $$exifTool{TIFF_END} = $dataOffset if $dataOffset;
|
---|
1677 | }
|
---|
1678 | return undef;
|
---|
1679 | }
|
---|
1680 |
|
---|
1681 | #------------------------------------------------------------------------------
|
---|
1682 | # Process SRF maker notes
|
---|
1683 | # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
|
---|
1684 | # Returns: 1 on success
|
---|
1685 | sub ProcessSRF($$$)
|
---|
1686 | {
|
---|
1687 | my ($exifTool, $dirInfo, $tagTablePtr) = @_;
|
---|
1688 | my $dataPt = $$dirInfo{DataPt};
|
---|
1689 | my $start = $$dirInfo{DirStart};
|
---|
1690 | my $verbose = $exifTool->Options('Verbose');
|
---|
1691 |
|
---|
1692 | # process IFD chain
|
---|
1693 | my ($ifd, $success);
|
---|
1694 | for ($ifd=0; ; ) {
|
---|
1695 | # switch tag table for SRF2-5 and SRF6
|
---|
1696 | if ($ifd == 2) {
|
---|
1697 | $tagTablePtr = GetTagTable('Image::ExifTool::Sony::SRF2');
|
---|
1698 | } elsif ($ifd == 6) {
|
---|
1699 | # SRF6 uses standard EXIF tags
|
---|
1700 | $tagTablePtr = GetTagTable('Image::ExifTool::Exif::Main');
|
---|
1701 | }
|
---|
1702 | my $srf = $$dirInfo{DirName} = "SRF$ifd";
|
---|
1703 | $exifTool->{SET_GROUP1} = $srf;
|
---|
1704 | $success = Image::ExifTool::Exif::ProcessExif($exifTool, $dirInfo, $tagTablePtr);
|
---|
1705 | delete $exifTool->{SET_GROUP1};
|
---|
1706 | last unless $success;
|
---|
1707 | #
|
---|
1708 | # get pointer to next IFD
|
---|
1709 | #
|
---|
1710 | my $count = Get16u($dataPt, $$dirInfo{DirStart});
|
---|
1711 | my $dirEnd = $$dirInfo{DirStart} + 2 + $count * 12;
|
---|
1712 | last if $dirEnd + 4 > length($$dataPt);
|
---|
1713 | my $nextIFD = Get32u($dataPt, $dirEnd);
|
---|
1714 | last unless $nextIFD;
|
---|
1715 | $nextIFD -= $$dirInfo{DataPos}; # adjust for position of makernotes data
|
---|
1716 | $$dirInfo{DirStart} = $nextIFD;
|
---|
1717 | #
|
---|
1718 | # decrypt next IFD data if necessary
|
---|
1719 | #
|
---|
1720 | ++$ifd;
|
---|
1721 | my ($key, $len);
|
---|
1722 | if ($ifd == 1) {
|
---|
1723 | # get the key to decrypt IFD1
|
---|
1724 | my $cp = $start + 0x8ddc; # why?
|
---|
1725 | my $ip = $cp + 4 * unpack("x$cp C", $$dataPt);
|
---|
1726 | $key = unpack("x$ip N", $$dataPt);
|
---|
1727 | $len = $cp + $nextIFD; # decrypt up to $cp
|
---|
1728 | } elsif ($ifd == 2) {
|
---|
1729 | # get the key to decrypt IFD2
|
---|
1730 | $key = $exifTool->{SRF2Key};
|
---|
1731 | $len = length($$dataPt) - $nextIFD; # decrypt rest of maker notes
|
---|
1732 | } else {
|
---|
1733 | next; # no decryption needed
|
---|
1734 | }
|
---|
1735 | # decrypt data
|
---|
1736 | Decrypt($dataPt, $nextIFD, $len, $key) if defined $key;
|
---|
1737 | next unless $verbose > 2;
|
---|
1738 | # display decrypted data in verbose mode
|
---|
1739 | $exifTool->VerboseDir("Decrypted SRF$ifd", 0, $nextIFD + $len);
|
---|
1740 | $exifTool->VerboseDump($dataPt,
|
---|
1741 | Prefix => "$exifTool->{INDENT} ",
|
---|
1742 | Start => $nextIFD,
|
---|
1743 | DataPos => $$dirInfo{DataPos},
|
---|
1744 | );
|
---|
1745 | }
|
---|
1746 | }
|
---|
1747 |
|
---|
1748 | #------------------------------------------------------------------------------
|
---|
1749 | # Write SR2 data
|
---|
1750 | # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
|
---|
1751 | # Returns: 1 on success when reading, or SR2 directory or undef when writing
|
---|
1752 | sub WriteSR2($$$)
|
---|
1753 | {
|
---|
1754 | my ($exifTool, $dirInfo, $tagTablePtr) = @_;
|
---|
1755 | $exifTool or return 1; # allow dummy access
|
---|
1756 | my $buff = '';
|
---|
1757 | $$dirInfo{OutFile} = \$buff;
|
---|
1758 | return ProcessSR2($exifTool, $dirInfo, $tagTablePtr);
|
---|
1759 | }
|
---|
1760 |
|
---|
1761 | #------------------------------------------------------------------------------
|
---|
1762 | # Read/Write SR2 IFD and its encrypted subdirectories
|
---|
1763 | # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
|
---|
1764 | # Returns: 1 on success when reading, or SR2 directory or undef when writing
|
---|
1765 | sub ProcessSR2($$$)
|
---|
1766 | {
|
---|
1767 | my ($exifTool, $dirInfo, $tagTablePtr) = @_;
|
---|
1768 | my $raf = $$dirInfo{RAF};
|
---|
1769 | my $dataPt = $$dirInfo{DataPt};
|
---|
1770 | my $dataPos = $$dirInfo{DataPos};
|
---|
1771 | my $dataLen = $$dirInfo{DataLen} || length $$dataPt;
|
---|
1772 | my $base = $$dirInfo{Base} || 0;
|
---|
1773 | my $outfile = $$dirInfo{OutFile};
|
---|
1774 |
|
---|
1775 | # clear SR2 member variables to be safe
|
---|
1776 | delete $$exifTool{SR2SubIFDOffset};
|
---|
1777 | delete $$exifTool{SR2SubIFDLength};
|
---|
1778 | delete $$exifTool{SR2SubIFDKey};
|
---|
1779 |
|
---|
1780 | # make sure we have the first 4 bytes available to test directory type
|
---|
1781 | my $buff;
|
---|
1782 | if ($dataLen < 4 and $raf) {
|
---|
1783 | my $pos = $dataPos + ($$dirInfo{DirStart}||0) + $base;
|
---|
1784 | if ($raf->Seek($pos, 0) and $raf->Read($buff, 4) == 4) {
|
---|
1785 | $dataPt = \$buff;
|
---|
1786 | undef $$dirInfo{DataPt}; # must load data from file
|
---|
1787 | $raf->Seek($pos, 0);
|
---|
1788 | }
|
---|
1789 | }
|
---|
1790 | # this may either be a normal IFD, or a MRW data block
|
---|
1791 | # (only original ARW images from the A100 use the MRW block)
|
---|
1792 | my $dataOffset;
|
---|
1793 | if ($dataPt and $$dataPt =~ /^\0MR[IM]/) {
|
---|
1794 | my ($err, $srfPos, $srfLen, $dataOffset);
|
---|
1795 | $dataOffset = $$exifTool{A100DataOffset};
|
---|
1796 | if ($dataOffset) {
|
---|
1797 | # save information about the RAW data trailer so it will be preserved
|
---|
1798 | $$exifTool{KnownTrailer} = { Name => 'A100 RAW Data', Start => $dataOffset };
|
---|
1799 | } else {
|
---|
1800 | $err = 'A100DataOffset tag is missing from A100 ARW image';
|
---|
1801 | }
|
---|
1802 | $raf or $err = 'Unrecognized SR2 structure';
|
---|
1803 | unless ($err) {
|
---|
1804 | $srfPos = $raf->Tell();
|
---|
1805 | $srfLen = $dataOffset - $srfPos;
|
---|
1806 | unless ($srfLen > 0 and $raf->Read($buff, $srfLen) == $srfLen) {
|
---|
1807 | $err = 'Error reading MRW directory';
|
---|
1808 | }
|
---|
1809 | }
|
---|
1810 | if ($err) {
|
---|
1811 | $outfile and $exifTool->Error($err), return undef;
|
---|
1812 | $exifTool->Warn($err);
|
---|
1813 | return 0;
|
---|
1814 | }
|
---|
1815 | my %dirInfo = ( DataPt => \$buff );
|
---|
1816 | require Image::ExifTool::MinoltaRaw;
|
---|
1817 | if ($outfile) {
|
---|
1818 | # save MRW data to be written last
|
---|
1819 | $$exifTool{MRWDirData} = Image::ExifTool::MinoltaRaw::WriteMRW($exifTool, \%dirInfo);
|
---|
1820 | return $$exifTool{MRWDirData} ? "\0\0\0\0\0\0" : undef;
|
---|
1821 | } else {
|
---|
1822 | if (not $outfile and $$exifTool{HTML_DUMP}) {
|
---|
1823 | $exifTool->HDump($srfPos, $srfLen, '[A100 SRF Data]');
|
---|
1824 | }
|
---|
1825 | return Image::ExifTool::MinoltaRaw::ProcessMRW($exifTool, \%dirInfo);
|
---|
1826 | }
|
---|
1827 | } elsif ($$exifTool{A100DataOffset}) {
|
---|
1828 | my $err = 'Unexpected A100DataOffset tag';
|
---|
1829 | $outfile and $exifTool->Error($err), return undef;
|
---|
1830 | $exifTool->Warn($err);
|
---|
1831 | return 0;
|
---|
1832 | }
|
---|
1833 | my $verbose = $exifTool->Options('Verbose');
|
---|
1834 | my $result;
|
---|
1835 | if ($outfile) {
|
---|
1836 | $result = Image::ExifTool::Exif::WriteExif($exifTool, $dirInfo, $tagTablePtr);
|
---|
1837 | return undef unless $result;
|
---|
1838 | $$outfile .= $result;
|
---|
1839 |
|
---|
1840 | } else {
|
---|
1841 | $result = Image::ExifTool::Exif::ProcessExif($exifTool, $dirInfo, $tagTablePtr);
|
---|
1842 | }
|
---|
1843 | return $result unless $result and $$exifTool{SR2SubIFDOffset};
|
---|
1844 | # only take first offset value if more than one!
|
---|
1845 | my @offsets = split ' ', $exifTool->{SR2SubIFDOffset};
|
---|
1846 | my $offset = shift @offsets;
|
---|
1847 | my $length = $exifTool->{SR2SubIFDLength};
|
---|
1848 | my $key = $exifTool->{SR2SubIFDKey};
|
---|
1849 | my @subifdPos;
|
---|
1850 | if ($offset and $length and defined $key) {
|
---|
1851 | my $buff;
|
---|
1852 | # read encrypted SR2SubIFD from file
|
---|
1853 | if (($raf and $raf->Seek($offset+$base, 0) and
|
---|
1854 | $raf->Read($buff, $length) == $length) or
|
---|
1855 | # or read from data (when processing Adobe DNGPrivateData)
|
---|
1856 | ($offset - $dataPos >= 0 and $offset - $dataPos + $length < $dataLen and
|
---|
1857 | ($buff = substr($$dataPt, $offset - $dataPos, $length))))
|
---|
1858 | {
|
---|
1859 | Decrypt(\$buff, 0, $length, $key);
|
---|
1860 | # display decrypted data in verbose mode
|
---|
1861 | if ($verbose > 2 and not $outfile) {
|
---|
1862 | $exifTool->VerboseDir("Decrypted SR2SubIFD", 0, $length);
|
---|
1863 | $exifTool->VerboseDump(\$buff, Addr => $offset + $base);
|
---|
1864 | }
|
---|
1865 | my $num = '';
|
---|
1866 | my $dPos = $offset;
|
---|
1867 | for (;;) {
|
---|
1868 | my %dirInfo = (
|
---|
1869 | Base => $base,
|
---|
1870 | DataPt => \$buff,
|
---|
1871 | DataLen => length $buff,
|
---|
1872 | DirStart => $offset - $dPos,
|
---|
1873 | DirName => "SR2SubIFD$num",
|
---|
1874 | DataPos => $dPos,
|
---|
1875 | );
|
---|
1876 | my $subTable = GetTagTable('Image::ExifTool::Sony::SR2SubIFD');
|
---|
1877 | if ($outfile) {
|
---|
1878 | my $fixup = new Image::ExifTool::Fixup;
|
---|
1879 | $dirInfo{Fixup} = $fixup;
|
---|
1880 | $result = $exifTool->WriteDirectory(\%dirInfo, $subTable);
|
---|
1881 | return undef unless $result;
|
---|
1882 | # save position of this SubIFD
|
---|
1883 | push @subifdPos, length($$outfile);
|
---|
1884 | # add this directory to the returned data
|
---|
1885 | $$fixup{Start} += length($$outfile);
|
---|
1886 | $$outfile .= $result;
|
---|
1887 | $dirInfo->{Fixup}->AddFixup($fixup);
|
---|
1888 | } else {
|
---|
1889 | $result = $exifTool->ProcessDirectory(\%dirInfo, $subTable);
|
---|
1890 | }
|
---|
1891 | last unless @offsets;
|
---|
1892 | $offset = shift @offsets;
|
---|
1893 | $num = ($num || 1) + 1;
|
---|
1894 | }
|
---|
1895 |
|
---|
1896 | } else {
|
---|
1897 | $exifTool->Warn('Error reading SR2 data');
|
---|
1898 | }
|
---|
1899 | }
|
---|
1900 | if ($outfile and @subifdPos) {
|
---|
1901 | # the SR2SubIFD must be padded to a multiple of 4 bytes for the encryption
|
---|
1902 | my $sr2Len = length($$outfile) - $subifdPos[0];
|
---|
1903 | if ($sr2Len & 0x03) {
|
---|
1904 | my $pad = 4 - ($sr2Len & 0x03);
|
---|
1905 | $sr2Len += $pad;
|
---|
1906 | $$outfile .= ' ' x $pad;
|
---|
1907 | }
|
---|
1908 | # save the new SR2SubIFD Length and Key to be used later for encryption
|
---|
1909 | $$exifTool{SR2SubIFDLength} = $sr2Len;
|
---|
1910 | my $newKey = $$exifTool{VALUE}{SR2SubIFDKey};
|
---|
1911 | $$exifTool{SR2SubIFDKey} = $newKey if defined $newKey;
|
---|
1912 | # update SubIFD pointers manually and add to fixup, and set SR2SubIFDLength
|
---|
1913 | my $n = Get16u($outfile, 0);
|
---|
1914 | my ($i, %found);
|
---|
1915 | for ($i=0; $i<$n; ++$i) {
|
---|
1916 | my $entry = 2 + 12 * $i;
|
---|
1917 | my $tagID = Get16u($outfile, $entry);
|
---|
1918 | # only interested in SR2SubIFDOffset (0x7200) and SR2SubIFDLength (0x7201)
|
---|
1919 | next unless $tagID == 0x7200 or $tagID == 0x7201;
|
---|
1920 | $found{$tagID} = 1;
|
---|
1921 | my $fmt = Get16u($outfile, $entry + 2);
|
---|
1922 | if ($fmt != 0x04) { # must be int32u
|
---|
1923 | $exifTool->Error("Unexpected format ($fmt) for SR2SubIFD tag");
|
---|
1924 | return undef;
|
---|
1925 | }
|
---|
1926 | if ($tagID == 0x7201) { # SR2SubIFDLength
|
---|
1927 | Set32u($sr2Len, $outfile, $entry + 8);
|
---|
1928 | next;
|
---|
1929 | }
|
---|
1930 | my $tag = 'SR2SubIFDOffset';
|
---|
1931 | my $valuePtr = @subifdPos < 2 ? $entry+8 : Get32u($outfile, $entry+8);
|
---|
1932 | my $pos;
|
---|
1933 | foreach $pos (@subifdPos) {
|
---|
1934 | Set32u($pos, $outfile, $valuePtr);
|
---|
1935 | $dirInfo->{Fixup}->AddFixup($valuePtr, $tag);
|
---|
1936 | undef $tag;
|
---|
1937 | $valuePtr += 4;
|
---|
1938 | }
|
---|
1939 | }
|
---|
1940 | unless ($found{0x7200} and $found{0x7201}) {
|
---|
1941 | $exifTool->Error('Missing SR2SubIFD tag');
|
---|
1942 | return undef;
|
---|
1943 | }
|
---|
1944 | }
|
---|
1945 | return $outfile ? $$outfile : $result;
|
---|
1946 | }
|
---|
1947 |
|
---|
1948 | 1; # end
|
---|
1949 |
|
---|
1950 | __END__
|
---|
1951 |
|
---|
1952 | =head1 NAME
|
---|
1953 |
|
---|
1954 | Image::ExifTool::Sony - Sony EXIF maker notes tags
|
---|
1955 |
|
---|
1956 | =head1 SYNOPSIS
|
---|
1957 |
|
---|
1958 | This module is loaded automatically by Image::ExifTool when required.
|
---|
1959 |
|
---|
1960 | =head1 DESCRIPTION
|
---|
1961 |
|
---|
1962 | This module contains definitions required by Image::ExifTool to interpret
|
---|
1963 | Sony maker notes EXIF meta information.
|
---|
1964 |
|
---|
1965 | =head1 NOTES
|
---|
1966 |
|
---|
1967 | Also see Minolta.pm since Sony DSLR models use structures originating from
|
---|
1968 | Minolta.
|
---|
1969 |
|
---|
1970 | =head1 AUTHOR
|
---|
1971 |
|
---|
1972 | Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca)
|
---|
1973 |
|
---|
1974 | This library is free software; you can redistribute it and/or modify it
|
---|
1975 | under the same terms as Perl itself.
|
---|
1976 |
|
---|
1977 | =head1 REFERENCES
|
---|
1978 |
|
---|
1979 | =over 4
|
---|
1980 |
|
---|
1981 | =item L<http://www.cybercom.net/~dcoffin/dcraw/>
|
---|
1982 |
|
---|
1983 | =item L<http://homepage3.nifty.com/kamisaka/makernote/makernote_sony.htm>
|
---|
1984 |
|
---|
1985 | =item L<http://www.klingebiel.com/tempest/hd/pmp.html>
|
---|
1986 |
|
---|
1987 | =back
|
---|
1988 |
|
---|
1989 | =head1 ACKNOWLEDGEMENTS
|
---|
1990 |
|
---|
1991 | Thanks to Thomas Bodenmann, Philippe Devaux, Jens Duttke, Marcus
|
---|
1992 | Holland-Moritz, Andrey Tverdokhleb, Rudiger Lange, Igal Milchtaich and
|
---|
1993 | Michael Reitinger for help decoding some tags.
|
---|
1994 |
|
---|
1995 | =head1 SEE ALSO
|
---|
1996 |
|
---|
1997 | L<Image::ExifTool::TagNames/Sony Tags>,
|
---|
1998 | L<Image::ExifTool::TagNames/Minolta Tags>,
|
---|
1999 | L<Image::ExifTool(3pm)|Image::ExifTool>
|
---|
2000 |
|
---|
2001 | =cut
|
---|