| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 2 |  |  |  |  |  |  | # File:         Ricoh.pm | 
| 3 |  |  |  |  |  |  | # | 
| 4 |  |  |  |  |  |  | # Description:  Ricoh EXIF maker notes tags | 
| 5 |  |  |  |  |  |  | # | 
| 6 |  |  |  |  |  |  | # Revisions:    03/28/2005 - P. Harvey Created | 
| 7 |  |  |  |  |  |  | # | 
| 8 |  |  |  |  |  |  | # References:   1) http://www.ozhiker.com/electronics/pjmt/jpeg_info/ricoh_mn.html | 
| 9 |  |  |  |  |  |  | #               2) http://homepage3.nifty.com/kamisaka/makernote/makernote_ricoh.htm | 
| 10 |  |  |  |  |  |  | #               3) Tim Gray private communication (GR) | 
| 11 |  |  |  |  |  |  | #               4) https://github.com/atotto/ricoh-theta-tools/ | 
| 12 |  |  |  |  |  |  | #               IB) Iliah Borg private communication (LibRaw) | 
| 13 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 14 |  |  |  |  |  |  |  | 
| 15 |  |  |  |  |  |  | package Image::ExifTool::Ricoh; | 
| 16 |  |  |  |  |  |  |  | 
| 17 | 21 |  |  | 21 |  | 4933 | use strict; | 
|  | 21 |  |  |  |  | 68 |  | 
|  | 21 |  |  |  |  | 881 |  | 
| 18 | 21 |  |  | 21 |  | 138 | use vars qw($VERSION); | 
|  | 21 |  |  |  |  | 64 |  | 
|  | 21 |  |  |  |  | 1060 |  | 
| 19 | 21 |  |  | 21 |  | 213 | use Image::ExifTool qw(:DataAccess :Utils); | 
|  | 21 |  |  |  |  | 50 |  | 
|  | 21 |  |  |  |  | 4825 |  | 
| 20 | 21 |  |  | 21 |  | 1443 | use Image::ExifTool::Exif; | 
|  | 21 |  |  |  |  | 75 |  | 
|  | 21 |  |  |  |  | 64359 |  | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | $VERSION = '1.36'; | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | sub ProcessRicohText($$$); | 
| 25 |  |  |  |  |  |  | sub ProcessRicohRMETA($$$); | 
| 26 |  |  |  |  |  |  |  | 
| 27 |  |  |  |  |  |  | # lens types for Ricoh GXR | 
| 28 |  |  |  |  |  |  | my %ricohLensIDs = ( | 
| 29 |  |  |  |  |  |  | Notes => q{ | 
| 30 |  |  |  |  |  |  | Lens units available for the GXR, used by the Ricoh Composite LensID tag.  Note | 
| 31 |  |  |  |  |  |  | that unlike lenses for all other makes of cameras, the focal lengths in these | 
| 32 |  |  |  |  |  |  | model names have already been scaled to include the 35mm crop factor. | 
| 33 |  |  |  |  |  |  | }, | 
| 34 |  |  |  |  |  |  | # (the exact lens model names used by Ricoh, except for a change in case) | 
| 35 |  |  |  |  |  |  | 'RL1' => 'GR Lens A12 50mm F2.5 Macro', | 
| 36 |  |  |  |  |  |  | 'RL2' => 'Ricoh Lens S10 24-70mm F2.5-4.4 VC', | 
| 37 |  |  |  |  |  |  | 'RL3' => 'Ricoh Lens P10 28-300mm F3.5-5.6 VC', | 
| 38 |  |  |  |  |  |  | 'RL5' => 'GR Lens A12 28mm F2.5', | 
| 39 |  |  |  |  |  |  | 'RL8' => 'Mount A12', | 
| 40 |  |  |  |  |  |  | 'RL6' => 'Ricoh Lens A16 24-85mm F3.5-5.5', | 
| 41 |  |  |  |  |  |  | ); | 
| 42 |  |  |  |  |  |  |  | 
| 43 |  |  |  |  |  |  | %Image::ExifTool::Ricoh::Main = ( | 
| 44 |  |  |  |  |  |  | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, | 
| 45 |  |  |  |  |  |  | WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, | 
| 46 |  |  |  |  |  |  | CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, | 
| 47 |  |  |  |  |  |  | WRITABLE => 1, | 
| 48 |  |  |  |  |  |  | 0x0001 => { Name => 'MakerNoteType',   Writable => 'string' }, | 
| 49 |  |  |  |  |  |  | 0x0002 => { #PH | 
| 50 |  |  |  |  |  |  | Name => 'FirmwareVersion', | 
| 51 |  |  |  |  |  |  | Writable => 'string', | 
| 52 |  |  |  |  |  |  | # eg. "Rev0113" is firmware version 1.13 | 
| 53 |  |  |  |  |  |  | PrintConv => '$val=~/^Rev(\d+)$/ ? sprintf("%.2f",$1/100) : $val', | 
| 54 |  |  |  |  |  |  | PrintConvInv => '$val=~/^(\d+)\.(\d+)$/ ? sprintf("Rev%.2d%.2d",$1,$2) : $val', | 
| 55 |  |  |  |  |  |  | }, | 
| 56 |  |  |  |  |  |  | 0x0005 => [ #PH | 
| 57 |  |  |  |  |  |  | { | 
| 58 |  |  |  |  |  |  | Condition => '$$valPt =~ /^[-\w ]+$/', | 
| 59 |  |  |  |  |  |  | Name => 'SerialNumber', # (verified for GXR) | 
| 60 |  |  |  |  |  |  | Writable => 'undef', | 
| 61 |  |  |  |  |  |  | Count => 16, | 
| 62 |  |  |  |  |  |  | Notes => q{ | 
| 63 |  |  |  |  |  |  | the serial number stamped on the camera begins with 2 model-specific letters | 
| 64 |  |  |  |  |  |  | followed by the last 8 digits of this value.  For the GXR, this is the | 
| 65 |  |  |  |  |  |  | serial number of the lens unit | 
| 66 |  |  |  |  |  |  | }, | 
| 67 |  |  |  |  |  |  | PrintConv => '$val=~s/^(.*)(.{8})$/($1)$2/; $val', | 
| 68 |  |  |  |  |  |  | PrintConvInv => '$val=~tr/()//d; $val', | 
| 69 |  |  |  |  |  |  | },{ | 
| 70 |  |  |  |  |  |  | Name => 'InternalSerialNumber', | 
| 71 |  |  |  |  |  |  | Writable => 'undef', | 
| 72 |  |  |  |  |  |  | Count => 16, | 
| 73 |  |  |  |  |  |  | ValueConv => 'unpack("H*", $val)', | 
| 74 |  |  |  |  |  |  | ValueConvInv => 'pack("H*", $val)', | 
| 75 |  |  |  |  |  |  | }, | 
| 76 |  |  |  |  |  |  | ], | 
| 77 |  |  |  |  |  |  | 0x0e00 => { | 
| 78 |  |  |  |  |  |  | Name => 'PrintIM', | 
| 79 |  |  |  |  |  |  | Writable => 0, | 
| 80 |  |  |  |  |  |  | Description => 'Print Image Matching', | 
| 81 |  |  |  |  |  |  | SubDirectory => { TagTable => 'Image::ExifTool::PrintIM::Main' }, | 
| 82 |  |  |  |  |  |  | }, | 
| 83 |  |  |  |  |  |  | 0x1000 => { #3 | 
| 84 |  |  |  |  |  |  | Name => 'RecordingFormat', | 
| 85 |  |  |  |  |  |  | Writable => 'int16u', | 
| 86 |  |  |  |  |  |  | PrintConv => { | 
| 87 |  |  |  |  |  |  | 2 => 'JPEG', | 
| 88 |  |  |  |  |  |  | 3 => 'DNG', | 
| 89 |  |  |  |  |  |  | }, | 
| 90 |  |  |  |  |  |  | }, | 
| 91 |  |  |  |  |  |  | 0x1001 => [{ | 
| 92 |  |  |  |  |  |  | Name => 'ImageInfo', | 
| 93 |  |  |  |  |  |  | Condition => '$format ne "int16u"', | 
| 94 |  |  |  |  |  |  | SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::ImageInfo' }, | 
| 95 |  |  |  |  |  |  | },{ #3 | 
| 96 |  |  |  |  |  |  | Name => 'ExposureProgram', | 
| 97 |  |  |  |  |  |  | Writable => 'int16u', | 
| 98 |  |  |  |  |  |  | Notes => 'GR', | 
| 99 |  |  |  |  |  |  | PrintConv => { | 
| 100 |  |  |  |  |  |  | 1 => 'Auto', | 
| 101 |  |  |  |  |  |  | 2 => 'Program AE', | 
| 102 |  |  |  |  |  |  | 3 => 'Aperture-priority AE', | 
| 103 |  |  |  |  |  |  | 4 => 'Shutter speed priority AE', | 
| 104 |  |  |  |  |  |  | 5 => 'Shutter/aperture priority AE', # TAv | 
| 105 |  |  |  |  |  |  | 6 => 'Manual', | 
| 106 |  |  |  |  |  |  | 7 => 'Movie', #PH | 
| 107 |  |  |  |  |  |  | }, | 
| 108 |  |  |  |  |  |  | }], | 
| 109 |  |  |  |  |  |  | 0x1002 => { #3 | 
| 110 |  |  |  |  |  |  | Name => 'DriveMode', | 
| 111 |  |  |  |  |  |  | Condition => '$format eq "int16u"', | 
| 112 |  |  |  |  |  |  | Notes => 'valid only for some models', | 
| 113 |  |  |  |  |  |  | Writable => 'int16u', | 
| 114 |  |  |  |  |  |  | PrintConv => { | 
| 115 |  |  |  |  |  |  | 0 => 'Single-frame', | 
| 116 |  |  |  |  |  |  | 1 => 'Continuous', | 
| 117 |  |  |  |  |  |  | 8 => 'AF-priority Continuous', | 
| 118 |  |  |  |  |  |  | }, | 
| 119 |  |  |  |  |  |  | }, | 
| 120 |  |  |  |  |  |  | 0x1003 => [{ | 
| 121 |  |  |  |  |  |  | Name => 'Sharpness', | 
| 122 |  |  |  |  |  |  | Condition => '$format ne "int16u"', | 
| 123 |  |  |  |  |  |  | Writable => 'int32u', | 
| 124 |  |  |  |  |  |  | PrintConv => { | 
| 125 |  |  |  |  |  |  | 0 => 'Sharp', | 
| 126 |  |  |  |  |  |  | 1 => 'Normal', | 
| 127 |  |  |  |  |  |  | 2 => 'Soft', | 
| 128 |  |  |  |  |  |  | }, | 
| 129 |  |  |  |  |  |  | },{ #3 | 
| 130 |  |  |  |  |  |  | Name => 'WhiteBalance', | 
| 131 |  |  |  |  |  |  | Writable => 'int16u', | 
| 132 |  |  |  |  |  |  | Notes => 'GR', | 
| 133 |  |  |  |  |  |  | PrintConv => { | 
| 134 |  |  |  |  |  |  | 0 => 'Auto', | 
| 135 |  |  |  |  |  |  | 1 => 'Multi-P Auto', | 
| 136 |  |  |  |  |  |  | 2 => 'Daylight', | 
| 137 |  |  |  |  |  |  | 3 => 'Cloudy', | 
| 138 |  |  |  |  |  |  | 4 => 'Incandescent 1', | 
| 139 |  |  |  |  |  |  | 5 => 'Incandescent 2', | 
| 140 |  |  |  |  |  |  | 6 => 'Daylight Fluorescent', | 
| 141 |  |  |  |  |  |  | 7 => 'Neutral White Fluorescent', | 
| 142 |  |  |  |  |  |  | 8 => 'Cool White Fluorescent', | 
| 143 |  |  |  |  |  |  | 9 => 'Warm White Fluorescent', | 
| 144 |  |  |  |  |  |  | 10 => 'Manual', | 
| 145 |  |  |  |  |  |  | 11 => 'Kelvin', | 
| 146 |  |  |  |  |  |  | 12 => 'Shade', #IB | 
| 147 |  |  |  |  |  |  | }, | 
| 148 |  |  |  |  |  |  | }], | 
| 149 |  |  |  |  |  |  | 0x1004 => { #3 | 
| 150 |  |  |  |  |  |  | Name => 'WhiteBalanceFineTune', | 
| 151 |  |  |  |  |  |  | Condition => '$format eq "int16u"', | 
| 152 |  |  |  |  |  |  | Format => 'int16s', | 
| 153 |  |  |  |  |  |  | Writable => 'int16u', | 
| 154 |  |  |  |  |  |  | Notes => q{ | 
| 155 |  |  |  |  |  |  | 2 numbers: amount of adjustment towards Amber and Green.  Not valid for all | 
| 156 |  |  |  |  |  |  | models | 
| 157 |  |  |  |  |  |  | }, | 
| 158 |  |  |  |  |  |  | }, | 
| 159 |  |  |  |  |  |  | # 0x1005 int16u - 5 | 
| 160 |  |  |  |  |  |  | 0x1006 => { #3 | 
| 161 |  |  |  |  |  |  | Name => 'FocusMode', | 
| 162 |  |  |  |  |  |  | Writable => 'int16u', | 
| 163 |  |  |  |  |  |  | PrintConv => { | 
| 164 |  |  |  |  |  |  | 1 => 'Manual', | 
| 165 |  |  |  |  |  |  | 2 => 'Multi AF', | 
| 166 |  |  |  |  |  |  | 3 => 'Spot AF', | 
| 167 |  |  |  |  |  |  | 4 => 'Snap', | 
| 168 |  |  |  |  |  |  | 5 => 'Infinity', | 
| 169 |  |  |  |  |  |  | 7 => 'Face Detect', #PH | 
| 170 |  |  |  |  |  |  | 8 => 'Subject Tracking', | 
| 171 |  |  |  |  |  |  | 9 => 'Pinpoint AF', | 
| 172 |  |  |  |  |  |  | 10 => 'Movie', #PH | 
| 173 |  |  |  |  |  |  | }, | 
| 174 |  |  |  |  |  |  | }, | 
| 175 |  |  |  |  |  |  | 0x1007 => { #3 | 
| 176 |  |  |  |  |  |  | Name => 'AutoBracketing', | 
| 177 |  |  |  |  |  |  | Writable => 'int16u', | 
| 178 |  |  |  |  |  |  | PrintConv => { | 
| 179 |  |  |  |  |  |  | 0 => 'Off', | 
| 180 |  |  |  |  |  |  | 9 => 'AE', | 
| 181 |  |  |  |  |  |  | 11 => 'WB', | 
| 182 |  |  |  |  |  |  | 16 => 'DR', # (dynamic range) | 
| 183 |  |  |  |  |  |  | 17 => 'Contrast', | 
| 184 |  |  |  |  |  |  | 18 => 'WB2', # (selects two different WB presets besides normal) | 
| 185 |  |  |  |  |  |  | 19 => 'Effect', | 
| 186 |  |  |  |  |  |  | }, | 
| 187 |  |  |  |  |  |  | }, | 
| 188 |  |  |  |  |  |  | 0x1009 => { #3 | 
| 189 |  |  |  |  |  |  | Name => 'MacroMode', | 
| 190 |  |  |  |  |  |  | Writable => 'int16u', | 
| 191 |  |  |  |  |  |  | PrintConv => { 0 => 'Off', 1 => 'On' }, | 
| 192 |  |  |  |  |  |  | }, | 
| 193 |  |  |  |  |  |  | 0x100a => { #3 | 
| 194 |  |  |  |  |  |  | Name => 'FlashMode', | 
| 195 |  |  |  |  |  |  | Writable => 'int16u', | 
| 196 |  |  |  |  |  |  | PrintConv => { | 
| 197 |  |  |  |  |  |  | 0 => 'Off', | 
| 198 |  |  |  |  |  |  | 1 => 'Auto, Fired', | 
| 199 |  |  |  |  |  |  | 2 => 'On', | 
| 200 |  |  |  |  |  |  | 3 => 'Auto, Fired, Red-eye reduction', | 
| 201 |  |  |  |  |  |  | 4 => 'Slow Sync', | 
| 202 |  |  |  |  |  |  | 5 => 'Manual', | 
| 203 |  |  |  |  |  |  | 6 => 'On, Red-eye reduction', | 
| 204 |  |  |  |  |  |  | 7 => 'Synchro, Red-eye reduction', | 
| 205 |  |  |  |  |  |  | 8 => 'Auto, Did not fire', | 
| 206 |  |  |  |  |  |  | }, | 
| 207 |  |  |  |  |  |  | }, | 
| 208 |  |  |  |  |  |  | 0x100b => { #3 | 
| 209 |  |  |  |  |  |  | Name => 'FlashExposureComp', | 
| 210 |  |  |  |  |  |  | Writable => 'rational64s', | 
| 211 |  |  |  |  |  |  | PrintConv => '$val ? sprintf("%+.1f",$val) : 0', | 
| 212 |  |  |  |  |  |  | PrintConvInv => '$val', | 
| 213 |  |  |  |  |  |  | }, | 
| 214 |  |  |  |  |  |  | 0x100c => { #3 | 
| 215 |  |  |  |  |  |  | Name => 'ManualFlashOutput', | 
| 216 |  |  |  |  |  |  | Writable => 'rational64s', | 
| 217 |  |  |  |  |  |  | PrintConv => { | 
| 218 |  |  |  |  |  |  | 0 => 'Full', | 
| 219 |  |  |  |  |  |  | -24 => '1/1.4', | 
| 220 |  |  |  |  |  |  | -48 => '1/2', | 
| 221 |  |  |  |  |  |  | -72 => '1/2.8', | 
| 222 |  |  |  |  |  |  | -96 => '1/4', | 
| 223 |  |  |  |  |  |  | -120 => '1/5.6', | 
| 224 |  |  |  |  |  |  | -144 => '1/8', | 
| 225 |  |  |  |  |  |  | -168 => '1/11', | 
| 226 |  |  |  |  |  |  | -192 => '1/16', | 
| 227 |  |  |  |  |  |  | -216 => '1/22', | 
| 228 |  |  |  |  |  |  | -240 => '1/32', | 
| 229 |  |  |  |  |  |  | -288 => '1/64', | 
| 230 |  |  |  |  |  |  | }, | 
| 231 |  |  |  |  |  |  | }, | 
| 232 |  |  |  |  |  |  | 0x100d => { #3 | 
| 233 |  |  |  |  |  |  | Name => 'FullPressSnap', | 
| 234 |  |  |  |  |  |  | Writable => 'int16u', | 
| 235 |  |  |  |  |  |  | PrintConv => { 0 => 'Off', 1 => 'On' }, | 
| 236 |  |  |  |  |  |  | }, | 
| 237 |  |  |  |  |  |  | 0x100e => { #3 | 
| 238 |  |  |  |  |  |  | Name => 'DynamicRangeExpansion', | 
| 239 |  |  |  |  |  |  | Writable => 'int16u', | 
| 240 |  |  |  |  |  |  | PrintConv => { | 
| 241 |  |  |  |  |  |  | 0 => 'Off', | 
| 242 |  |  |  |  |  |  | 3 => 'Weak', | 
| 243 |  |  |  |  |  |  | 4 => 'Medium', | 
| 244 |  |  |  |  |  |  | 5 => 'Strong', | 
| 245 |  |  |  |  |  |  | }, | 
| 246 |  |  |  |  |  |  | }, | 
| 247 |  |  |  |  |  |  | 0x100f => { #3 | 
| 248 |  |  |  |  |  |  | Name => 'NoiseReduction', | 
| 249 |  |  |  |  |  |  | Writable => 'int16u', | 
| 250 |  |  |  |  |  |  | PrintConv => { | 
| 251 |  |  |  |  |  |  | 0 => 'Off', | 
| 252 |  |  |  |  |  |  | 1 => 'Weak', | 
| 253 |  |  |  |  |  |  | 2 => 'Medium', | 
| 254 |  |  |  |  |  |  | 3 => 'Strong', | 
| 255 |  |  |  |  |  |  | }, | 
| 256 |  |  |  |  |  |  | }, | 
| 257 |  |  |  |  |  |  | 0x1010 => { #3 | 
| 258 |  |  |  |  |  |  | Name => 'ImageEffects', | 
| 259 |  |  |  |  |  |  | Writable => 'int16u', | 
| 260 |  |  |  |  |  |  | PrintConv => { | 
| 261 |  |  |  |  |  |  | 0 => 'Standard', | 
| 262 |  |  |  |  |  |  | 1 => 'Vivid', | 
| 263 |  |  |  |  |  |  | 3 => 'Black & White', | 
| 264 |  |  |  |  |  |  | 5 => 'B&W Toning Effect', | 
| 265 |  |  |  |  |  |  | 6 => 'Setting 1', | 
| 266 |  |  |  |  |  |  | 7 => 'Setting 2', | 
| 267 |  |  |  |  |  |  | 9 => 'High-contrast B&W', | 
| 268 |  |  |  |  |  |  | 10 => 'Cross Process', | 
| 269 |  |  |  |  |  |  | 11 => 'Positive Film', | 
| 270 |  |  |  |  |  |  | 12 => 'Bleach Bypass', | 
| 271 |  |  |  |  |  |  | 13 => 'Retro', | 
| 272 |  |  |  |  |  |  | 15 => 'Miniature', | 
| 273 |  |  |  |  |  |  | 17 => 'High Key', | 
| 274 |  |  |  |  |  |  | }, | 
| 275 |  |  |  |  |  |  | }, | 
| 276 |  |  |  |  |  |  | 0x1011 => { #3 | 
| 277 |  |  |  |  |  |  | Name => 'Vignetting', | 
| 278 |  |  |  |  |  |  | Writable => 'int16u', | 
| 279 |  |  |  |  |  |  | PrintConv => { | 
| 280 |  |  |  |  |  |  | 0 => 'Off', | 
| 281 |  |  |  |  |  |  | 1 => 'Low', | 
| 282 |  |  |  |  |  |  | 2 => 'Medium', | 
| 283 |  |  |  |  |  |  | 3 => 'High', | 
| 284 |  |  |  |  |  |  | }, | 
| 285 |  |  |  |  |  |  | }, | 
| 286 |  |  |  |  |  |  | 0x1012 => { #PH | 
| 287 |  |  |  |  |  |  | Name => 'Contrast', | 
| 288 |  |  |  |  |  |  | Writable => 'int32u', | 
| 289 |  |  |  |  |  |  | Format => 'int32s', #3 (high-contrast B&W also has -1 and -2 settings) | 
| 290 |  |  |  |  |  |  | PrintConv => { | 
| 291 |  |  |  |  |  |  | OTHER => sub { shift }, | 
| 292 |  |  |  |  |  |  | 2147483647 => 'MAX', #3 (high-contrast B&W effect MAX setting) | 
| 293 |  |  |  |  |  |  | }, | 
| 294 |  |  |  |  |  |  | }, | 
| 295 |  |  |  |  |  |  | 0x1013 => { Name => 'Saturation', Writable => 'int32u' }, #PH | 
| 296 |  |  |  |  |  |  | 0x1014 => { Name => 'Sharpness',  Writable => 'int32u' }, #3 | 
| 297 |  |  |  |  |  |  | 0x1015 => { #3 | 
| 298 |  |  |  |  |  |  | Name => 'ToningEffect', | 
| 299 |  |  |  |  |  |  | Writable => 'int16u', | 
| 300 |  |  |  |  |  |  | PrintConv => { | 
| 301 |  |  |  |  |  |  | 0 => 'Off', | 
| 302 |  |  |  |  |  |  | 1 => 'Sepia', | 
| 303 |  |  |  |  |  |  | 2 => 'Red', | 
| 304 |  |  |  |  |  |  | 3 => 'Green', | 
| 305 |  |  |  |  |  |  | 4 => 'Blue', | 
| 306 |  |  |  |  |  |  | 5 => 'Purple', | 
| 307 |  |  |  |  |  |  | 6 => 'B&W', | 
| 308 |  |  |  |  |  |  | 7 => 'Color', | 
| 309 |  |  |  |  |  |  | }, | 
| 310 |  |  |  |  |  |  | }, | 
| 311 |  |  |  |  |  |  | 0x1016 => { #3 | 
| 312 |  |  |  |  |  |  | Name => 'HueAdjust', | 
| 313 |  |  |  |  |  |  | Writable => 'int16u', | 
| 314 |  |  |  |  |  |  | PrintConv => { | 
| 315 |  |  |  |  |  |  | 0 => 'Off', | 
| 316 |  |  |  |  |  |  | 1 => 'Basic', | 
| 317 |  |  |  |  |  |  | 2 => 'Magenta', | 
| 318 |  |  |  |  |  |  | 3 => 'Yellow', | 
| 319 |  |  |  |  |  |  | 4 => 'Normal', | 
| 320 |  |  |  |  |  |  | 5 => 'Warm', | 
| 321 |  |  |  |  |  |  | 6 => 'Cool', | 
| 322 |  |  |  |  |  |  | }, | 
| 323 |  |  |  |  |  |  | }, | 
| 324 |  |  |  |  |  |  | 0x1017 => { #3 | 
| 325 |  |  |  |  |  |  | Name => 'WideAdapter', | 
| 326 |  |  |  |  |  |  | Writable => 'int16u', | 
| 327 |  |  |  |  |  |  | PrintConv => { | 
| 328 |  |  |  |  |  |  | 0 => 'Not Attached', | 
| 329 |  |  |  |  |  |  | 2 => 'Attached', # (21mm) | 
| 330 |  |  |  |  |  |  | }, | 
| 331 |  |  |  |  |  |  | }, | 
| 332 |  |  |  |  |  |  | 0x1018 => { #3 | 
| 333 |  |  |  |  |  |  | Name => 'CropMode', | 
| 334 |  |  |  |  |  |  | Writable => 'int16u', | 
| 335 |  |  |  |  |  |  | PrintConv => { | 
| 336 |  |  |  |  |  |  | 0 => 'Off', | 
| 337 |  |  |  |  |  |  | 1 => 'On (35mm)', | 
| 338 |  |  |  |  |  |  | 2 => 'On (47mm)', #IB | 
| 339 |  |  |  |  |  |  | }, | 
| 340 |  |  |  |  |  |  | }, | 
| 341 |  |  |  |  |  |  | 0x1019 => { #3 | 
| 342 |  |  |  |  |  |  | Name => 'NDFilter', | 
| 343 |  |  |  |  |  |  | Writable => 'int16u', | 
| 344 |  |  |  |  |  |  | PrintConv => { 0 => 'Off', 1 => 'On' }, | 
| 345 |  |  |  |  |  |  | }, | 
| 346 |  |  |  |  |  |  | 0x101a => { Name => 'WBBracketShotNumber', Writable => 'int16u' }, #3 | 
| 347 |  |  |  |  |  |  | # 0x1100 - related to DR correction (ref 3) | 
| 348 |  |  |  |  |  |  | 0x1307 => { Name => 'ColorTempKelvin',     Writable => 'int32u' }, #3 | 
| 349 |  |  |  |  |  |  | 0x1308 => { Name => 'ColorTemperature',    Writable => 'int32u' }, #3 | 
| 350 |  |  |  |  |  |  | 0x1500 => { #3 | 
| 351 |  |  |  |  |  |  | Name => 'FocalLength', | 
| 352 |  |  |  |  |  |  | Writable => 'rational64u', | 
| 353 |  |  |  |  |  |  | PrintConv => 'sprintf("%.1f mm",$val)', | 
| 354 |  |  |  |  |  |  | PrintConvInv => '$val=~s/\s*mm$//;$val', | 
| 355 |  |  |  |  |  |  | }, | 
| 356 |  |  |  |  |  |  | 0x1200 => { #3 | 
| 357 |  |  |  |  |  |  | Name => 'AFStatus', | 
| 358 |  |  |  |  |  |  | Writable => 'int16u', | 
| 359 |  |  |  |  |  |  | PrintConv => { | 
| 360 |  |  |  |  |  |  | 0 => 'Out of Focus', | 
| 361 |  |  |  |  |  |  | 1 => 'In Focus', | 
| 362 |  |  |  |  |  |  | }, | 
| 363 |  |  |  |  |  |  | }, | 
| 364 |  |  |  |  |  |  | # 0x1201-0x1204 - related to focus points (ref 3) | 
| 365 |  |  |  |  |  |  | 0x1201 => { #PH (NC) | 
| 366 |  |  |  |  |  |  | Name => 'AFAreaXPosition1', | 
| 367 |  |  |  |  |  |  | Writable => 'int32u', | 
| 368 |  |  |  |  |  |  | Notes => 'manual AF area position in a 1280x864 image', | 
| 369 |  |  |  |  |  |  | }, | 
| 370 |  |  |  |  |  |  | 0x1202 => { Name => 'AFAreaYPosition1', Writable => 'int32u' }, #PH (NC) | 
| 371 |  |  |  |  |  |  | 0x1203 => { #PH (NC) | 
| 372 |  |  |  |  |  |  | Name => 'AFAreaXPosition', | 
| 373 |  |  |  |  |  |  | Writable => 'int32u', | 
| 374 |  |  |  |  |  |  | Notes => 'manual AF area position in the full image', | 
| 375 |  |  |  |  |  |  | # (coordinates change to correspond with smaller image | 
| 376 |  |  |  |  |  |  | #  when recording reduced-size JPEG) | 
| 377 |  |  |  |  |  |  | }, | 
| 378 |  |  |  |  |  |  | 0x1204 => { Name => 'AFAreaYPosition', Writable => 'int32u' }, #PH (NC) | 
| 379 |  |  |  |  |  |  | 0x1205 => { #3 | 
| 380 |  |  |  |  |  |  | Name => 'AFAreaMode', | 
| 381 |  |  |  |  |  |  | Writable => 'int16u', | 
| 382 |  |  |  |  |  |  | PrintConv => { | 
| 383 |  |  |  |  |  |  | 0 => 'Auto', | 
| 384 |  |  |  |  |  |  | 2 => 'Manual', | 
| 385 |  |  |  |  |  |  | }, | 
| 386 |  |  |  |  |  |  | }, | 
| 387 |  |  |  |  |  |  | 0x1601 => { Name => 'SensorWidth',  Writable => 'int32u' }, #3 | 
| 388 |  |  |  |  |  |  | 0x1602 => { Name => 'SensorHeight', Writable => 'int32u' }, #3 | 
| 389 |  |  |  |  |  |  | 0x1603 => { Name => 'CroppedImageWidth',  Writable => 'int32u' }, #3 | 
| 390 |  |  |  |  |  |  | 0x1604 => { Name => 'CroppedImageHeight', Writable => 'int32u' }, #3 | 
| 391 |  |  |  |  |  |  | # 0x1700 - Composite? (0=normal image, 1=interval composite, 2=multi-exposure composite) (ref 3) | 
| 392 |  |  |  |  |  |  | # 0x1703 - 0=normal, 1=final composite (ref 3) | 
| 393 |  |  |  |  |  |  | # 0x1704 - 0=normal, 2=final composite (ref 3) | 
| 394 |  |  |  |  |  |  | 0x2001 => [ | 
| 395 |  |  |  |  |  |  | { | 
| 396 |  |  |  |  |  |  | Name => 'RicohSubdir', | 
| 397 |  |  |  |  |  |  | Condition => q{ | 
| 398 |  |  |  |  |  |  | $self->{Model} !~ /^Caplio RR1\b/ and | 
| 399 |  |  |  |  |  |  | ($format ne 'int32u' or $count != 1) | 
| 400 |  |  |  |  |  |  | }, | 
| 401 |  |  |  |  |  |  | SubDirectory => { | 
| 402 |  |  |  |  |  |  | Validate => '$val =~ /^\[Ricoh Camera Info\]/', | 
| 403 |  |  |  |  |  |  | TagTable => 'Image::ExifTool::Ricoh::Subdir', | 
| 404 |  |  |  |  |  |  | Start => '$valuePtr + 20', | 
| 405 |  |  |  |  |  |  | ByteOrder => 'BigEndian', | 
| 406 |  |  |  |  |  |  | }, | 
| 407 |  |  |  |  |  |  | }, | 
| 408 |  |  |  |  |  |  | { | 
| 409 |  |  |  |  |  |  | Name => 'RicohSubdirIFD', | 
| 410 |  |  |  |  |  |  | # the CX6 and GR Digital 4 write an int32u pointer in AVI videos -- doh! | 
| 411 |  |  |  |  |  |  | Condition => '$self->{Model} !~ /^Caplio RR1\b/', | 
| 412 |  |  |  |  |  |  | Flags => 'SubIFD', | 
| 413 |  |  |  |  |  |  | SubDirectory => { | 
| 414 |  |  |  |  |  |  | TagTable => 'Image::ExifTool::Ricoh::Subdir', | 
| 415 |  |  |  |  |  |  | Start => '$val + 20', # (skip over "[Ricoh Camera Info]\0" header) | 
| 416 |  |  |  |  |  |  | ByteOrder => 'BigEndian', | 
| 417 |  |  |  |  |  |  | }, | 
| 418 |  |  |  |  |  |  | }, | 
| 419 |  |  |  |  |  |  | { | 
| 420 |  |  |  |  |  |  | Name => 'RicohRR1Subdir', | 
| 421 |  |  |  |  |  |  | SubDirectory => { | 
| 422 |  |  |  |  |  |  | Validate => '$val =~ /^\[Ricoh Camera Info\]/', | 
| 423 |  |  |  |  |  |  | TagTable => 'Image::ExifTool::Ricoh::Subdir', | 
| 424 |  |  |  |  |  |  | Start => '$valuePtr + 20', | 
| 425 |  |  |  |  |  |  | ByteOrder => 'BigEndian', | 
| 426 |  |  |  |  |  |  | # the Caplio RR1 uses a different base address -- doh! | 
| 427 |  |  |  |  |  |  | Base => '$start-20', | 
| 428 |  |  |  |  |  |  | }, | 
| 429 |  |  |  |  |  |  | }, | 
| 430 |  |  |  |  |  |  | ], | 
| 431 |  |  |  |  |  |  | 0x4001 => { | 
| 432 |  |  |  |  |  |  | Name => 'ThetaSubdir', | 
| 433 |  |  |  |  |  |  | Groups => { 1 => 'MakerNotes' },    # SubIFD needs group 1 set | 
| 434 |  |  |  |  |  |  | Flags => 'SubIFD', | 
| 435 |  |  |  |  |  |  | SubDirectory => { | 
| 436 |  |  |  |  |  |  | TagTable => 'Image::ExifTool::Ricoh::ThetaSubdir', | 
| 437 |  |  |  |  |  |  | Start => '$val', | 
| 438 |  |  |  |  |  |  | }, | 
| 439 |  |  |  |  |  |  | }, | 
| 440 |  |  |  |  |  |  | ); | 
| 441 |  |  |  |  |  |  |  | 
| 442 |  |  |  |  |  |  | # Ricoh type 2 maker notes (ref PH) | 
| 443 |  |  |  |  |  |  | # (similar to Kodak::Type11 and GE::Main) | 
| 444 |  |  |  |  |  |  | %Image::ExifTool::Ricoh::Type2 = ( | 
| 445 |  |  |  |  |  |  | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, | 
| 446 |  |  |  |  |  |  | NOTES => q{ | 
| 447 |  |  |  |  |  |  | Tags written by models such as the Ricoh HZ15 and the Pentax XG-1.  These | 
| 448 |  |  |  |  |  |  | are not writable due to numerous formatting errors as written by these | 
| 449 |  |  |  |  |  |  | cameras. | 
| 450 |  |  |  |  |  |  | }, | 
| 451 |  |  |  |  |  |  | # 0x104 - int32u: 1 | 
| 452 |  |  |  |  |  |  | # 0x200 - int32u[3]: 0 0 0 | 
| 453 |  |  |  |  |  |  | # 0x202 - int16u: 0 (GE Macro?) | 
| 454 |  |  |  |  |  |  | # 0x203 - int16u: 0,3 (Kodak PictureEffect?) | 
| 455 |  |  |  |  |  |  | # 0x204 - rational64u: 0/10 | 
| 456 |  |  |  |  |  |  | # 0x205 - rational64u: 150/1 | 
| 457 |  |  |  |  |  |  | # 0x206 - float[6]: (not really float because size should be 2 bytes) | 
| 458 |  |  |  |  |  |  | 0x207 => { | 
| 459 |  |  |  |  |  |  | Name => 'RicohModel', | 
| 460 |  |  |  |  |  |  | Writable => 'string', | 
| 461 |  |  |  |  |  |  | }, | 
| 462 |  |  |  |  |  |  | 0x300 => { | 
| 463 |  |  |  |  |  |  | # brutal.  There are lots of errors in the XG-1 maker notes.  For the XG-1, | 
| 464 |  |  |  |  |  |  | # 0x300 has a value of "XG-1Pentax".  The "XG-1" part is likely an improperly | 
| 465 |  |  |  |  |  |  | # stored 0x207 RicohModel, resulting in an erroneous 4-byte offset for this tag | 
| 466 |  |  |  |  |  |  | Name => 'RicohMake', | 
| 467 |  |  |  |  |  |  | Writable => 'undef', | 
| 468 |  |  |  |  |  |  | ValueConv => '$val =~ s/ *$//; $val', | 
| 469 |  |  |  |  |  |  | }, | 
| 470 |  |  |  |  |  |  | # 0x306 - int16u: 1 | 
| 471 |  |  |  |  |  |  | # 0x500 - int16u: 0,1 | 
| 472 |  |  |  |  |  |  | # 0x501 - int16u: 0 | 
| 473 |  |  |  |  |  |  | # 0x502 - int16u: 0 | 
| 474 |  |  |  |  |  |  | # 0x9c9c - int8u[6]: ? | 
| 475 |  |  |  |  |  |  | # 0xadad - int8u[20480]: ? | 
| 476 |  |  |  |  |  |  | ); | 
| 477 |  |  |  |  |  |  |  | 
| 478 |  |  |  |  |  |  | # Ricoh image info (ref 2) | 
| 479 |  |  |  |  |  |  | %Image::ExifTool::Ricoh::ImageInfo = ( | 
| 480 |  |  |  |  |  |  | GROUPS => { 0 => 'MakerNotes', 2 => 'Image' }, | 
| 481 |  |  |  |  |  |  | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, | 
| 482 |  |  |  |  |  |  | WRITE_PROC => \&Image::ExifTool::WriteBinaryData, | 
| 483 |  |  |  |  |  |  | CHECK_PROC => \&Image::ExifTool::CheckBinaryData, | 
| 484 |  |  |  |  |  |  | WRITABLE => 1, | 
| 485 |  |  |  |  |  |  | PRIORITY => 0, | 
| 486 |  |  |  |  |  |  | FORMAT => 'int8u', | 
| 487 |  |  |  |  |  |  | FIRST_ENTRY => 0, | 
| 488 |  |  |  |  |  |  | IS_OFFSET => [ 28 ],   # tag 28 is 'IsOffset' | 
| 489 |  |  |  |  |  |  | 0 => { | 
| 490 |  |  |  |  |  |  | Name => 'RicohImageWidth', | 
| 491 |  |  |  |  |  |  | Format => 'int16u', | 
| 492 |  |  |  |  |  |  | }, | 
| 493 |  |  |  |  |  |  | 2 => { | 
| 494 |  |  |  |  |  |  | Name => 'RicohImageHeight', | 
| 495 |  |  |  |  |  |  | Format => 'int16u', | 
| 496 |  |  |  |  |  |  | }, | 
| 497 |  |  |  |  |  |  | 6 => { | 
| 498 |  |  |  |  |  |  | Name => 'RicohDate', | 
| 499 |  |  |  |  |  |  | Groups => { 2 => 'Time' }, | 
| 500 |  |  |  |  |  |  | Format => 'int8u[7]', | 
| 501 |  |  |  |  |  |  | # (what an insane way to encode the date) | 
| 502 |  |  |  |  |  |  | ValueConv => q{ | 
| 503 |  |  |  |  |  |  | sprintf("%.2x%.2x:%.2x:%.2x %.2x:%.2x:%.2x", | 
| 504 |  |  |  |  |  |  | split(' ', $val)); | 
| 505 |  |  |  |  |  |  | }, | 
| 506 |  |  |  |  |  |  | ValueConvInv => q{ | 
| 507 |  |  |  |  |  |  | my @vals = ($val =~ /(\d{1,2})/g); | 
| 508 |  |  |  |  |  |  | push @vals, 0 if @vals < 7; | 
| 509 |  |  |  |  |  |  | join(' ', map(hex, @vals)); | 
| 510 |  |  |  |  |  |  | }, | 
| 511 |  |  |  |  |  |  | }, | 
| 512 |  |  |  |  |  |  | 28 => { | 
| 513 |  |  |  |  |  |  | Name => 'PreviewImageStart', | 
| 514 |  |  |  |  |  |  | Format => 'int16u', # ha!  (only the lower 16 bits, even if > 0xffff) | 
| 515 |  |  |  |  |  |  | Flags => 'IsOffset', | 
| 516 |  |  |  |  |  |  | OffsetPair => 30,   # associated byte count tagID | 
| 517 |  |  |  |  |  |  | DataTag => 'PreviewImage', | 
| 518 |  |  |  |  |  |  | Protected => 2, | 
| 519 |  |  |  |  |  |  | WriteGroup => 'MakerNotes', | 
| 520 |  |  |  |  |  |  | # prevent preview from being written to MakerNotes of DNG images | 
| 521 |  |  |  |  |  |  | RawConvInv => q{ | 
| 522 |  |  |  |  |  |  | return $val if $$self{FILE_TYPE} eq "JPEG"; | 
| 523 |  |  |  |  |  |  | warn "\n"; # suppress warning | 
| 524 |  |  |  |  |  |  | return undef; | 
| 525 |  |  |  |  |  |  | }, | 
| 526 |  |  |  |  |  |  | }, | 
| 527 |  |  |  |  |  |  | 30 => { | 
| 528 |  |  |  |  |  |  | Name => 'PreviewImageLength', | 
| 529 |  |  |  |  |  |  | Format => 'int16u', | 
| 530 |  |  |  |  |  |  | OffsetPair => 28,   # point to associated offset | 
| 531 |  |  |  |  |  |  | DataTag => 'PreviewImage', | 
| 532 |  |  |  |  |  |  | Protected => 2, | 
| 533 |  |  |  |  |  |  | WriteGroup => 'MakerNotes', | 
| 534 |  |  |  |  |  |  | RawConvInv => q{ | 
| 535 |  |  |  |  |  |  | return $val if $$self{FILE_TYPE} eq "JPEG"; | 
| 536 |  |  |  |  |  |  | warn "\n"; # suppress warning | 
| 537 |  |  |  |  |  |  | return undef; | 
| 538 |  |  |  |  |  |  | }, | 
| 539 |  |  |  |  |  |  | }, | 
| 540 |  |  |  |  |  |  | 32 => { | 
| 541 |  |  |  |  |  |  | Name => 'FlashMode', | 
| 542 |  |  |  |  |  |  | PrintConv => { | 
| 543 |  |  |  |  |  |  | 0 => 'Off', | 
| 544 |  |  |  |  |  |  | 1 => 'Auto', #PH | 
| 545 |  |  |  |  |  |  | 2 => 'On', | 
| 546 |  |  |  |  |  |  | }, | 
| 547 |  |  |  |  |  |  | }, | 
| 548 |  |  |  |  |  |  | 33 => { | 
| 549 |  |  |  |  |  |  | Name => 'Macro', | 
| 550 |  |  |  |  |  |  | PrintConv => { 0 => 'Off', 1 => 'On' }, | 
| 551 |  |  |  |  |  |  | }, | 
| 552 |  |  |  |  |  |  | 34 => { | 
| 553 |  |  |  |  |  |  | Name => 'Sharpness', | 
| 554 |  |  |  |  |  |  | PrintConv => { | 
| 555 |  |  |  |  |  |  | 0 => 'Sharp', | 
| 556 |  |  |  |  |  |  | 1 => 'Normal', | 
| 557 |  |  |  |  |  |  | 2 => 'Soft', | 
| 558 |  |  |  |  |  |  | }, | 
| 559 |  |  |  |  |  |  | }, | 
| 560 |  |  |  |  |  |  | 38 => { | 
| 561 |  |  |  |  |  |  | Name => 'WhiteBalance', | 
| 562 |  |  |  |  |  |  | PrintConv => { | 
| 563 |  |  |  |  |  |  | 0 => 'Auto', | 
| 564 |  |  |  |  |  |  | 1 => 'Daylight', | 
| 565 |  |  |  |  |  |  | 2 => 'Cloudy', | 
| 566 |  |  |  |  |  |  | 3 => 'Tungsten', | 
| 567 |  |  |  |  |  |  | 4 => 'Fluorescent', | 
| 568 |  |  |  |  |  |  | 5 => 'Manual', #PH (GXR) | 
| 569 |  |  |  |  |  |  | 7 => 'Detail', | 
| 570 |  |  |  |  |  |  | 9 => 'Multi-pattern Auto', #PH (GXR) | 
| 571 |  |  |  |  |  |  | }, | 
| 572 |  |  |  |  |  |  | }, | 
| 573 |  |  |  |  |  |  | 39 => { | 
| 574 |  |  |  |  |  |  | Name => 'ISOSetting', | 
| 575 |  |  |  |  |  |  | PrintConv => { | 
| 576 |  |  |  |  |  |  | 0 => 'Auto', | 
| 577 |  |  |  |  |  |  | 1 => 64, | 
| 578 |  |  |  |  |  |  | 2 => 100, | 
| 579 |  |  |  |  |  |  | 4 => 200, | 
| 580 |  |  |  |  |  |  | 6 => 400, | 
| 581 |  |  |  |  |  |  | 7 => 800, | 
| 582 |  |  |  |  |  |  | 8 => 1600, | 
| 583 |  |  |  |  |  |  | 9 => 'Auto', #PH (? CX3) | 
| 584 |  |  |  |  |  |  | 10 => 3200, #PH (A16) | 
| 585 |  |  |  |  |  |  | 11 => '100 (Low)', #PH (A16) | 
| 586 |  |  |  |  |  |  | }, | 
| 587 |  |  |  |  |  |  | }, | 
| 588 |  |  |  |  |  |  | 40 => { | 
| 589 |  |  |  |  |  |  | Name => 'Saturation', | 
| 590 |  |  |  |  |  |  | PrintConv => { | 
| 591 |  |  |  |  |  |  | 0 => 'High', | 
| 592 |  |  |  |  |  |  | 1 => 'Normal', | 
| 593 |  |  |  |  |  |  | 2 => 'Low', | 
| 594 |  |  |  |  |  |  | 3 => 'B&W', | 
| 595 |  |  |  |  |  |  | 6 => 'Toning Effect', #PH (GXR Sepia,Red,Green,Blue,Purple) | 
| 596 |  |  |  |  |  |  | 9 => 'Vivid', #PH (GXR) | 
| 597 |  |  |  |  |  |  | 10 => 'Natural', #PH (GXR) | 
| 598 |  |  |  |  |  |  | }, | 
| 599 |  |  |  |  |  |  | }, | 
| 600 |  |  |  |  |  |  | ); | 
| 601 |  |  |  |  |  |  |  | 
| 602 |  |  |  |  |  |  | # Ricoh subdirectory tags (ref PH) | 
| 603 |  |  |  |  |  |  | # NOTE: this subdir is currently not writable because the offsets would require | 
| 604 |  |  |  |  |  |  | # special code to handle the funny start location and base offset | 
| 605 |  |  |  |  |  |  | %Image::ExifTool::Ricoh::Subdir = ( | 
| 606 |  |  |  |  |  |  | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, | 
| 607 |  |  |  |  |  |  | WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, | 
| 608 |  |  |  |  |  |  | CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, | 
| 609 |  |  |  |  |  |  | # the significance of the following 2 dates is not known.  They are usually | 
| 610 |  |  |  |  |  |  | # within a month of each other, but I have seen differences of nearly a year. | 
| 611 |  |  |  |  |  |  | # Sometimes the first is more recent, and sometimes the second. | 
| 612 |  |  |  |  |  |  | # 0x0003 - int32u[1] | 
| 613 |  |  |  |  |  |  | 0x0004 => { # (NC) | 
| 614 |  |  |  |  |  |  | Name => 'ManufactureDate1', | 
| 615 |  |  |  |  |  |  | Groups => { 2 => 'Time' }, | 
| 616 |  |  |  |  |  |  | Writable => 'string', | 
| 617 |  |  |  |  |  |  | Count => 20, | 
| 618 |  |  |  |  |  |  | }, | 
| 619 |  |  |  |  |  |  | 0x0005 => { # (NC) | 
| 620 |  |  |  |  |  |  | Name => 'ManufactureDate2', | 
| 621 |  |  |  |  |  |  | Groups => { 2 => 'Time' }, | 
| 622 |  |  |  |  |  |  | Writable => 'string', | 
| 623 |  |  |  |  |  |  | Count => 20, | 
| 624 |  |  |  |  |  |  | }, | 
| 625 |  |  |  |  |  |  | # 0x0006 - undef[16] ? | 
| 626 |  |  |  |  |  |  | # 0x0007 - int32u[1] ? | 
| 627 |  |  |  |  |  |  | # 0x000c - int32u[2] 1st number is a counter (file number? shutter count?) - PH | 
| 628 |  |  |  |  |  |  | # 0x0014 - int8u[338] could contain some data related to face detection? - PH | 
| 629 |  |  |  |  |  |  | # 0x0015 - int8u[2]: related to noise reduction? | 
| 630 |  |  |  |  |  |  | 0x001a => { #PH | 
| 631 |  |  |  |  |  |  | Name => 'FaceInfo', | 
| 632 |  |  |  |  |  |  | SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::FaceInfo' }, | 
| 633 |  |  |  |  |  |  | }, | 
| 634 |  |  |  |  |  |  | 0x0029 => { | 
| 635 |  |  |  |  |  |  | Name => 'FirmwareInfo', | 
| 636 |  |  |  |  |  |  | SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::FirmwareInfo' }, | 
| 637 |  |  |  |  |  |  | }, | 
| 638 |  |  |  |  |  |  | 0x002a => { | 
| 639 |  |  |  |  |  |  | Name => 'NoiseReduction', | 
| 640 |  |  |  |  |  |  | # this is the applied value if NR is set to "Auto" | 
| 641 |  |  |  |  |  |  | Writable => 'int32u', | 
| 642 |  |  |  |  |  |  | PrintConv => { | 
| 643 |  |  |  |  |  |  | 0 => 'Off', | 
| 644 |  |  |  |  |  |  | 1 => 'Weak', | 
| 645 |  |  |  |  |  |  | 2 => 'Strong', | 
| 646 |  |  |  |  |  |  | 3 => 'Max', | 
| 647 |  |  |  |  |  |  | }, | 
| 648 |  |  |  |  |  |  | }, | 
| 649 |  |  |  |  |  |  | 0x002c => { # (GXR) | 
| 650 |  |  |  |  |  |  | Name => 'SerialInfo', | 
| 651 |  |  |  |  |  |  | SubDirectory => { TagTable => 'Image::ExifTool::Ricoh::SerialInfo' }, | 
| 652 |  |  |  |  |  |  | } | 
| 653 |  |  |  |  |  |  | # 0x000E ProductionNumber? (ref 2) [no. zero for most models - PH] | 
| 654 |  |  |  |  |  |  | ); | 
| 655 |  |  |  |  |  |  |  | 
| 656 |  |  |  |  |  |  | # Ricoh Theta subdirectory tags - Contains orientation information (ref 4) | 
| 657 |  |  |  |  |  |  | %Image::ExifTool::Ricoh::ThetaSubdir = ( | 
| 658 |  |  |  |  |  |  | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, | 
| 659 |  |  |  |  |  |  | WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, | 
| 660 |  |  |  |  |  |  | CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, | 
| 661 |  |  |  |  |  |  | # 0x0001 - int16u[1] ? | 
| 662 |  |  |  |  |  |  | # 0x0002 - int16u[1] ? | 
| 663 |  |  |  |  |  |  | 0x0003 => { | 
| 664 |  |  |  |  |  |  | Name => 'Accelerometer', | 
| 665 |  |  |  |  |  |  | Writable => 'rational64s', | 
| 666 |  |  |  |  |  |  | Count => 2, | 
| 667 |  |  |  |  |  |  | }, | 
| 668 |  |  |  |  |  |  | 0x0004 => { | 
| 669 |  |  |  |  |  |  | Name => 'Compass', | 
| 670 |  |  |  |  |  |  | Writable => 'rational64u', | 
| 671 |  |  |  |  |  |  | }, | 
| 672 |  |  |  |  |  |  | # 0x0005 - int16u[1] ? | 
| 673 |  |  |  |  |  |  | # 0x0006 - int16u[1] ? | 
| 674 |  |  |  |  |  |  | # 0x0007 - int16u[1] ? | 
| 675 |  |  |  |  |  |  | # 0x0008 - int16u[1] ? | 
| 676 |  |  |  |  |  |  | # 0x0009 - int16u[1] ? | 
| 677 |  |  |  |  |  |  | 0x000a => { | 
| 678 |  |  |  |  |  |  | Name => 'TimeZone', | 
| 679 |  |  |  |  |  |  | Writable => 'string', | 
| 680 |  |  |  |  |  |  | }, | 
| 681 |  |  |  |  |  |  | # 0x0101 - int16u[4] ISO (why 4 values?) | 
| 682 |  |  |  |  |  |  | # 0x0102 - rational64s[2] FNumber (why 2 values?) | 
| 683 |  |  |  |  |  |  | # 0x0103 - rational64u[2] ExposureTime (why 2 values?) | 
| 684 |  |  |  |  |  |  | # 0x0104 - string[9] SerialNumber? | 
| 685 |  |  |  |  |  |  | # 0x0105 - string[9] SerialNumber? | 
| 686 |  |  |  |  |  |  | ); | 
| 687 |  |  |  |  |  |  |  | 
| 688 |  |  |  |  |  |  | # face detection information (ref PH, CX4) | 
| 689 |  |  |  |  |  |  | %Image::ExifTool::Ricoh::FaceInfo = ( | 
| 690 |  |  |  |  |  |  | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, | 
| 691 |  |  |  |  |  |  | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, | 
| 692 |  |  |  |  |  |  | WRITE_PROC => \&Image::ExifTool::WriteBinaryData, | 
| 693 |  |  |  |  |  |  | CHECK_PROC => \&Image::ExifTool::CheckBinaryData, | 
| 694 |  |  |  |  |  |  | WRITABLE => 1, | 
| 695 |  |  |  |  |  |  | FIRST_ENTRY => 0, | 
| 696 |  |  |  |  |  |  | DATAMEMBER => [ 181 ], | 
| 697 |  |  |  |  |  |  | 0xb5 => { # (should be int16u at 0xb4?) | 
| 698 |  |  |  |  |  |  | Name => 'FacesDetected', | 
| 699 |  |  |  |  |  |  | DataMember => 'FacesDetected', | 
| 700 |  |  |  |  |  |  | RawConv => '$$self{FacesDetected} = $val', | 
| 701 |  |  |  |  |  |  | }, | 
| 702 |  |  |  |  |  |  | 0xb6 => { | 
| 703 |  |  |  |  |  |  | Name => 'FaceDetectFrameSize', | 
| 704 |  |  |  |  |  |  | Format => 'int16u[2]', | 
| 705 |  |  |  |  |  |  | }, | 
| 706 |  |  |  |  |  |  | 0xbc => { | 
| 707 |  |  |  |  |  |  | Name => 'Face1Position', | 
| 708 |  |  |  |  |  |  | Condition => '$$self{FacesDetected} >= 1', | 
| 709 |  |  |  |  |  |  | Format => 'int16u[4]', | 
| 710 |  |  |  |  |  |  | Notes => q{ | 
| 711 |  |  |  |  |  |  | left, top, width and height of detected face in coordinates of | 
| 712 |  |  |  |  |  |  | FaceDetectFrameSize with increasing Y downwards | 
| 713 |  |  |  |  |  |  | }, | 
| 714 |  |  |  |  |  |  | }, | 
| 715 |  |  |  |  |  |  | 0xc8 => { | 
| 716 |  |  |  |  |  |  | Name => 'Face2Position', | 
| 717 |  |  |  |  |  |  | Condition => '$$self{FacesDetected} >= 2', | 
| 718 |  |  |  |  |  |  | Format => 'int16u[4]', | 
| 719 |  |  |  |  |  |  | }, | 
| 720 |  |  |  |  |  |  | 0xd4 => { | 
| 721 |  |  |  |  |  |  | Name => 'Face3Position', | 
| 722 |  |  |  |  |  |  | Condition => '$$self{FacesDetected} >= 3', | 
| 723 |  |  |  |  |  |  | Format => 'int16u[4]', | 
| 724 |  |  |  |  |  |  | }, | 
| 725 |  |  |  |  |  |  | 0xe0 => { | 
| 726 |  |  |  |  |  |  | Name => 'Face4Position', | 
| 727 |  |  |  |  |  |  | Condition => '$$self{FacesDetected} >= 4', | 
| 728 |  |  |  |  |  |  | Format => 'int16u[4]', | 
| 729 |  |  |  |  |  |  | }, | 
| 730 |  |  |  |  |  |  | 0xec => { | 
| 731 |  |  |  |  |  |  | Name => 'Face5Position', | 
| 732 |  |  |  |  |  |  | Condition => '$$self{FacesDetected} >= 5', | 
| 733 |  |  |  |  |  |  | Format => 'int16u[4]', | 
| 734 |  |  |  |  |  |  | }, | 
| 735 |  |  |  |  |  |  | 0xf8 => { | 
| 736 |  |  |  |  |  |  | Name => 'Face6Position', | 
| 737 |  |  |  |  |  |  | Condition => '$$self{FacesDetected} >= 6', | 
| 738 |  |  |  |  |  |  | Format => 'int16u[4]', | 
| 739 |  |  |  |  |  |  | }, | 
| 740 |  |  |  |  |  |  | 0x104 => { | 
| 741 |  |  |  |  |  |  | Name => 'Face7Position', | 
| 742 |  |  |  |  |  |  | Condition => '$$self{FacesDetected} >= 7', | 
| 743 |  |  |  |  |  |  | Format => 'int16u[4]', | 
| 744 |  |  |  |  |  |  | }, | 
| 745 |  |  |  |  |  |  | 0x110 => { | 
| 746 |  |  |  |  |  |  | Name => 'Face8Position', | 
| 747 |  |  |  |  |  |  | Condition => '$$self{FacesDetected} >= 8', | 
| 748 |  |  |  |  |  |  | Format => 'int16u[4]', | 
| 749 |  |  |  |  |  |  | }, | 
| 750 |  |  |  |  |  |  | ); | 
| 751 |  |  |  |  |  |  |  | 
| 752 |  |  |  |  |  |  | # firmware version information (ref PH) | 
| 753 |  |  |  |  |  |  | %Image::ExifTool::Ricoh::FirmwareInfo = ( | 
| 754 |  |  |  |  |  |  | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, | 
| 755 |  |  |  |  |  |  | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, | 
| 756 |  |  |  |  |  |  | WRITE_PROC => \&Image::ExifTool::WriteBinaryData, | 
| 757 |  |  |  |  |  |  | CHECK_PROC => \&Image::ExifTool::CheckBinaryData, | 
| 758 |  |  |  |  |  |  | WRITABLE => 1, | 
| 759 |  |  |  |  |  |  | 0x00 => { | 
| 760 |  |  |  |  |  |  | Name => 'FirmwareRevision', | 
| 761 |  |  |  |  |  |  | Format => 'string[12]', | 
| 762 |  |  |  |  |  |  | }, | 
| 763 |  |  |  |  |  |  | 0x0c => { | 
| 764 |  |  |  |  |  |  | Name => 'FirmwareRevision2', | 
| 765 |  |  |  |  |  |  | Format => 'string[12]', | 
| 766 |  |  |  |  |  |  | }, | 
| 767 |  |  |  |  |  |  | ); | 
| 768 |  |  |  |  |  |  |  | 
| 769 |  |  |  |  |  |  | # serial/version number information written by GXR (ref PH) | 
| 770 |  |  |  |  |  |  | %Image::ExifTool::Ricoh::SerialInfo = ( | 
| 771 |  |  |  |  |  |  | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, | 
| 772 |  |  |  |  |  |  | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, | 
| 773 |  |  |  |  |  |  | WRITE_PROC => \&Image::ExifTool::WriteBinaryData, | 
| 774 |  |  |  |  |  |  | CHECK_PROC => \&Image::ExifTool::CheckBinaryData, | 
| 775 |  |  |  |  |  |  | WRITABLE => 1, | 
| 776 |  |  |  |  |  |  | NOTES => 'This information is found in images from the GXR.', | 
| 777 |  |  |  |  |  |  | 0 => { | 
| 778 |  |  |  |  |  |  | Name => 'BodyFirmware', #(NC) | 
| 779 |  |  |  |  |  |  | Format => 'string[16]', | 
| 780 |  |  |  |  |  |  | # observed: "RS1 :V00560000" --> FirmwareVersion "Rev0056" | 
| 781 |  |  |  |  |  |  | #           "RS1 :V01020200" --> FirmwareVersion "Rev0102" | 
| 782 |  |  |  |  |  |  | }, | 
| 783 |  |  |  |  |  |  | 16 => { | 
| 784 |  |  |  |  |  |  | Name => 'BodySerialNumber', | 
| 785 |  |  |  |  |  |  | Format => 'string[16]', | 
| 786 |  |  |  |  |  |  | # observed: "SID:00100056" --> "WD00100056" on plate | 
| 787 |  |  |  |  |  |  | }, | 
| 788 |  |  |  |  |  |  | 32 => { | 
| 789 |  |  |  |  |  |  | Name => 'LensFirmware', #(NC) | 
| 790 |  |  |  |  |  |  | Format => 'string[16]', | 
| 791 |  |  |  |  |  |  | # observed: "RL1 :V00560000", "RL1 :V01020200" - A12 50mm F2.5 Macro | 
| 792 |  |  |  |  |  |  | #           "RL2 :V00560000", "RL2 :V01020300" - S10 24-70mm F2.5-4.4 VC | 
| 793 |  |  |  |  |  |  | # --> used in a Composite tag to determine LensType | 
| 794 |  |  |  |  |  |  | }, | 
| 795 |  |  |  |  |  |  | 48 => { | 
| 796 |  |  |  |  |  |  | Name => 'LensSerialNumber', | 
| 797 |  |  |  |  |  |  | Format => 'string[16]', | 
| 798 |  |  |  |  |  |  | # observed: (S10) "LID:00010024" --> "WF00010024" on plate | 
| 799 |  |  |  |  |  |  | #           (A12) "LID:00010054" --> "WE00010029" on plate?? | 
| 800 |  |  |  |  |  |  | }, | 
| 801 |  |  |  |  |  |  | ); | 
| 802 |  |  |  |  |  |  |  | 
| 803 |  |  |  |  |  |  | # Ricoh text-type maker notes (PH) | 
| 804 |  |  |  |  |  |  | %Image::ExifTool::Ricoh::Text = ( | 
| 805 |  |  |  |  |  |  | GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' }, | 
| 806 |  |  |  |  |  |  | PROCESS_PROC => \&ProcessRicohText, | 
| 807 |  |  |  |  |  |  | NOTES => q{ | 
| 808 |  |  |  |  |  |  | Some Ricoh DC and RDC models use a text-based format for their maker notes | 
| 809 |  |  |  |  |  |  | instead of the IFD format used by the Caplio models.  Below is a list of known | 
| 810 |  |  |  |  |  |  | tags in this information. | 
| 811 |  |  |  |  |  |  | }, | 
| 812 |  |  |  |  |  |  | Rev => { | 
| 813 |  |  |  |  |  |  | Name => 'FirmwareVersion', | 
| 814 |  |  |  |  |  |  | PrintConv => '$val=~/^\d+$/ ? sprintf("%.2f",$val/100) : $val', | 
| 815 |  |  |  |  |  |  | PrintConvInv => '$val=~/^(\d+)\.(\d+)$/ ? sprintf("%.2d%.2d",$1,$2) : $val', | 
| 816 |  |  |  |  |  |  | }, | 
| 817 |  |  |  |  |  |  | Rv => { | 
| 818 |  |  |  |  |  |  | Name => 'FirmwareVersion', | 
| 819 |  |  |  |  |  |  | PrintConv => '$val=~/^\d+$/ ? sprintf("%.2f",$val/100) : $val', | 
| 820 |  |  |  |  |  |  | PrintConvInv => '$val=~/^(\d+)\.(\d+)$/ ? sprintf("%.2d%.2d",$1,$2) : $val', | 
| 821 |  |  |  |  |  |  | }, | 
| 822 |  |  |  |  |  |  | Rg => 'RedGain', | 
| 823 |  |  |  |  |  |  | Gg => 'GreenGain', | 
| 824 |  |  |  |  |  |  | Bg => 'BlueGain', | 
| 825 |  |  |  |  |  |  | ); | 
| 826 |  |  |  |  |  |  |  | 
| 827 |  |  |  |  |  |  | %Image::ExifTool::Ricoh::RMETA = ( | 
| 828 |  |  |  |  |  |  | GROUPS => { 0 => 'APP5', 1 => 'RMETA', 2 => 'Image' }, | 
| 829 |  |  |  |  |  |  | PROCESS_PROC => \&Image::ExifTool::Ricoh::ProcessRicohRMETA, | 
| 830 |  |  |  |  |  |  | NOTES => q{ | 
| 831 |  |  |  |  |  |  | The Ricoh Caplio Pro G3 has the ability to add custom fields to the APP5 | 
| 832 |  |  |  |  |  |  | "RMETA" segment of JPEG images.  While only a few observed tags have been | 
| 833 |  |  |  |  |  |  | defined below, ExifTool will extract any information found here. | 
| 834 |  |  |  |  |  |  | }, | 
| 835 |  |  |  |  |  |  | 'Sign type' => { Name => 'SignType', PrintConv => { | 
| 836 |  |  |  |  |  |  | 1 => 'Directional', | 
| 837 |  |  |  |  |  |  | 2 => 'Warning', | 
| 838 |  |  |  |  |  |  | 3 => 'Information', | 
| 839 |  |  |  |  |  |  | } }, | 
| 840 |  |  |  |  |  |  | Location => { PrintConv => { | 
| 841 |  |  |  |  |  |  | 1 => 'Verge', | 
| 842 |  |  |  |  |  |  | 2 => 'Gantry', | 
| 843 |  |  |  |  |  |  | 3 => 'Central reservation', | 
| 844 |  |  |  |  |  |  | 4 => 'Roundabout', | 
| 845 |  |  |  |  |  |  | } }, | 
| 846 |  |  |  |  |  |  | Lit => { PrintConv => { | 
| 847 |  |  |  |  |  |  | 1 => 'Yes', | 
| 848 |  |  |  |  |  |  | 2 => 'No', | 
| 849 |  |  |  |  |  |  | } }, | 
| 850 |  |  |  |  |  |  | Condition => { PrintConv => { | 
| 851 |  |  |  |  |  |  | 1 => 'Good', | 
| 852 |  |  |  |  |  |  | 2 => 'Fair', | 
| 853 |  |  |  |  |  |  | 3 => 'Poor', | 
| 854 |  |  |  |  |  |  | 4 => 'Damaged', | 
| 855 |  |  |  |  |  |  | } }, | 
| 856 |  |  |  |  |  |  | Azimuth => { PrintConv => { | 
| 857 |  |  |  |  |  |  | 1 => 'N', | 
| 858 |  |  |  |  |  |  | 2 => 'NNE', | 
| 859 |  |  |  |  |  |  | 3 => 'NE', | 
| 860 |  |  |  |  |  |  | 4 => 'ENE', | 
| 861 |  |  |  |  |  |  | 5 => 'E', | 
| 862 |  |  |  |  |  |  | 6 => 'ESE', | 
| 863 |  |  |  |  |  |  | 7 => 'SE', | 
| 864 |  |  |  |  |  |  | 8 => 'SSE', | 
| 865 |  |  |  |  |  |  | 9 => 'S', | 
| 866 |  |  |  |  |  |  | 10 => 'SSW', | 
| 867 |  |  |  |  |  |  | 11 => 'SW', | 
| 868 |  |  |  |  |  |  | 12 => 'WSW', | 
| 869 |  |  |  |  |  |  | 13 => 'W', | 
| 870 |  |  |  |  |  |  | 14 => 'WNW', | 
| 871 |  |  |  |  |  |  | 15 => 'NW', | 
| 872 |  |  |  |  |  |  | 16 => 'NNW', | 
| 873 |  |  |  |  |  |  | } }, | 
| 874 |  |  |  |  |  |  | _audio => { | 
| 875 |  |  |  |  |  |  | Name => 'SoundFile', | 
| 876 |  |  |  |  |  |  | Notes => 'audio data recorded in JPEG images by the G700SE', | 
| 877 |  |  |  |  |  |  | }, | 
| 878 |  |  |  |  |  |  | _barcode => { Name => 'Barcodes', List => 1 }, | 
| 879 |  |  |  |  |  |  | ); | 
| 880 |  |  |  |  |  |  |  | 
| 881 |  |  |  |  |  |  | # information stored in Ricoh AVI images (ref PH) | 
| 882 |  |  |  |  |  |  | %Image::ExifTool::Ricoh::AVI = ( | 
| 883 |  |  |  |  |  |  | GROUPS => { 0 => 'MakerNotes', 2 => 'Video' }, | 
| 884 |  |  |  |  |  |  | ucmt => { | 
| 885 |  |  |  |  |  |  | Name => 'Comment', | 
| 886 |  |  |  |  |  |  | # Ricoh writes a "Unicode" header even when text is ASCII (spaces anyway) | 
| 887 |  |  |  |  |  |  | ValueConv => '$_=$val; s/^(Unicode\0|ASCII\0\0\0)//; tr/\0//d; s/\s+$//; $_', | 
| 888 |  |  |  |  |  |  | }, | 
| 889 |  |  |  |  |  |  | mnrt => { | 
| 890 |  |  |  |  |  |  | Name => 'MakerNoteRicoh', | 
| 891 |  |  |  |  |  |  | SubDirectory => { | 
| 892 |  |  |  |  |  |  | TagTable => 'Image::ExifTool::Ricoh::Main', | 
| 893 |  |  |  |  |  |  | Start => '$valuePtr + 8', | 
| 894 |  |  |  |  |  |  | ByteOrder => 'BigEndian', | 
| 895 |  |  |  |  |  |  | Base => '8', | 
| 896 |  |  |  |  |  |  | }, | 
| 897 |  |  |  |  |  |  | }, | 
| 898 |  |  |  |  |  |  | rdc2 => { | 
| 899 |  |  |  |  |  |  | Name => 'RicohRDC2', | 
| 900 |  |  |  |  |  |  | Unknown => 1, | 
| 901 |  |  |  |  |  |  | ValueConv => 'unpack("H*",$val)', | 
| 902 |  |  |  |  |  |  | # have seen values like 0a000444 and 00000000 - PH | 
| 903 |  |  |  |  |  |  | }, | 
| 904 |  |  |  |  |  |  | thum => { | 
| 905 |  |  |  |  |  |  | Name => 'ThumbnailImage', | 
| 906 |  |  |  |  |  |  | Groups => { 2 => 'Preview' }, | 
| 907 |  |  |  |  |  |  | Binary => 1, | 
| 908 |  |  |  |  |  |  | }, | 
| 909 |  |  |  |  |  |  | ); | 
| 910 |  |  |  |  |  |  |  | 
| 911 |  |  |  |  |  |  | # Ricoh composite tags | 
| 912 |  |  |  |  |  |  | %Image::ExifTool::Ricoh::Composite = ( | 
| 913 |  |  |  |  |  |  | GROUPS => { 2 => 'Camera' }, | 
| 914 |  |  |  |  |  |  | LensID => { | 
| 915 |  |  |  |  |  |  | SeparateTable => 'Ricoh LensID', | 
| 916 |  |  |  |  |  |  | Require => 'Ricoh:LensFirmware', | 
| 917 |  |  |  |  |  |  | RawConv => '$val[0] ? $val[0] : undef', | 
| 918 |  |  |  |  |  |  | ValueConv => '$val=~s/\s*:.*//; $val', | 
| 919 |  |  |  |  |  |  | PrintConv => \%ricohLensIDs, | 
| 920 |  |  |  |  |  |  | }, | 
| 921 |  |  |  |  |  |  | RicohPitch => { | 
| 922 |  |  |  |  |  |  | Require => 'Ricoh:Accelerometer', | 
| 923 |  |  |  |  |  |  | ValueConv => 'my @v = split(" ",$val); $v[1]', | 
| 924 |  |  |  |  |  |  | }, | 
| 925 |  |  |  |  |  |  | RicohRoll => { | 
| 926 |  |  |  |  |  |  | Require => 'Ricoh:Accelerometer', | 
| 927 |  |  |  |  |  |  | ValueConv => 'my @v = split(" ",$val); $v[0] <= 180 ? $v[0] : $v[0] - 360', | 
| 928 |  |  |  |  |  |  | }, | 
| 929 |  |  |  |  |  |  | ); | 
| 930 |  |  |  |  |  |  |  | 
| 931 |  |  |  |  |  |  | # add our composite tags | 
| 932 |  |  |  |  |  |  | Image::ExifTool::AddCompositeTags('Image::ExifTool::Ricoh'); | 
| 933 |  |  |  |  |  |  |  | 
| 934 |  |  |  |  |  |  |  | 
| 935 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 936 |  |  |  |  |  |  | # Process Ricoh text-based maker notes | 
| 937 |  |  |  |  |  |  | # Inputs: 0) ExifTool object reference | 
| 938 |  |  |  |  |  |  | #         1) Reference to directory information hash | 
| 939 |  |  |  |  |  |  | #         2) Pointer to tag table for this directory | 
| 940 |  |  |  |  |  |  | # Returns: 1 on success, otherwise returns 0 and sets a Warning | 
| 941 |  |  |  |  |  |  | sub ProcessRicohText($$$) | 
| 942 |  |  |  |  |  |  | { | 
| 943 | 0 |  |  | 0 | 0 | 0 | my ($et, $dirInfo, $tagTablePtr) = @_; | 
| 944 | 0 |  |  |  |  | 0 | my $dataPt = $$dirInfo{DataPt}; | 
| 945 | 0 |  |  |  |  | 0 | my $dataLen = $$dirInfo{DataLen}; | 
| 946 | 0 |  | 0 |  |  | 0 | my $dirStart = $$dirInfo{DirStart} || 0; | 
| 947 | 0 |  | 0 |  |  | 0 | my $dirLen = $$dirInfo{DirLen} || $dataLen - $dirStart; | 
| 948 | 0 |  |  |  |  | 0 | my $verbose = $et->Options('Verbose'); | 
| 949 |  |  |  |  |  |  |  | 
| 950 | 0 |  |  |  |  | 0 | my $data = substr($$dataPt, $dirStart, $dirLen); | 
| 951 | 0 | 0 |  |  |  | 0 | return 1 if $data =~ /^\0/;     # blank Ricoh maker notes | 
| 952 | 0 |  |  |  |  | 0 | $et->VerboseDir('RicohText', undef, $dirLen); | 
| 953 |  |  |  |  |  |  | # validate text maker notes | 
| 954 | 0 | 0 |  |  |  | 0 | unless ($data =~ /^(Rev|Rv)/) { | 
| 955 | 0 |  |  |  |  | 0 | $et->Warn('Bad Ricoh maker notes'); | 
| 956 | 0 |  |  |  |  | 0 | return 0; | 
| 957 |  |  |  |  |  |  | } | 
| 958 | 0 |  |  |  |  | 0 | while ($data =~ m/([A-Z][a-z]{1,2})([0-9A-F]+);/sg) { | 
| 959 | 0 |  |  |  |  | 0 | my $tag = $1; | 
| 960 | 0 |  |  |  |  | 0 | my $val = $2; | 
| 961 | 0 |  |  |  |  | 0 | my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); | 
| 962 | 0 | 0 |  |  |  | 0 | if ($verbose) { | 
| 963 | 0 |  |  |  |  | 0 | $et->VerboseInfo($tag, $tagInfo, | 
| 964 |  |  |  |  |  |  | Table  => $tagTablePtr, | 
| 965 |  |  |  |  |  |  | Value  => $val, | 
| 966 |  |  |  |  |  |  | ); | 
| 967 |  |  |  |  |  |  | } | 
| 968 | 0 | 0 |  |  |  | 0 | unless ($tagInfo) { | 
| 969 | 0 | 0 |  |  |  | 0 | next unless $$et{OPTIONS}{Unknown}; | 
| 970 | 0 |  |  |  |  | 0 | $tagInfo = { | 
| 971 |  |  |  |  |  |  | Name => "Ricoh_Text_$tag", | 
| 972 |  |  |  |  |  |  | Unknown => 1, | 
| 973 |  |  |  |  |  |  | PrintConv => 'length($val) > 60 ? substr($val,0,55) . "[...]" : $val', | 
| 974 |  |  |  |  |  |  | }; | 
| 975 |  |  |  |  |  |  | # add tag information to table | 
| 976 | 0 |  |  |  |  | 0 | AddTagToTable($tagTablePtr, $tag, $tagInfo); | 
| 977 |  |  |  |  |  |  | } | 
| 978 | 0 |  |  |  |  | 0 | $et->FoundTag($tagInfo, $val); | 
| 979 |  |  |  |  |  |  | } | 
| 980 | 0 |  |  |  |  | 0 | return 1; | 
| 981 |  |  |  |  |  |  | } | 
| 982 |  |  |  |  |  |  |  | 
| 983 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 984 |  |  |  |  |  |  | # Process Ricoh APP5 RMETA information | 
| 985 |  |  |  |  |  |  | # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref | 
| 986 |  |  |  |  |  |  | # Returns: 1 on success, otherwise returns 0 and sets a Warning | 
| 987 |  |  |  |  |  |  | sub ProcessRicohRMETA($$$) | 
| 988 |  |  |  |  |  |  | { | 
| 989 | 20 |  |  | 20 | 0 | 83 | my ($et, $dirInfo, $tagTablePtr) = @_; | 
| 990 | 20 |  |  |  |  | 68 | my $dataPt = $$dirInfo{DataPt}; | 
| 991 | 20 |  |  |  |  | 60 | my $dirStart = $$dirInfo{DirStart}; | 
| 992 | 20 |  |  |  |  | 86 | my $dataLen = length($$dataPt); | 
| 993 | 20 |  |  |  |  | 51 | my $dirLen = $dataLen - $dirStart; | 
| 994 | 20 |  |  |  |  | 83 | my $verbose = $et->Options('Verbose'); | 
| 995 |  |  |  |  |  |  |  | 
| 996 | 20 | 50 |  |  |  | 154 | $et->VerboseDir('Ricoh RMETA') if $verbose; | 
| 997 | 20 | 50 |  |  |  | 173 | $dirLen < 20 and $et->Warn('Truncated Ricoh RMETA data', 1), return 0; | 
| 998 | 20 |  |  |  |  | 75 | my $byteOrder = substr($$dataPt, $dirStart, 2); | 
| 999 | 20 | 50 |  |  |  | 85 | $byteOrder = GetByteOrder() if $byteOrder eq "\0\0"; # (same order as container) | 
| 1000 | 20 | 50 |  |  |  | 82 | SetByteOrder($byteOrder) or $et->Warn('Bad Ricoh RMETA data', 1), return 0; | 
| 1001 |  |  |  |  |  |  | # get the RMETA segment number | 
| 1002 | 20 |  |  |  |  | 131 | my $rmetaNum = Get16u($dataPt, $dirStart+4); | 
| 1003 | 20 | 50 |  |  |  | 110 | if ($rmetaNum != 0) { | 
| 1004 |  |  |  |  |  |  | # not sure how to recognize audio, so do it by checking for "RIFF" header | 
| 1005 |  |  |  |  |  |  | # and assume all subsequent RMETA segments are part of the audio data | 
| 1006 |  |  |  |  |  |  | # (but it looks like the int16u at $dirStart+6 is the next block number | 
| 1007 |  |  |  |  |  |  | # if the data is continued, or 0 for the last block) | 
| 1008 | 0 | 0 |  |  |  | 0 | $dirLen < 14 and $et->Warn('Short Ricoh RMETA block', 1), return 0; | 
| 1009 | 0 | 0 |  |  |  | 0 | if ($$dataPt =~ /^.{20}BARCODE/s) { | 
|  |  | 0 |  |  |  |  |  | 
| 1010 | 0 |  |  |  |  | 0 | my $val = substr($$dataPt, 20); | 
| 1011 | 0 |  |  |  |  | 0 | $val =~ s/\0.*//s; | 
| 1012 | 0 |  |  |  |  | 0 | $val =~ s/^BARCODE\w+,\d{2},//; | 
| 1013 | 0 |  |  |  |  | 0 | my @codes; | 
| 1014 | 0 |  |  |  |  | 0 | for (;;) { | 
| 1015 | 0 | 0 | 0 |  |  | 0 | $val =~ s/(\d+),// and length $val >= $1 or last; | 
| 1016 | 0 |  |  |  |  | 0 | push @codes, substr($val, 0, $1); | 
| 1017 | 0 | 0 |  |  |  | 0 | last unless length $val > $1; | 
| 1018 | 0 |  |  |  |  | 0 | $val = substr($val, $1+1); | 
| 1019 |  |  |  |  |  |  | } | 
| 1020 | 0 | 0 |  |  |  | 0 | $et->HandleTag($tagTablePtr, '_barcode', \@codes) if @codes; | 
| 1021 | 0 |  |  |  |  | 0 | return 1; | 
| 1022 |  |  |  |  |  |  | } elsif ($$dataPt =~ /^.{18}ASCII/s) { | 
| 1023 |  |  |  |  |  |  | # (ignore barcode tag names for now) | 
| 1024 | 0 |  |  |  |  | 0 | return 1; | 
| 1025 |  |  |  |  |  |  | } | 
| 1026 | 0 |  |  |  |  | 0 | my $audioLen = Get16u($dataPt, $dirStart+12); | 
| 1027 | 0 | 0 |  |  |  | 0 | $audioLen + 14 > $dirLen and $et->Warn('Truncated Ricoh RMETA audio data', 1), return 0; | 
| 1028 | 0 |  |  |  |  | 0 | my $buff = substr($$dataPt, $dirStart + 14, $audioLen); | 
| 1029 | 0 | 0 | 0 |  |  | 0 | if ($audioLen >= 4 and substr($buff, 0, 4) eq 'RIFF') { | 
|  |  | 0 |  |  |  |  |  | 
| 1030 | 0 |  |  |  |  | 0 | $et->HandleTag($tagTablePtr, '_audio', \$buff); | 
| 1031 |  |  |  |  |  |  | } elsif ($$et{VALUE}{SoundFile}) { | 
| 1032 | 0 |  |  |  |  | 0 | ${$$et{VALUE}{SoundFile}} .= $buff; | 
|  | 0 |  |  |  |  | 0 |  | 
| 1033 |  |  |  |  |  |  | } else { | 
| 1034 | 0 |  |  |  |  | 0 | $et->Warn('Unknown Ricoh RMETA type', 1); | 
| 1035 | 0 |  |  |  |  | 0 | return 0; | 
| 1036 |  |  |  |  |  |  | } | 
| 1037 | 0 |  |  |  |  | 0 | return 1; | 
| 1038 |  |  |  |  |  |  | } | 
| 1039 |  |  |  |  |  |  | # decode standard RMETA tag directory | 
| 1040 | 20 |  |  |  |  | 76 | my (@tags, @vals, @nums, $valPos, $numPos); | 
| 1041 | 20 |  |  |  |  | 84 | my $pos = $dirStart + Get16u($dataPt, $dirStart+8); | 
| 1042 | 20 |  |  |  |  | 92 | my $numEntries = Get16u($dataPt, $pos); | 
| 1043 | 20 | 50 |  |  |  | 116 | $numEntries > 100 and $et->Warn('Bad RMETA entry count'), return 0; | 
| 1044 | 20 |  |  |  |  | 81 | $pos += 10; # start of first RMETA section | 
| 1045 |  |  |  |  |  |  | # loop through RMETA sections | 
| 1046 | 20 |  |  |  |  | 123 | while ($pos <= $dataLen - 4) { | 
| 1047 | 80 |  |  |  |  | 202 | my $type = Get16u($dataPt, $pos); | 
| 1048 | 80 |  |  |  |  | 250 | my $size = Get16u($dataPt, $pos + 2); | 
| 1049 | 80 | 50 |  |  |  | 217 | last unless $size; | 
| 1050 | 80 |  |  |  |  | 122 | $pos += 4; | 
| 1051 | 80 |  |  |  |  | 125 | $size -= 2; | 
| 1052 | 80 | 50 | 33 |  |  | 328 | if ($size < 0 or $pos + $size > $dataLen) { | 
| 1053 | 0 |  |  |  |  | 0 | $et->Warn('Corrupted Ricoh RMETA data', 1); | 
| 1054 | 0 |  |  |  |  | 0 | last; | 
| 1055 |  |  |  |  |  |  | } | 
| 1056 | 80 |  |  |  |  | 207 | my $dat = substr($$dataPt, $pos, $size); | 
| 1057 | 80 | 50 |  |  |  | 182 | if ($verbose) { | 
| 1058 | 0 |  |  |  |  | 0 | $et->VPrint(2, "$$et{INDENT}RMETA section type=$type size=$size\n"); | 
| 1059 | 0 |  |  |  |  | 0 | $et->VerboseDump(\$dat, Addr => $$dirInfo{DataPos} + $pos); | 
| 1060 |  |  |  |  |  |  | } | 
| 1061 | 80 | 100 | 66 |  |  | 653 | if ($type == 1) {                       # section 1: tag names | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 100 |  |  |  |  |  | 
|  |  | 50 |  |  |  |  |  | 
| 1062 |  |  |  |  |  |  | # save the tag names | 
| 1063 | 20 |  |  |  |  | 164 | @tags = split /\0/, $dat, $numEntries+1; | 
| 1064 |  |  |  |  |  |  | } elsif ($type == 2 || $type == 18) {   # section 2/18: string values (G800 uses type 18) | 
| 1065 |  |  |  |  |  |  | # save the tag values (assume "ASCII\0" encoding since others never seen) | 
| 1066 | 20 |  |  |  |  | 126 | @vals = split /\0/, $dat, $numEntries+1; | 
| 1067 | 20 |  |  |  |  | 50 | $valPos = $pos; # save position of first string value | 
| 1068 |  |  |  |  |  |  | } elsif ($type == 3) {                  # section 3: numerical values | 
| 1069 | 20 | 50 |  |  |  | 91 | if ($size < $numEntries * 2) { | 
| 1070 | 0 |  |  |  |  | 0 | $et->Warn('Truncated RMETA section 3'); | 
| 1071 |  |  |  |  |  |  | } else { | 
| 1072 |  |  |  |  |  |  | # save the numerical tag values | 
| 1073 |  |  |  |  |  |  | # (0=empty, 0xffff=text input, otherwise menu item number) | 
| 1074 | 20 | 50 |  |  |  | 112 | @nums = unpack(($byteOrder eq 'MM' ? 'n' : 'v').$numEntries, $dat); | 
| 1075 | 20 |  |  |  |  | 60 | $numPos = $pos; # save position of numerical values | 
| 1076 |  |  |  |  |  |  | } | 
| 1077 |  |  |  |  |  |  | } elsif ($type != 16) { | 
| 1078 | 0 |  |  |  |  | 0 | $et->Warn("Unrecognized RMETA section (type $type, len $size)"); | 
| 1079 |  |  |  |  |  |  | } | 
| 1080 | 80 |  |  |  |  | 207 | $pos += $size; | 
| 1081 |  |  |  |  |  |  | } | 
| 1082 | 20 | 50 | 33 |  |  | 101 | return 1 unless @tags or @vals; | 
| 1083 | 20 | 50 |  |  |  | 64 | $valPos or $valPos = 0; # (just in case there was no value section) | 
| 1084 |  |  |  |  |  |  | # find next tag in null-delimited list | 
| 1085 |  |  |  |  |  |  | # unpack numerical values from block of int16u values | 
| 1086 | 20 |  |  |  |  | 51 | my ($i, $name); | 
| 1087 | 20 |  |  |  |  | 94 | for ($i=0; $i<$numEntries; ++$i) { | 
| 1088 | 100 |  |  |  |  | 213 | my $tag = $tags[$i]; | 
| 1089 | 100 |  |  |  |  | 203 | my $val = $vals[$i]; | 
| 1090 | 100 | 50 |  |  |  | 232 | $val = '' unless defined $val; | 
| 1091 | 100 | 50 | 33 |  |  | 656 | unless (defined $tag and length $tag) { | 
| 1092 | 0 | 0 |  |  |  | 0 | length $val or ++$valPos, next;     # (skip empty entries) | 
| 1093 | 0 |  |  |  |  | 0 | $tag = ''; | 
| 1094 |  |  |  |  |  |  | } | 
| 1095 | 100 |  |  |  |  | 500 | ($name = $tag) =~ s/\b([a-z])/\U$1/gs;  # capitalize all words | 
| 1096 | 100 |  |  |  |  | 302 | $name =~ s/ (\w)/\U$1/g;                # remove special characters | 
| 1097 | 100 | 50 |  |  |  | 237 | $name = 'RMETA_Unknown' unless length($name); | 
| 1098 | 100 |  |  |  |  | 188 | my $num = $nums[$i]; | 
| 1099 | 100 |  |  |  |  | 292 | my $tagInfo = $et->GetTagInfo($tagTablePtr, $tag); | 
| 1100 | 100 | 50 |  |  |  | 290 | if ($tagInfo) { | 
| 1101 |  |  |  |  |  |  | # make sure print conversion is defined | 
| 1102 | 100 | 50 |  |  |  | 326 | $$tagInfo{PrintConv} = { } unless ref $$tagInfo{PrintConv} eq 'HASH'; | 
| 1103 |  |  |  |  |  |  | } else { | 
| 1104 |  |  |  |  |  |  | # create tagInfo hash | 
| 1105 | 0 |  |  |  |  | 0 | $tagInfo = { Name => $name, PrintConv => { } }; | 
| 1106 | 0 |  |  |  |  | 0 | AddTagToTable($tagTablePtr, $tag, $tagInfo); | 
| 1107 |  |  |  |  |  |  | } | 
| 1108 |  |  |  |  |  |  | # use string value directly if no numerical value | 
| 1109 | 100 | 50 |  |  |  | 215 | $num = $val unless defined $num; | 
| 1110 |  |  |  |  |  |  | # add conversion for this value (replacing any existing entry) | 
| 1111 | 100 | 50 |  |  |  | 371 | $tagInfo->{PrintConv}->{$num} = length $val ? $val : $num; | 
| 1112 | 100 | 50 |  |  |  | 201 | if ($verbose) { | 
| 1113 | 0 |  |  |  |  | 0 | my %datParms; | 
| 1114 | 0 | 0 |  |  |  | 0 | if (length $val) { | 
|  |  | 0 |  |  |  |  |  | 
| 1115 | 0 |  |  |  |  | 0 | %datParms = ( Start => $valPos, Size => length($val), Format => 'string' ); | 
| 1116 |  |  |  |  |  |  | } elsif ($numPos) { | 
| 1117 | 0 |  |  |  |  | 0 | %datParms = ( Start => $numPos + $i * 2, Size => 2, Format => 'int16u' ); | 
| 1118 |  |  |  |  |  |  | } | 
| 1119 | 0 | 0 |  |  |  | 0 | %datParms and $datParms{DataPt} = $dataPt, $datParms{DataPos} = $$dirInfo{DataPos}; | 
| 1120 | 0 |  |  |  |  | 0 | $et->VerboseInfo($tag, $tagInfo, Table=>$tagTablePtr, Value=>$num, %datParms); | 
| 1121 |  |  |  |  |  |  | } | 
| 1122 | 100 |  |  |  |  | 313 | $et->FoundTag($tagInfo, $num); | 
| 1123 | 100 |  |  |  |  | 357 | $valPos += length($val) + 1; | 
| 1124 |  |  |  |  |  |  | } | 
| 1125 | 20 |  |  |  |  | 143 | return 1; | 
| 1126 |  |  |  |  |  |  | } | 
| 1127 |  |  |  |  |  |  |  | 
| 1128 |  |  |  |  |  |  | 1;  # end | 
| 1129 |  |  |  |  |  |  |  | 
| 1130 |  |  |  |  |  |  | __END__ |