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__ |