source: main/trunk/greenstone2/perllib/cpan/Image/ExifTool/FujiFilm.pm@ 34921

Last change on this file since 34921 was 34921, checked in by anupama, 3 years ago

Committing the improvements to EmbeddedMetaPlugin's processing of Keywords vs other metadata fields. Keywords were literally stored as arrays of words rather than phrases in PDFs (at least in Diego's sample PDF), whereas other meta fields like Subjects and Creators stored them as arrays of phrases. To get both to work, Kathy updated EXIF to a newer version, to retrieve the actual EXIF values stored in the PDF. And Kathy and Dr Bainbridge came up with a new option that I added called apply_join_before_split_to_metafields that's a regex which can list the metadata fields to apply the join_before_split to and whcih previously always got applied to all metadata fields. Now it's applied to any *Keywords metafields by default, as that's the metafield we have experience of that behaves differently to the others, as it stores by word instead of phrases. Tested on Diego's sample PDF. Diego has double-checked it to works on his sample PDF too, setting the split char to ; and turning on the join_before_split and leaving apply_join_before_split_to_metafields at its default of .*Keywords. File changes are strings.properties for the tooltip, the plugin introducing the option and working with it and Kathy's EXIF updates affecting cpan/File and cpan/Image.

File size: 54.1 KB
Line 
1#------------------------------------------------------------------------------
2# File: FujiFilm.pm
3#
4# Description: Read/write FujiFilm maker notes and RAF images
5#
6# Revisions: 11/25/2003 - P. Harvey Created
7# 11/14/2007 - PH Added ability to write RAF images
8#
9# References: 1) http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html
10# 2) http://homepage3.nifty.com/kamisaka/makernote/makernote_fuji.htm (2007/09/11)
11# 3) Michael Meissner private communication
12# 4) Paul Samuelson private communication (S5)
13# 5) http://www.cybercom.net/~dcoffin/dcraw/
14# 6) http://forums.dpreview.com/forums/readflat.asp?forum=1012&thread=31350384
15# and http://forum.photome.de/viewtopic.php?f=2&t=353&p=742#p740
16# 7) Kai Lappalainen private communication
17# 8) https://exiftool.org/forum/index.php/topic,5223.0.html
18# 9) Zilvinas Brobliauskas private communication
19# 10) Albert Shan private communication
20# 11) https://exiftool.org/forum/index.php/topic,8377.0.html
21# 12) https://exiftool.org/forum/index.php/topic,9607.0.html
22# 13) https://exiftool.org/forum/index.php/topic=10481.0.html
23# IB) Iliah Borg private communication (LibRaw)
24# JD) Jens Duttke private communication
25#------------------------------------------------------------------------------
26
27package Image::ExifTool::FujiFilm;
28
29use strict;
30use vars qw($VERSION);
31use Image::ExifTool qw(:DataAccess :Utils);
32use Image::ExifTool::Exif;
33
34$VERSION = '1.79';
35
36sub ProcessFujiDir($$$);
37sub ProcessFaceRec($$$);
38
39# the following RAF version numbers have been tested for writing:
40# (as of ExifTool 11.70, this lookup is no longer used if the version number is numerical)
41my %testedRAF = (
42 '0100' => 'E550, E900, F770, S5600, S6000fd, S6500fd, HS10/HS11, HS30, S200EXR, X100, XF1, X-Pro1, X-S1, XQ2 Ver1.00, X-T100, GFX 50R, XF10',
43 '0101' => 'X-E1, X20 Ver1.01, X-T3',
44 '0102' => 'S100FS, X10 Ver1.02',
45 '0103' => 'IS Pro Ver1.03',
46 '0104' => 'S5Pro Ver1.04',
47 '0106' => 'S5Pro Ver1.06',
48 '0111' => 'S5Pro Ver1.11',
49 '0114' => 'S9600 Ver1.00',
50 '0132' => 'X-T2 Ver1.32',
51 '0144' => 'X100T Ver1.44',
52 '0159' => 'S2Pro Ver1.00',
53 '0200' => 'X10 Ver2.00',
54 '0201' => 'X-H1 Ver2.01',
55 '0212' => 'S3Pro Ver2.12',
56 '0216' => 'S3Pro Ver2.16', # (NC)
57 '0218' => 'S3Pro Ver2.18',
58 '0240' => 'X-E1 Ver2.40',
59 '0264' => 'F700 Ver2.00',
60 '0266' => 'S9500 Ver1.01',
61 '0261' => 'X-E1 Ver2.61',
62 '0269' => 'S9500 Ver1.02',
63 '0271' => 'S3Pro Ver2.71', # UV/IR model?
64 '0300' => 'X-E2',
65 # 0400 - expect to see this for X-T1
66 '0540' => 'X-T1 Ver5.40',
67 '0712' => 'S5000 Ver3.00',
68 '0716' => 'S5000 Ver3.00', # (yes, 2 RAF versions with the same Software version)
69 '0Dgi' => 'X-A10 Ver1.01 and X-A3 Ver1.02', # (yes, non-digits in the firmware number)
70);
71
72my %faceCategories = (
73 Format => 'int8u',
74 PrintConv => { BITMASK => {
75 1 => 'Partner',
76 2 => 'Family',
77 3 => 'Friend',
78 }},
79);
80
81# FujiFilm MakerNotes tags
82%Image::ExifTool::FujiFilm::Main = (
83 WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
84 CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
85 WRITABLE => 1,
86 GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
87 0x0 => {
88 Name => 'Version',
89 Writable => 'undef',
90 },
91 0x0010 => { #PH/IB
92 Name => 'InternalSerialNumber',
93 Writable => 'string',
94 Notes => q{
95 this number is unique for most models, and contains the camera model ID and
96 the date of manufacture
97 },
98 # eg) "FPX20017035 592D31313034060427796060110384"
99 # "FPX 20495643 592D313335310701318AD010110047" (F40fd)
100 # HHHHHHHHHHHHyymmdd
101 # HHHHHHHHHHHH = camera body number in hex
102 # yymmdd = date of manufacture
103 PrintConv => q{
104 if ($val =~ /^(.*?\s*)([0-9a-fA-F]*)(\d{2})(\d{2})(\d{2})(.{12})\s*\0*$/s
105 and $4 >= 1 and $4 <= 12 and $5 >= 1 and $5 <= 31)
106 {
107 my $yr = $3 + ($3 < 70 ? 2000 : 1900);
108 my $sn = pack 'H*', $2;
109 return "$1$sn $yr:$4:$5 $6";
110 } else {
111 # handle a couple of models which use a slightly different format
112 $val =~ s/\b(592D(3[0-9])+)/pack("H*",$1).' '/e;
113 }
114 return $val;
115 },
116 # (this inverse conversion doesn't work in all cases, so it is best to write
117 # the ValueConv value if an authentic internal serial number is required)
118 PrintConvInv => '$_=$val; s/(\S+) (19|20)(\d{2}):(\d{2}):(\d{2}) /unpack("H*",$1)."$3$4$5"/e; $_',
119 },
120 0x1000 => {
121 Name => 'Quality',
122 Writable => 'string',
123 },
124 0x1001 => {
125 Name => 'Sharpness',
126 Flags => 'PrintHex',
127 Writable => 'int16u',
128 PrintConv => {
129 0x00 => '-4 (softest)', #10
130 0x01 => '-3 (very soft)',
131 0x02 => '-2 (soft)',
132 0x03 => '0 (normal)',
133 0x04 => '+2 (hard)',
134 0x05 => '+3 (very hard)',
135 0x06 => '+4 (hardest)',
136 0x82 => '-1 (medium soft)', #2
137 0x84 => '+1 (medium hard)', #2
138 0x8000 => 'Film Simulation', #2
139 0xffff => 'n/a', #2
140 },
141 },
142 0x1002 => {
143 Name => 'WhiteBalance',
144 Flags => 'PrintHex',
145 Writable => 'int16u',
146 PrintConv => {
147 0x0 => 'Auto',
148 0x1 => 'Auto (white priority)', #forum10890
149 0x2 => 'Auto (ambiance priority)', #forum10890
150 0x100 => 'Daylight',
151 0x200 => 'Cloudy',
152 0x300 => 'Daylight Fluorescent',
153 0x301 => 'Day White Fluorescent',
154 0x302 => 'White Fluorescent',
155 0x303 => 'Warm White Fluorescent', #2/PH (S5)
156 0x304 => 'Living Room Warm White Fluorescent', #2/PH (S5)
157 0x400 => 'Incandescent',
158 0x500 => 'Flash', #4
159 0x600 => 'Underwater', #forum6109
160 0xf00 => 'Custom',
161 0xf01 => 'Custom2', #2
162 0xf02 => 'Custom3', #2
163 0xf03 => 'Custom4', #2
164 0xf04 => 'Custom5', #2
165 # 0xfe0 => 'Gray Point?', #2
166 0xff0 => 'Kelvin', #4
167 },
168 },
169 0x1003 => {
170 Name => 'Saturation',
171 Flags => 'PrintHex',
172 Writable => 'int16u',
173 PrintConv => {
174 0x0 => '0 (normal)', # # ("Color 0", ref 8)
175 0x080 => '+1 (medium high)', #2 ("Color +1", ref 8)
176 0x100 => '+2 (high)', # ("Color +2", ref 8)
177 0x0c0 => '+3 (very high)',
178 0x0e0 => '+4 (highest)',
179 0x180 => '-1 (medium low)', #2 ("Color -1", ref 8)
180 0x200 => 'Low',
181 0x300 => 'None (B&W)', #2
182 0x301 => 'B&W Red Filter', #PH/8
183 0x302 => 'B&W Yellow Filter', #PH (X100)
184 0x303 => 'B&W Green Filter', #PH/8
185 0x310 => 'B&W Sepia', #PH (X100)
186 0x400 => '-2 (low)', #8 ("Color -2")
187 0x4c0 => '-3 (very low)',
188 0x4e0 => '-4 (lowest)',
189 0x500 => 'Acros', #PH (X-Pro2)
190 0x501 => 'Acros Red Filter', #PH (X-Pro2)
191 0x502 => 'Acros Yellow Filter', #PH (X-Pro2)
192 0x503 => 'Acros Green Filter', #PH (X-Pro2)
193 0x8000 => 'Film Simulation', #2
194 },
195 },
196 0x1004 => {
197 Name => 'Contrast',
198 Flags => 'PrintHex',
199 Writable => 'int16u',
200 PrintConv => {
201 0x0 => 'Normal',
202 0x080 => 'Medium High', #2
203 0x100 => 'High',
204 0x180 => 'Medium Low', #2
205 0x200 => 'Low',
206 0x8000 => 'Film Simulation', #2
207 },
208 },
209 0x1005 => { #4
210 Name => 'ColorTemperature',
211 Writable => 'int16u',
212 },
213 0x1006 => { #JD
214 Name => 'Contrast',
215 Flags => 'PrintHex',
216 Writable => 'int16u',
217 PrintConv => {
218 0x0 => 'Normal',
219 0x100 => 'High',
220 0x300 => 'Low',
221 },
222 },
223 0x100a => { #2
224 Name => 'WhiteBalanceFineTune',
225 Writable => 'int32s',
226 Count => 2,
227 PrintConv => 'sprintf("Red %+d, Blue %+d", split(" ", $val))',
228 PrintConvInv => 'my @v=($val=~/-?\d+/g);"@v"',
229 },
230 0x100b => { #2
231 Name => 'NoiseReduction',
232 Flags => 'PrintHex',
233 Writable => 'int16u',
234 RawConv => '$val == 0x100 ? undef : $val',
235 PrintConv => {
236 0x40 => 'Low',
237 0x80 => 'Normal',
238 0x100 => 'n/a', #PH (NC) (all X100 samples)
239 },
240 },
241 0x100e => { #PH (X100)
242 Name => 'NoiseReduction',
243 Flags => 'PrintHex',
244 Writable => 'int16u',
245 PrintConv => {
246 0x000 => '0 (normal)', # ("NR 0, ref 8)
247 0x100 => '+2 (strong)', # ("NR+2, ref 8)
248 0x180 => '+1 (medium strong)', #8 ("NR+1")
249 0x1c0 => '+3 (very strong)',
250 0x1e0 => '+4 (strongest)',
251 0x200 => '-2 (weak)', # ("NR-2, ref 8)
252 0x280 => '-1 (medium weak)', #8 ("NR-1")
253 0x2c0 => '-3 (very weak)', #10 (-3)
254 0x2e0 => '-4 (weakest)', #10 (-4)
255 },
256 },
257 0x1010 => {
258 Name => 'FujiFlashMode',
259 Writable => 'int16u',
260 PrintHex => 1,
261 PrintConv => {
262 0 => 'Auto',
263 1 => 'On',
264 2 => 'Off',
265 3 => 'Red-eye reduction',
266 4 => 'External', #JD
267 16 => 'Commander',
268 0x8000 => 'Not Attached', #10 (X-T2) (or external flash off)
269 0x8120 => 'TTL', #10 (X-T2)
270 0x8320 => 'TTL Auto - Did not fire',
271 0x9840 => 'Manual', #10 (X-T2)
272 0x9860 => 'Flash Commander', #13
273 0x9880 => 'Multi-flash', #10 (X-T2)
274 0xa920 => '1st Curtain (front)', #10 (EF-X500 flash)
275 0xaa20 => 'TTL Slow - 1st Curtain (front)', #13
276 0xab20 => 'TTL Auto - 1st Curtain (front)', #13
277 0xad20 => 'TTL - Red-eye Flash - 1st Curtain (front)', #13
278 0xae20 => 'TTL Slow - Red-eye Flash - 1st Curtain (front)', #13
279 0xaf20 => 'TTL Auto - Red-eye Flash - 1st Curtain (front)', #13
280 0xc920 => '2nd Curtain (rear)', #10
281 0xca20 => 'TTL Slow - 2nd Curtain (rear)', #13
282 0xcb20 => 'TTL Auto - 2nd Curtain (rear)', #13
283 0xcd20 => 'TTL - Red-eye Flash - 2nd Curtain (rear)', #13
284 0xce20 => 'TTL Slow - Red-eye Flash - 2nd Curtain (rear)', #13
285 0xcf20 => 'TTL Auto - Red-eye Flash - 2nd Curtain (rear)', #13
286 0xe920 => 'High Speed Sync (HSS)', #10
287 },
288 },
289 0x1011 => {
290 Name => 'FlashExposureComp', #JD
291 Writable => 'rational64s',
292 },
293 0x1020 => {
294 Name => 'Macro',
295 Writable => 'int16u',
296 PrintConv => {
297 0 => 'Off',
298 1 => 'On',
299 },
300 },
301 0x1021 => {
302 Name => 'FocusMode',
303 Writable => 'int16u',
304 PrintConv => {
305 0 => 'Auto',
306 1 => 'Manual',
307 65535 => 'Movie', #forum10766
308 },
309 },
310 0x1022 => { #8/forum6579
311 Name => 'AFMode',
312 Writable => 'int16u',
313 Notes => '"No" for manual and some AF-multi focus modes',
314 PrintConv => {
315 0 => 'No',
316 1 => 'Single Point',
317 256 => 'Zone',
318 512 => 'Wide/Tracking',
319 },
320 },
321 0x102b => {
322 Name => 'PrioritySettings',
323 SubDirectory => { TagTable => 'Image::ExifTool::FujiFilm::PrioritySettings' },
324 },
325 0x102d => {
326 Name => 'FocusSettings',
327 SubDirectory => { TagTable => 'Image::ExifTool::FujiFilm::FocusSettings' },
328 },
329 0x102e => {
330 Name => 'AFCSettings',
331 SubDirectory => { TagTable => 'Image::ExifTool::FujiFilm::AFCSettings' },
332 },
333 0x1023 => { #2
334 Name => 'FocusPixel',
335 Writable => 'int16u',
336 Count => 2,
337 },
338 0x1030 => {
339 Name => 'SlowSync',
340 Writable => 'int16u',
341 PrintConv => {
342 0 => 'Off',
343 1 => 'On',
344 },
345 },
346 0x1031 => {
347 Name => 'PictureMode',
348 Flags => 'PrintHex',
349 Writable => 'int16u',
350 PrintConv => {
351 0x0 => 'Auto', # (or 'SR+' if SceneRecognition present, ref 11)
352 0x1 => 'Portrait',
353 0x2 => 'Landscape',
354 0x3 => 'Macro', #JD
355 0x4 => 'Sports',
356 0x5 => 'Night Scene',
357 0x6 => 'Program AE',
358 0x7 => 'Natural Light', #3
359 0x8 => 'Anti-blur', #3
360 0x9 => 'Beach & Snow', #JD
361 0xa => 'Sunset', #3
362 0xb => 'Museum', #3
363 0xc => 'Party', #3
364 0xd => 'Flower', #3
365 0xe => 'Text', #3
366 0xf => 'Natural Light & Flash', #3
367 0x10 => 'Beach', #3
368 0x11 => 'Snow', #3
369 0x12 => 'Fireworks', #3
370 0x13 => 'Underwater', #3
371 0x14 => 'Portrait with Skin Correction', #7
372 0x16 => 'Panorama', #PH (X100)
373 0x17 => 'Night (tripod)', #7
374 0x18 => 'Pro Low-light', #7
375 0x19 => 'Pro Focus', #7
376 0x1a => 'Portrait 2', #PH (NC, T500, maybe "Smile & Shoot"?)
377 0x1b => 'Dog Face Detection', #7
378 0x1c => 'Cat Face Detection', #7
379 0x30 => 'HDR', #forum10799
380 0x40 => 'Advanced Filter',
381 0x100 => 'Aperture-priority AE',
382 0x200 => 'Shutter speed priority AE',
383 0x300 => 'Manual',
384 },
385 },
386 0x1032 => { #8
387 Name => 'ExposureCount',
388 Writable => 'int16u',
389 Notes => 'number of exposures used for this image',
390 },
391 0x1033 => { #6
392 Name => 'EXRAuto',
393 Writable => 'int16u',
394 PrintConv => {
395 0 => 'Auto',
396 1 => 'Manual',
397 },
398 },
399 0x1034 => { #6
400 Name => 'EXRMode',
401 Writable => 'int16u',
402 PrintHex => 1,
403 PrintConv => {
404 0x100 => 'HR (High Resolution)',
405 0x200 => 'SN (Signal to Noise priority)',
406 0x300 => 'DR (Dynamic Range priority)',
407 },
408 },
409 0x1040 => { #8
410 Name => 'ShadowTone',
411 Writable => 'int32s',
412 PrintConv => {
413 -64 => '+4 (hardest)',
414 -48 => '+3 (very hard)',
415 -32 => '+2 (hard)',
416 -16 => '+1 (medium hard)',
417 0 => '0 (normal)',
418 16 => '-1 (medium soft)',
419 32 => '-2 (soft)',
420 },
421 },
422 0x1041 => { #8
423 Name => 'HighlightTone',
424 Writable => 'int32s',
425 PrintConv => {
426 -64 => '+4 (hardest)',
427 -48 => '+3 (very hard)',
428 -32 => '+2 (hard)',
429 -16 => '+1 (medium hard)',
430 0 => '0 (normal)',
431 16 => '-1 (medium soft)',
432 32 => '-2 (soft)',
433 },
434 },
435 0x1044 => { #forum7668
436 Name => 'DigitalZoom',
437 Writable => 'int32u',
438 ValueConv => '$val / 8',
439 ValueConvInv => '$val * 8',
440 },
441 0x1045 => { #12
442 Name => 'LensModulationOptimizer',
443 Writable => 'int32u',
444 PrintConv => { 0 => 'Off', 1 => 'On' },
445 },
446 0x1047 => { #12
447 Name => 'GrainEffect',
448 Writable => 'int32s',
449 PrintConv => {
450 0 => 'Off',
451 32 => 'Weak',
452 64 => 'Strong',
453 },
454 },
455 0x1048 => { #12
456 Name => 'ColorChromeEffect',
457 Writable => 'int32s',
458 PrintConv => {
459 0 => 'Off',
460 32 => 'Weak',
461 64 => 'Strong',
462 },
463 },
464 0x1049 => { #12
465 Name => 'BWAdjustment',
466 Notes => 'positive values are warm, negative values are cool',
467 Format => 'int8s',
468 PrintConv => '$val > 0 ? "+$val" : $val',
469 PrintConvInv => '$val + 0',
470 },
471 # 0x104b - BWAdjustment for Green->Magenta (forum10800)
472 0x104d => { #forum9634
473 Name => 'CropMode',
474 Writable => 'int16u',
475 PrintConv => { # (perhaps this is a bit mask?)
476 0 => 'n/a',
477 1 => 'Full-frame on GFX', #IB
478 2 => 'Sports Finder Mode', # (mechanical shutter)
479 4 => 'Electronic Shutter 1.25x Crop', # (continuous high)
480 },
481 },
482 0x1050 => { #forum6109
483 Name => 'ShutterType',
484 Writable => 'int16u',
485 PrintConv => {
486 0 => 'Mechanical',
487 1 => 'Electronic',
488 2 => 'Electronic (long shutter speed)', #12
489 3 => 'Electronic Front Curtain', #10
490 },
491 },
492 0x1100 => [{
493 Name => 'AutoBracketing',
494 Condition => '$$self{Model} eq "X-T3"',
495 Notes => 'X-T3 only',
496 Writable => 'int16u',
497 PrintConv => {
498 0 => 'Off',
499 1 => 'On',
500 2 => 'Pre-shot', #12 (Electronic Shutter and Continuous High drive mode only)
501 },
502 },{
503 Name => 'AutoBracketing',
504 Notes => 'other models',
505 Writable => 'int16u',
506 PrintConv => {
507 0 => 'Off',
508 1 => 'On',
509 2 => 'No flash & flash', #3
510 },
511 }],
512 0x1101 => {
513 Name => 'SequenceNumber',
514 Writable => 'int16u',
515 },
516 0x1103 => {
517 Name => 'DriveSettings',
518 SubDirectory => { TagTable => 'Image::ExifTool::FujiFilm::DriveSettings' },
519 },
520 # (0x1150-0x1152 exist only for Pro Low-light and Pro Focus PictureModes)
521 # 0x1150 - Pro Low-light - val=1; Pro Focus - val=2 (ref 7); HDR - val=128 (forum10799)
522 # 0x1151 - Pro Low-light - val=4 (number of pictures taken?); Pro Focus - val=2,3 (ref 7); HDR - val=3 (forum10799)
523 # 0x1152 - Pro Low-light - val=1,3,4 (stacked pictures used?); Pro Focus - val=1,2 (ref 7); HDR - val=3 (forum10799)
524 0x1153 => { #forum7668
525 Name => 'PanoramaAngle',
526 Writable => 'int16u',
527 },
528 0x1154 => { #forum7668
529 Name => 'PanoramaDirection',
530 Writable => 'int16u',
531 PrintConv => {
532 1 => 'Right',
533 2 => 'Up',
534 3 => 'Left',
535 4 => 'Down',
536 },
537 },
538 0x1201 => { #forum6109
539 Name => 'AdvancedFilter',
540 Writable => 'int32u',
541 PrintHex => 1,
542 PrintConv => {
543 0x10000 => 'Pop Color',
544 0x20000 => 'Hi Key',
545 0x30000 => 'Toy Camera',
546 0x40000 => 'Miniature',
547 0x50000 => 'Dynamic Tone',
548 0x60001 => 'Partial Color Red',
549 0x60002 => 'Partial Color Yellow',
550 0x60003 => 'Partial Color Green',
551 0x60004 => 'Partial Color Blue',
552 0x60005 => 'Partial Color Orange',
553 0x60006 => 'Partial Color Purple',
554 0x70000 => 'Soft Focus',
555 0x90000 => 'Low Key',
556 },
557 },
558 0x1210 => { #2
559 Name => 'ColorMode',
560 Writable => 'int16u',
561 PrintHex => 1,
562 PrintConv => {
563 0x00 => 'Standard',
564 0x10 => 'Chrome',
565 0x30 => 'B & W',
566 },
567 },
568 0x1300 => {
569 Name => 'BlurWarning',
570 Writable => 'int16u',
571 PrintConv => {
572 0 => 'None',
573 1 => 'Blur Warning',
574 },
575 },
576 0x1301 => {
577 Name => 'FocusWarning',
578 Writable => 'int16u',
579 PrintConv => {
580 0 => 'Good',
581 1 => 'Out of focus',
582 },
583 },
584 0x1302 => {
585 Name => 'ExposureWarning',
586 Writable => 'int16u',
587 PrintConv => {
588 0 => 'Good',
589 1 => 'Bad exposure',
590 },
591 },
592 0x1304 => { #PH
593 Name => 'GEImageSize',
594 Condition => '$$self{Make} =~ /^GENERAL IMAGING/',
595 Writable => 'string',
596 Notes => 'GE models only',
597 },
598 0x1400 => { #2
599 Name => 'DynamicRange',
600 Writable => 'int16u',
601 PrintConv => {
602 1 => 'Standard',
603 3 => 'Wide',
604 # the S5Pro has 100%(STD),130%,170%,230%(W1),300%,400%(W2) - PH
605 },
606 },
607 0x1401 => { #2 (this doesn't seem to work for the X100 - PH)
608 Name => 'FilmMode',
609 Writable => 'int16u',
610 PrintHex => 1,
611 PrintConv => {
612 0x000 => 'F0/Standard (Provia)', # X-Pro2 "Provia/Standard"
613 0x100 => 'F1/Studio Portrait',
614 0x110 => 'F1a/Studio Portrait Enhanced Saturation',
615 0x120 => 'F1b/Studio Portrait Smooth Skin Tone (Astia)', # X-Pro2 "Astia/Soft"
616 0x130 => 'F1c/Studio Portrait Increased Sharpness',
617 0x200 => 'F2/Fujichrome (Velvia)', # X-Pro2 "Velvia/Vivid"
618 0x300 => 'F3/Studio Portrait Ex',
619 0x400 => 'F4/Velvia',
620 0x500 => 'Pro Neg. Std', #PH (X-Pro1)
621 0x501 => 'Pro Neg. Hi', #PH (X-Pro1)
622 0x600 => 'Classic Chrome', #forum6109
623 0x700 => 'Eterna', #12
624 0x800 => 'Classic Negative', #forum10536
625 0x900 => 'Bleach Bypass', #forum10890
626 0xa00 => 'Nostalgic Neg', #forum12085
627 },
628 },
629 0x1402 => { #2
630 Name => 'DynamicRangeSetting',
631 Writable => 'int16u',
632 PrintHex => 1,
633 PrintConv => {
634 0x000 => 'Auto',
635 0x001 => 'Manual', #(ref http://forum.photome.de/viewtopic.php?f=2&t=353)
636 0x100 => 'Standard (100%)',
637 0x200 => 'Wide1 (230%)',
638 0x201 => 'Wide2 (400%)',
639 0x8000 => 'Film Simulation',
640 },
641 },
642 0x1403 => { #2 (only valid for manual DR, ref 6)
643 Name => 'DevelopmentDynamicRange',
644 Writable => 'int16u',
645 # (shows 200, 400 or 800 for HDR200,HDR400,HDR800, ref forum10799)
646 },
647 0x1404 => { #2
648 Name => 'MinFocalLength',
649 Writable => 'rational64s',
650 },
651 0x1405 => { #2
652 Name => 'MaxFocalLength',
653 Writable => 'rational64s',
654 },
655 0x1406 => { #2
656 Name => 'MaxApertureAtMinFocal',
657 Writable => 'rational64s',
658 },
659 0x1407 => { #2
660 Name => 'MaxApertureAtMaxFocal',
661 Writable => 'rational64s',
662 },
663 # 0x1408 - values: '0100', 'S100', 'VQ10'
664 # 0x1409 - values: same as 0x1408
665 # 0x140a - values: 0, 1, 3, 5, 7 (bit 2=red-eye detection, ref 11/13)
666 0x140b => { #6
667 Name => 'AutoDynamicRange',
668 Writable => 'int16u',
669 PrintConv => '"$val%"',
670 PrintConvInv => '$val=~s/\s*\%$//; $val',
671 },
672 0x104e => { #forum10800 (X-Pro3)
673 Name => 'ColorChromeFXBlue',
674 Writable => 'int32s',
675 PrintConv => {
676 0 => 'Off',
677 32 => 'Weak', # (NC)
678 64 => 'Strong',
679 },
680 },
681 0x1422 => { #8
682 Name => 'ImageStabilization',
683 Writable => 'int16u',
684 Count => 3,
685 PrintConv => [{
686 0 => 'None',
687 1 => 'Optical', #PH
688 2 => 'Sensor-shift', #PH
689 3 => 'OIS Lens', #forum9815 (optical+sensor?)
690 512 => 'Digital', #PH
691 },{
692 0 => 'Off',
693 1 => 'On (mode 1, continuous)',
694 2 => 'On (mode 2, shooting only)',
695 }],
696 },
697 0x1425 => { # if present and 0x1031 PictureMode is zero, then PictureMode is SR+, not Auto (ref 11)
698 Name => 'SceneRecognition',
699 Writable => 'int16u',
700 PrintHex => 1,
701 PrintConv => {
702 0 => 'Unrecognized',
703 0x100 => 'Portrait Image',
704 0x103 => 'Night Portrait', #forum10651
705 0x105 => 'Backlit Portrait', #forum10651
706 0x200 => 'Landscape Image',
707 0x300 => 'Night Scene',
708 0x400 => 'Macro',
709 },
710 },
711 0x1431 => { #forum6109
712 Name => 'Rating',
713 Groups => { 2 => 'Image' },
714 Writable => 'int32u',
715 Priority => 0,
716 },
717 0x1436 => { #8
718 Name => 'ImageGeneration',
719 Writable => 'int16u',
720 PrintConv => {
721 0 => 'Original Image',
722 1 => 'Re-developed from RAW',
723 },
724 },
725 0x1438 => { #forum6579 (X-T1 firmware version 3)
726 Name => 'ImageCount',
727 Notes => 'may reset to 0 when new firmware is installed',
728 Writable => 'int16u',
729 ValueConv => '$val & 0x7fff',
730 ValueConvInv => '$val | 0x8000',
731 },
732 0x1443 => { #12 (X-T3)
733 Name => 'DRangePriority',
734 Writable => 'int16u',
735 PrintConv => { 0 => 'Auto', 1 => 'Fixed' },
736 },
737 0x1444 => { #12 (X-T3, only exists if DRangePriority is 'Auto')
738 Name => 'DRangePriorityAuto',
739 Writable => 'int16u',
740 PrintConv => {
741 1 => 'Weak',
742 2 => 'Strong',
743 3 => 'Plus', #forum10799
744 },
745 },
746 0x1445 => { #12 (X-T3, only exists if DRangePriority is 'Fixed')
747 Name => 'DRangePriorityFixed',
748 Writable => 'int16u',
749 PrintConv => { 1 => 'Weak', 2 => 'Strong' },
750 },
751 0x1446 => { #12
752 Name => 'FlickerReduction',
753 Writable => 'int32u',
754 # seen values: Off=0x0000, On=0x2100,0x3100
755 PrintConv => q{
756 my $on = ((($val >> 8) & 0x0f) == 1) ? 'On' : 'Off';
757 return sprintf('%s (0x%.4x)', $on, $val);
758 },
759 PrintConvInv => '$val=~/(0x[0-9a-f]+)/i; hex $1',
760 },
761 0x3803 => { #forum10037
762 Name => 'VideoRecordingMode',
763 Groups => { 2 => 'Video' },
764 Writable => 'int32u',
765 PrintHex => 1,
766 PrintConv => {
767 0x00 => 'Normal',
768 0x10 => 'F-log',
769 0x20 => 'HLG',
770 },
771 },
772 0x3804 => { #forum10037
773 Name => 'PeripheralLighting',
774 Groups => { 2 => 'Video' },
775 Writable => 'int16u',
776 PrintConv => { 0 => 'Off', 1 => 'On' },
777 },
778 # 0x3805 - int16u: seen 1
779 0x3806 => { #forum10037
780 Name => 'VideoCompression',
781 Groups => { 2 => 'Video' },
782 Writable => 'int16u',
783 PrintConv => {
784 1 => 'Log GOP',
785 2 => 'All Intra',
786 },
787 },
788 # 0x3810 - int32u: related to video codec (ref forum10037)
789 0x3820 => { #PH (HS20EXR MOV)
790 Name => 'FrameRate',
791 Writable => 'int16u',
792 Groups => { 2 => 'Video' },
793 },
794 0x3821 => { #PH (HS20EXR MOV)
795 Name => 'FrameWidth',
796 Writable => 'int16u',
797 Groups => { 2 => 'Video' },
798 },
799 0x3822 => { #PH (HS20EXR MOV)
800 Name => 'FrameHeight',
801 Writable => 'int16u',
802 Groups => { 2 => 'Video' },
803 },
804 0x3824 => { #forum10480 (X series)
805 Name => 'FullHDHighSpeedRec',
806 Writable => 'int32u',
807 Groups => { 2 => 'Video' },
808 PrintConv => { 1 => 'Off', 2 => 'On' },
809 },
810 0x4005 => { #forum9634
811 Name => 'FaceElementSelected', # (could be face or eye)
812 Writable => 'int16u',
813 Count => 4,
814 },
815 0x4100 => { #PH
816 Name => 'FacesDetected',
817 Writable => 'int16u',
818 },
819 0x4103 => { #PH
820 Name => 'FacePositions',
821 Writable => 'int16u',
822 Count => -1,
823 Notes => q{
824 left, top, right and bottom coordinates in full-sized image for each face
825 detected
826 },
827 },
828 0x4200 => { #11
829 Name => 'NumFaceElements',
830 Writable => 'int16u',
831 },
832 0x4201 => { #11
833 Name => 'FaceElementTypes',
834 Writable => 'int8u',
835 Count => -1,
836 PrintConv => [{
837 1 => 'Face',
838 2 => 'Left Eye',
839 3 => 'Right Eye',
840 },'REPEAT'],
841 },
842 # 0x4202 int8u[-1] - number of cooredinates in each rectangle? (ref 11)
843 0x4203 => { #11
844 Name => 'FaceElementPositions',
845 Writable => 'int16u',
846 Count => -1,
847 Notes => q{
848 left, top, right and bottom coordinates in full-sized image for each face
849 element
850 },
851 },
852 # 0x4101-0x4105 - exist only if face detection active
853 # 0x4104 - also related to face detection (same number of entries as FacePositions)
854 # 0x4200 - same as 0x4100?
855 # 0x4203 - same as 0x4103
856 # 0x4204 - same as 0x4104
857 0x4282 => { #PH
858 Name => 'FaceRecInfo',
859 SubDirectory => { TagTable => 'Image::ExifTool::FujiFilm::FaceRecInfo' },
860 },
861 0x8000 => { #2
862 Name => 'FileSource',
863 Writable => 'string',
864 },
865 0x8002 => { #2
866 Name => 'OrderNumber',
867 Writable => 'int32u',
868 },
869 0x8003 => { #2
870 Name => 'FrameNumber',
871 Writable => 'int16u',
872 },
873 0xb211 => { #PH
874 Name => 'Parallax',
875 # (value set in camera is -0.5 times this value in MPImage2... why?)
876 Writable => 'rational64s',
877 Notes => 'only found in MPImage2 of .MPO images',
878 },
879 # 0xb212 - also found in MPIMage2 images - PH
880);
881
882# Focus Priority settings, tag 0x102b (X-T3, ref forum 9607)
883%Image::ExifTool::FujiFilm::PrioritySettings = (
884 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
885 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
886 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
887 GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
888 FORMAT => 'int16u',
889 WRITABLE => 1,
890 0.1 => {
891 Name => 'AF-SPriority',
892 Mask => 0x000f,
893 PrintConv => {
894 1 => 'Release',
895 2 => 'Focus',
896 },
897 },
898 0.2 => {
899 Name => 'AF-CPriority',
900 Mask => 0x00f0,
901 PrintConv => {
902 1 => 'Release',
903 2 => 'Focus',
904 },
905 },
906);
907
908# Focus settings, tag 0x102d (X-T3, ref forum 9607)
909%Image::ExifTool::FujiFilm::FocusSettings = (
910 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
911 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
912 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
913 GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
914 FORMAT => 'int32u',
915 WRITABLE => 1,
916 0.1 => {
917 Name => 'FocusMode2',
918 Mask => 0x000000ff,
919 PrintConv => {
920 0x00 => 'AF-M',
921 0x01 => 'AF-S',
922 0x02 => 'AF-C',
923 0x11 => 'AF-S (Auto)',
924 },
925 },
926 0.2 => {
927 Name => 'AFAreaMode',
928 Mask => 0x0f00,
929 PrintConv => {
930 0 => 'Single Point',
931 1 => 'Zone',
932 2 => 'Wide/Tracking',
933 },
934 },
935 0.3 => {
936 Name => 'AFAreaPointSize',
937 Mask => 0xf000,
938 PrintConv => {
939 0 => 'n/a',
940 OTHER => sub { return $_[0] },
941 },
942 },
943 0.4 => {
944 Name => 'AFAreaZoneSize',
945 Mask => 0xf0000,
946 PrintConv => {
947 0 => 'n/a',
948 OTHER => sub {
949 my ($val, $inv) = @_;
950 return "$val x $val" unless $inv;
951 $val =~ s/ ?x.*//;
952 return $val;
953 },
954 },
955 },
956);
957
958# AF-C settings, tag 0x102e (ref forum 9607)
959%Image::ExifTool::FujiFilm::AFCSettings = (
960 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
961 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
962 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
963 GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
964 FORMAT => 'int32u',
965 WRITABLE => 1,
966 0 => {
967 Name => 'AF-CSetting',
968 PrintHex => 3,
969 PrintSort => 1, # sort PrintConv by value
970 # decode in-camera preset values (X-T3)
971 PrintConv => {
972 0x102 => 'Set 1 (multi-purpose)', # (2,0,Auto)
973 0x203 => 'Set 2 (ignore obstacles)', # (3,0,Center)
974 0x122 => 'Set 3 (accelerating subject)', # (2,2,Auto)
975 0x010 => 'Set 4 (suddenly appearing subject)', # (0,1,Front)
976 0x123 => 'Set 5 (erratic motion)', # (3,2,Auto)
977 OTHER => sub {
978 my ($val, $inv) = @_;
979 return $val =~ /(0x\w+)/ ? hex $1 : undef if $inv;
980 return sprintf 'Set 6 (custom 0x%.3x)', $val;
981 },
982 },
983 },
984 0.1 => {
985 Name => 'AF-CTrackingSensitivity',
986 Mask => 0x000f, # (values 0-4)
987 },
988 0.2 => {
989 Name => 'AF-CSpeedTrackingSensitivity',
990 Mask => 0x00f0,
991 # (values 0-2)
992 },
993 0.3 => {
994 Name => 'AF-CZoneAreaSwitching',
995 Mask => 0x0f00,
996 PrintConv => {
997 0 => 'Front',
998 1 => 'Auto',
999 2 => 'Center',
1000 },
1001 },
1002);
1003
1004# DriveMode settings, tag 0x1103 (X-T3, ref forum 9607)
1005%Image::ExifTool::FujiFilm::DriveSettings = (
1006 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1007 WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
1008 CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
1009 GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
1010 FORMAT => 'int32u',
1011 WRITABLE => 1,
1012 0.1 => {
1013 Name => 'DriveMode',
1014 Mask => 0x000000ff,
1015 PrintConv => {
1016 0 => 'Single',
1017 1 => 'Continuous Low',
1018 2 => 'Continuous High',
1019 },
1020 },
1021 0.2 => {
1022 Name => 'DriveSpeed',
1023 Mask => 0xff000000,
1024 PrintConv => {
1025 0 => 'n/a',
1026 OTHER => sub {
1027 my ($val, $inv) = @_;
1028 return "$val fps" unless $inv;
1029 $val =~ s/ ?fps$//;
1030 return $val;
1031 },
1032 },
1033 },
1034);
1035
1036# Face recognition information from FinePix F550EXR (ref PH)
1037%Image::ExifTool::FujiFilm::FaceRecInfo = (
1038 PROCESS_PROC => \&ProcessFaceRec,
1039 GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
1040 VARS => { NO_ID => 1 },
1041 NOTES => 'Face recognition information.',
1042 Face1Name => { },
1043 Face2Name => { },
1044 Face3Name => { },
1045 Face4Name => { },
1046 Face5Name => { },
1047 Face6Name => { },
1048 Face7Name => { },
1049 Face8Name => { },
1050 Face1Category => { %faceCategories },
1051 Face2Category => { %faceCategories },
1052 Face3Category => { %faceCategories },
1053 Face4Category => { %faceCategories },
1054 Face5Category => { %faceCategories },
1055 Face6Category => { %faceCategories },
1056 Face7Category => { %faceCategories },
1057 Face8Category => { %faceCategories },
1058 Face1Birthday => { },
1059 Face2Birthday => { },
1060 Face3Birthday => { },
1061 Face4Birthday => { },
1062 Face5Birthday => { },
1063 Face6Birthday => { },
1064 Face7Birthday => { },
1065 Face8Birthday => { },
1066);
1067
1068# tags in RAF images (ref 5)
1069%Image::ExifTool::FujiFilm::RAF = (
1070 PROCESS_PROC => \&ProcessFujiDir,
1071 GROUPS => { 0 => 'RAF', 1 => 'RAF', 2 => 'Image' },
1072 PRIORITY => 0, # so the first RAF directory takes precedence
1073 NOTES => q{
1074 FujiFilm RAF images contain meta information stored in a proprietary
1075 FujiFilm RAF format, as well as EXIF information stored inside an embedded
1076 JPEG preview image. The table below lists tags currently decoded from the
1077 RAF-format information.
1078 },
1079 0x100 => {
1080 Name => 'RawImageFullSize',
1081 Format => 'int16u',
1082 Groups => { 1 => 'RAF2' }, # (so RAF2 shows up in family 1 list)
1083 Count => 2,
1084 Notes => 'including borders',
1085 ValueConv => 'my @v=reverse split(" ",$val);"@v"', # reverse to show width first
1086 PrintConv => '$val=~tr/ /x/; $val',
1087 },
1088 0x110 => {
1089 Name => 'RawImageCropTopLeft',
1090 Format => 'int16u',
1091 Count => 2,
1092 Notes => 'top margin first, then left margin',
1093 },
1094 0x111 => {
1095 Name => 'RawImageCroppedSize',
1096 Format => 'int16u',
1097 Count => 2,
1098 Notes => 'including borders',
1099 ValueConv => 'my @v=reverse split(" ",$val);"@v"', # reverse to show width first
1100 PrintConv => '$val=~tr/ /x/; $val',
1101 },
1102 0x115 => {
1103 Name => 'RawImageAspectRatio',
1104 Format => 'int16u',
1105 Count => 2,
1106 ValueConv => 'my @v=reverse split(" ",$val);"@v"', # reverse to show width first
1107 PrintConv => '$val=~tr/ /:/; $val',
1108 },
1109 0x121 => [
1110 {
1111 Name => 'RawImageSize',
1112 Condition => '$$self{Model} eq "FinePixS2Pro"',
1113 Format => 'int16u',
1114 Count => 2,
1115 ValueConv => q{
1116 my @v=split(" ",$val);
1117 $v[0]*=2, $v[1]/=2;
1118 return "@v";
1119 },
1120 PrintConv => '$val=~tr/ /x/; $val',
1121 },
1122 {
1123 Name => 'RawImageSize',
1124 Format => 'int16u',
1125 Count => 2,
1126 # values are height then width, adjusted for the layout
1127 ValueConv => q{
1128 my @v=reverse split(" ",$val);
1129 $$self{FujiLayout} and $v[0]/=2, $v[1]*=2;
1130 return "@v";
1131 },
1132 PrintConv => '$val=~tr/ /x/; $val',
1133 },
1134 ],
1135 0x130 => {
1136 Name => 'FujiLayout',
1137 Format => 'int8u',
1138 RawConv => q{
1139 my ($v) = split ' ', $val;
1140 $$self{FujiLayout} = $v & 0x80 ? 1 : 0;
1141 return $val;
1142 },
1143 },
1144 0x131 => { #5
1145 Name => 'XTransLayout',
1146 Description => 'X-Trans Layout',
1147 Format => 'int8u',
1148 Count => 36,
1149 PrintConv => '$val =~ tr/012 /RGB/d; join " ", $val =~ /....../g',
1150 },
1151 0x2000 => { #IB
1152 Name => 'WB_GRGBLevelsAuto',
1153 Format => 'int16u',
1154 Count => 4, # (ignore the duplicate values)
1155 },
1156 0x2100 => { #IB
1157 Name => 'WB_GRGBLevelsDaylight',
1158 Format => 'int16u',
1159 Count => 4,
1160 },
1161 0x2200 => { #IB
1162 Name => 'WB_GRGBLevelsCloudy',
1163 Format => 'int16u',
1164 Count => 4,
1165 },
1166 0x2300 => { #IB
1167 Name => 'WB_GRGBLevelsDaylightFluor',
1168 Format => 'int16u',
1169 Count => 4,
1170 },
1171 0x2301 => { #IB
1172 Name => 'WB_GRGBLevelsDayWhiteFluor',
1173 Format => 'int16u',
1174 Count => 4,
1175 },
1176 0x2302 => { #IB
1177 Name => 'WB_GRGBLevelsWhiteFluorescent',
1178 Format => 'int16u',
1179 Count => 4,
1180 },
1181 0x2310 => { #IB
1182 Name => 'WB_GRGBLevelsWarmWhiteFluor',
1183 Format => 'int16u',
1184 Count => 4,
1185 },
1186 0x2311 => { #IB
1187 Name => 'WB_GRGBLevelsLivingRoomWarmWhiteFluor',
1188 Format => 'int16u',
1189 Count => 4,
1190 },
1191 0x2400 => { #IB
1192 Name => 'WB_GRGBLevelsTungsten',
1193 Format => 'int16u',
1194 Count => 4,
1195 },
1196 # 0x2f00 => WB_GRGBLevelsCustom: int32u count, then count * (int16u GRGBGRGB), ref IB
1197 0x2ff0 => {
1198 Name => 'WB_GRGBLevels',
1199 Format => 'int16u',
1200 Count => 4,
1201 },
1202 0x9200 => { #Frank Markesteijn
1203 Name => 'RelativeExposure',
1204 Format => 'rational32s',
1205 ValueConv => 'log($val) / log(2)',
1206 ValueConvInv => 'exp($val * log(2))',
1207 PrintConv => '$val ? sprintf("%+.1f",$val) : 0',
1208 PrintConvInv => '$val',
1209 },
1210 # 0x9200 - relative exposure? (ref Frank Markesteijn)
1211 0x9650 => { #Frank Markesteijn
1212 Name => 'RawExposureBias',
1213 Format => 'rational32s',
1214 PrintConv => '$val ? sprintf("%+.1f",$val) : 0',
1215 PrintConvInv => '$val',
1216 },
1217 0xc000 => {
1218 Name => 'RAFData',
1219 SubDirectory => {
1220 TagTable => 'Image::ExifTool::FujiFilm::RAFData',
1221 ByteOrder => 'Little-endian',
1222 }
1223 },
1224);
1225
1226%Image::ExifTool::FujiFilm::RAFData = (
1227 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1228 GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
1229 DATAMEMBER => [ 0, 4, 8 ],
1230 FIRST_ENTRY => 0,
1231 # (FujiFilm image dimensions are REALLY confusing)
1232 # --> this needs some cleaning up
1233 # [Note to self: See email from Iliah Borg for more information about WB settings in this data]
1234 0 => {
1235 Name => 'RawImageWidth',
1236 Format => 'int32u',
1237 DataMember => 'FujiWidth',
1238 RawConv => '$val < 10000 ? $$self{FujiWidth} = $val : undef', #5
1239 ValueConv => '$$self{FujiLayout} ? ($val / 2) : $val',
1240 },
1241 4 => [
1242 {
1243 Name => 'RawImageWidth',
1244 Condition => 'not $$self{FujiWidth}',
1245 Format => 'int32u',
1246 DataMember => 'FujiWidth',
1247 RawConv => '$val < 10000 ? $$self{FujiWidth} = $val : undef', #PH
1248 ValueConv => '$$self{FujiLayout} ? ($val / 2) : $val',
1249 },
1250 {
1251 Name => 'RawImageHeight',
1252 Format => 'int32u',
1253 DataMember => 'FujiHeight',
1254 RawConv => '$$self{FujiHeight} = $val',
1255 ValueConv => '$$self{FujiLayout} ? ($val * 2) : $val',
1256 },
1257 ],
1258 8 => [
1259 {
1260 Name => 'RawImageWidth',
1261 Condition => 'not $$self{FujiWidth}',
1262 Format => 'int32u',
1263 DataMember => 'FujiWidth',
1264 RawConv => '$val < 10000 ? $$self{FujiWidth} = $val : undef', #PH
1265 ValueConv => '$$self{FujiLayout} ? ($val / 2) : $val',
1266 },
1267 {
1268 Name => 'RawImageHeight',
1269 Condition => 'not $$self{FujiHeight}',
1270 Format => 'int32u',
1271 DataMember => 'FujiHeight',
1272 RawConv => '$$self{FujiHeight} = $val',
1273 ValueConv => '$$self{FujiLayout} ? ($val * 2) : $val',
1274 },
1275 ],
1276 12 => {
1277 Name => 'RawImageHeight',
1278 Condition => 'not $$self{FujiHeight}',
1279 Format => 'int32u',
1280 ValueConv => '$$self{FujiLayout} ? ($val * 2) : $val',
1281 },
1282);
1283
1284# TIFF IFD-format information stored in FujiFilm RAF images (ref 5)
1285%Image::ExifTool::FujiFilm::IFD = (
1286 PROCESS_PROC => \&Image::ExifTool::Exif::ProcessExif,
1287 GROUPS => { 0 => 'RAF', 1 => 'FujiIFD', 2 => 'Image' },
1288 NOTES => 'Tags found in the FujiIFD information of RAF images from some models.',
1289 0xf000 => {
1290 Name => 'FujiIFD',
1291 Groups => { 1 => 'FujiIFD' },
1292 Flags => 'SubIFD',
1293 SubDirectory => {
1294 TagTable => 'Image::ExifTool::FujiFilm::IFD',
1295 DirName => 'FujiSubIFD',
1296 Start => '$val',
1297 },
1298 },
1299 0xf001 => 'RawImageFullWidth',
1300 0xf002 => 'RawImageFullHeight',
1301 0xf003 => 'BitsPerSample',
1302 # 0xf004 - values: 4
1303 # 0xf005 - values: 1374, 1668
1304 # 0xf006 - some sort of flag indicating packed format?
1305 0xf007 => {
1306 Name => 'StripOffsets',
1307 IsOffset => 1,
1308 OffsetPair => 0xf008, # point to associated byte counts
1309 },
1310 0xf008 => {
1311 Name => 'StripByteCounts',
1312 OffsetPair => 0xf007, # point to associated offsets
1313 },
1314 # 0xf009 - values: 0, 3
1315 0xf00a => 'BlackLevel', #IB
1316 0xf00b => 'GeometricDistortionParams', #9 (rational64s[23, 35 or 43])
1317 0xf00c => 'WB_GRBLevelsStandard', #IB (GRBXGRBX; X=17 is standard illuminant A, X=21 is D65)
1318 0xf00d => 'WB_GRBLevelsAuto', #IB
1319 0xf00e => 'WB_GRBLevels',
1320 0xf00f => 'ChromaticAberrationParams', # (rational64s[23])
1321 0xf010 => 'VignettingParams', #9 (rational64s[31 or 64])
1322);
1323
1324# information found in FFMV atom of MOV videos
1325%Image::ExifTool::FujiFilm::FFMV = (
1326 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1327 GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
1328 FIRST_ENTRY => 0,
1329 NOTES => 'Information found in the FFMV atom of MOV videos.',
1330 0 => {
1331 Name => 'MovieStreamName',
1332 Format => 'string[34]',
1333 },
1334);
1335
1336# tags in FujiFilm QuickTime videos (ref PH)
1337# (similar information in Kodak,Minolta,Nikon,Olympus,Pentax and Sanyo videos)
1338%Image::ExifTool::FujiFilm::MOV = (
1339 PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1340 GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
1341 FIRST_ENTRY => 0,
1342 NOTES => 'This information is found in MOV videos from some FujiFilm cameras.',
1343 0x00 => {
1344 Name => 'Make',
1345 Format => 'string[24]',
1346 },
1347 0x18 => {
1348 Name => 'Model',
1349 Description => 'Camera Model Name',
1350 Format => 'string[16]',
1351 },
1352 0x2e => { # (NC)
1353 Name => 'ExposureTime',
1354 Format => 'int32u',
1355 ValueConv => '$val ? 1 / $val : 0',
1356 PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
1357 },
1358 0x32 => {
1359 Name => 'FNumber',
1360 Format => 'rational64u',
1361 PrintConv => 'sprintf("%.1f",$val)',
1362 },
1363 0x3a => { # (NC)
1364 Name => 'ExposureCompensation',
1365 Format => 'rational64s',
1366 PrintConv => '$val ? sprintf("%+.1f", $val) : 0',
1367 },
1368);
1369
1370#------------------------------------------------------------------------------
1371# decode information from FujiFilm face recognition information
1372# Inputs: 0) ExifTool object reference, 1) dirInfo reference, 2) tag table ref
1373# Returns: 1
1374sub ProcessFaceRec($$$)
1375{
1376 my ($et, $dirInfo, $tagTablePtr) = @_;
1377 my $dataPt = $$dirInfo{DataPt};
1378 my $dataPos = $$dirInfo{DataPos} + ($$dirInfo{Base} || 0);
1379 my $dirStart = $$dirInfo{DirStart};
1380 my $dirLen = $$dirInfo{DirLen};
1381 my $pos = $dirStart;
1382 my $end = $dirStart + $dirLen;
1383 my ($i, $n, $p, $val);
1384 $et->VerboseDir('FaceRecInfo');
1385 for ($i=1; ; ++$i) {
1386 last if $pos + 8 > $end;
1387 my $off = Get32u($dataPt, $pos) + $dirStart;
1388 my $len = Get32u($dataPt, $pos + 4);
1389 last if $len==0 or $off>$end or $off+$len>$end or $len < 62;
1390 # values observed for each offset (always zero if not listed):
1391 # 0=5; 3=1; 4=4; 6=1; 10-13=numbers(constant for a given registered face)
1392 # 15=16; 16=3; 18=1; 22=nameLen; 26=1; 27=16; 28=7; 30-33=nameLen(int32u)
1393 # 34-37=nameOffset(int32u); 38=32; 39=16; 40=4; 42=1; 46=0,2,4,8(category)
1394 # 50=33; 51=16; 52=7; 54-57=dateLen(int32u); 58-61=dateOffset(int32u)
1395 $n = Get32u($dataPt, $off + 30);
1396 $p = Get32u($dataPt, $off + 34) + $dirStart;
1397 last if $p < $dirStart or $p + $n > $end;
1398 $val = substr($$dataPt, $p, $n);
1399 $et->HandleTag($tagTablePtr, "Face${i}Name", $val,
1400 DataPt => $dataPt,
1401 DataPos => $dataPos,
1402 Start => $p,
1403 Size => $n,
1404 );
1405 $n = Get32u($dataPt, $off + 54);
1406 $p = Get32u($dataPt, $off + 58) + $dirStart;
1407 last if $p < $dirStart or $p + $n > $end;
1408 $val = substr($$dataPt, $p, $n);
1409 $val =~ s/(\d{4})(\d{2})(\d{2})/$1:$2:$2/;
1410 $et->HandleTag($tagTablePtr, "Face${i}Birthday", $val,
1411 DataPt => $dataPt,
1412 DataPos => $dataPos,
1413 Start => $p,
1414 Size => $n,
1415 );
1416 $et->HandleTag($tagTablePtr, "Face${i}Category", undef,
1417 DataPt => $dataPt,
1418 DataPos => $dataPos,
1419 Start => $off + 46,
1420 Size => 1,
1421 );
1422 $pos += 8;
1423 }
1424 return 1;
1425}
1426
1427#------------------------------------------------------------------------------
1428# get information from FujiFilm RAF directory
1429# Inputs: 0) ExifTool object reference, 1) dirInfo reference, 2) tag table ref
1430# Returns: 1 if this was a valid FujiFilm directory
1431sub ProcessFujiDir($$$)
1432{
1433 my ($et, $dirInfo, $tagTablePtr) = @_;
1434 my $raf = $$dirInfo{RAF};
1435 my $offset = $$dirInfo{DirStart};
1436 $raf->Seek($offset, 0) or return 0;
1437 my ($buff, $index);
1438 $raf->Read($buff, 4) or return 0;
1439 my $entries = unpack 'N', $buff;
1440 $entries < 256 or return 0;
1441 $et->Options('Verbose') and $et->VerboseDir('Fuji', $entries);
1442 SetByteOrder('MM');
1443 my $pos = $offset + 4;
1444 for ($index=0; $index<$entries; ++$index) {
1445 $raf->Read($buff,4) or return 0;
1446 $pos += 4;
1447 my ($tag, $len) = unpack 'nn', $buff;
1448 my ($val, $vbuf);
1449 $raf->Read($vbuf, $len) or return 0;
1450 my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag);
1451 if ($tagInfo and $$tagInfo{Format}) {
1452 $val = ReadValue(\$vbuf, 0, $$tagInfo{Format}, $$tagInfo{Count}, $len);
1453 next unless defined $val;
1454 } elsif ($len == 4) {
1455 # interpret unknown 4-byte values as int32u
1456 $val = Get32u(\$vbuf, 0);
1457 } else {
1458 # treat other unknown values as binary data
1459 $val = \$vbuf;
1460 }
1461 $et->HandleTag($tagTablePtr, $tag, $val,
1462 Index => $index,
1463 DataPt => \$vbuf,
1464 DataPos => $pos,
1465 Size => $len,
1466 TagInfo => $tagInfo,
1467 );
1468 $pos += $len;
1469 }
1470 return 1;
1471}
1472
1473#------------------------------------------------------------------------------
1474# write information to FujiFilm RAW file (RAF)
1475# Inputs: 0) ExifTool object reference, 1) dirInfo reference
1476# Returns: 1 on success, 0 if this wasn't a valid RAF file, or -1 on write error
1477sub WriteRAF($$)
1478{
1479 my ($et, $dirInfo) = @_;
1480 my $raf = $$dirInfo{RAF};
1481 my ($hdr, $jpeg, $outJpeg, $offset, $err, $buff);
1482
1483 $raf->Read($hdr,0x94) == 0x94 or return 0;
1484 $hdr =~ /^FUJIFILM/ or return 0;
1485 my $ver = substr($hdr, 0x3c, 4);
1486 $ver =~ /^\d{4}$/ or $testedRAF{$ver} or return 0;
1487
1488 # get the position and size of embedded JPEG
1489 my ($jpos, $jlen) = unpack('x84NN', $hdr);
1490 # check to be sure the JPEG starts in the expected location
1491 if ($jpos > 0x94 or $jpos < 0x68 or $jpos & 0x03) {
1492 $et->Error("Unsupported or corrupted RAF image (version $ver)");
1493 return 1;
1494 }
1495 # check to make sure this version of RAF has been tested
1496 #(removed in ExifTool 11.70)
1497 #unless ($testedRAF{$ver}) {
1498 # $et->Warn("RAF version $ver not yet tested", 1);
1499 #}
1500 # read the embedded JPEG
1501 unless ($raf->Seek($jpos, 0) and $raf->Read($jpeg, $jlen) == $jlen) {
1502 $et->Error('Error reading RAF meta information');
1503 return 1;
1504 }
1505 # use same write directories as JPEG
1506 $et->InitWriteDirs('JPEG');
1507 # rewrite the embedded JPEG in memory
1508 my %jpegInfo = (
1509 Parent => 'RAF',
1510 RAF => new File::RandomAccess(\$jpeg),
1511 OutFile => \$outJpeg,
1512 );
1513 $$et{FILE_TYPE} = 'JPEG';
1514 my $success = $et->WriteJPEG(\%jpegInfo);
1515 $$et{FILE_TYPE} = 'RAF';
1516 unless ($success and $outJpeg) {
1517 $et->Error("Invalid RAF format");
1518 return 1;
1519 }
1520 return -1 if $success < 0;
1521
1522 # rewrite the RAF image
1523 SetByteOrder('MM');
1524 my $jpegLen = length $outJpeg;
1525 # pad JPEG to an even 4 bytes (ALWAYS use padding as Fuji does)
1526 my $pad = "\0" x (4 - ($jpegLen % 4));
1527 # update JPEG size in header (size without padding)
1528 Set32u(length($outJpeg), \$hdr, 0x58);
1529 # get pointer to start of the next RAF block
1530 my $nextPtr = Get32u(\$hdr, 0x5c);
1531 # determine the length of padding at the end of the original JPEG
1532 my $oldPadLen = $nextPtr - ($jpos + $jlen);
1533 if ($oldPadLen) {
1534 if ($oldPadLen > 1000000 or $oldPadLen < 0 or
1535 not $raf->Seek($jpos+$jlen, 0) or
1536 $raf->Read($buff, $oldPadLen) != $oldPadLen)
1537 {
1538 $et->Error('Bad RAF pointer at 0x5c');
1539 return 1;
1540 }
1541 # make sure padding is only zero bytes (can be >100k for HS10)
1542 # (have seen non-null padding in X-Pro1)
1543 if ($buff =~ /[^\0]/) {
1544 return 1 if $et->Error('Non-null bytes found in padding', 2);
1545 }
1546 }
1547 # calculate offset difference due to change in JPEG size
1548 my $ptrDiff = length($outJpeg) + length($pad) - ($jlen + $oldPadLen);
1549 # update necessary pointers in header
1550 foreach $offset (0x5c, 0x64, 0x78, 0x80) {
1551 last if $offset >= $jpos; # some versions have a short header
1552 my $oldPtr = Get32u(\$hdr, $offset);
1553 next unless $oldPtr; # don't update if pointer is zero
1554 Set32u($oldPtr + $ptrDiff, \$hdr, $offset);
1555 }
1556 # write the new header
1557 my $outfile = $$dirInfo{OutFile};
1558 Write($outfile, substr($hdr, 0, $jpos)) or $err = 1;
1559 # write the updated JPEG plus padding
1560 Write($outfile, $outJpeg, $pad) or $err = 1;
1561 # copy over the rest of the RAF image
1562 unless ($raf->Seek($nextPtr, 0)) {
1563 $et->Error('Error reading RAF image');
1564 return 1;
1565 }
1566 while ($raf->Read($buff, 65536)) {
1567 Write($outfile, $buff) or $err = 1, last;
1568 }
1569 return $err ? -1 : 1;
1570}
1571
1572#------------------------------------------------------------------------------
1573# get information from FujiFilm RAW file (RAF)
1574# Inputs: 0) ExifTool object reference, 1) dirInfo reference
1575# Returns: 1 if this was a valid RAF file
1576sub ProcessRAF($$)
1577{
1578 my ($et, $dirInfo) = @_;
1579 my ($buff, $jpeg, $warn, $offset);
1580
1581 my $raf = $$dirInfo{RAF};
1582 $raf->Read($buff,0x5c) == 0x5c or return 0;
1583 $buff =~ /^FUJIFILM/ or return 0;
1584 my ($jpos, $jlen) = unpack('x84NN', $buff);
1585 $jpos & 0x8000 and return 0;
1586 $raf->Seek($jpos, 0) or return 0;
1587 $raf->Read($jpeg, $jlen) == $jlen or return 0;
1588
1589 $et->SetFileType();
1590 $et->FoundTag('RAFVersion', substr($buff, 0x3c, 4));
1591
1592 # extract information from embedded JPEG
1593 my %dirInfo = (
1594 Parent => 'RAF',
1595 RAF => new File::RandomAccess(\$jpeg),
1596 );
1597 $$et{BASE} += $jpos;
1598 my $rtnVal = $et->ProcessJPEG(\%dirInfo);
1599 $$et{BASE} -= $jpos;
1600 $et->FoundTag('PreviewImage', \$jpeg) if $rtnVal;
1601
1602 # extract information from Fuji RAF and TIFF directories
1603 my ($rafNum, $ifdNum) = ('','');
1604 foreach $offset (0x5c, 0x64, 0x78, 0x80) {
1605 last if $offset >= $jpos;
1606 unless ($raf->Seek($offset, 0) and $raf->Read($buff, 4)) {
1607 $warn = 1;
1608 last;
1609 }
1610 my $start = unpack('N',$buff);
1611 next unless $start;
1612 if ($offset == 0x64 or $offset == 0x80) {
1613 # parse FujiIFD directory
1614 %dirInfo = (
1615 RAF => $raf,
1616 Base => $start,
1617 );
1618 $$et{SET_GROUP1} = "FujiIFD$ifdNum";
1619 my $tagTablePtr = GetTagTable('Image::ExifTool::FujiFilm::IFD');
1620 # this is TIFF-format data only for some models, so no warning if it fails
1621 $et->ProcessTIFF(\%dirInfo, $tagTablePtr, \&Image::ExifTool::ProcessTIFF);
1622 delete $$et{SET_GROUP1};
1623 $ifdNum = ($ifdNum || 1) + 1;
1624 } else {
1625 # parse RAF directory
1626 %dirInfo = (
1627 RAF => $raf,
1628 DirStart => $start,
1629 );
1630 $$et{SET_GROUP1} = "RAF$rafNum";
1631 my $tagTablePtr = GetTagTable('Image::ExifTool::FujiFilm::RAF');
1632 $et->ProcessDirectory(\%dirInfo, $tagTablePtr) or $warn = 1;
1633 delete $$et{SET_GROUP1};
1634 $rafNum = ($rafNum || 1) + 1;
1635 }
1636 }
1637 $warn and $et->Warn('Possibly corrupt RAF information');
1638
1639 return $rtnVal;
1640}
1641
16421; # end
1643
1644__END__
1645
1646=head1 NAME
1647
1648Image::ExifTool::FujiFilm - Read/write FujiFilm maker notes and RAF images
1649
1650=head1 SYNOPSIS
1651
1652This module is loaded automatically by Image::ExifTool when required.
1653
1654=head1 DESCRIPTION
1655
1656This module contains definitions required by Image::ExifTool to interpret
1657FujiFilm maker notes in EXIF information, and to read/write FujiFilm RAW
1658(RAF) images.
1659
1660=head1 AUTHOR
1661
1662Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)
1663
1664This library is free software; you can redistribute it and/or modify it
1665under the same terms as Perl itself.
1666
1667=head1 REFERENCES
1668
1669=over 4
1670
1671=item L<http://park2.wakwak.com/~tsuruzoh/Computer/Digicams/exif-e.html>
1672
1673=item L<http://homepage3.nifty.com/kamisaka/makernote/makernote_fuji.htm>
1674
1675=item L<http://www.cybercom.net/~dcoffin/dcraw/>
1676
1677=item (...plus testing with my own FinePix 2400 Zoom)
1678
1679=back
1680
1681=head1 ACKNOWLEDGEMENTS
1682
1683Thanks to Michael Meissner, Paul Samuelson and Jens Duttke for help decoding
1684some FujiFilm information.
1685
1686=head1 SEE ALSO
1687
1688L<Image::ExifTool::TagNames/FujiFilm Tags>,
1689L<Image::ExifTool(3pm)|Image::ExifTool>
1690
1691=cut
Note: See TracBrowser for help on using the repository browser.