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