File Coverage

blib/lib/Image/ExifTool/Samsung.pm
Criterion Covered Total %
statement 98 198 49.4
branch 39 110 35.4
condition 25 73 34.2
subroutine 6 10 60.0
pod 0 6 0.0
total 168 397 42.3


line stmt bran cond sub pod time code
1             #------------------------------------------------------------------------------
2             # File: Samsung.pm
3             #
4             # Description: Samsung EXIF maker notes tags
5             #
6             # Revisions: 2010/03/01 - P. Harvey Created
7             #
8             # References: 1) Tae-Sun Park private communication
9             # 2) http://www.cybercom.net/~dcoffin/dcraw/
10             # 3) Pascal de Bruijn private communication (NX100)
11             # 4) Jaroslav Stepanek via rt.cpan.org
12             # 5) Nick Livchits private communication
13             # 6) Sreerag Raghavan private communication (SM-C200)
14             # IB) Iliah Borg private communication (LibRaw)
15             # NJ) Niels Kristian Bech Jensen private communication
16             #------------------------------------------------------------------------------
17              
18             package Image::ExifTool::Samsung;
19              
20 14     14   115 use strict;
  14         41  
  14         571  
21 14     14   103 use vars qw($VERSION %samsungLensTypes);
  14         29  
  14         4253  
22 14     14   119 use Image::ExifTool qw(:DataAccess :Utils);
  14         46  
  14         3062  
23 14     14   138 use Image::ExifTool::Exif;
  14         36  
  14         66206  
24              
25             $VERSION = '1.53';
26              
27             sub WriteSTMN($$$);
28             sub ProcessINFO($$$);
29             sub ProcessSamsungMeta($$$);
30             sub ProcessSamsungIFD($$$);
31             sub ProcessSamsung($$$);
32              
33             # Samsung LensType lookup
34             %samsungLensTypes = (
35             # (added "Samsung NX" in all of these lens names - ref 4)
36             0 => 'Built-in or Manual Lens', #PH (EX1, WB2000)
37             1 => 'Samsung NX 30mm F2 Pancake',
38             2 => 'Samsung NX 18-55mm F3.5-5.6 OIS', # (also version II, ref 1)
39             3 => 'Samsung NX 50-200mm F4-5.6 ED OIS',
40             # what about the non-OIS version of the 18-55,
41             # which was supposed to be available before the 20-50? - PH
42             4 => 'Samsung NX 20-50mm F3.5-5.6 ED', #PH/4
43             5 => 'Samsung NX 20mm F2.8 Pancake', #PH
44             6 => 'Samsung NX 18-200mm F3.5-6.3 ED OIS', #4
45             7 => 'Samsung NX 60mm F2.8 Macro ED OIS SSA', #1
46             8 => 'Samsung NX 16mm F2.4 Pancake', #1/4
47             9 => 'Samsung NX 85mm F1.4 ED SSA', #4
48             10 => 'Samsung NX 45mm F1.8', #3
49             11 => 'Samsung NX 45mm F1.8 2D/3D', #3
50             12 => 'Samsung NX 12-24mm F4-5.6 ED', #4
51             13 => 'Samsung NX 16-50mm F2-2.8 S ED OIS', #forum3833
52             14 => 'Samsung NX 10mm F3.5 Fisheye', #NJ
53             15 => 'Samsung NX 16-50mm F3.5-5.6 Power Zoom ED OIS', #5
54             20 => 'Samsung NX 50-150mm F2.8 S ED OIS', #PH
55             21 => 'Samsung NX 300mm F2.8 ED OIS', #IB
56             );
57              
58             # range of values for Formats used in encrypted information
59             my %formatMinMax = (
60             int16u => [ 0, 65535 ],
61             int32u => [ 0, 4294967295 ],
62             int16s => [ -32768, 32767 ],
63             int32s => [ -2147483648, 2147483647 ],
64             );
65              
66             # Samsung "STMN" maker notes (ref PH)
67             %Image::ExifTool::Samsung::Main = (
68             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
69             WRITE_PROC => \&WriteSTMN,
70             CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
71             WRITABLE => 1,
72             FORMAT => 'int32u',
73             FIRST_ENTRY => 0,
74             IS_OFFSET => [ 2 ], # tag 2 is 'IsOffset'
75             IS_SUBDIR => [ 11 ],
76             GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
77             NOTES => q{
78             Tags found in the binary "STMN" format maker notes written by a number of
79             Samsung models.
80             },
81             0 => {
82             Name => 'MakerNoteVersion',
83             Format => 'undef[8]',
84             },
85             2 => {
86             Name => 'PreviewImageStart',
87             OffsetPair => 3, # associated byte count tagID
88             DataTag => 'PreviewImage',
89             IsOffset => 3,
90             Protected => 2,
91             WriteGroup => 'MakerNotes',
92             },
93             3 => {
94             Name => 'PreviewImageLength',
95             OffsetPair => 2, # point to associated offset
96             DataTag => 'PreviewImage',
97             Protected => 2,
98             WriteGroup => 'MakerNotes',
99             },
100             11 => {
101             Name => 'SamsungIFD',
102             # Note: this is not always an IFD. In many models the string
103             # "Park Byeongchan" is found at this location
104             Condition => '$$valPt =~ /^[^\0]\0\0\0/',
105             Format => 'undef[$size - 44]',
106             SubDirectory => { TagTable => 'Image::ExifTool::Samsung::IFD' },
107             },
108             );
109              
110             %Image::ExifTool::Samsung::IFD = (
111             PROCESS_PROC => \&ProcessSamsungIFD,
112             NOTES => q{
113             This is a standard-format IFD found in the maker notes of some Samsung
114             models, except that the entry count is a 4-byte integer and the offsets are
115             relative to the end of the IFD. Currently, no tags in this IFD are known,
116             so the L (-u) or L (-v) option must be used to see this
117             information.
118             },
119             GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
120             # 0x0001 - undef[4000|4100]: starts with "MN_PRV" (or all zeros)
121             # 0x0002 - undef[7000] : starts with "Kim Miae"
122             # 0x0003 - undef[5000] : starts with "Lee BK"
123             # 0x0004 - undef[500|2000] : starts with "IPCD" (or all zeros)
124             # 0x0006 - undef[100|200] : starts with "MN_ADS" (or all zeros)
125             );
126              
127             # Samsung maker notes (ref PH)
128             %Image::ExifTool::Samsung::Type2 = (
129             WRITE_PROC => \&Image::ExifTool::Exif::WriteExif,
130             CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
131             WRITABLE => 1,
132             GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
133             NOTES => 'Tags found in the EXIF-format maker notes of newer Samsung models.',
134             0x0001 => {
135             Name => 'MakerNoteVersion',
136             Writable => 'undef',
137             Count => 4,
138             },
139             0x0002 => {
140             Name => 'DeviceType',
141             Groups => { 2 => 'Camera' },
142             Writable => 'int32u',
143             PrintHex => 1,
144             PrintConv => {
145             0x1000 => 'Compact Digital Camera',
146             0x2000 => 'High-end NX Camera',
147             0x3000 => 'HXM Video Camera',
148             0x12000 => 'Cell Phone',
149             0x300000 => 'SMX Video Camera',
150             },
151             },
152             0x0003 => {
153             Name => 'SamsungModelID',
154             Groups => { 2 => 'Camera' },
155             Writable => 'int32u',
156             PrintHex => 1,
157             PrintConv => {
158             0x100101c => 'NX10',
159             0x1001226 => 'HMX-S10BP',
160             0x1001226 => 'HMX-S15BP',
161             0x1001233 => 'HMX-Q10',
162             0x1001234 => 'HMX-H300',
163             0x1001234 => 'HMX-H304',
164             0x100130c => 'NX100',
165             0x1001327 => 'NX11',
166             0x170104b => 'ES65, ES67 / VLUU ES65, ES67 / SL50',
167             0x170104e => 'ES70, ES71 / VLUU ES70, ES71 / SL600',
168             0x1701052 => 'ES73 / VLUU ES73 / SL605',
169             0x1701055 => 'ES25, ES27 / VLUU ES25, ES27 / SL45',
170             0x1701300 => 'ES28 / VLUU ES28',
171             0x1701303 => 'ES74,ES75,ES78 / VLUU ES75,ES78',
172             0x2001046 => 'PL150 / VLUU PL150 / TL210 / PL151',
173             0x2001048 => 'PL100 / TL205 / VLUU PL100 / PL101',
174             0x2001311 => 'PL120,PL121 / VLUU PL120,PL121',
175             0x2001315 => 'PL170,PL171 / VLUUPL170,PL171',
176             0x200131e => 'PL210, PL211 / VLUU PL210, PL211',
177             0x2701317 => 'PL20,PL21 / VLUU PL20,PL21',
178             0x2a0001b => 'WP10 / VLUU WP10 / AQ100',
179             0x3000000 => 'Various Models (0x3000000)',
180             #0x3000000 => 'DV150F / DV151F / DV155F',
181             #0x3000000 => 'NX mini',
182             #0x3000000 => 'NX3000',
183             #0x3000000 => 'NX3300',
184             #0x3000000 => 'ST150F / ST151F / ST152F',
185             #0x3000000 => 'WB200F / WB201F / WB202F',
186             #0x3000000 => 'WB250F / WB251F / WB252F',
187             #0x3000000 => 'WB30F / WB31F / WB32F',
188             #0x3000000 => 'WB350F / WB351F / WB352F',
189             #0x3000000 => 'WB800F',
190             0x3a00018 => 'Various Models (0x3a00018)',
191             #0x3a00018 => 'ES30 / VLUU ES30',
192             #0x3a00018 => 'ES80 / ES81',
193             #0x3a00018 => 'ES9 / ES8',
194             #0x3a00018 => 'PL200 / VLUU PL200',
195             #0x3a00018 => 'PL80 / VLUU PL80 / SL630 / PL81',
196             #0x3a00018 => 'PL90 / VLUU PL90',
197             #0x3a00018 => 'WB1100F / WB1101F / WB1102F',
198             #0x3a00018 => 'WB2200F',
199             0x400101f => 'ST1000 / ST1100 / VLUU ST1000 / CL65',
200             0x4001022 => 'ST550 / VLUU ST550 / TL225',
201             0x4001025 => 'Various Models (0x4001025)',
202             #0x4001025 => 'DV300 / DV300F / DV305F',
203             #0x4001025 => 'ST500 / VLUU ST500 / TL220',
204             #0x4001025 => 'ST200 / ST200F / ST201 / ST201F / ST205F',
205             0x400103e => 'VLUU ST5500, ST5500, CL80',
206             0x4001041 => 'VLUU ST5000, ST5000, TL240',
207             0x4001043 => 'ST70 / VLUU ST70 / ST71',
208             0x400130a => 'Various Models (0x400130a)',
209             #0x400130a => 'VLUU ST100, ST100',
210             #0x400130a => 'VLUU ST600, ST600',
211             #0x400130a => 'VLUU ST80, ST80',
212             0x400130e => 'ST90,ST91 / VLUU ST90,ST91',
213             0x4001313 => 'VLUU ST95, ST95',
214             0x4a00015 => 'VLUU ST60',
215             0x4a0135b => 'ST30, ST65 / VLUU ST65 / ST67',
216             0x5000000 => 'Various Models (0x5000000)',
217             #0x5000000 => 'EX2F',
218             #0x5000000 => 'NX1000',
219             #0x5000000 => 'NX20',
220             #0x5000000 => 'NX200',
221             #0x5000000 => 'NX210',
222             #0x5000000 => 'ST96',
223             #0x5000000 => 'WB750',
224             #0x5000000 => 'ST700',
225             0x5001038 => 'Various Models (0x5001038)',
226             #0x5001038 => 'EK-GN120',
227             #0x5001038 => 'HMX-E10',
228             #0x5001038 => 'NX1',
229             #0x5001038 => 'NX2000',
230             #0x5001038 => 'NX30',
231             #0x5001038 => 'NX300',
232             #0x5001038 => 'NX500',
233             #0x5001038 => 'SM-C200',
234             #0x5001038 => 'WB2000',
235             0x500103a => 'WB650 / VLUU WB650 / WB660',
236             0x500103c => 'WB600 / VLUU WB600 / WB610',
237             0x500133e => 'WB150 / WB150F / WB152 / WB152F / WB151',
238             0x5a0000f => 'WB5000 / HZ25W',
239             0x5a0001e => 'WB5500 / VLUU WB5500 / HZ50W',
240             0x6001036 => 'EX1',
241             0x700131c => 'VLUU SH100, SH100',
242             0x27127002 => 'SMX-C20N',
243             },
244             },
245             # 0x0004 - undef[x] (SamsungContentsID?)
246             # 0x000a - int32u (ContinuousShotMode?)
247             # 0x000b - int16u (BestPhotoMode?)
248             # 0x000c - int32u ? values: 0,1
249             # 0x000e - int32u[2] (SoundMultiPicture?)
250             # 0x0010 - rational64u ? values: undef,inf
251             0x0011 => { #6
252             Name => 'OrientationInfo',
253             SubDirectory => { TagTable => 'Image::ExifTool::Samsung::OrientationInfo' },
254             },
255             0x0020 => [{ #forum7685
256             Name => 'SmartAlbumColor',
257             Condition => '$$valPt =~ /^\0{4}/',
258             Writable => 'int16u',
259             Count => 2,
260             PrintConv => {
261             '0 0' => 'n/a',
262             },
263             },{
264             Name => 'SmartAlbumColor',
265             Writable => 'int16u',
266             Count => 2,
267             PrintConv => [{
268             0 => 'Red',
269             1 => 'Yellow',
270             2 => 'Green',
271             3 => 'Blue',
272             4 => 'Magenta',
273             5 => 'Black',
274             6 => 'White',
275             7 => 'Various',
276             }],
277             }],
278             0x0021 => { #1
279             Name => 'PictureWizard',
280             Writable => 'int16u',
281             SubDirectory => { TagTable => 'Image::ExifTool::Samsung::PictureWizard' },
282             },
283             # 0x0022 - int32u (CaptureMode?) (Gamma? eg. 65538 = 1.2, ref forum7720)
284             # 0x0023 - string: "0123456789" (PH) (placeholder for SerialNumber?)
285             # 0x0025 - int32u (ImageCount?)
286             # 0x002a - undef[4] (SNSDirectShare?)
287             # 0x002f - string (GPSInfo01?)
288             0x0030 => { #1 (NX100 with GPS)
289             Name => 'LocalLocationName',
290             Groups => { 2 => 'Location' },
291             Writable => 'string',
292             Format => 'undef',
293             # this contains 2 place names (in Korean if in Korea), separated by a null+space
294             # - terminate at double-null and replace nulls with newlines
295             ValueConv => '$val=~s/\0\0.*//; $val=~s/\0 */\n/g; $val',
296             ValueConvInv => '$val=~s/(\x0d\x0a|\x0d|\x0a)/\0 /g; $val . "\0\0"'
297             },
298             0x0031 => { #1 (NX100 with GPS)
299             Name => 'LocationName',
300             Groups => { 2 => 'Location' },
301             Writable => 'string',
302             },
303             # 0x0032 - string (GPSInfo03)
304             # 0x0033 - string (GPSInfo04)
305             # 0x0034 - string (GPSInfo05)
306             0x0035 => [{
307             Name => 'PreviewIFD',
308             Condition => '$$self{TIFF_TYPE} eq "SRW" and $$self{Model} ne "EK-GN120"', # (not an IFD in JPEG images)
309             Groups => { 1 => 'PreviewIFD' },
310             Flags => 'SubIFD',
311             SubDirectory => {
312             TagTable => 'Image::ExifTool::Nikon::PreviewIFD',
313             ByteOrder => 'Unknown',
314             Start => '$val',
315             },
316             },{
317             Name => 'PreviewIFD',
318             Condition => '$$self{TIFF_TYPE} eq "SRW"', # (not an IFD in JPEG images)
319             Groups => { 1 => 'PreviewIFD' },
320             Flags => 'SubIFD',
321             SubDirectory => {
322             TagTable => 'Image::ExifTool::Nikon::PreviewIFD',
323             ByteOrder => 'Unknown',
324             Start => '$val - 36',
325             },
326             }],
327             # 0x003a - int16u[2] (SmartLensInfo?)
328             # 0x003b - int16u[2] (PhotoStyleSelectInfo?)
329             # 0x003c - int16u (SmartRange?)
330             # 0x003d - int16u[5] (SmartCropInfo?)
331             # 0x003e - int32u (DualCapture?)
332             # 0x003f - int16u[2] (SGIFInfo?)
333             0x0040 => { #forum7432
334             Name => 'RawDataByteOrder',
335             PrintConv => {
336             0 => 'Little-endian (Intel, II)',
337             1 => 'Big-endian (Motorola, MM)', #(NC)
338             },
339             },
340             0x0041 => { #forum7684
341             Name => 'WhiteBalanceSetup',
342             Writable => 'int32u',
343             PrintConv => {
344             0 => 'Auto',
345             1 => 'Manual',
346             },
347             },
348             0x0043 => { #1 (NC)
349             Name => 'CameraTemperature',
350             Groups => { 2 => 'Camera' },
351             Writable => 'rational64s',
352             # (DPreview samples all 0.2 C --> pre-production model)
353             PrintConv => '$val =~ /\d/ ? "$val C" : $val',
354             PrintConvInv => '$val=~s/ ?C//; $val',
355             },
356             # 0x0045 => { Name => 'RawCompressionMode', Writable => 'int32u' }, # (related to ExposureMode, not raw compresison? ref forum7432)
357             # 0x004a - int32u[7] (ImageVerification?)
358             # 0x004b - int32u[2] (RewindInfo?)
359             # 0x0050 - int32u (ColorSpace? - inconsistent) values: 1 (related to compression mode, ref forum7432)
360             0x0050 => { #forum7432
361             Name => 'RawDataCFAPattern',
362             PrintConv => {
363             0 => 'Unchanged',
364             1 => 'Swap',
365             65535 => 'Roll',
366             },
367             },
368             # 0x0054 - int16u[2] (WeatherInfo?)
369             # 0x0060 - undef (AEInfo?)
370             # 0x0080 - undef (AFInfo?)
371             # 0x00a0 - undef[8192] (AWBInfo1): white balance information (ref 1):
372             # At byte 5788, the WBAdjust: "Adjust\0\X\0\Y\0\Z\xee\xea\xce\xab", where
373             # Y = BA adjust (0=Blue7, 7=0, 14=Amber7), Z = MG (0=Magenta7, 7=0, 14=Green7)
374             # 0x00a1 - undef (AWBInfo2?)
375             # 0x00c0 - undef (IPCInfo?)
376             # 0x00c7 - undef (SmartFunctionInfo?)
377             # 0x00e0 - int16u (SceneResult?)
378             # 0x00e1 - int16u[8] (SADebugInfo01?)
379             # 0x00e1 - int16u[x] (SADebugInfo02?)
380             0x0100 => {
381             Name => 'FaceDetect',
382             Writable => 'int16u',
383             PrintConv => { 0 => 'Off', 1 => 'On' }, #(NC)
384             },
385             # 0x0101 - int16u[6] (FaceDetectInfo?)
386             # 0x0102 - int16u[x] (FaceDetectInfo?)
387             0x0120 => {
388             Name => 'FaceRecognition',
389             Writable => 'int32u',
390             PrintConv => { 0 => 'Off', 1 => 'On' }, #(NC)
391             },
392             0x0123 => { Name => 'FaceName', Writable => 'string' },
393             # 0x140 - undef (LensInfo?)
394             #
395             # the following tags found only in SRW images
396             #
397             # 0xa000 - rational64u: 1 or 1.1 (ref PH) (MakerNoteVersion?)
398             0xa001 => { #1
399             Name => 'FirmwareName',
400             Groups => { 2 => 'Camera' },
401             Writable => 'string',
402             },
403             0xa002 => { #PH/IB
404             Name => 'SerialNumber',
405             Condition => '$$valPt =~ /^\w{5}/', # should be at least 5 characters long
406             Groups => { 2 => 'Camera' },
407             Writable => 'string',
408             },
409             0xa003 => { #1 (SRW images only)
410             Name => 'LensType',
411             Groups => { 2 => 'Camera' },
412             Writable => 'int16u',
413             Count => -1,
414             PrintConv => [ \%samsungLensTypes ],
415             },
416             0xa004 => { #1
417             Name => 'LensFirmware',
418             Groups => { 2 => 'Camera' },
419             Writable => 'string',
420             },
421             0xa005 => {
422             Name => 'InternalLensSerialNumber', # Not the printed serial number (ref 1)
423             Groups => { 2 => 'Camera' },
424             Writable => 'string',
425             },
426             0xa010 => { #1
427             Name => 'SensorAreas',
428             Groups => { 2 => 'Camera' },
429             Notes => 'full and valid sensor areas',
430             Writable => 'int32u',
431             Count => 8,
432             },
433             0xa011 => { #1
434             Name => 'ColorSpace',
435             Writable => 'int16u',
436             PrintConv => {
437             0 => 'sRGB',
438             1 => 'Adobe RGB',
439             },
440             },
441             0xa012 => { #1
442             Name => 'SmartRange',
443             Writable => 'int16u',
444             PrintConv => { 0 => 'Off', 1 => 'On' },
445             },
446             0xa013 => { #1
447             Name => 'ExposureCompensation',
448             Writable => 'rational64s',
449             },
450             0xa014 => { #1
451             Name => 'ISO',
452             Writable => 'int32u',
453             },
454             0xa018 => { #1
455             Name => 'ExposureTime',
456             Writable => 'rational64u',
457             ValueConv => '$val=~s/ .*//; $val', # some models write 2 values here
458             ValueConvInv => '$val',
459             PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
460             PrintConvInv => '$val',
461             },
462             0xa019 => { #1
463             Name => 'FNumber',
464             Priority => 0,
465             Writable => 'rational64u',
466             ValueConv => '$val=~s/ .*//; $val', # some models write 2 values here
467             ValueConvInv => '$val',
468             PrintConv => 'sprintf("%.1f",$val)',
469             PrintConvInv => '$val',
470             },
471             0xa01a => { #1
472             Name => 'FocalLengthIn35mmFormat',
473             Groups => { 2 => 'Camera' },
474             Priority => 0,
475             Format => 'int32u',
476             ValueConv => '$val / 10',
477             ValueConvInv => '$val * 10',
478             PrintConv => '"$val mm"',
479             PrintConvInv => '$val=~s/\s*mm$//;$val',
480             },
481             # 0xa01b - int32u (ImageCount?)
482             # 0xa01b - int16u (LDCLens?)
483             0xa020 => { #1
484             Name => 'EncryptionKey',
485             Writable => 'int32u',
486             Count => 11,
487             Protected => 1,
488             DataMember => 'EncryptionKey',
489             RawConv => '$$self{EncryptionKey} = [ split(" ",$val) ]; $val',
490             Notes => 'key used to decrypt the tags below',
491             # value is "305 72 737 456 282 307 519 724 13 505 193"
492             },
493             0xa021 => { #1
494             Name => 'WB_RGGBLevelsUncorrected',
495             Writable => 'int32u',
496             Count => 4,
497             Notes => 'these tags not corrected for WB_RGGBLevelsBlack',
498             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")',
499             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0)',
500             },
501             0xa022 => { #1
502             Name => 'WB_RGGBLevelsAuto',
503             Writable => 'int32u',
504             Count => 4,
505             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-4)',
506             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,4)',
507             },
508             0xa023 => { #1
509             Name => 'WB_RGGBLevelsIlluminator1',
510             Writable => 'int32u',
511             Count => 4,
512             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-8)',
513             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,8)',
514             },
515             0xa024 => { #1
516             Name => 'WB_RGGBLevelsIlluminator2',
517             Writable => 'int32u',
518             Count => 4,
519             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-1)',
520             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,1)',
521             },
522             0xa025 => { # (PostAEGain?)
523             Name => 'DigitalGain', #IB
524             Writable => 'int32u',
525             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,6)',
526             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-6)',
527             },
528             0xa025 => { #IB
529             Name => 'HighlightLinearityLimit',
530             Writable => 'int32u',
531             },
532             0xa028 => { #2/PH
533             Name => 'WB_RGGBLevelsBlack',
534             Writable => 'int32s',
535             Count => 4,
536             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")',
537             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0)',
538             },
539             0xa030 => { #1
540             Name => 'ColorMatrix',
541             Writable => 'int32s',
542             Count => 9,
543             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0)',
544             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")',
545             },
546             0xa031 => { #1
547             Name => 'ColorMatrixSRGB',
548             Writable => 'int32s',
549             Count => 9,
550             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0)',
551             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")',
552             },
553             0xa032 => { #1
554             Name => 'ColorMatrixAdobeRGB',
555             Writable => 'int32s',
556             Count => 9,
557             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0)',
558             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")',
559             },
560             0xa033 => { #1
561             Name => 'CbCrMatrixDefault',
562             Writable => 'int32s',
563             Count => 4,
564             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0)',
565             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")',
566             },
567             0xa034 => { #1
568             Name => 'CbCrMatrix',
569             Writable => 'int32s',
570             Count => 4,
571             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,4)',
572             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-4)',
573             },
574             0xa035 => { #1
575             Name => 'CbCrGainDefault',
576             Writable => 'int32u',
577             Count => 2,
578             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")',
579             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0)',
580             },
581             0xa036 => { #1
582             Name => 'CbCrGain',
583             Writable => 'int32u',
584             Count => 2,
585             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-2)',
586             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,2)',
587             },
588             0xa040 => { #1
589             Name => 'ToneCurveSRGBDefault',
590             Writable => 'int32u',
591             Count => 23,
592             Notes => q{
593             first value gives the number of tone curve entries. This is followed by an
594             array of X coordinates then an array of Y coordinates
595             },
596             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0,"-0")',
597             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0",0)',
598             },
599             0xa041 => { #1
600             Name => 'ToneCurveAdobeRGBDefault',
601             Writable => 'int32u',
602             Count => 23,
603             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0,"-0")',
604             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0",0)',
605             },
606             0xa042 => { #1
607             Name => 'ToneCurveSRGB',
608             Writable => 'int32u',
609             Count => 23,
610             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0,"-0")',
611             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0",0)',
612             },
613             0xa043 => { #1
614             Name => 'ToneCurveAdobeRGB',
615             Writable => 'int32u',
616             Count => 23,
617             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0,"-0")',
618             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0",0)',
619             },
620             0xa048 => { #1
621             Name => 'RawData',
622             Unknown => 1,
623             Writable => 'int32s',
624             Count => 12,
625             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0)',
626             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")',
627             },
628             0xa050 => { #1
629             Name => 'Distortion',
630             Unknown => 1,
631             Writable => 'int32s',
632             Count => 8,
633             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0)',
634             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")',
635             },
636             0xa051 => { #1
637             Name => 'ChromaticAberration',
638             Unknown => 1,
639             Writable => 'int16u',
640             Count => 22,
641             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0",-7,-3)',
642             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0,7,3)',
643             },
644             0xa052 => { #1
645             Name => 'Vignetting',
646             Unknown => 1,
647             Writable => 'int16u',
648             Count => 15,
649             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0,"-0")',
650             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0",0)',
651             },
652             0xa053 => { #1
653             Name => 'VignettingCorrection',
654             Unknown => 1,
655             Writable => 'int16u',
656             Count => 15,
657             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0,"-0")',
658             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0",0)',
659             },
660             0xa054 => { #1
661             Name => 'VignettingSetting',
662             Unknown => 1,
663             Writable => 'int16u',
664             Count => 15,
665             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0,"-0")',
666             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0",0)',
667             },
668             0xa055 => { #1
669             Name => 'Samsung_Type2_0xa055', # (DistortionCamera1st?)
670             Unknown => 1,
671             Hidden => 1,
672             Writable => 'int32s',
673             Count => 8,
674             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,8)',
675             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-8)',
676             },
677             0xa056 => { #1
678             Name => 'Samsung_Type2_0xa056', # (DistortionCamera2nd?)
679             Unknown => 1,
680             Hidden => 1,
681             Writable => 'int32s',
682             Count => 8,
683             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,5)',
684             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-5)',
685             },
686             0xa057 => { #1
687             Name => 'Samsung_Type2_0xa057', # (DistortionCameraSetting?)
688             Unknown => 1,
689             Hidden => 1,
690             Writable => 'int32s',
691             Count => 8,
692             RawConv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,2)',
693             RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-2)',
694             },
695             # 0xa060 - rational64u (CISTemperature?)
696             # 0xa061 - int16u (Compression?)
697             );
698              
699             # orientation information (ref 6)
700             %Image::ExifTool::Samsung::OrientationInfo = (
701             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
702             WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
703             CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
704             WRITABLE => 1,
705             FORMAT => 'rational64s',
706             FIRST_ENTRY => 0,
707             GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
708             NOTES => 'Camera orientation information written by the Gear 360 (SM-C200).',
709             0 => {
710             Name => 'YawAngle', #(NC)
711             Unknown => 1,
712             Notes => 'always zero',
713             },
714             1 => {
715             Name => 'PitchAngle',
716             Notes => 'upward tilt of rear camera in degrees',
717             },
718             2 => {
719             Name => 'RollAngle',
720             Notes => 'clockwise rotation of rear camera in degrees',
721             },
722             );
723              
724             # Picture Wizard information (ref 1)
725             %Image::ExifTool::Samsung::PictureWizard = (
726             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
727             WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
728             CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
729             WRITABLE => 1,
730             FORMAT => 'int16u',
731             FIRST_ENTRY => 0,
732             GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
733             0 => {
734             Name => 'PictureWizardMode',
735             PrintConvColumns => 3,
736             PrintConv => { #3
737             0 => 'Standard',
738             1 => 'Vivid',
739             2 => 'Portrait',
740             3 => 'Landscape',
741             4 => 'Forest',
742             5 => 'Retro',
743             6 => 'Cool',
744             7 => 'Calm',
745             8 => 'Classic',
746             9 => 'Custom1',
747             10 => 'Custom2',
748             11 => 'Custom3',
749             255 => 'n/a', #PH
750             },
751             },
752             1 => 'PictureWizardColor',
753             2 => {
754             Name => 'PictureWizardSaturation',
755             ValueConv => '$val - 4',
756             ValueConvInv => '$val + 4',
757             },
758             3 => {
759             Name => 'PictureWizardSharpness',
760             ValueConv => '$val - 4',
761             ValueConvInv => '$val + 4',
762             },
763             4 => {
764             Name => 'PictureWizardContrast',
765             ValueConv => '$val - 4',
766             ValueConvInv => '$val + 4',
767             },
768             );
769              
770             # INFO tags in Samsung MP4 videos (ref PH)
771             %Image::ExifTool::Samsung::INFO = (
772             PROCESS_PROC => \&ProcessINFO,
773             GROUPS => { 0 => 'MakerNotes', 2 => 'Video' },
774             NOTES => q{
775             This information is found in MP4 videos from Samsung models such as the
776             SMX-C20N.
777             },
778             EFCT => 'Effect', # (guess)
779             QLTY => 'Quality',
780             # MDEL - value: 0
781             # ASPT - value: 1, 2
782             );
783              
784             # Samsung MP4 TAGS information (PH - from WP10 sample)
785             # --> very similar to Sanyo MP4 information
786             %Image::ExifTool::Samsung::MP4 = (
787             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
788             GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
789             NOTES => q{
790             This information is found in Samsung MP4 videos from models such as the
791             WP10.
792             },
793             0x00 => {
794             Name => 'Make',
795             Format => 'string[24]',
796             PrintConv => 'ucfirst(lc($val))',
797             },
798             0x18 => {
799             Name => 'Model',
800             Description => 'Camera Model Name',
801             Format => 'string[16]',
802             },
803             0x2e => { #(NC)
804             Name => 'ExposureTime',
805             Format => 'int32u',
806             ValueConv => '$val ? 10 / $val : 0',
807             PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
808             },
809             0x32 => {
810             Name => 'FNumber',
811             Format => 'rational64u',
812             PrintConv => 'sprintf("%.1f",$val)',
813             },
814             0x3a => { #(NC)
815             Name => 'ExposureCompensation',
816             Format => 'rational64s',
817             PrintConv => '$val ? sprintf("%+.1f", $val) : 0',
818             },
819             0x6a => {
820             Name => 'ISO',
821             Format => 'int32u',
822             },
823             0x7d => {
824             Name => 'Software',
825             Format => 'string[32]',
826             # (these tags are not at a constant offset for Olympus/Sanyo videos,
827             # so just to be safe use this to validate subsequent tags)
828             RawConv => q{
829             $val =~ /^SAMSUNG/ or return undef;
830             $$self{SamsungMP4} = 1;
831             return $val;
832             },
833             },
834             0xf4 => {
835             Name => 'Thumbnail',
836             Condition => '$$self{SamsungMP4}',
837             SubDirectory => {
838             TagTable => 'Image::ExifTool::Samsung::Thumbnail',
839             Base => '$start',
840             },
841             },
842             );
843              
844             # thumbnail image information found in MP4 videos (similar in Olympus,Samsung,Sanyo)
845             %Image::ExifTool::Samsung::Thumbnail = (
846             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
847             GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
848             FIRST_ENTRY => 0,
849             FORMAT => 'int32u',
850             1 => 'ThumbnailWidth',
851             2 => 'ThumbnailHeight',
852             3 => 'ThumbnailLength',
853             4 => { Name => 'ThumbnailOffset', IsOffset => 1 },
854             );
855              
856             # Samsung MP4 @sec information (PH - from WB30F sample)
857             %Image::ExifTool::Samsung::sec = (
858             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
859             GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
860             NOTES => q{
861             This information is found in the @sec atom of Samsung MP4 videos from models
862             such as the WB30F.
863             },
864             0x00 => {
865             Name => 'Make',
866             Format => 'string[32]',
867             PrintConv => 'ucfirst(lc($val))',
868             },
869             0x20 => {
870             Name => 'Model',
871             Description => 'Camera Model Name',
872             Format => 'string[32]',
873             },
874             0x200 => { Name => 'ThumbnailWidth', Format => 'int32u' },
875             0x204 => { Name => 'ThumbnailHeight', Format => 'int32u' },
876             0x208 => { Name => 'ThumbnailLength', Format => 'int32u' }, # (2 bytes too long in my sample)
877             0x20c => {
878             Name => 'ThumbnailImage',
879             Groups => { 2 => 'Preview' },
880             Format => 'undef[$val{0x208}]',
881             Notes => 'the THM image, embedded metadata is extracted as the first sub-document',
882             SetBase => 1,
883             RawConv => q{
884             my $pt = $self->ValidateImage(\$val, $tag);
885             if ($pt) {
886             $$self{BASE} += 0x20c;
887             $$self{DOC_NUM} = ++$$self{DOC_COUNT};
888             $self->ExtractInfo($pt, { ReEntry => 1 });
889             $$self{DOC_NUM} = 0;
890             }
891             return $pt;
892             },
893             },
894             );
895              
896             # Samsung MP4 smta information (PH - from SM-C101 sample)
897             %Image::ExifTool::Samsung::smta = (
898             GROUPS => { 0 => 'MakerNotes', 2 => 'Video' },
899             NOTES => q{
900             This information is found in the smta atom of Samsung MP4 videos from models
901             such as the Galaxy S4.
902             },
903             svss => {
904             Name => 'SamsungSvss',
905             SubDirectory => { TagTable => 'Image::ExifTool::Samsung::svss' },
906             },
907             # swtr - 4 bytes, all zero
908             # scid - 8 bytes, all zero
909             # saut - 4 bytes, all zero
910             );
911              
912             # Samsung MP4 svss information (PH - from SM-C101 sample)
913             %Image::ExifTool::Samsung::svss = (
914             GROUPS => { 0 => 'MakerNotes', 2 => 'Video' },
915             NOTES => q{
916             This information is found in the svss atom of Samsung MP4 videos from models
917             such as the Galaxy S4.
918             },
919             # junk - 10240 bytes, all zero
920             );
921              
922             # thumbnail image information found in some MP4 videos
923             %Image::ExifTool::Samsung::Thumbnail2 = (
924             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
925             GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
926             FIRST_ENTRY => 0,
927             FORMAT => 'int32u',
928             1 => 'ThumbnailWidth',
929             2 => 'ThumbnailHeight',
930             3 => 'ThumbnailLength',
931             4 => { Name => 'ThumbnailOffset', IsOffset => 1 },
932             );
933              
934             # information extracted from "ssuniqueid\0" APP5 (ref PH)
935             %Image::ExifTool::Samsung::APP5 = (
936             GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
937             ssuniqueid => {
938             Name => 'UniqueID',
939             # 32 bytes - some sort of serial number?
940             ValueConv => 'unpack("H*",$val)',
941             },
942             );
943              
944             # information extracted from Samsung trailer (ie. Samsung SM-T805 "Sound & Shot" JPEG) (ref PH)
945             %Image::ExifTool::Samsung::Trailer = (
946             GROUPS => { 0 => 'MakerNotes', 2 => 'Other' },
947             VARS => { NO_ID => 1, HEX_ID => 0 },
948             PROCESS_PROC => \&ProcessSamsung,
949             PRIORITY => 0, # (first one takes priority so DepthMapWidth/Height match first DepthMapData)
950             NOTES => q{
951             Tags extracted from the trailer of JPEG images written when using certain
952             features (such as "Sound & Shot" or "Shot & More") from Samsung models such
953             as the Galaxy S4 and Tab S, and from the 'sefd' atom in HEIC images from the
954             Samsung S10+.
955             },
956             '0x0001-name' => {
957             Name => 'EmbeddedImageName', # ("DualShot_1","DualShot_2")
958             RawConv => '$$self{EmbeddedImageName} = $val',
959             },
960             '0x0001' => [
961             {
962             Name => 'EmbeddedImage',
963             Condition => '$$self{EmbeddedImageName} eq "DualShot_1"',
964             Groups => { 2 => 'Preview' },
965             Binary => 1,
966             },
967             {
968             Name => 'EmbeddedImage2',
969             Groups => { 2 => 'Preview' },
970             Binary => 1,
971             },
972             ],
973             '0x0100-name' => 'EmbeddedAudioFileName', # ("SoundShot_000")
974             '0x0100' => { Name => 'EmbeddedAudioFile', Groups => { 2 => 'Audio' }, Binary => 1 },
975             '0x0201-name' => 'SurroundShotVideoName', # ("Interactive_Panorama_000")
976             '0x0201' => { Name => 'SurroundShotVideo', Groups => { 2 => 'Video' }, Binary => 1 },
977             # 0x0800-name - seen 'SoundShot_Meta_Info'
978             # 0x0800 - unknown (29 bytes) (contains already-extracted EmbeddedAudioFileName)
979             # 0x0830-name - seen '1165724808.pre'
980             # 0x0830 - unknown (164004 bytes)
981             # 0x08d0-name - seen 'Interactive_Panorama_Info'
982             # 0x08d0 - unknown (7984 bytes)
983             # 0x08e0-name - seen 'Panorama_Shot_Info'
984             # 0x08e0 - string, seen 'PanoramaShot'
985             # 0x08e1-name - seen 'Motion_Panorama_Info'
986             # 0x0910-name - seen 'Front_Cam_Selfie_Info'
987             # 0x0910 - string, seen 'Front_Cam_Selfie_Info'
988             # 0x09e0-name - seen 'Burst_Shot_Info'
989             # 0x09e0 - string, seen '489489125'
990             # 0x0a01-name - seen 'Image_UTC_Data'
991             '0x0a01' => { #forum7161
992             Name => 'TimeStamp',
993             Groups => { 2 => 'Time' },
994             ValueConv => 'ConvertUnixTime($val / 1e3, 1, 3)',
995             PrintConv => '$self->ConvertDateTime($val)',
996             },
997             '0x0a20-name' => 'DualCameraImageName', # ("FlipPhoto_002")
998             '0x0a20' => { Name => 'DualCameraImage', Groups => { 2 => 'Preview' }, Binary => 1 },
999             '0x0a30-name' => 'EmbeddedVideoType', # ("MotionPhoto_Data")
1000             '0x0a30' => { Name => 'EmbeddedVideoFile', Groups => { 2 => 'Video' }, Binary => 1 }, #forum7161
1001             # 0x0aa1-name - seen 'MCC_Data'
1002             # 0x0aa1 - seen '204','222','234','302','429'
1003             '0x0aa1' => {
1004             Name => 'MCCData',
1005             Groups => { 2 => 'Location' },
1006             PrintConv => {
1007             202 => 'Greece',
1008             204 => 'Netherlands',
1009             206 => 'Belgium',
1010             208 => 'France',
1011             212 => 'Monaco',
1012             213 => 'Andorra',
1013             214 => 'Spain',
1014             216 => 'Hungary',
1015             218 => 'Bosnia & Herzegov.',
1016             219 => 'Croatia',
1017             220 => 'Serbia',
1018             221 => 'Kosovo',
1019             222 => 'Italy',
1020             226 => 'Romania',
1021             228 => 'Switzerland',
1022             230 => 'Czech Rep.',
1023             231 => 'Slovakia',
1024             232 => 'Austria',
1025             234 => 'United Kingdom',
1026             235 => 'United Kingdom',
1027             238 => 'Denmark',
1028             240 => 'Sweden',
1029             242 => 'Norway',
1030             244 => 'Finland',
1031             246 => 'Lithuania',
1032             247 => 'Latvia',
1033             248 => 'Estonia',
1034             250 => 'Russian Federation',
1035             255 => 'Ukraine',
1036             257 => 'Belarus',
1037             259 => 'Moldova',
1038             260 => 'Poland',
1039             262 => 'Germany',
1040             266 => 'Gibraltar',
1041             268 => 'Portugal',
1042             270 => 'Luxembourg',
1043             272 => 'Ireland',
1044             274 => 'Iceland',
1045             276 => 'Albania',
1046             278 => 'Malta',
1047             280 => 'Cyprus',
1048             282 => 'Georgia',
1049             283 => 'Armenia',
1050             284 => 'Bulgaria',
1051             286 => 'Turkey',
1052             288 => 'Faroe Islands',
1053             289 => 'Abkhazia',
1054             290 => 'Greenland',
1055             292 => 'San Marino',
1056             293 => 'Slovenia',
1057             294 => 'Macedonia',
1058             295 => 'Liechtenstein',
1059             297 => 'Montenegro',
1060             302 => 'Canada',
1061             308 => 'St. Pierre & Miquelon',
1062             310 => 'United States / Guam',
1063             311 => 'United States / Guam',
1064             312 => 'United States',
1065             316 => 'United States',
1066             330 => 'Puerto Rico',
1067             334 => 'Mexico',
1068             338 => 'Jamaica',
1069             340 => 'French Guiana / Guadeloupe / Martinique',
1070             342 => 'Barbados',
1071             344 => 'Antigua and Barbuda',
1072             346 => 'Cayman Islands',
1073             348 => 'British Virgin Islands',
1074             350 => 'Bermuda',
1075             352 => 'Grenada',
1076             354 => 'Montserrat',
1077             356 => 'Saint Kitts and Nevis',
1078             358 => 'Saint Lucia',
1079             360 => 'St. Vincent & Gren.',
1080             362 => 'Bonaire, Sint Eustatius and Saba / Curacao / Netherlands Antilles',
1081             363 => 'Aruba',
1082             364 => 'Bahamas',
1083             365 => 'Anguilla',
1084             366 => 'Dominica',
1085             368 => 'Cuba',
1086             370 => 'Dominican Republic',
1087             372 => 'Haiti',
1088             374 => 'Trinidad and Tobago',
1089             376 => 'Turks and Caicos Islands / US Virgin Islands',
1090             400 => 'Azerbaijan',
1091             401 => 'Kazakhstan',
1092             402 => 'Bhutan',
1093             404 => 'India',
1094             405 => 'India',
1095             410 => 'Pakistan',
1096             412 => 'Afghanistan',
1097             413 => 'Sri Lanka',
1098             414 => 'Myanmar (Burma)',
1099             415 => 'Lebanon',
1100             416 => 'Jordan',
1101             417 => 'Syrian Arab Republic',
1102             418 => 'Iraq',
1103             419 => 'Kuwait',
1104             420 => 'Saudi Arabia',
1105             421 => 'Yemen',
1106             422 => 'Oman',
1107             424 => 'United Arab Emirates',
1108             425 => 'Israel / Palestinian Territory',
1109             426 => 'Bahrain',
1110             427 => 'Qatar',
1111             428 => 'Mongolia',
1112             429 => 'Nepal',
1113             430 => 'United Arab Emirates',
1114             431 => 'United Arab Emirates',
1115             432 => 'Iran',
1116             434 => 'Uzbekistan',
1117             436 => 'Tajikistan',
1118             437 => 'Kyrgyzstan',
1119             438 => 'Turkmenistan',
1120             440 => 'Japan',
1121             441 => 'Japan',
1122             450 => 'South Korea',
1123             452 => 'Viet Nam',
1124             454 => 'Hongkong, China',
1125             455 => 'Macao, China',
1126             456 => 'Cambodia',
1127             457 => 'Laos P.D.R.',
1128             460 => 'China',
1129             466 => 'Taiwan',
1130             467 => 'North Korea',
1131             470 => 'Bangladesh',
1132             472 => 'Maldives',
1133             502 => 'Malaysia',
1134             505 => 'Australia',
1135             510 => 'Indonesia',
1136             514 => 'Timor-Leste',
1137             515 => 'Philippines',
1138             520 => 'Thailand',
1139             525 => 'Singapore',
1140             528 => 'Brunei Darussalam',
1141             530 => 'New Zealand',
1142             537 => 'Papua New Guinea',
1143             539 => 'Tonga',
1144             540 => 'Solomon Islands',
1145             541 => 'Vanuatu',
1146             542 => 'Fiji',
1147             544 => 'American Samoa',
1148             545 => 'Kiribati',
1149             546 => 'New Caledonia',
1150             547 => 'French Polynesia',
1151             548 => 'Cook Islands',
1152             549 => 'Samoa',
1153             550 => 'Micronesia',
1154             552 => 'Palau',
1155             553 => 'Tuvalu',
1156             555 => 'Niue',
1157             602 => 'Egypt',
1158             603 => 'Algeria',
1159             604 => 'Morocco',
1160             605 => 'Tunisia',
1161             606 => 'Libya',
1162             607 => 'Gambia',
1163             608 => 'Senegal',
1164             609 => 'Mauritania',
1165             610 => 'Mali',
1166             611 => 'Guinea',
1167             612 => 'Ivory Coast',
1168             613 => 'Burkina Faso',
1169             614 => 'Niger',
1170             615 => 'Togo',
1171             616 => 'Benin',
1172             617 => 'Mauritius',
1173             618 => 'Liberia',
1174             619 => 'Sierra Leone',
1175             620 => 'Ghana',
1176             621 => 'Nigeria',
1177             622 => 'Chad',
1178             623 => 'Central African Rep.',
1179             624 => 'Cameroon',
1180             625 => 'Cape Verde',
1181             626 => 'Sao Tome & Principe',
1182             627 => 'Equatorial Guinea',
1183             628 => 'Gabon',
1184             629 => 'Congo, Republic',
1185             630 => 'Congo, Dem. Rep.',
1186             631 => 'Angola',
1187             632 => 'Guinea-Bissau',
1188             633 => 'Seychelles',
1189             634 => 'Sudan',
1190             635 => 'Rwanda',
1191             636 => 'Ethiopia',
1192             637 => 'Somalia',
1193             638 => 'Djibouti',
1194             639 => 'Kenya',
1195             640 => 'Tanzania',
1196             641 => 'Uganda',
1197             642 => 'Burundi',
1198             643 => 'Mozambique',
1199             645 => 'Zambia',
1200             646 => 'Madagascar',
1201             647 => 'Reunion',
1202             648 => 'Zimbabwe',
1203             649 => 'Namibia',
1204             650 => 'Malawi',
1205             651 => 'Lesotho',
1206             652 => 'Botswana',
1207             653 => 'Swaziland',
1208             654 => 'Comoros',
1209             655 => 'South Africa',
1210             657 => 'Eritrea',
1211             659 => 'South Sudan',
1212             702 => 'Belize',
1213             704 => 'Guatemala',
1214             706 => 'El Salvador',
1215             708 => 'Honduras',
1216             710 => 'Nicaragua',
1217             712 => 'Costa Rica',
1218             714 => 'Panama',
1219             716 => 'Peru',
1220             722 => 'Argentina Republic',
1221             724 => 'Brazil',
1222             730 => 'Chile',
1223             732 => 'Colombia',
1224             734 => 'Venezuela',
1225             736 => 'Bolivia',
1226             738 => 'Guyana',
1227             740 => 'Ecuador',
1228             744 => 'Paraguay',
1229             746 => 'Suriname',
1230             748 => 'Uruguay',
1231             750 => 'Falkland Islands (Malvinas)',
1232             901 => 'International Networks / Satellite Networks',
1233             },
1234             },
1235             # 0x0ab0-name - seen 'DualShot_Meta_Info'
1236             '0x0ab1-name' => {
1237             Name => 'DepthMapName',
1238             # seen 'DualShot_DepthMap_1' (SM-N950U), DualShot_DepthMap_5 (SM-G998W)
1239             RawConv => '$$self{DepthMapName} = $val',
1240             },
1241             '0x0ab1' => [
1242             {
1243             Name => 'DepthMapData',
1244             Condition => '$$self{DepthMapName} eq "DualShot_DepthMap_1"',
1245             Binary => 1,
1246             },{
1247             Name => 'DepthMapData2',
1248             Binary => 1,
1249             },
1250             ],
1251             # 0x0ab3-name - seen 'DualShot_Extra_Info' (SM-N950U)
1252             '0x0ab3' => { # (SM-N950U)
1253             Name => 'DualShotExtra',
1254             SubDirectory => { TagTable => 'Image::ExifTool::Samsung::DualShotExtra' },
1255             },
1256             # 0x0ac0-name - seen 'ZoomInOut_Info' (SM-N950U)
1257             # 0x0ac0 - 2048 bytes of interesting stuff including firmware version? (SM-N950U)
1258             '0x0b40' => { # (SM-N975X front camera)
1259             Name => 'SingleShotMeta',
1260             SubDirectory => { TagTable => 'Image::ExifTool::Samsung::SingleShotMeta' },
1261             },
1262             # 0x0b41-name - seen 'SingeShot_DepthMap_1' (Yes, "Singe") (SM-N975X front camera)
1263             '0x0b41' => { Name => 'SingleShotDepthMap', Binary => 1 },
1264             # 0xa050-name - seen 'Jpeg360_2D_Info' (Samsung Gear 360)
1265             # 0xa050 - seen 'Jpeg3602D' (Samsung Gear 360)
1266             );
1267              
1268             # DualShot Extra Info (ref PH)
1269             %Image::ExifTool::Samsung::DualShotExtra = (
1270             PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
1271             GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
1272             FIRST_ENTRY => 0,
1273             FORMAT => 'int32u',
1274             # This is a pain, but the DepthMapWidth/Height move around in this record.
1275             # In all of my samples so far, the bytes "01 00 ff ff" precede these tags.
1276             # I have seen this byte sequence at offsets 32, 60, 64 and 68, so look for
1277             # it in bytes 32-95, and use its location to adjust the tag positions
1278             8 => {
1279             Name => 'DualShotDummy',
1280             Format => 'undef[64]',
1281             Hidden => 1,
1282             Hook => q{
1283             if ($size >= 96) {
1284             my $tmp = substr($$dataPt, $pos, 64);
1285             # (have seen 0x01,0x03 and 0x07)
1286             if ($tmp =~ /[\x01-\x09]\0\xff\xff/g and not pos($tmp) % 4) {
1287             $$self{DepthMapTagPos} = pos($tmp);
1288             $varSize += $$self{DepthMapTagPos} - 32;
1289             }
1290             }
1291             },
1292             RawConv => 'undef', # not a real tag
1293             },
1294             16 => {
1295             Name => 'DepthMapWidth',
1296             Condition => '$$self{DepthMapTagPos}',
1297             Notes => 'index varies depending on model',
1298             },
1299             17 => {
1300             Name => 'DepthMapHeight',
1301             Condition => '$$self{DepthMapTagPos}',
1302             Notes => 'index varies depending on model',
1303             },
1304             );
1305              
1306             # SingleShot Meta Info (ref PH) (SM-N975X front camera)
1307             %Image::ExifTool::Samsung::SingleShotMeta = (
1308             PROCESS_PROC => \&ProcessSamsungMeta,
1309             GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
1310             inputWidth => { },
1311             inputHeight => { },
1312             outputWidth => { },
1313             outputHeight => { },
1314             segWidth => { },
1315             segHeight => { },
1316             depthSWWidth => { },
1317             depthSWHeight => { },
1318             depthHWWidth => { },
1319             depthHWHeight => { },
1320             flipStatus => { },
1321             lensFacing => { },
1322             deviceOrientation => { },
1323             objectOrientation => { },
1324             isArtBokeh => { },
1325             beautyRetouchLevel => { },
1326             beautyColorLevel => { },
1327             effectType => { },
1328             effectStrength => { },
1329             blurStrength => { },
1330             spinStrength => { },
1331             zoomStrength => { },
1332             colorpopStrength => { },
1333             monoStrength => { },
1334             sidelightStrength => { },
1335             vintageStrength => { },
1336             bokehShape => { },
1337             perfMode => { },
1338             );
1339              
1340             # Samsung composite tags
1341             %Image::ExifTool::Samsung::Composite = (
1342             GROUPS => { 2 => 'Image' },
1343             WB_RGGBLevels => {
1344             Require => {
1345             0 => 'WB_RGGBLevelsUncorrected',
1346             1 => 'WB_RGGBLevelsBlack',
1347             },
1348             ValueConv => q{
1349             my @a = split ' ', $val[0];
1350             my @b = split ' ', $val[1];
1351             $a[$_] -= $b[$_] foreach 0..$#a;
1352             return "@a";
1353             },
1354             },
1355             DepthMapTiff => {
1356             Require => {
1357             0 => 'DepthMapData',
1358             1 => 'DepthMapWidth',
1359             2 => 'DepthMapHeight',
1360             },
1361             ValueConv => q{
1362             return undef unless length ${$val[0]} == $val[1] * $val[2];
1363             my $tiff = MakeTiffHeader($val[1],$val[2],1,8) . ${$val[0]};
1364             return \$tiff;
1365             },
1366             },
1367             SingleShotDepthMapTiff => {
1368             Require => {
1369             0 => 'SingleShotDepthMap',
1370             1 => 'SegWidth',
1371             2 => 'SegHeight',
1372             },
1373             ValueConv => q{
1374             return undef unless length ${$val[0]} == $val[1] * $val[2];
1375             my $tiff = MakeTiffHeader($val[1],$val[2],1,8) . ${$val[0]};
1376             return \$tiff;
1377             },
1378             },
1379             );
1380              
1381             # add our composite tags
1382             Image::ExifTool::AddCompositeTags('Image::ExifTool::Samsung');
1383              
1384             #------------------------------------------------------------------------------
1385             # Encrypt/Decrypt NX10 information
1386             # Inputs: 0) ExifTool ref, 1) value as a string of integers,
1387             # 2) tagInfo hash ref, 3-N) encryption salt values
1388             # Returns: encrypted/decrypted value
1389             # Notes:
1390             # 1) The encryption salt starts with '-' to reverse the encryption algorithm
1391             # 2) Additional salt values are provided when tag stores multiple arrays
1392             # (in which case the first value of the tag gives the array length)
1393             sub Crypt($$$@)
1394             {
1395 0     0 0 0 my ($et, $val, $tagInfo, @salt) = @_;
1396 0 0       0 my $key = $$et{EncryptionKey} or return undef;
1397 0 0 0     0 my $format = $$tagInfo{Writable} || $$tagInfo{Format} or return undef;
1398 0 0       0 return undef unless $formatMinMax{$format};
1399 0         0 my ($min, $max) = @{$formatMinMax{$format}};
  0         0  
1400 0         0 my @a = split ' ', $val;
1401 0 0       0 my $newSalt = (@salt > 1) ? 1 : 0; # skip length entry if this is an array
1402 0         0 my ($i, $sign, $salt, $start);
1403 0         0 for ($i=$newSalt; $i<@a; ++$i) {
1404 0 0       0 if ($i == $newSalt) {
1405 0         0 $start = $i;
1406 0         0 $salt = shift @salt;
1407 0 0       0 $sign = ($salt =~ s/^-//) ? -1 : 1;
1408 0 0       0 $newSalt += $a[0] if @salt;
1409             }
1410 0         0 $a[$i] += $sign * $$key[($salt+$i-$start) % scalar(@$key)];
1411             # handle integer wrap-around
1412 0 0       0 if ($sign > 0) {
1413 0 0       0 $a[$i] -= $max - $min + 1 if $a[$i] > $max;
1414             } else {
1415 0 0       0 $a[$i] += $max - $min + 1 if $a[$i] < $min;
1416             }
1417             }
1418 0         0 return "@a";
1419             }
1420              
1421             #------------------------------------------------------------------------------
1422             # Process Samsung MP4 INFO data
1423             # Inputs: 0) ExifTool ref, 1) dirInfo ref, 2) tag table ref
1424             # Returns: 1 on success
1425             sub ProcessINFO($$$)
1426             {
1427 0     0 0 0 my ($et, $dirInfo, $tagTablePtr) = @_;
1428 0         0 my $dataPt = $$dirInfo{DataPt};
1429 0         0 my $pos = $$dirInfo{DirStart};
1430 0         0 my $len = $$dirInfo{DirLen};
1431 0         0 my $end = $pos + $len;
1432 0         0 $et->VerboseDir('INFO', undef, $len);
1433 0         0 while ($pos + 8 <= $end) {
1434 0         0 my $tag = substr($$dataPt, $pos, 4);
1435 0         0 my $val = Get32u($dataPt, $pos + 4);
1436 0 0       0 unless ($$tagTablePtr{$tag}) {
1437 0         0 my $name = "Samsung_INFO_$tag";
1438 0         0 $name =~ tr/-_0-9a-zA-Z//dc;
1439 0 0       0 AddTagToTable($tagTablePtr, $tag, { Name => $name }) if $name;
1440             }
1441 0         0 $et->HandleTag($tagTablePtr, $tag, $val);
1442 0         0 $pos += 8;
1443             }
1444 0         0 return 1;
1445             }
1446              
1447             #------------------------------------------------------------------------------
1448             # Read Samsung Meta Info from trailer
1449             # Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref
1450             # Returns: true on success
1451             sub ProcessSamsungMeta($$$)
1452             {
1453 0     0 0 0 my ($et, $dirInfo, $tagTablePtr) = @_;
1454 0         0 my $dirName = $$dirInfo{DirName};
1455 0         0 my $dataPt = $$dirInfo{DataPt};
1456 0         0 my $pos = $$dirInfo{DirStart};
1457 0         0 my $end = $$dirInfo{DirLen} + $pos;
1458 0 0 0     0 unless ($pos + 8 <= $end and substr($$dataPt, $pos, 4) eq 'DOFS') {
1459 0         0 $et->Warn("Unrecognized $dirName data");
1460 0         0 return 0;
1461             }
1462 0         0 my $ver = Get32u($dataPt, $pos + 4);
1463 0 0       0 if ($ver == 3) {
1464 0 0 0     0 unless ($pos + 18 <= $end and Get32u($dataPt, $pos + 12) == $$dirInfo{DirLen}) {
1465 0         0 $et->Warn("Unrecognized $dirName version $ver data");
1466 0         0 return 0;
1467             }
1468 0         0 my $num = Get16u($dataPt, $pos + 16);
1469 0         0 $et->VerboseDir("$dirName version $ver", $num);
1470 0         0 $pos += 18;
1471 0         0 my ($i, $val);
1472 0         0 for ($i=0; $i<$num; ++$i) {
1473 0 0       0 last if $pos + 2 > $end;
1474 0         0 my ($x, $n) = unpack("x${pos}CC", $$dataPt);
1475 0         0 $pos += 2;
1476 0 0       0 last if $pos + $n + 2 > $end;
1477 0         0 my $tag = substr($$dataPt, $pos, $n);
1478 0         0 my $len = Get16u($dataPt, $pos + $n);
1479 0         0 $pos += $n + 2;
1480 0 0       0 last if $pos + $len > $end;
1481 0 0       0 if ($len == 4) {
1482 0         0 $val = Get32u($dataPt, $pos);
1483             } else {
1484 0         0 my $tmp = substr($$dataPt, $pos, $len);
1485 0         0 $val = \$pos;
1486             }
1487 0         0 $et->HandleTag($tagTablePtr, $tag, $val);
1488 0         0 $pos += $len;
1489             }
1490 0 0       0 $et->Warn("Unexpected end of $dirName version $ver $i $num data") if $i < $num;
1491             }
1492 0         0 return 1;
1493             }
1494              
1495             #------------------------------------------------------------------------------
1496             # Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref
1497             # Returns: true on success
1498             sub ProcessSamsungIFD($$$)
1499             {
1500 0     0 0 0 my ($et, $dirInfo, $tagTablePtr) = @_;
1501 0         0 my $len = $$dirInfo{DataLen};
1502 0         0 my $pos = $$dirInfo{DirStart};
1503 0 0       0 return 0 unless $pos + 4 < $len;
1504 0         0 my $dataPt = $$dirInfo{DataPt};
1505 0         0 my $buff = substr($$dataPt, $pos, 4);
1506             # this is not an IFD for many models
1507             # (the string "Park Byeongchan" is often found here)
1508 0 0       0 return 0 unless $buff =~ s/^([^\0])\0\0\0/$1\0$1\0/s;
1509 0         0 my $numEntries = ord $1;
1510 0 0       0 if ($$et{HTML_DUMP}) {
1511 0         0 my $pt = $$dirInfo{DirStart} + $$dirInfo{DataPos} + $$dirInfo{Base};
1512 0         0 $et->HDump($pt-44, 44, "MakerNotes header", 'Samsung');
1513 0         0 $et->HDump($pt, 4, "MakerNotes entries", "Format: int32u\nEntry count: $numEntries");
1514 0         0 $$dirInfo{NoDumpEntryCount} = 1;
1515             }
1516 0         0 substr($$dataPt, $pos, 4) = $buff; # insert bogus 2-byte entry count
1517             # offset base is at end of IFD
1518 0         0 my $shift = $$dirInfo{DirStart} + 4 + $numEntries * 12 + 4;
1519 0         0 $$dirInfo{Base} += $shift;
1520 0         0 $$dirInfo{DataPos} -= $shift;
1521 0         0 $$dirInfo{DirStart} += 2; # start at bogus entry count
1522 0         0 $$dirInfo{ZeroOffsetOK} = 1; # disable check for zero offset
1523 0         0 delete $$et{NO_UNKNOWN}; # (set for BinaryData, but not for EXIF IFD's)
1524 0         0 my $rtn = Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr);
1525 0         0 substr($$dataPt, $pos + 2, 1) = "\0"; # remove bogus count
1526 0         0 return $rtn;
1527             }
1528              
1529             #------------------------------------------------------------------------------
1530             # Read/write Samsung trailer (ie. "Sound & Shot" written by Galaxy Tab S (SM-T805))
1531             # Inputs: 0) ExifTool object reference, 1) dirInfo reference
1532             # Returns: 1 on success, 0 not valid Samsung trailer, or -1 error writing
1533             # - updates DataPos to point to start of Samsung trailer
1534             # - updates DirLen to existing trailer length
1535             sub ProcessSamsung($$$)
1536             {
1537 26     26 0 93 my ($et, $dirInfo) = @_;
1538 26         79 my $raf = $$dirInfo{RAF};
1539 26   50     152 my $offset = $$dirInfo{Offset} || 0;
1540 26         70 my $outfile = $$dirInfo{OutFile};
1541 26         112 my $verbose = $et->Options('Verbose');
1542 26         136 my $unknown = $et->Options('Unknown');
1543 26         118 my ($buff, $buf2, $index, $offsetPos, $audioNOff, $audioSize);
1544              
1545 26 50       122 unless ($raf) {
1546 0         0 $raf = new File::RandomAccess($$dirInfo{DataPt});
1547 0         0 $et->VerboseDir('SamsungTrailer');
1548             }
1549 26 50 33     128 return 0 unless $raf->Seek(-6-$offset, 2) and $raf->Read($buff, 6) == 6 and
      33        
      33        
1550             ($buff eq 'QDIOBS' or $buff eq "\0\0SEFT");
1551 26         149 my $endPos = $raf->Tell();
1552 26 50 50     161 $raf->Seek(-2, 1) or return 0 if $buff eq 'QDIOBS'; # rewind to before 'BS'
1553 26         171 my $blockEnd = $raf->Tell();
1554 26         168 SetByteOrder('II');
1555              
1556             # read blocks backward until we find the SEFH/SEFT block
1557             # (the only other block I have seen is QDIO/QDIO)
1558             SamBlock:
1559 26         114 for (;;) {
1560 52 50 33     236 last unless $raf->Seek($blockEnd-8, 0) and $raf->Read($buff, 8) == 8;
1561 52         218 my $type = substr($buff, 4);
1562 52 50       344 last unless $type =~ /^\w+$/;
1563 52         198 my $len = Get32u(\$buff, 0);
1564 52 50 33     404 last unless $len < 0x10000 and $len >= 4 and $len + 8 < $blockEnd;
      33        
1565 52 50 33     216 last unless $raf->Seek(-8-$len, 1) and $raf->Read($buff, $len) == $len;
1566 52         174 $blockEnd -= $len + 8;
1567 52 100       194 unless ($type eq 'SEFT') { # look for directory block (ends with "SEFT")
1568 26 100 66     171 next unless $outfile and $type eq 'QDIO';
1569             # QDIO block format:
1570             # 0 - 'QDIO'
1571             # 4 - int32u: 101 (version)
1572             # 8 - int32u: 1
1573             # 12 - int32u: absolute offset of audio file start (augh!!)
1574             # 16 - int32u: absolute offset of audio file end (augh!!)
1575             # 20 - int32u: 20 (QDIO block length minus 8)
1576             # 24 - 'QDIO'
1577 7 50       56 if ($len == 20) {
1578             # save position of audio file offset in QDIO block
1579 7         40 $offsetPos = $endPos - $raf->Tell() + $len - 12;
1580             } else {
1581 0         0 $et->Error('Unsupported Samsung trailer QDIO block', 1);
1582             }
1583 7         23 next;
1584             }
1585 26 50 33     319 last unless $buff =~ /^SEFH/ and $len >= 12; # validate SEFH header
1586 26         191 my $dirPos = $raf->Tell() - $len;
1587             # my $ver = Get32u(\$buff, 0x04); # version (=101)
1588 26         144 my $count = Get32u(\$buff, 0x08);
1589 26 50       158 last if 12 + 12 * $count > $len;
1590 26         111 my $tagTablePtr = GetTagTable('Image::ExifTool::Samsung::Trailer');
1591              
1592             # scan ahead quickly to look for the block where the data comes first
1593             # (have only seen this to be the first in the directory, but just in case)
1594 26         97 my $firstBlock = 0;
1595 26         118 for ($index=0; $index<$count; ++$index) {
1596 52         99 my $entry = 12 + 12 * $index;
1597 52         136 my $noff = Get32u(\$buff, $entry + 4); # negative offset
1598 52 100       253 $firstBlock = $noff if $firstBlock < $noff;
1599             }
1600             # save trailer position and length
1601 26         120 my $dataPos = $$dirInfo{DataPos} = $dirPos - $firstBlock;
1602 26         114 my $dirLen = $$dirInfo{DirLen} = $endPos - $dataPos;
1603 26 0 33     217 if (($verbose or $$et{HTML_DUMP}) and not $outfile and $$dirInfo{RAF}) {
      33        
      33        
1604 0         0 $et->DumpTrailer($dirInfo);
1605 0 0       0 return 1 if $$et{HTML_DUMP};
1606             }
1607             # read through the SEFH/SEFT directory entries
1608 26         138 for ($index=0; $index<$count; ++$index) {
1609 52         121 my $entry = 12 + 12 * $index;
1610             # first 2 bytes always 0 (may be part of block type)
1611 52         167 my $type = Get16u(\$buff, $entry + 2); # block type
1612 52         168 my $noff = Get32u(\$buff, $entry + 4); # negative offset
1613 52         180 my $size = Get32u(\$buff, $entry + 8); # block size
1614 52 50 33     421 last SamBlock if $noff > $dirPos or $size > $noff or $size < 8;
      33        
1615 52 50       151 $firstBlock = $noff if $firstBlock < $noff;
1616 52 100       152 if ($outfile) {
1617 14 100 66     76 next unless $type == 0x0100 and not $audioNOff;
1618             # save offset and length of first audio file for QDIO block
1619 7 50 33     35 last unless $raf->Seek($dirPos-$noff, 0) and $raf->Read($buf2, 8) == 8;
1620 7         48 $len = Get32u(\$buf2, 4);
1621 7         38 $audioNOff = $noff - 8 - $len; # negative offset to start of audio data
1622 7         24 $audioSize = $size - 8 - $len;
1623 7         26 next;
1624             }
1625             # add unknown tags if necessary
1626 38         165 my $tag = sprintf("0x%.4x", $type);
1627 38 100       162 unless ($$tagTablePtr{$tag}) {
1628 17 100 66     151 next unless $unknown or $verbose;
1629 1         9 my %tagInfo = (
1630             Name => "SamsungTrailer_$tag",
1631             Description => "Samsung Trailer $tag",
1632             Unknown => 1,
1633             Binary => 1,
1634             );
1635 1         7 AddTagToTable($tagTablePtr, $tag, \%tagInfo);
1636             }
1637 22 100       105 unless ($$tagTablePtr{"$tag-name"}) {
1638 1         8 my %tagInfo2 = (
1639             Name => "SamsungTrailer_${tag}Name",
1640             Description => "Samsung Trailer $tag Name",
1641             Unknown => 1,
1642             );
1643 1         6 AddTagToTable($tagTablePtr, "$tag-name", \%tagInfo2);
1644             }
1645 22 50 33     119 last unless $raf->Seek($dirPos-$noff, 0) and $raf->Read($buf2, $size) == $size;
1646             # (could validate the first 4 bytes of the block because they
1647             # are the same as the first 4 bytes of the directory entry)
1648 22         106 $len = Get32u(\$buf2, 4);
1649 22 50       113 last if $len + 8 > $size;
1650             # extract tag name and value
1651 22         172 $et->HandleTag($tagTablePtr, "$tag-name", undef,
1652             DataPt => \$buf2,
1653             DataPos => $dirPos - $noff,
1654             Start => 8,
1655             Size => $len,
1656             );
1657 22         154 $et->HandleTag($tagTablePtr, $tag, undef,
1658             DataPt => \$buf2,
1659             DataPos => $dirPos - $noff,
1660             Start => 8 + $len,
1661             Size => $size - (8 + $len),
1662             );
1663             }
1664 26 100       127 if ($outfile) {
1665 7 50 33     74 last unless $raf->Seek($dataPos, 0) and $raf->Read($buff, $dirLen) == $dirLen;
1666             # adjust the absolute offset in the QDIO block if necessary
1667 7 50 33     55 if ($offsetPos and $audioNOff) {
1668             # initialize the audio file start/end position in the QDIO block
1669 7         35 my $newPos = Tell($outfile) + $dirPos - $audioNOff - $dataPos;
1670 7         50 Set32u($newPos, \$buff, length($buff) - $offsetPos);
1671 7         53 Set32u($newPos + $audioSize, \$buff, length($buff) - $offsetPos + 4);
1672             # add a fixup so the calling routine can apply further shifts if necessary
1673 7         55 require Image::ExifTool::Fixup;
1674 7         29 my $fixup = $$dirInfo{Fixup};
1675 7 50       78 $fixup or $fixup = $$dirInfo{Fixup} = new Image::ExifTool::Fixup;
1676 7         45 $fixup->AddFixup(length($buff) - $offsetPos);
1677 7         48 $fixup->AddFixup(length($buff) - $offsetPos + 4);
1678             }
1679 7 50       50 $et->VPrint(0, "Writing Samsung trailer ($dirLen bytes)\n") if $verbose;
1680 7 50       40 Write($$dirInfo{OutFile}, $buff) or return -1;
1681 7         37 return 1;
1682             }
1683 19         82 return 1;
1684             }
1685 0         0 $et->Warn('Error processing Samsung trailer',1);
1686 0         0 return 0;
1687             }
1688              
1689             #------------------------------------------------------------------------------
1690             # Write Samsung STMN maker notes
1691             # Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref
1692             # Returns: Binary data block or undefined on error
1693             sub WriteSTMN($$$)
1694             {
1695 70     70 0 195 my ($et, $dirInfo, $tagTablePtr) = @_;
1696             # create a Fixup for the PreviewImage
1697 70         433 $$dirInfo{Fixup} = new Image::ExifTool::Fixup;
1698 70         289 my $val = Image::ExifTool::WriteBinaryData($et, $dirInfo, $tagTablePtr);
1699             # force PreviewImage into the trailer even if it fits in EXIF segment
1700 70 50       325 $$et{PREVIEW_INFO}{IsTrailer} = 1 if $$et{PREVIEW_INFO};
1701 70         407 return $val;
1702             }
1703              
1704             1; # end
1705              
1706             __END__