| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 2 |  |  |  |  |  |  | # File:         PanasonicRaw.pm | 
| 3 |  |  |  |  |  |  | # | 
| 4 |  |  |  |  |  |  | # Description:  Read/write Panasonic/Leica RAW/RW2/RWL meta information | 
| 5 |  |  |  |  |  |  | # | 
| 6 |  |  |  |  |  |  | # Revisions:    2009/03/24 - P. Harvey Created | 
| 7 |  |  |  |  |  |  | #               2009/05/12 - PH Added RWL file type (same format as RW2) | 
| 8 |  |  |  |  |  |  | # | 
| 9 |  |  |  |  |  |  | # References:   1) https://exiftool.org/forum/index.php/topic,1542.0.html | 
| 10 |  |  |  |  |  |  | #               2) http://www.cybercom.net/~dcoffin/dcraw/ | 
| 11 |  |  |  |  |  |  | #               3) http://syscall.eu/#pana | 
| 12 |  |  |  |  |  |  | #               4) Klaus Homeister private communication | 
| 13 |  |  |  |  |  |  | #              IB) Iliah Borg private communication (LibRaw) | 
| 14 |  |  |  |  |  |  | #              JD) Jens Duttke private communication (TZ3,FZ30,FZ50) | 
| 15 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 16 |  |  |  |  |  |  |  | 
| 17 |  |  |  |  |  |  | package Image::ExifTool::PanasonicRaw; | 
| 18 |  |  |  |  |  |  |  | 
| 19 | 14 |  |  | 14 |  | 102 | use strict; | 
|  | 14 |  |  |  |  | 29 |  | 
|  | 14 |  |  |  |  | 477 |  | 
| 20 | 14 |  |  | 14 |  | 87 | use vars qw($VERSION); | 
|  | 14 |  |  |  |  | 31 |  | 
|  | 14 |  |  |  |  | 613 |  | 
| 21 | 14 |  |  | 14 |  | 85 | use Image::ExifTool qw(:DataAccess :Utils); | 
|  | 14 |  |  |  |  | 34 |  | 
|  | 14 |  |  |  |  | 2998 |  | 
| 22 | 14 |  |  | 14 |  | 91 | use Image::ExifTool::Exif; | 
|  | 14 |  |  |  |  | 31 |  | 
|  | 14 |  |  |  |  | 29881 |  | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | $VERSION = '1.25'; | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | sub ProcessJpgFromRaw($$$); | 
| 27 |  |  |  |  |  |  | sub WriteJpgFromRaw($$$); | 
| 28 |  |  |  |  |  |  | sub WriteDistortionInfo($$$); | 
| 29 |  |  |  |  |  |  | sub ProcessDistortionInfo($$$); | 
| 30 |  |  |  |  |  |  |  | 
| 31 |  |  |  |  |  |  | my %jpgFromRawMap = ( | 
| 32 |  |  |  |  |  |  | IFD1         => 'IFD0', | 
| 33 |  |  |  |  |  |  | EXIF         => 'IFD0', # to write EXIF as a block | 
| 34 |  |  |  |  |  |  | ExifIFD      => 'IFD0', | 
| 35 |  |  |  |  |  |  | GPS          => 'IFD0', | 
| 36 |  |  |  |  |  |  | SubIFD       => 'IFD0', | 
| 37 |  |  |  |  |  |  | GlobParamIFD => 'IFD0', | 
| 38 |  |  |  |  |  |  | PrintIM      => 'IFD0', | 
| 39 |  |  |  |  |  |  | InteropIFD   => 'ExifIFD', | 
| 40 |  |  |  |  |  |  | MakerNotes   => 'ExifIFD', | 
| 41 |  |  |  |  |  |  | IFD0         => 'APP1', | 
| 42 |  |  |  |  |  |  | MakerNotes   => 'ExifIFD', | 
| 43 |  |  |  |  |  |  | Comment      => 'COM', | 
| 44 |  |  |  |  |  |  | ); | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  | my %wbTypeInfo = ( | 
| 47 |  |  |  |  |  |  | PrintConv => \%Image::ExifTool::Exif::lightSource, | 
| 48 |  |  |  |  |  |  | SeparateTable => 'EXIF LightSource', | 
| 49 |  |  |  |  |  |  | ); | 
| 50 |  |  |  |  |  |  |  | 
| 51 |  |  |  |  |  |  | my %panasonicWhiteBalance = ( #forum9396 | 
| 52 |  |  |  |  |  |  | 0 => 'Auto', | 
| 53 |  |  |  |  |  |  | 1 => 'Daylight', | 
| 54 |  |  |  |  |  |  | 2 => 'Cloudy', | 
| 55 |  |  |  |  |  |  | 3 => 'Tungsten', | 
| 56 |  |  |  |  |  |  | 4 => 'n/a', | 
| 57 |  |  |  |  |  |  | 5 => 'Flash', | 
| 58 |  |  |  |  |  |  | 6 => 'n/a', | 
| 59 |  |  |  |  |  |  | 7 => 'n/a', | 
| 60 |  |  |  |  |  |  | 8 => 'Custom#1', | 
| 61 |  |  |  |  |  |  | 9 => 'Custom#2', | 
| 62 |  |  |  |  |  |  | 10 => 'Custom#3', | 
| 63 |  |  |  |  |  |  | 11 => 'Custom#4', | 
| 64 |  |  |  |  |  |  | 12 => 'Shade', | 
| 65 |  |  |  |  |  |  | 13 => 'Kelvin', | 
| 66 |  |  |  |  |  |  | 16 => 'AWBc', # GH5 and G9 (Makernotes WB==19) | 
| 67 |  |  |  |  |  |  | ); | 
| 68 |  |  |  |  |  |  |  | 
| 69 |  |  |  |  |  |  | # Tags found in Panasonic RAW/RW2/RWL images (ref PH) | 
| 70 |  |  |  |  |  |  | %Image::ExifTool::PanasonicRaw::Main = ( | 
| 71 |  |  |  |  |  |  | GROUPS => { 0 => 'EXIF', 1 => 'IFD0', 2 => 'Image'}, | 
| 72 |  |  |  |  |  |  | WRITE_PROC => \&Image::ExifTool::Exif::WriteExif, | 
| 73 |  |  |  |  |  |  | CHECK_PROC => \&Image::ExifTool::Exif::CheckExif, | 
| 74 |  |  |  |  |  |  | WRITE_GROUP => 'IFD0',   # default write group | 
| 75 |  |  |  |  |  |  | NOTES => 'These tags are found in IFD0 of Panasonic/Leica RAW, RW2 and RWL images.', | 
| 76 |  |  |  |  |  |  | 0x01 => { | 
| 77 |  |  |  |  |  |  | Name => 'PanasonicRawVersion', | 
| 78 |  |  |  |  |  |  | Writable => 'undef', | 
| 79 |  |  |  |  |  |  | }, | 
| 80 |  |  |  |  |  |  | 0x02 => 'SensorWidth', #1/PH | 
| 81 |  |  |  |  |  |  | 0x03 => 'SensorHeight', #1/PH | 
| 82 |  |  |  |  |  |  | 0x04 => 'SensorTopBorder', #JD | 
| 83 |  |  |  |  |  |  | 0x05 => 'SensorLeftBorder', #JD | 
| 84 |  |  |  |  |  |  | 0x06 => 'SensorBottomBorder', #PH | 
| 85 |  |  |  |  |  |  | 0x07 => 'SensorRightBorder', #PH | 
| 86 |  |  |  |  |  |  | # observed values for unknown tags - PH | 
| 87 |  |  |  |  |  |  | # 0x08: 1 | 
| 88 |  |  |  |  |  |  | # 0x09: 1,3,4 | 
| 89 |  |  |  |  |  |  | # 0x0a: 12 | 
| 90 |  |  |  |  |  |  | # (IB gave 0x08-0x0a as BlackLevel tags, but Klaus' decoding makes more sense) | 
| 91 |  |  |  |  |  |  | 0x08 => { Name => 'SamplesPerPixel', Writable => 'int16u', Protected => 1 }, #4 | 
| 92 |  |  |  |  |  |  | 0x09 => { #4 | 
| 93 |  |  |  |  |  |  | Name => 'CFAPattern', | 
| 94 |  |  |  |  |  |  | Writable => 'int16u', | 
| 95 |  |  |  |  |  |  | Protected => 1, | 
| 96 |  |  |  |  |  |  | PrintConv => { | 
| 97 |  |  |  |  |  |  | 0 => 'n/a', | 
| 98 |  |  |  |  |  |  | 1 => '[Red,Green][Green,Blue]', # (CM-1, FZ70) | 
| 99 |  |  |  |  |  |  | 2 => '[Green,Red][Blue,Green]', # (LX-7) | 
| 100 |  |  |  |  |  |  | 3 => '[Green,Blue][Red,Green]', # (ZS100, FZ2500, FZ1000, ...) | 
| 101 |  |  |  |  |  |  | 4 => '[Blue,Green][Green,Red]', # (LC-100, G-7, V-LUX1, ...) | 
| 102 |  |  |  |  |  |  | }, | 
| 103 |  |  |  |  |  |  | }, | 
| 104 |  |  |  |  |  |  | 0x0a => { Name => 'BitsPerSample', Writable => 'int16u', Protected => 1 }, #4 | 
| 105 |  |  |  |  |  |  | 0x0b => { #4 | 
| 106 |  |  |  |  |  |  | Name => 'Compression', | 
| 107 |  |  |  |  |  |  | Writable => 'int16u', | 
| 108 |  |  |  |  |  |  | Protected => 1, | 
| 109 |  |  |  |  |  |  | PrintConv => { | 
| 110 |  |  |  |  |  |  | 34316 => 'Panasonic RAW 1', # (most models - RAW/RW2/RWL) | 
| 111 |  |  |  |  |  |  | 34826 => 'Panasonic RAW 2', # (DIGILUX 2 - RAW) | 
| 112 |  |  |  |  |  |  | 34828 => 'Panasonic RAW 3', # (D-LUX2,D-LUX3,FZ30,LX1 - RAW) | 
| 113 |  |  |  |  |  |  | 34830 => 'Panasonic RAW 4', #IB (Leica DIGILUX 3, Panasonic DMC-L1) | 
| 114 |  |  |  |  |  |  | }, | 
| 115 |  |  |  |  |  |  | }, | 
| 116 |  |  |  |  |  |  | # 0x0c: 2 (only Leica Digilux 2) | 
| 117 |  |  |  |  |  |  | # 0x0d: 0,1 | 
| 118 |  |  |  |  |  |  | # 0x0e,0x0f,0x10: 4095 | 
| 119 |  |  |  |  |  |  | 0x0e => { Name => 'LinearityLimitRed',   Writable => 'int16u' }, #IB | 
| 120 |  |  |  |  |  |  | 0x0f => { Name => 'LinearityLimitGreen', Writable => 'int16u' }, #IB | 
| 121 |  |  |  |  |  |  | 0x10 => { Name => 'LinearityLimitBlue',  Writable => 'int16u' }, #IB | 
| 122 |  |  |  |  |  |  | 0x11 => { #JD | 
| 123 |  |  |  |  |  |  | Name => 'RedBalance', | 
| 124 |  |  |  |  |  |  | Writable => 'int16u', | 
| 125 |  |  |  |  |  |  | ValueConv => '$val / 256', | 
| 126 |  |  |  |  |  |  | ValueConvInv => 'int($val * 256 + 0.5)', | 
| 127 |  |  |  |  |  |  | Notes => 'found in Digilux 2 RAW images', | 
| 128 |  |  |  |  |  |  | }, | 
| 129 |  |  |  |  |  |  | 0x12 => { #JD | 
| 130 |  |  |  |  |  |  | Name => 'BlueBalance', | 
| 131 |  |  |  |  |  |  | Writable => 'int16u', | 
| 132 |  |  |  |  |  |  | ValueConv => '$val / 256', | 
| 133 |  |  |  |  |  |  | ValueConvInv => 'int($val * 256 + 0.5)', | 
| 134 |  |  |  |  |  |  | }, | 
| 135 |  |  |  |  |  |  | 0x13 => { #IB | 
| 136 |  |  |  |  |  |  | Name => 'WBInfo', | 
| 137 |  |  |  |  |  |  | SubDirectory => { TagTable => 'Image::ExifTool::PanasonicRaw::WBInfo' }, | 
| 138 |  |  |  |  |  |  | }, | 
| 139 |  |  |  |  |  |  | 0x17 => { #1 | 
| 140 |  |  |  |  |  |  | Name => 'ISO', | 
| 141 |  |  |  |  |  |  | Writable => 'int16u', | 
| 142 |  |  |  |  |  |  | }, | 
| 143 |  |  |  |  |  |  | # 0x18,0x19,0x1a: 0 | 
| 144 |  |  |  |  |  |  | 0x18 => { #IB | 
| 145 |  |  |  |  |  |  | Name => 'HighISOMultiplierRed', | 
| 146 |  |  |  |  |  |  | Writable => 'int16u', | 
| 147 |  |  |  |  |  |  | ValueConv => '$val / 256', | 
| 148 |  |  |  |  |  |  | ValueConvInv => 'int($val * 256 + 0.5)', | 
| 149 |  |  |  |  |  |  | }, | 
| 150 |  |  |  |  |  |  | 0x19 => { #IB | 
| 151 |  |  |  |  |  |  | Name => 'HighISOMultiplierGreen', | 
| 152 |  |  |  |  |  |  | Writable => 'int16u', | 
| 153 |  |  |  |  |  |  | ValueConv => '$val / 256', | 
| 154 |  |  |  |  |  |  | ValueConvInv => 'int($val * 256 + 0.5)', | 
| 155 |  |  |  |  |  |  | }, | 
| 156 |  |  |  |  |  |  | 0x1a => { #IB | 
| 157 |  |  |  |  |  |  | Name => 'HighISOMultiplierBlue', | 
| 158 |  |  |  |  |  |  | Writable => 'int16u', | 
| 159 |  |  |  |  |  |  | ValueConv => '$val / 256', | 
| 160 |  |  |  |  |  |  | ValueConvInv => 'int($val * 256 + 0.5)', | 
| 161 |  |  |  |  |  |  | }, | 
| 162 |  |  |  |  |  |  | # 0x1b: [binary data] (something to do with the camera ISO cababilities: int16u count N, | 
| 163 |  |  |  |  |  |  | #                      followed by table of  N entries: int16u ISO, int16u[3] RGB gains - ref IB) | 
| 164 |  |  |  |  |  |  | 0x1c => { Name => 'BlackLevelRed',   Writable => 'int16u' }, #IB | 
| 165 |  |  |  |  |  |  | 0x1d => { Name => 'BlackLevelGreen', Writable => 'int16u' }, #IB | 
| 166 |  |  |  |  |  |  | 0x1e => { Name => 'BlackLevelBlue',  Writable => 'int16u' }, #IB | 
| 167 |  |  |  |  |  |  | 0x24 => { #2 | 
| 168 |  |  |  |  |  |  | Name => 'WBRedLevel', | 
| 169 |  |  |  |  |  |  | Writable => 'int16u', | 
| 170 |  |  |  |  |  |  | }, | 
| 171 |  |  |  |  |  |  | 0x25 => { #2 | 
| 172 |  |  |  |  |  |  | Name => 'WBGreenLevel', | 
| 173 |  |  |  |  |  |  | Writable => 'int16u', | 
| 174 |  |  |  |  |  |  | }, | 
| 175 |  |  |  |  |  |  | 0x26 => { #2 | 
| 176 |  |  |  |  |  |  | Name => 'WBBlueLevel', | 
| 177 |  |  |  |  |  |  | Writable => 'int16u', | 
| 178 |  |  |  |  |  |  | }, | 
| 179 |  |  |  |  |  |  | 0x27 => { #IB | 
| 180 |  |  |  |  |  |  | Name => 'WBInfo2', | 
| 181 |  |  |  |  |  |  | SubDirectory => { TagTable => 'Image::ExifTool::PanasonicRaw::WBInfo2' }, | 
| 182 |  |  |  |  |  |  | }, | 
| 183 |  |  |  |  |  |  | # 0x27,0x29,0x2a,0x2b,0x2c: [binary data] | 
| 184 |  |  |  |  |  |  | 0x2d => { #IB | 
| 185 |  |  |  |  |  |  | Name => 'RawFormat', | 
| 186 |  |  |  |  |  |  | Writable => 'int16u', | 
| 187 |  |  |  |  |  |  | Protected => 1, | 
| 188 |  |  |  |  |  |  | # 2 - RAW DMC-FZ8/FZ18 | 
| 189 |  |  |  |  |  |  | # 3 - RAW DMC-L10 | 
| 190 |  |  |  |  |  |  | # 4 - RW2 for most other models, including G9 in "pixel shift off" mode and YUNEEC CGO4 | 
| 191 |  |  |  |  |  |  | #     (must add 15 to black levels for RawFormat == 4) | 
| 192 |  |  |  |  |  |  | # 5 - RW2 DC-GH5s; G9 in "pixel shift on" mode | 
| 193 |  |  |  |  |  |  | # 6 - RW2 DC-S1, DC-S1r in "pixel shift off" mode | 
| 194 |  |  |  |  |  |  | # 7 - RW2 DC-S1r (and probably DC-S1, have no raw samples) in "pixel shift on" mode | 
| 195 |  |  |  |  |  |  | # not used - DMC-LX1/FZ30/FZ50/L1/LX1/LX2 | 
| 196 |  |  |  |  |  |  | # (modes 5 and 7 are lossless) | 
| 197 |  |  |  |  |  |  | }, | 
| 198 |  |  |  |  |  |  | 0x2e => { #JD | 
| 199 |  |  |  |  |  |  | Name => 'JpgFromRaw', # (writable directory!) | 
| 200 |  |  |  |  |  |  | Groups => { 2 => 'Preview' }, | 
| 201 |  |  |  |  |  |  | Writable => 'undef', | 
| 202 |  |  |  |  |  |  | # protect this tag because it contains all the metadata | 
| 203 |  |  |  |  |  |  | Flags => [ 'Binary', 'Protected', 'NestedHtmlDump', 'BlockExtract' ], | 
| 204 |  |  |  |  |  |  | Notes => 'processed as an embedded document because it contains full EXIF', | 
| 205 |  |  |  |  |  |  | WriteCheck => '$val eq "none" ? undef : $self->CheckImage(\$val)', | 
| 206 |  |  |  |  |  |  | DataTag => 'JpgFromRaw', | 
| 207 |  |  |  |  |  |  | RawConv => '$self->ValidateImage(\$val,$tag)', | 
| 208 |  |  |  |  |  |  | SubDirectory => { | 
| 209 |  |  |  |  |  |  | # extract information from embedded image since it is metadata-rich, | 
| 210 |  |  |  |  |  |  | # unless HtmlDump option set (note that the offsets will be relative, | 
| 211 |  |  |  |  |  |  | # not absolute like they should be in verbose mode) | 
| 212 |  |  |  |  |  |  | TagTable => 'Image::ExifTool::JPEG::Main', | 
| 213 |  |  |  |  |  |  | WriteProc => \&WriteJpgFromRaw, | 
| 214 |  |  |  |  |  |  | ProcessProc => \&ProcessJpgFromRaw, | 
| 215 |  |  |  |  |  |  | }, | 
| 216 |  |  |  |  |  |  | }, | 
| 217 |  |  |  |  |  |  | 0x2f => { Name => 'CropTop',    Writable => 'int16u' }, | 
| 218 |  |  |  |  |  |  | 0x30 => { Name => 'CropLeft',   Writable => 'int16u' }, | 
| 219 |  |  |  |  |  |  | 0x31 => { Name => 'CropBottom', Writable => 'int16u' }, | 
| 220 |  |  |  |  |  |  | 0x32 => { Name => 'CropRight',  Writable => 'int16u' }, | 
| 221 |  |  |  |  |  |  | 0x10f => { | 
| 222 |  |  |  |  |  |  | Name => 'Make', | 
| 223 |  |  |  |  |  |  | Groups => { 2 => 'Camera' }, | 
| 224 |  |  |  |  |  |  | Writable => 'string', | 
| 225 |  |  |  |  |  |  | DataMember => 'Make', | 
| 226 |  |  |  |  |  |  | # save this value as an ExifTool member variable | 
| 227 |  |  |  |  |  |  | RawConv => '$self->{Make} = $val', | 
| 228 |  |  |  |  |  |  | }, | 
| 229 |  |  |  |  |  |  | 0x110 => { | 
| 230 |  |  |  |  |  |  | Name => 'Model', | 
| 231 |  |  |  |  |  |  | Description => 'Camera Model Name', | 
| 232 |  |  |  |  |  |  | Groups => { 2 => 'Camera' }, | 
| 233 |  |  |  |  |  |  | Writable => 'string', | 
| 234 |  |  |  |  |  |  | DataMember => 'Model', | 
| 235 |  |  |  |  |  |  | # save this value as an ExifTool member variable | 
| 236 |  |  |  |  |  |  | RawConv => '$self->{Model} = $val', | 
| 237 |  |  |  |  |  |  | }, | 
| 238 |  |  |  |  |  |  | 0x111 => { | 
| 239 |  |  |  |  |  |  | Name => 'StripOffsets', | 
| 240 |  |  |  |  |  |  | # (this value is 0xffffffff for some models, and RawDataOffset must be used) | 
| 241 |  |  |  |  |  |  | Flags => [ 'IsOffset', 'PanasonicHack' ], | 
| 242 |  |  |  |  |  |  | OffsetPair => 0x117,  # point to associated byte counts | 
| 243 |  |  |  |  |  |  | ValueConv => 'length($val) > 32 ? \$val : $val', | 
| 244 |  |  |  |  |  |  | }, | 
| 245 |  |  |  |  |  |  | 0x112 => { | 
| 246 |  |  |  |  |  |  | Name => 'Orientation', | 
| 247 |  |  |  |  |  |  | Writable => 'int16u', | 
| 248 |  |  |  |  |  |  | PrintConv => \%Image::ExifTool::Exif::orientation, | 
| 249 |  |  |  |  |  |  | Priority => 0,  # so IFD1 doesn't take precedence | 
| 250 |  |  |  |  |  |  | }, | 
| 251 |  |  |  |  |  |  | 0x116 => { | 
| 252 |  |  |  |  |  |  | Name => 'RowsPerStrip', | 
| 253 |  |  |  |  |  |  | Priority => 0, | 
| 254 |  |  |  |  |  |  | }, | 
| 255 |  |  |  |  |  |  | 0x117 => { | 
| 256 |  |  |  |  |  |  | Name => 'StripByteCounts', | 
| 257 |  |  |  |  |  |  | # (note that this value may represent something like uncompressed byte count | 
| 258 |  |  |  |  |  |  | # for RAW/RW2/RWL images from some models, and is zero for some other models) | 
| 259 |  |  |  |  |  |  | OffsetPair => 0x111,   # point to associated offset | 
| 260 |  |  |  |  |  |  | ValueConv => 'length($val) > 32 ? \$val : $val', | 
| 261 |  |  |  |  |  |  | }, | 
| 262 |  |  |  |  |  |  | 0x118 => { | 
| 263 |  |  |  |  |  |  | Name => 'RawDataOffset', #PH (RW2/RWL) | 
| 264 |  |  |  |  |  |  | IsOffset => '$$et{TIFF_TYPE} =~ /^(RW2|RWL)$/', # (invalid in DNG-converted files) | 
| 265 |  |  |  |  |  |  | PanasonicHack => 1, | 
| 266 |  |  |  |  |  |  | OffsetPair => 0x117, # (use StripByteCounts as the offset pair) | 
| 267 |  |  |  |  |  |  | NotRealPair => 1,    # (to avoid Validate warning) | 
| 268 |  |  |  |  |  |  | }, | 
| 269 |  |  |  |  |  |  | 0x119 => { | 
| 270 |  |  |  |  |  |  | Name => 'DistortionInfo', | 
| 271 |  |  |  |  |  |  | SubDirectory => { TagTable => 'Image::ExifTool::PanasonicRaw::DistortionInfo' }, | 
| 272 |  |  |  |  |  |  | }, | 
| 273 |  |  |  |  |  |  | # 0x11b - chromatic aberration correction (ref 3) (also see forum9366) | 
| 274 |  |  |  |  |  |  | 0x11c => { #forum9373 | 
| 275 |  |  |  |  |  |  | Name => 'Gamma', | 
| 276 |  |  |  |  |  |  | Writable => 'int16u', | 
| 277 |  |  |  |  |  |  | # unfortunately it seems that the scaling factor varies with model... | 
| 278 |  |  |  |  |  |  | ValueConv => '$val / ($val >= 1024 ? 1024 : ($val >= 256 ? 256 : 100))', | 
| 279 |  |  |  |  |  |  | ValueConvInv => 'int($val * 256 + 0.5)', | 
| 280 |  |  |  |  |  |  | }, | 
| 281 |  |  |  |  |  |  | 0x120 => { | 
| 282 |  |  |  |  |  |  | Name => 'CameraIFD', | 
| 283 |  |  |  |  |  |  | SubDirectory => { | 
| 284 |  |  |  |  |  |  | TagTable => 'Image::ExifTool::PanasonicRaw::CameraIFD', | 
| 285 |  |  |  |  |  |  | Base => '$start', | 
| 286 |  |  |  |  |  |  | ProcessProc => \&Image::ExifTool::ProcessTIFF, | 
| 287 |  |  |  |  |  |  | }, | 
| 288 |  |  |  |  |  |  | }, | 
| 289 |  |  |  |  |  |  | 0x121 => { #forum9295 | 
| 290 |  |  |  |  |  |  | Name => 'Multishot', | 
| 291 |  |  |  |  |  |  | Writable => 'int32u', | 
| 292 |  |  |  |  |  |  | PrintConv => { | 
| 293 |  |  |  |  |  |  | 0 => 'Off', | 
| 294 |  |  |  |  |  |  | 65536 => 'Pixel Shift', | 
| 295 |  |  |  |  |  |  | }, | 
| 296 |  |  |  |  |  |  | }, | 
| 297 |  |  |  |  |  |  | # 0x122 - int32u: RAWDataOffset for the GH5s/GX9, or pointer to end of raw data for G9 (forum9295) | 
| 298 |  |  |  |  |  |  | 0x2bc => { # PH Extension!! | 
| 299 |  |  |  |  |  |  | Name => 'ApplicationNotes', # (writable directory!) | 
| 300 |  |  |  |  |  |  | Writable => 'int8u', | 
| 301 |  |  |  |  |  |  | Format => 'undef', | 
| 302 |  |  |  |  |  |  | Flags => [ 'Binary', 'Protected' ], | 
| 303 |  |  |  |  |  |  | SubDirectory => { | 
| 304 |  |  |  |  |  |  | DirName => 'XMP', | 
| 305 |  |  |  |  |  |  | TagTable => 'Image::ExifTool::XMP::Main', | 
| 306 |  |  |  |  |  |  | }, | 
| 307 |  |  |  |  |  |  | }, | 
| 308 |  |  |  |  |  |  | 0x001b => { #forum9250 | 
| 309 |  |  |  |  |  |  | Name => 'NoiseReductionParams', | 
| 310 |  |  |  |  |  |  | Writable => 'undef', | 
| 311 |  |  |  |  |  |  | Format => 'int16u', | 
| 312 |  |  |  |  |  |  | Count => -1, | 
| 313 |  |  |  |  |  |  | Flags => 'Protected', | 
| 314 |  |  |  |  |  |  | Notes => q{ | 
| 315 |  |  |  |  |  |  | the camera's default noise reduction setup.  The first number is the number | 
| 316 |  |  |  |  |  |  | of entries, then for each entry there are 4 numbers: an ISO speed, and | 
| 317 |  |  |  |  |  |  | noise-reduction strengths the R, G and B channels | 
| 318 |  |  |  |  |  |  | }, | 
| 319 |  |  |  |  |  |  | }, | 
| 320 |  |  |  |  |  |  | 0x83bb => { # PH Extension!! | 
| 321 |  |  |  |  |  |  | Name => 'IPTC-NAA', # (writable directory!) | 
| 322 |  |  |  |  |  |  | Format => 'undef',      # convert binary values as undef | 
| 323 |  |  |  |  |  |  | Writable => 'int32u',   # but write int32u format code in IFD | 
| 324 |  |  |  |  |  |  | WriteGroup => 'IFD0', | 
| 325 |  |  |  |  |  |  | Flags => [ 'Binary', 'Protected' ], | 
| 326 |  |  |  |  |  |  | SubDirectory => { | 
| 327 |  |  |  |  |  |  | DirName => 'IPTC', | 
| 328 |  |  |  |  |  |  | TagTable => 'Image::ExifTool::IPTC::Main', | 
| 329 |  |  |  |  |  |  | }, | 
| 330 |  |  |  |  |  |  | }, | 
| 331 |  |  |  |  |  |  | 0x8769 => { | 
| 332 |  |  |  |  |  |  | Name => 'ExifOffset', | 
| 333 |  |  |  |  |  |  | Groups => { 1 => 'ExifIFD' }, | 
| 334 |  |  |  |  |  |  | Flags => 'SubIFD', | 
| 335 |  |  |  |  |  |  | SubDirectory => { | 
| 336 |  |  |  |  |  |  | TagTable => 'Image::ExifTool::Exif::Main', | 
| 337 |  |  |  |  |  |  | DirName => 'ExifIFD', | 
| 338 |  |  |  |  |  |  | Start => '$val', | 
| 339 |  |  |  |  |  |  | }, | 
| 340 |  |  |  |  |  |  | }, | 
| 341 |  |  |  |  |  |  | 0x8825 => { | 
| 342 |  |  |  |  |  |  | Name => 'GPSInfo', | 
| 343 |  |  |  |  |  |  | Groups => { 1 => 'GPS' }, | 
| 344 |  |  |  |  |  |  | Flags => 'SubIFD', | 
| 345 |  |  |  |  |  |  | SubDirectory => { | 
| 346 |  |  |  |  |  |  | DirName => 'GPS', | 
| 347 |  |  |  |  |  |  | TagTable => 'Image::ExifTool::GPS::Main', | 
| 348 |  |  |  |  |  |  | Start => '$val', | 
| 349 |  |  |  |  |  |  | }, | 
| 350 |  |  |  |  |  |  | }, | 
| 351 |  |  |  |  |  |  | # 0xffff => 'DCSHueShiftValues', #exifprobe (NC) | 
| 352 |  |  |  |  |  |  | ); | 
| 353 |  |  |  |  |  |  |  | 
| 354 |  |  |  |  |  |  | # white balance information (ref IB) | 
| 355 |  |  |  |  |  |  | # (PanasonicRawVersion<200: Digilux 2) | 
| 356 |  |  |  |  |  |  | %Image::ExifTool::PanasonicRaw::WBInfo = ( | 
| 357 |  |  |  |  |  |  | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, | 
| 358 |  |  |  |  |  |  | WRITE_PROC => \&Image::ExifTool::WriteBinaryData, | 
| 359 |  |  |  |  |  |  | CHECK_PROC => \&Image::ExifTool::CheckBinaryData, | 
| 360 |  |  |  |  |  |  | WRITABLE => 1, | 
| 361 |  |  |  |  |  |  | FORMAT => 'int16u', | 
| 362 |  |  |  |  |  |  | FIRST_ENTRY => 0, | 
| 363 |  |  |  |  |  |  | 0 => 'NumWBEntries', | 
| 364 |  |  |  |  |  |  | 1 => { Name => 'WBType1', %wbTypeInfo }, | 
| 365 |  |  |  |  |  |  | 2 => { Name => 'WB_RBLevels1', Format => 'int16u[2]' }, | 
| 366 |  |  |  |  |  |  | 4 => { Name => 'WBType2', %wbTypeInfo }, | 
| 367 |  |  |  |  |  |  | 5 => { Name => 'WB_RBLevels2', Format => 'int16u[2]' }, | 
| 368 |  |  |  |  |  |  | 7 => { Name => 'WBType3', %wbTypeInfo }, | 
| 369 |  |  |  |  |  |  | 8 => { Name => 'WB_RBLevels3', Format => 'int16u[2]' }, | 
| 370 |  |  |  |  |  |  | 10 => { Name => 'WBType4', %wbTypeInfo }, | 
| 371 |  |  |  |  |  |  | 11 => { Name => 'WB_RBLevels4', Format => 'int16u[2]' }, | 
| 372 |  |  |  |  |  |  | 13 => { Name => 'WBType5', %wbTypeInfo }, | 
| 373 |  |  |  |  |  |  | 14 => { Name => 'WB_RBLevels5', Format => 'int16u[2]' }, | 
| 374 |  |  |  |  |  |  | 16 => { Name => 'WBType6', %wbTypeInfo }, | 
| 375 |  |  |  |  |  |  | 17 => { Name => 'WB_RBLevels6', Format => 'int16u[2]' }, | 
| 376 |  |  |  |  |  |  | 19 => { Name => 'WBType7', %wbTypeInfo }, | 
| 377 |  |  |  |  |  |  | 20 => { Name => 'WB_RBLevels7', Format => 'int16u[2]' }, | 
| 378 |  |  |  |  |  |  | ); | 
| 379 |  |  |  |  |  |  |  | 
| 380 |  |  |  |  |  |  | # white balance information (ref IB) | 
| 381 |  |  |  |  |  |  | # (PanasonicRawVersion>=200: D-Lux2, D-Lux3, DMC-FZ18/FZ30/LX1/L10) | 
| 382 |  |  |  |  |  |  | %Image::ExifTool::PanasonicRaw::WBInfo2 = ( | 
| 383 |  |  |  |  |  |  | PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData, | 
| 384 |  |  |  |  |  |  | WRITE_PROC => \&Image::ExifTool::WriteBinaryData, | 
| 385 |  |  |  |  |  |  | CHECK_PROC => \&Image::ExifTool::CheckBinaryData, | 
| 386 |  |  |  |  |  |  | WRITABLE => 1, | 
| 387 |  |  |  |  |  |  | FORMAT => 'int16u', | 
| 388 |  |  |  |  |  |  | FIRST_ENTRY => 0, | 
| 389 |  |  |  |  |  |  | 0 => 'NumWBEntries', | 
| 390 |  |  |  |  |  |  | 1 => { Name => 'WBType1', %wbTypeInfo }, | 
| 391 |  |  |  |  |  |  | 2 => { Name => 'WB_RGBLevels1', Format => 'int16u[3]' }, | 
| 392 |  |  |  |  |  |  | 5 => { Name => 'WBType2', %wbTypeInfo }, | 
| 393 |  |  |  |  |  |  | 6 => { Name => 'WB_RGBLevels2', Format => 'int16u[3]' }, | 
| 394 |  |  |  |  |  |  | 9 => { Name => 'WBType3', %wbTypeInfo }, | 
| 395 |  |  |  |  |  |  | 10 => { Name => 'WB_RGBLevels3', Format => 'int16u[3]' }, | 
| 396 |  |  |  |  |  |  | 13 => { Name => 'WBType4', %wbTypeInfo }, | 
| 397 |  |  |  |  |  |  | 14 => { Name => 'WB_RGBLevels4', Format => 'int16u[3]' }, | 
| 398 |  |  |  |  |  |  | 17 => { Name => 'WBType5', %wbTypeInfo }, | 
| 399 |  |  |  |  |  |  | 18 => { Name => 'WB_RGBLevels5', Format => 'int16u[3]' }, | 
| 400 |  |  |  |  |  |  | 21 => { Name => 'WBType6', %wbTypeInfo }, | 
| 401 |  |  |  |  |  |  | 22 => { Name => 'WB_RGBLevels6', Format => 'int16u[3]' }, | 
| 402 |  |  |  |  |  |  | 25 => { Name => 'WBType7', %wbTypeInfo }, | 
| 403 |  |  |  |  |  |  | 26 => { Name => 'WB_RGBLevels7', Format => 'int16u[3]' }, | 
| 404 |  |  |  |  |  |  | ); | 
| 405 |  |  |  |  |  |  |  | 
| 406 |  |  |  |  |  |  | # lens distortion information (ref 3) | 
| 407 |  |  |  |  |  |  | # (distortion correction equation: Ru = scale*(Rd + a*Rd^3 + b*Rd^5 + c*Rd^7), ref 3) | 
| 408 |  |  |  |  |  |  | %Image::ExifTool::PanasonicRaw::DistortionInfo = ( | 
| 409 |  |  |  |  |  |  | PROCESS_PROC => \&ProcessDistortionInfo, | 
| 410 |  |  |  |  |  |  | WRITE_PROC => \&WriteDistortionInfo, | 
| 411 |  |  |  |  |  |  | CHECK_PROC => \&Image::ExifTool::CheckBinaryData, | 
| 412 |  |  |  |  |  |  | # (don't make this family 0 MakerNotes because we don't want it to be a deletable group) | 
| 413 |  |  |  |  |  |  | GROUPS => { 0 => 'PanasonicRaw', 1 => 'PanasonicRaw', 2 => 'Image'}, | 
| 414 |  |  |  |  |  |  | WRITABLE => 1, | 
| 415 |  |  |  |  |  |  | FORMAT => 'int16s', | 
| 416 |  |  |  |  |  |  | FIRST_ENTRY => 0, | 
| 417 |  |  |  |  |  |  | NOTES => 'Lens distortion correction information.', | 
| 418 |  |  |  |  |  |  | # 0,1 - checksums | 
| 419 |  |  |  |  |  |  | 2 => { | 
| 420 |  |  |  |  |  |  | Name => 'DistortionParam02', | 
| 421 |  |  |  |  |  |  | ValueConv => '$val / 32768', | 
| 422 |  |  |  |  |  |  | ValueConvInv => '$val * 32768', | 
| 423 |  |  |  |  |  |  | }, | 
| 424 |  |  |  |  |  |  | # 3 - usually 0, but seen 0x026b when value 5 is non-zero | 
| 425 |  |  |  |  |  |  | 4 => { | 
| 426 |  |  |  |  |  |  | Name => 'DistortionParam04', | 
| 427 |  |  |  |  |  |  | ValueConv => '$val / 32768', | 
| 428 |  |  |  |  |  |  | ValueConvInv => '$val * 32768', | 
| 429 |  |  |  |  |  |  | }, | 
| 430 |  |  |  |  |  |  | 5 => { | 
| 431 |  |  |  |  |  |  | Name => 'DistortionScale', | 
| 432 |  |  |  |  |  |  | ValueConv => '1 / (1 + $val/32768)', | 
| 433 |  |  |  |  |  |  | ValueConvInv => '(1/$val - 1) * 32768', | 
| 434 |  |  |  |  |  |  | }, | 
| 435 |  |  |  |  |  |  | # 6 - seen 0x0000-0x027f | 
| 436 |  |  |  |  |  |  | 7.1 => { | 
| 437 |  |  |  |  |  |  | Name => 'DistortionCorrection', | 
| 438 |  |  |  |  |  |  | Mask => 0x0f, | 
| 439 |  |  |  |  |  |  | # (have seen the upper 4 bits set for GF5 and GX1, giving a value of -4095 - PH) | 
| 440 |  |  |  |  |  |  | PrintConv => { 0 => 'Off', 1 => 'On' }, | 
| 441 |  |  |  |  |  |  | }, | 
| 442 |  |  |  |  |  |  | 8 => { | 
| 443 |  |  |  |  |  |  | Name => 'DistortionParam08', | 
| 444 |  |  |  |  |  |  | ValueConv => '$val / 32768', | 
| 445 |  |  |  |  |  |  | ValueConvInv => '$val * 32768', | 
| 446 |  |  |  |  |  |  | }, | 
| 447 |  |  |  |  |  |  | 9 => { | 
| 448 |  |  |  |  |  |  | Name => 'DistortionParam09', | 
| 449 |  |  |  |  |  |  | ValueConv => '$val / 32768', | 
| 450 |  |  |  |  |  |  | ValueConvInv => '$val * 32768', | 
| 451 |  |  |  |  |  |  | }, | 
| 452 |  |  |  |  |  |  | # 10 - seen 0xfc,0x0101,0x01f4,0x021d,0x0256 | 
| 453 |  |  |  |  |  |  | 11 => { | 
| 454 |  |  |  |  |  |  | Name => 'DistortionParam11', | 
| 455 |  |  |  |  |  |  | ValueConv => '$val / 32768', | 
| 456 |  |  |  |  |  |  | ValueConvInv => '$val * 32768', | 
| 457 |  |  |  |  |  |  | }, | 
| 458 |  |  |  |  |  |  | 12 => { | 
| 459 |  |  |  |  |  |  | Name => 'DistortionN', | 
| 460 |  |  |  |  |  |  | Unknown => 1, | 
| 461 |  |  |  |  |  |  | }, | 
| 462 |  |  |  |  |  |  | # 13 - seen 0x0000,0x01f9-0x02b2 | 
| 463 |  |  |  |  |  |  | # 14,15 - checksums | 
| 464 |  |  |  |  |  |  | ); | 
| 465 |  |  |  |  |  |  |  | 
| 466 |  |  |  |  |  |  | # Panasonic RW2 camera IFD written by GH5 (ref PH) | 
| 467 |  |  |  |  |  |  | # (doesn't seem to be valid for the GF7 or GM5 -- encrypted?) | 
| 468 |  |  |  |  |  |  | %Image::ExifTool::PanasonicRaw::CameraIFD = ( | 
| 469 |  |  |  |  |  |  | GROUPS => { 0 => 'PanasonicRaw', 1 => 'CameraIFD', 2 => 'Camera'}, | 
| 470 |  |  |  |  |  |  | # (don't know what format codes 0x101 and 0x102 are for, so just | 
| 471 |  |  |  |  |  |  | #  map them into 4 = int32u for now) | 
| 472 |  |  |  |  |  |  | VARS => { MAP_FORMAT => { 0x101 => 4, 0x102 => 4 } }, | 
| 473 |  |  |  |  |  |  | 0x1001 => { #forum9388 | 
| 474 |  |  |  |  |  |  | Name => 'MultishotOn', | 
| 475 |  |  |  |  |  |  | Writable => 'int32u', | 
| 476 |  |  |  |  |  |  | PrintConv => { 0 => 'No', 1 => 'Yes' }, | 
| 477 |  |  |  |  |  |  | }, | 
| 478 |  |  |  |  |  |  | 0x1100 => { #forum9274 | 
| 479 |  |  |  |  |  |  | Name => 'FocusStepNear', | 
| 480 |  |  |  |  |  |  | Writable => 'int16s', | 
| 481 |  |  |  |  |  |  | }, | 
| 482 |  |  |  |  |  |  | 0x1101 => { #forum9274 (was forum8484) | 
| 483 |  |  |  |  |  |  | Name => 'FocusStepCount', | 
| 484 |  |  |  |  |  |  | Writable => 'int16s', | 
| 485 |  |  |  |  |  |  | }, | 
| 486 |  |  |  |  |  |  | 0x1102 => { #forum9417 | 
| 487 |  |  |  |  |  |  | Name => 'FlashFired', | 
| 488 |  |  |  |  |  |  | Writable => 'int32u', | 
| 489 |  |  |  |  |  |  | PrintConv => { 0 => 'No', 1 => 'Yes' }, | 
| 490 |  |  |  |  |  |  | }, | 
| 491 |  |  |  |  |  |  | # 0x1104 - set when camera shoots on lowest possible Extended-ISO (forum9290) | 
| 492 |  |  |  |  |  |  | 0x1105 => { #forum9392 | 
| 493 |  |  |  |  |  |  | Name => 'ZoomPosition', | 
| 494 |  |  |  |  |  |  | Notes => 'in the range 0-255 for most cameras', | 
| 495 |  |  |  |  |  |  | Writable => 'int32u', | 
| 496 |  |  |  |  |  |  | }, | 
| 497 |  |  |  |  |  |  | 0x1200 => { #forum9278 | 
| 498 |  |  |  |  |  |  | Name => 'LensAttached', | 
| 499 |  |  |  |  |  |  | Notes => 'many CameraIFD tags are invalid if there is no lens attached', | 
| 500 |  |  |  |  |  |  | Writable => 'int32u', | 
| 501 |  |  |  |  |  |  | PrintConv => { 0 => 'No', 1 => 'Yes' }, | 
| 502 |  |  |  |  |  |  | }, | 
| 503 |  |  |  |  |  |  | # Note: LensTypeMake and LensTypeModel are combined into a Composite LensType tag | 
| 504 |  |  |  |  |  |  | # defined in Olympus.pm which has the same values as Olympus:LensType | 
| 505 |  |  |  |  |  |  | 0x1201 => { #IB | 
| 506 |  |  |  |  |  |  | Name => 'LensTypeMake', | 
| 507 |  |  |  |  |  |  | Condition => '$format eq "int16u"', | 
| 508 |  |  |  |  |  |  | Writable => 'int16u', | 
| 509 |  |  |  |  |  |  | # when format is int16u, these values have been observed: | 
| 510 |  |  |  |  |  |  | #  0 - Olympus or unknown lens | 
| 511 |  |  |  |  |  |  | #  2 - Leica or Lumix lens | 
| 512 |  |  |  |  |  |  | # when format is int32u (S models), these values have been observed (ref IB): | 
| 513 |  |  |  |  |  |  | #  256 - Leica lens | 
| 514 |  |  |  |  |  |  | #  257 - Lumix lens | 
| 515 |  |  |  |  |  |  | #  258 - ? (seen once) | 
| 516 |  |  |  |  |  |  | }, | 
| 517 |  |  |  |  |  |  | 0x1202 => { #IB | 
| 518 |  |  |  |  |  |  | Name => 'LensTypeModel', | 
| 519 |  |  |  |  |  |  | Condition => '$format eq "int16u"', | 
| 520 |  |  |  |  |  |  | Writable => 'int16u', | 
| 521 |  |  |  |  |  |  | RawConv => q{ | 
| 522 |  |  |  |  |  |  | return undef unless $val; | 
| 523 |  |  |  |  |  |  | require Image::ExifTool::Olympus; # (to load Composite LensID) | 
| 524 |  |  |  |  |  |  | return $val; | 
| 525 |  |  |  |  |  |  | }, | 
| 526 |  |  |  |  |  |  | ValueConv => '$_=sprintf("%.4x",$val); s/(..)(..)/$2 $1/; $_', | 
| 527 |  |  |  |  |  |  | ValueConvInv => '$val =~ s/(..) (..)/$2$1/; hex($val)', | 
| 528 |  |  |  |  |  |  | }, | 
| 529 |  |  |  |  |  |  | 0x1203 => { #4 | 
| 530 |  |  |  |  |  |  | Name => 'FocalLengthIn35mmFormat', | 
| 531 |  |  |  |  |  |  | Writable => 'int16u', | 
| 532 |  |  |  |  |  |  | PrintConv => '"$val mm"', | 
| 533 |  |  |  |  |  |  | PrintConvInv => '$val=~s/\s*mm$//;$val', | 
| 534 |  |  |  |  |  |  | }, | 
| 535 |  |  |  |  |  |  | # 0x1300 - incident light value? (ref forum11395) | 
| 536 |  |  |  |  |  |  | 0x1301 => { #forum11395 | 
| 537 |  |  |  |  |  |  | Name => 'ApertureValue', | 
| 538 |  |  |  |  |  |  | Writable => 'int16s', | 
| 539 |  |  |  |  |  |  | Priority => 0, | 
| 540 |  |  |  |  |  |  | ValueConv => '2 ** ($val / 512)', | 
| 541 |  |  |  |  |  |  | ValueConvInv => '$val>0 ? 512*log($val)/log(2) : 0', | 
| 542 |  |  |  |  |  |  | PrintConv => 'sprintf("%.1f",$val)', | 
| 543 |  |  |  |  |  |  | PrintConvInv => '$val', | 
| 544 |  |  |  |  |  |  | }, | 
| 545 |  |  |  |  |  |  | 0x1302 => { #forum11395 | 
| 546 |  |  |  |  |  |  | Name => 'ShutterSpeedValue', | 
| 547 |  |  |  |  |  |  | Writable => 'int16s', | 
| 548 |  |  |  |  |  |  | Priority => 0, | 
| 549 |  |  |  |  |  |  | ValueConv => 'abs($val/256)<100 ? 2**(-$val/256) : 0', | 
| 550 |  |  |  |  |  |  | ValueConvInv => '$val>0 ? -256*log($val)/log(2) : -25600', | 
| 551 |  |  |  |  |  |  | PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)', | 
| 552 |  |  |  |  |  |  | PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)', | 
| 553 |  |  |  |  |  |  | }, | 
| 554 |  |  |  |  |  |  | 0x1303 => { #forum11395 | 
| 555 |  |  |  |  |  |  | Name => 'SensitivityValue', | 
| 556 |  |  |  |  |  |  | Writable => 'int16s', | 
| 557 |  |  |  |  |  |  | ValueConv => '$val / 256', | 
| 558 |  |  |  |  |  |  | ValueConvInv => 'int($val * 256)', | 
| 559 |  |  |  |  |  |  | }, | 
| 560 |  |  |  |  |  |  | 0x1305 => { #forum9384 | 
| 561 |  |  |  |  |  |  | Name => 'HighISOMode', | 
| 562 |  |  |  |  |  |  | Writable => 'int16u', | 
| 563 |  |  |  |  |  |  | RawConv => '$val || undef', | 
| 564 |  |  |  |  |  |  | PrintConv => { 1 => 'On', 2 => 'Off' }, | 
| 565 |  |  |  |  |  |  | }, | 
| 566 |  |  |  |  |  |  | # 0x1306 EV for some models like the GX8 (forum11395) | 
| 567 |  |  |  |  |  |  | # 0x140b - scaled overall black level? (ref forum9281) | 
| 568 |  |  |  |  |  |  | # 0x1411 - scaled black level per channel difference (ref forum9281) | 
| 569 |  |  |  |  |  |  | 0x1412 => { #forum11397 | 
| 570 |  |  |  |  |  |  | Name => 'FacesDetected', | 
| 571 |  |  |  |  |  |  | Writable => 'int8u', | 
| 572 |  |  |  |  |  |  | PrintConv => { 0 => 'No', 1 => 'Yes' }, | 
| 573 |  |  |  |  |  |  | }, | 
| 574 |  |  |  |  |  |  | # 0x2000 - WB tungsten=3, daylight=4 (ref forum9467) | 
| 575 |  |  |  |  |  |  | # 0x2009 - scaled black level per channel (ref forum9281) | 
| 576 |  |  |  |  |  |  | # 0x3000-0x310b - red/blue balances * 1024 (ref forum9467) | 
| 577 |  |  |  |  |  |  | #  0x3000 modifiedTungsten-Red (-2?) | 
| 578 |  |  |  |  |  |  | #  0x3001 modifiedTungsten-Blue (-2?) | 
| 579 |  |  |  |  |  |  | #  0x3002 modifiedDaylight-Red (-2?) | 
| 580 |  |  |  |  |  |  | #  0x3003 modifiedDaylight-Blue (-2?) | 
| 581 |  |  |  |  |  |  | #  0x3004 modifiedTungsten-Red (-1?) | 
| 582 |  |  |  |  |  |  | #  0x3005 modifiedTungsten-Blue (-1?) | 
| 583 |  |  |  |  |  |  | #  0x3006 modifiedDaylight-Red (-1?) | 
| 584 |  |  |  |  |  |  | #  0x3007 modifiedDaylight-Blue (-1?) | 
| 585 |  |  |  |  |  |  | #  0x3100 DefaultTungsten-Red | 
| 586 |  |  |  |  |  |  | #  0x3101 DefaultTungsten-Blue | 
| 587 |  |  |  |  |  |  | #  0x3102 DefaultDaylight-Red | 
| 588 |  |  |  |  |  |  | #  0x3103 DefaultDaylight-Blue | 
| 589 |  |  |  |  |  |  | #  0x3104 modifiedTungsten-Red (+1?) | 
| 590 |  |  |  |  |  |  | #  0x3105 modifiedTungsten-Blue (+1?) | 
| 591 |  |  |  |  |  |  | #  0x3106 modifiedDaylight-Red (+1?) | 
| 592 |  |  |  |  |  |  | #  0x3107 modifiedDaylight-Blue (+1?) | 
| 593 |  |  |  |  |  |  | #  0x3108 modifiedTungsten-Red (+2?) | 
| 594 |  |  |  |  |  |  | #  0x3109 modifiedTungsten-Blue (+2?) | 
| 595 |  |  |  |  |  |  | #  0x310a modifiedDaylight-Red (+2?) | 
| 596 |  |  |  |  |  |  | #  0x310b modifiedDaylight-Blue (+2?) | 
| 597 |  |  |  |  |  |  | 0x3200 => { #forum9275 | 
| 598 |  |  |  |  |  |  | Name => 'WB_CFA0_LevelDaylight', | 
| 599 |  |  |  |  |  |  | Writable => 'int16u', | 
| 600 |  |  |  |  |  |  | }, | 
| 601 |  |  |  |  |  |  | 0x3201 => { #forum9275 | 
| 602 |  |  |  |  |  |  | Name => 'WB_CFA1_LevelDaylight', | 
| 603 |  |  |  |  |  |  | Writable => 'int16u', | 
| 604 |  |  |  |  |  |  | }, | 
| 605 |  |  |  |  |  |  | 0x3202 => { #forum9275 | 
| 606 |  |  |  |  |  |  | Name => 'WB_CFA2_LevelDaylight', | 
| 607 |  |  |  |  |  |  | Writable => 'int16u', | 
| 608 |  |  |  |  |  |  | }, | 
| 609 |  |  |  |  |  |  | 0x3203 => { #forum9275 | 
| 610 |  |  |  |  |  |  | Name => 'WB_CFA3_LevelDaylight', | 
| 611 |  |  |  |  |  |  | Writable => 'int16u', | 
| 612 |  |  |  |  |  |  | }, | 
| 613 |  |  |  |  |  |  | # 0x3204-0x3207 - user multipliers * 1024 ? (ref forum9275) | 
| 614 |  |  |  |  |  |  | # 0x320a - scaled maximum value of raw data (scaling = 4x) (ref forum9281) | 
| 615 |  |  |  |  |  |  | # 0x3209 - gamma (x256) (ref forum9281) | 
| 616 |  |  |  |  |  |  | 0x3300 => { #forum9296/9396 | 
| 617 |  |  |  |  |  |  | Name => 'WhiteBalanceSet', | 
| 618 |  |  |  |  |  |  | Writable => 'int8u', | 
| 619 |  |  |  |  |  |  | PrintConv => \%panasonicWhiteBalance, | 
| 620 |  |  |  |  |  |  | SeparateTable => 'WhiteBalance', | 
| 621 |  |  |  |  |  |  | }, | 
| 622 |  |  |  |  |  |  | 0x3420 => { #forum9276 | 
| 623 |  |  |  |  |  |  | Name => 'WB_RedLevelAuto', | 
| 624 |  |  |  |  |  |  | Writable => 'int16u', | 
| 625 |  |  |  |  |  |  | }, | 
| 626 |  |  |  |  |  |  | 0x3421 => { #forum9276 | 
| 627 |  |  |  |  |  |  | Name => 'WB_BlueLevelAuto', | 
| 628 |  |  |  |  |  |  | Writable => 'int16u', | 
| 629 |  |  |  |  |  |  | }, | 
| 630 |  |  |  |  |  |  | 0x3501 => { #4 | 
| 631 |  |  |  |  |  |  | Name => 'Orientation', | 
| 632 |  |  |  |  |  |  | Writable => 'int8u', | 
| 633 |  |  |  |  |  |  | PrintConv => \%Image::ExifTool::Exif::orientation, | 
| 634 |  |  |  |  |  |  | }, | 
| 635 |  |  |  |  |  |  | # 0x3504 = Tag 0x1301+0x1302-0x1303 (Bv = Av+Tv-Sv) (forum11395) | 
| 636 |  |  |  |  |  |  | # 0x3505 - same as 0x1300 (forum11395) | 
| 637 |  |  |  |  |  |  | 0x3600 => { #forum9396 | 
| 638 |  |  |  |  |  |  | Name => 'WhiteBalanceDetected', | 
| 639 |  |  |  |  |  |  | Writable => 'int8u', | 
| 640 |  |  |  |  |  |  | PrintConv => \%panasonicWhiteBalance, | 
| 641 |  |  |  |  |  |  | SeparateTable => 'WhiteBalance', | 
| 642 |  |  |  |  |  |  | }, | 
| 643 |  |  |  |  |  |  | ); | 
| 644 |  |  |  |  |  |  |  | 
| 645 |  |  |  |  |  |  | # PanasonicRaw composite tags | 
| 646 |  |  |  |  |  |  | %Image::ExifTool::PanasonicRaw::Composite = ( | 
| 647 |  |  |  |  |  |  | ImageWidth => { | 
| 648 |  |  |  |  |  |  | Require => { | 
| 649 |  |  |  |  |  |  | 0 => 'IFD0:SensorLeftBorder', | 
| 650 |  |  |  |  |  |  | 1 => 'IFD0:SensorRightBorder', | 
| 651 |  |  |  |  |  |  | }, | 
| 652 |  |  |  |  |  |  | ValueConv => '$val[1] - $val[0]', | 
| 653 |  |  |  |  |  |  | }, | 
| 654 |  |  |  |  |  |  | ImageHeight => { | 
| 655 |  |  |  |  |  |  | Require => { | 
| 656 |  |  |  |  |  |  | 0 => 'IFD0:SensorTopBorder', | 
| 657 |  |  |  |  |  |  | 1 => 'IFD0:SensorBottomBorder', | 
| 658 |  |  |  |  |  |  | }, | 
| 659 |  |  |  |  |  |  | ValueConv => '$val[1] - $val[0]', | 
| 660 |  |  |  |  |  |  | }, | 
| 661 |  |  |  |  |  |  | ); | 
| 662 |  |  |  |  |  |  |  | 
| 663 |  |  |  |  |  |  | # add our composite tags | 
| 664 |  |  |  |  |  |  | Image::ExifTool::AddCompositeTags('Image::ExifTool::PanasonicRaw'); | 
| 665 |  |  |  |  |  |  |  | 
| 666 |  |  |  |  |  |  |  | 
| 667 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 668 |  |  |  |  |  |  | # checksum algorithm for lens distortion correction information (ref 3) | 
| 669 |  |  |  |  |  |  | # Inputs: 0) data ref, 1) start position, 2) number of bytes, 3) incement | 
| 670 |  |  |  |  |  |  | # Returns: checksum value | 
| 671 |  |  |  |  |  |  | sub Checksum($$$$) | 
| 672 |  |  |  |  |  |  | { | 
| 673 | 12 |  |  | 12 | 0 | 22 | my ($dataPt, $start, $num, $inc) = @_; | 
| 674 | 12 |  |  |  |  | 17 | my $csum = 0; | 
| 675 | 12 |  |  |  |  | 16 | my $i; | 
| 676 | 12 |  |  |  |  | 29 | for ($i=0; $i<$num; ++$i) { | 
| 677 | 156 |  |  |  |  | 271 | $csum = (73 * $csum + Get8u($dataPt, $start + $i * $inc)) % 0xffef; | 
| 678 |  |  |  |  |  |  | } | 
| 679 | 12 |  |  |  |  | 45 | return $csum; | 
| 680 |  |  |  |  |  |  | } | 
| 681 |  |  |  |  |  |  |  | 
| 682 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 683 |  |  |  |  |  |  | # Read lens distortion information | 
| 684 |  |  |  |  |  |  | # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref | 
| 685 |  |  |  |  |  |  | # Returns: 1 on success | 
| 686 |  |  |  |  |  |  | sub ProcessDistortionInfo($$$) | 
| 687 |  |  |  |  |  |  | { | 
| 688 | 2 |  |  | 2 | 0 | 7 | my ($et, $dirInfo, $tagTablePtr) = @_; | 
| 689 | 2 |  |  |  |  | 7 | my $dataPt = $$dirInfo{DataPt}; | 
| 690 | 2 |  | 50 |  |  | 11 | my $start = $$dirInfo{DirStart} || 0; | 
| 691 | 2 |  | 33 |  |  | 13 | my $size = $$dirInfo{DirLen} || (length($$dataPt) - $start); | 
| 692 | 2 | 50 |  |  |  | 6 | if ($size == 32) { | 
| 693 |  |  |  |  |  |  | # verify the checksums (ref 3) | 
| 694 | 2 |  |  |  |  | 10 | my $csum1 = Checksum($dataPt, $start +  4, 12, 1); | 
| 695 | 2 |  |  |  |  | 7 | my $csum2 = Checksum($dataPt, $start + 16, 12, 1); | 
| 696 | 2 |  |  |  |  | 6 | my $csum3 = Checksum($dataPt, $start +  2, 14, 2); | 
| 697 | 2 |  |  |  |  | 7 | my $csum4 = Checksum($dataPt, $start +  3, 14, 2); | 
| 698 | 2 |  |  |  |  | 8 | my $res = $csum1 ^ Get16u($dataPt, $start + 2) ^ | 
| 699 |  |  |  |  |  |  | $csum2 ^ Get16u($dataPt, $start + 28) ^ | 
| 700 |  |  |  |  |  |  | $csum3 ^ Get16u($dataPt, $start + 0) ^ | 
| 701 |  |  |  |  |  |  | $csum4 ^ Get16u($dataPt, $start + 30); | 
| 702 | 2 | 50 |  |  |  | 9 | $et->Warn('Invalid DistortionInfo checksum',1) if $res; | 
| 703 |  |  |  |  |  |  | } else { | 
| 704 | 0 |  |  |  |  | 0 | $et->Warn('Invalid DistortionInfo',1); | 
| 705 |  |  |  |  |  |  | } | 
| 706 | 2 |  |  |  |  | 13 | return $et->ProcessBinaryData($dirInfo, $tagTablePtr); | 
| 707 |  |  |  |  |  |  | } | 
| 708 |  |  |  |  |  |  |  | 
| 709 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 710 |  |  |  |  |  |  | # Write lens distortion information | 
| 711 |  |  |  |  |  |  | # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref | 
| 712 |  |  |  |  |  |  | # Returns: updated distortion information or undef on error | 
| 713 |  |  |  |  |  |  | sub WriteDistortionInfo($$$) | 
| 714 |  |  |  |  |  |  | { | 
| 715 | 9 |  |  | 9 | 0 | 18 | my ($et, $dirInfo, $tagTablePtr) = @_; | 
| 716 | 9 | 100 |  |  |  | 34 | $et or return 1;  # (allow dummy access) | 
| 717 | 1 |  |  |  |  | 7 | my $dat = $et->WriteBinaryData($dirInfo, $tagTablePtr); | 
| 718 | 1 | 50 | 33 |  |  | 9 | if (defined $dat and length($dat) == 32) { | 
| 719 |  |  |  |  |  |  | # fix checksums (ref 3) | 
| 720 | 1 |  |  |  |  | 6 | Set16u(Checksum(\$dat,  4, 12, 1), \$dat,  2); | 
| 721 | 1 |  |  |  |  | 5 | Set16u(Checksum(\$dat, 16, 12, 1), \$dat, 28); | 
| 722 | 1 |  |  |  |  | 3 | Set16u(Checksum(\$dat,  2, 14, 2), \$dat,  0); | 
| 723 | 1 |  |  |  |  | 4 | Set16u(Checksum(\$dat,  3, 14, 2), \$dat, 30); | 
| 724 |  |  |  |  |  |  | } else { | 
| 725 | 0 |  |  |  |  | 0 | $et->Warn('Error wriing DistortionInfo',1); | 
| 726 |  |  |  |  |  |  | } | 
| 727 | 1 |  |  |  |  | 4 | return $dat; | 
| 728 |  |  |  |  |  |  | } | 
| 729 |  |  |  |  |  |  |  | 
| 730 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 731 |  |  |  |  |  |  | # Patch for writing non-standard Panasonic RAW/RW2/RWL raw data | 
| 732 |  |  |  |  |  |  | # Inputs: 0) offset info ref, 1) raf ref, 2) IFD number | 
| 733 |  |  |  |  |  |  | # Returns: error string, or undef on success | 
| 734 |  |  |  |  |  |  | # OffsetInfo is a hash by tag ID of lists with the following elements: | 
| 735 |  |  |  |  |  |  | #  0 - tag info ref | 
| 736 |  |  |  |  |  |  | #  1 - pointer to int32u offset in IFD or value data | 
| 737 |  |  |  |  |  |  | #  2 - value count | 
| 738 |  |  |  |  |  |  | #  3 - reference to list of original offset values | 
| 739 |  |  |  |  |  |  | #  4 - IFD format number | 
| 740 |  |  |  |  |  |  | sub PatchRawDataOffset($$$) | 
| 741 |  |  |  |  |  |  | { | 
| 742 | 1 |  |  | 1 | 0 | 5 | my ($offsetInfo, $raf, $ifd) = @_; | 
| 743 | 1 |  |  |  |  | 4 | my $stripOffsets = $$offsetInfo{0x111}; | 
| 744 | 1 |  |  |  |  | 3 | my $stripByteCounts = $$offsetInfo{0x117}; | 
| 745 | 1 |  |  |  |  | 3 | my $rawDataOffset = $$offsetInfo{0x118}; | 
| 746 | 1 |  |  |  |  | 3 | my $err; | 
| 747 | 1 | 50 |  |  |  | 5 | $err = 1 unless $ifd == 0; | 
| 748 | 1 | 50 | 33 |  |  | 11 | $err = 1 unless $stripOffsets and $stripByteCounts and $$stripOffsets[2] == 1; | 
|  |  |  | 33 |  |  |  |  | 
| 749 | 1 | 50 |  |  |  | 3 | if ($rawDataOffset) { | 
| 750 | 1 | 50 |  |  |  | 5 | $err = 1 unless $$rawDataOffset[2] == 1; | 
| 751 | 1 | 50 | 33 |  |  | 6 | $err = 1 unless $$stripOffsets[3][0] == 0xffffffff or $$stripByteCounts[3][0] == 0; | 
| 752 |  |  |  |  |  |  | } | 
| 753 | 1 | 50 |  |  |  | 3 | $err and return 'Unsupported Panasonic/Leica RAW variant'; | 
| 754 | 1 | 50 |  |  |  | 4 | if ($rawDataOffset) { | 
| 755 |  |  |  |  |  |  | # update StripOffsets along with this tag if it contains a reasonable value | 
| 756 | 1 | 50 |  |  |  | 7 | unless ($$stripOffsets[3][0] == 0xffffffff) { | 
| 757 |  |  |  |  |  |  | # save pointer to StripOffsets value for updating later | 
| 758 | 0 |  |  |  |  | 0 | push @$rawDataOffset, $$stripOffsets[1]; | 
| 759 |  |  |  |  |  |  | } | 
| 760 |  |  |  |  |  |  | # handle via RawDataOffset instead of StripOffsets | 
| 761 | 1 |  |  |  |  | 4 | $stripOffsets = $$offsetInfo{0x111} = $rawDataOffset; | 
| 762 | 1 |  |  |  |  | 3 | delete $$offsetInfo{0x118}; | 
| 763 |  |  |  |  |  |  | } | 
| 764 |  |  |  |  |  |  | # determine the length of the raw data | 
| 765 | 1 |  |  |  |  | 7 | my $pos = $raf->Tell(); | 
| 766 | 1 | 50 |  |  |  | 6 | $raf->Seek(0, 2) or $err = 1; # seek to end of file | 
| 767 | 1 |  |  |  |  | 5 | my $len = $raf->Tell() - $$stripOffsets[3][0]; | 
| 768 | 1 |  |  |  |  | 4 | $raf->Seek($pos, 0); | 
| 769 |  |  |  |  |  |  | # quick check to be sure the raw data length isn't unreasonable | 
| 770 |  |  |  |  |  |  | # (the 22-byte length is for '' in our tests) | 
| 771 | 1 | 50 | 33 |  |  | 13 | $err = 1 if ($len < 1000 and $len != 22) or $len & 0x80000000; | 
|  |  |  | 33 |  |  |  |  | 
| 772 | 1 | 50 |  |  |  | 4 | $err and return 'Error reading Panasonic raw data'; | 
| 773 |  |  |  |  |  |  | # update StripByteCounts info with raw data length | 
| 774 |  |  |  |  |  |  | # (note that the original value is maintained in the file) | 
| 775 | 1 |  |  |  |  | 3 | $$stripByteCounts[3][0] = $len; | 
| 776 |  |  |  |  |  |  |  | 
| 777 | 1 |  |  |  |  | 4 | return undef; | 
| 778 |  |  |  |  |  |  | } | 
| 779 |  |  |  |  |  |  |  | 
| 780 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 781 |  |  |  |  |  |  | # Write meta information to Panasonic JpgFromRaw in RAW/RW2/RWL image | 
| 782 |  |  |  |  |  |  | # Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref | 
| 783 |  |  |  |  |  |  | # Returns: updated image data, or undef if nothing changed | 
| 784 |  |  |  |  |  |  | sub WriteJpgFromRaw($$$) | 
| 785 |  |  |  |  |  |  | { | 
| 786 | 1 |  |  | 1 | 0 | 4 | my ($et, $dirInfo, $tagTablePtr) = @_; | 
| 787 | 1 |  |  |  |  | 4 | my $dataPt = $$dirInfo{DataPt}; | 
| 788 | 1 |  |  |  |  | 17 | my $byteOrder = GetByteOrder(); | 
| 789 | 1 |  |  |  |  | 6 | my $fileType = $$et{TIFF_TYPE};   # RAW, RW2 or RWL | 
| 790 | 1 |  |  |  |  | 2 | my $dirStart = $$dirInfo{DirStart}; | 
| 791 | 1 | 50 |  |  |  | 5 | if ($dirStart) { # DirStart is non-zero in DNG-converted RW2/RWL | 
| 792 | 0 |  |  |  |  | 0 | my $dirLen = $$dirInfo{DirLen} | length($$dataPt) - $dirStart; | 
| 793 | 0 |  |  |  |  | 0 | my $buff = substr($$dataPt, $dirStart, $dirLen); | 
| 794 | 0 |  |  |  |  | 0 | $dataPt = \$buff; | 
| 795 |  |  |  |  |  |  | } | 
| 796 | 1 |  |  |  |  | 7 | my $raf = new File::RandomAccess($dataPt); | 
| 797 | 1 |  |  |  |  | 2 | my $outbuff; | 
| 798 | 1 |  |  |  |  | 4 | my %dirInfo = ( | 
| 799 |  |  |  |  |  |  | RAF => $raf, | 
| 800 |  |  |  |  |  |  | OutFile => \$outbuff, | 
| 801 |  |  |  |  |  |  | ); | 
| 802 | 1 |  |  |  |  | 4 | $$et{BASE} = $$dirInfo{DataPos}; | 
| 803 | 1 |  |  |  |  | 4 | $$et{FILE_TYPE} = $$et{TIFF_TYPE} = 'JPEG'; | 
| 804 |  |  |  |  |  |  | # use a specialized map so we don't write XMP or IPTC (or other junk) into the JPEG | 
| 805 | 1 |  |  |  |  | 3 | my $editDirs = $$et{EDIT_DIRS}; | 
| 806 | 1 |  |  |  |  | 3 | my $addDirs = $$et{ADD_DIRS}; | 
| 807 | 1 |  |  |  |  | 6 | $et->InitWriteDirs(\%jpgFromRawMap); | 
| 808 |  |  |  |  |  |  | # don't add XMP segment (IPTC won't get added because it is in Photoshop record) | 
| 809 | 1 |  |  |  |  | 3 | delete $$et{ADD_DIRS}{XMP}; | 
| 810 | 1 |  |  |  |  | 6 | my $result = $et->WriteJPEG(\%dirInfo); | 
| 811 |  |  |  |  |  |  | # restore variables we changed | 
| 812 | 1 |  |  |  |  | 5 | $$et{BASE} = 0; | 
| 813 | 1 |  |  |  |  | 4 | $$et{FILE_TYPE} = 'TIFF'; | 
| 814 | 1 |  |  |  |  | 5 | $$et{TIFF_TYPE} = $fileType; | 
| 815 | 1 |  |  |  |  | 7 | $$et{EDIT_DIRS} = $editDirs; | 
| 816 | 1 |  |  |  |  | 4 | $$et{ADD_DIRS} = $addDirs; | 
| 817 | 1 |  |  |  |  | 7 | SetByteOrder($byteOrder); | 
| 818 | 1 | 50 |  |  |  | 13 | return $result > 0 ? $outbuff : $$dataPt; | 
| 819 |  |  |  |  |  |  | } | 
| 820 |  |  |  |  |  |  |  | 
| 821 |  |  |  |  |  |  | #------------------------------------------------------------------------------ | 
| 822 |  |  |  |  |  |  | # Extract meta information from an Panasonic JpgFromRaw | 
| 823 |  |  |  |  |  |  | # Inputs: 0) ExifTool object reference, 1) dirInfo reference | 
| 824 |  |  |  |  |  |  | # Returns: 1 on success, 0 if this wasn't a valid JpgFromRaw image | 
| 825 |  |  |  |  |  |  | sub ProcessJpgFromRaw($$$) | 
| 826 |  |  |  |  |  |  | { | 
| 827 | 2 |  |  | 2 | 0 | 8 | my ($et, $dirInfo, $tagTablePtr) = @_; | 
| 828 | 2 |  |  |  |  | 9 | my $dataPt = $$dirInfo{DataPt}; | 
| 829 | 2 |  |  |  |  | 7 | my $byteOrder = GetByteOrder(); | 
| 830 | 2 |  |  |  |  | 5 | my $fileType = $$et{TIFF_TYPE};   # RAW, RW2 or RWL | 
| 831 | 2 |  |  |  |  | 6 | my $tagInfo = $$dirInfo{TagInfo}; | 
| 832 | 2 |  |  |  |  | 11 | my $verbose = $et->Options('Verbose'); | 
| 833 | 2 |  |  |  |  | 4 | my ($indent, $out); | 
| 834 | 2 | 50 |  |  |  | 9 | $tagInfo or $et->Warn('No tag info for Panasonic JpgFromRaw'), return 0; | 
| 835 | 2 |  |  |  |  | 7 | my $dirStart = $$dirInfo{DirStart}; | 
| 836 | 2 | 50 |  |  |  | 7 | if ($dirStart) { # DirStart is non-zero in DNG-converted RW2/RWL | 
| 837 | 0 |  |  |  |  | 0 | my $dirLen = $$dirInfo{DirLen} | length($$dataPt) - $dirStart; | 
| 838 | 0 |  |  |  |  | 0 | my $buff = substr($$dataPt, $dirStart, $dirLen); | 
| 839 | 0 |  |  |  |  | 0 | $dataPt = \$buff; | 
| 840 |  |  |  |  |  |  | } | 
| 841 | 2 |  | 50 |  |  | 15 | $$et{BASE} = $$dirInfo{DataPos} + ($dirStart || 0); | 
| 842 | 2 |  |  |  |  | 25 | $$et{FILE_TYPE} = $$et{TIFF_TYPE} = 'JPEG'; | 
| 843 | 2 |  |  |  |  | 7 | $$et{DOC_NUM} = 1; | 
| 844 |  |  |  |  |  |  | # extract information from embedded JPEG | 
| 845 | 2 |  |  |  |  | 22 | my %dirInfo = ( | 
| 846 |  |  |  |  |  |  | Parent => 'RAF', | 
| 847 |  |  |  |  |  |  | RAF    => new File::RandomAccess($dataPt), | 
| 848 |  |  |  |  |  |  | ); | 
| 849 | 2 | 50 |  |  |  | 8 | if ($verbose) { | 
| 850 | 0 |  |  |  |  | 0 | my $indent = $$et{INDENT}; | 
| 851 | 0 |  |  |  |  | 0 | $$et{INDENT} = '  '; | 
| 852 | 0 |  |  |  |  | 0 | $out = $et->Options('TextOut'); | 
| 853 | 0 |  |  |  |  | 0 | print $out '--- DOC1:JpgFromRaw ',('-'x56),"\n"; | 
| 854 |  |  |  |  |  |  | } | 
| 855 |  |  |  |  |  |  | # fudge HtmlDump base offsets to show as a stand-alone JPEG | 
| 856 | 2 |  |  |  |  | 7 | $$et{BASE_FUDGE} = $$et{BASE}; | 
| 857 | 2 |  |  |  |  | 12 | my $rtnVal = $et->ProcessJPEG(\%dirInfo); | 
| 858 | 2 |  |  |  |  | 6 | $$et{BASE_FUDGE} = 0; | 
| 859 |  |  |  |  |  |  | # restore necessary variables for continued RW2/RWL processing | 
| 860 | 2 |  |  |  |  | 8 | $$et{BASE} = 0; | 
| 861 | 2 |  |  |  |  | 7 | $$et{FILE_TYPE} = 'TIFF'; | 
| 862 | 2 |  |  |  |  | 6 | $$et{TIFF_TYPE} = $fileType; | 
| 863 | 2 |  |  |  |  | 8 | delete $$et{DOC_NUM}; | 
| 864 | 2 |  |  |  |  | 11 | SetByteOrder($byteOrder); | 
| 865 | 2 | 50 |  |  |  | 6 | if ($verbose) { | 
| 866 | 0 |  |  |  |  | 0 | $$et{INDENT} = $indent; | 
| 867 | 0 |  |  |  |  | 0 | print $out ('-'x76),"\n"; | 
| 868 |  |  |  |  |  |  | } | 
| 869 | 2 |  |  |  |  | 15 | return $rtnVal; | 
| 870 |  |  |  |  |  |  | } | 
| 871 |  |  |  |  |  |  |  | 
| 872 |  |  |  |  |  |  | 1;  # end | 
| 873 |  |  |  |  |  |  |  | 
| 874 |  |  |  |  |  |  | __END__ |