Ignore:
Timestamp:
2021-02-26T19:39:51+13:00 (3 years ago)
Author:
anupama
Message:

Committing the improvements to EmbeddedMetaPlugin's processing of Keywords vs other metadata fields. Keywords were literally stored as arrays of words rather than phrases in PDFs (at least in Diego's sample PDF), whereas other meta fields like Subjects and Creators stored them as arrays of phrases. To get both to work, Kathy updated EXIF to a newer version, to retrieve the actual EXIF values stored in the PDF. And Kathy and Dr Bainbridge came up with a new option that I added called apply_join_before_split_to_metafields that's a regex which can list the metadata fields to apply the join_before_split to and whcih previously always got applied to all metadata fields. Now it's applied to any *Keywords metafields by default, as that's the metafield we have experience of that behaves differently to the others, as it stores by word instead of phrases. Tested on Diego's sample PDF. Diego has double-checked it to works on his sample PDF too, setting the split char to ; and turning on the join_before_split and leaving apply_join_before_split_to_metafields at its default of .*Keywords. File changes are strings.properties for the tooltip, the plugin introducing the option and working with it and Kathy's EXIF updates affecting cpan/File and cpan/Image.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • main/trunk/greenstone2/perllib/cpan/Image/ExifTool/Samsung.pm

    r24107 r34921  
    88# References:   1) Tae-Sun Park private communication
    99#               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
    1016#------------------------------------------------------------------------------
    1117
     
    1319
    1420use strict;
    15 use vars qw($VERSION);
     21use vars qw($VERSION %samsungLensTypes);
    1622use Image::ExifTool qw(:DataAccess :Utils);
    1723use Image::ExifTool::Exif;
    1824
    19 $VERSION = '1.08';
     25$VERSION = '1.48';
    2026
    2127sub WriteSTMN($$$);
    2228sub ProcessINFO($$$);
     29sub ProcessSamsungMeta($$$);
     30sub ProcessSamsungIFD($$$);
     31
     32# Samsung LensType lookup
     33%samsungLensTypes = (
     34    # (added "Samsung NX" in all of these lens names - ref 4)
     35    0 => 'Built-in or Manual Lens', #PH (EX1, WB2000)
     36    1 => 'Samsung NX 30mm F2 Pancake',
     37    2 => 'Samsung NX 18-55mm F3.5-5.6 OIS', # (also version II, ref 1)
     38    3 => 'Samsung NX 50-200mm F4-5.6 ED OIS',
     39    # what about the non-OIS version of the 18-55,
     40    # which was supposed to be available before the 20-50? - PH
     41    4 => 'Samsung NX 20-50mm F3.5-5.6 ED', #PH/4
     42    5 => 'Samsung NX 20mm F2.8 Pancake', #PH
     43    6 => 'Samsung NX 18-200mm F3.5-6.3 ED OIS', #4
     44    7 => 'Samsung NX 60mm F2.8 Macro ED OIS SSA', #1
     45    8 => 'Samsung NX 16mm F2.4 Pancake', #1/4
     46    9 => 'Samsung NX 85mm F1.4 ED SSA', #4
     47    10 => 'Samsung NX 45mm F1.8', #3
     48    11 => 'Samsung NX 45mm F1.8 2D/3D', #3
     49    12 => 'Samsung NX 12-24mm F4-5.6 ED', #4
     50    13 => 'Samsung NX 16-50mm F2-2.8 S ED OIS', #forum3833
     51    14 => 'Samsung NX 10mm F3.5 Fisheye', #NJ
     52    15 => 'Samsung NX 16-50mm F3.5-5.6 Power Zoom ED OIS', #5
     53    20 => 'Samsung NX 50-150mm F2.8 S ED OIS', #PH
     54    21 => 'Samsung NX 300mm F2.8 ED OIS', #IB
     55);
    2356
    2457# range of values for Formats used in encrypted information
     
    3164
    3265# Samsung "STMN" maker notes (ref PH)
    33 %Image::ExifTool::Samsung::Type1 = (
     66%Image::ExifTool::Samsung::Main = (
    3467    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
    3568    WRITE_PROC => \&WriteSTMN,
     
    3972    FIRST_ENTRY => 0,
    4073    IS_OFFSET => [ 2 ],   # tag 2 is 'IsOffset'
     74    IS_SUBDIR => [ 11 ],
    4175    GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
    4276    NOTES => q{
     
    5488        IsOffset => 3,
    5589        Protected => 2,
     90        WriteGroup => 'MakerNotes',
    5691    },
    5792    3 => {
     
    6095        DataTag => 'PreviewImage',
    6196        Protected => 2,
    62     },
     97        WriteGroup => 'MakerNotes',
     98    },
     99    11 => {
     100        Name => 'SamsungIFD',
     101        # Note: this is not always an IFD.  In many models the string
     102        # "Park Byeongchan" is found at this location
     103        Condition => '$$valPt =~ /^[^\0]\0\0\0/',
     104        Format => 'undef[$size - 44]',
     105        SubDirectory => { TagTable => 'Image::ExifTool::Samsung::IFD' },
     106    },
     107);
     108
     109%Image::ExifTool::Samsung::IFD = (
     110    PROCESS_PROC => \&ProcessSamsungIFD,
     111    NOTES => q{
     112        This is a standard-format IFD found in the maker notes of some Samsung
     113        models, except that the entry count is a 4-byte integer and the offsets are
     114        relative to the end of the IFD.  Currently, no tags in this IFD are known,
     115        so the L<Unknown|../ExifTool.html#Unknown> (-u) or L<Verbose|../ExifTool.html#Verbose> (-v) option must be used to see this
     116        information.
     117    },
     118    GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
     119    # 0x0001 - undef[4000|4100]: starts with "MN_PRV" (or all zeros)
     120    # 0x0002 - undef[7000]     : starts with "Kim Miae"
     121    # 0x0003 - undef[5000]     : starts with "Lee BK"
     122    # 0x0004 - undef[500|2000] : starts with "IPCD"   (or all zeros)
     123    # 0x0006 - undef[100|200]  : starts with "MN_ADS" (or all zeros)
    63124);
    64125
     
    75136        Count => 4,
    76137    },
     138    0x0002 => {
     139        Name => 'DeviceType',
     140        Groups => { 2 => 'Camera' },
     141        Writable => 'int32u',
     142        PrintHex => 1,
     143        PrintConv => {
     144            0x1000 => 'Compact Digital Camera',
     145            0x2000 => 'High-end NX Camera',
     146            0x3000 => 'HXM Video Camera',
     147            0x12000 => 'Cell Phone',
     148            0x300000 => 'SMX Video Camera',
     149        },
     150    },
     151    0x0003 => {
     152        Name => 'SamsungModelID',
     153        Groups => { 2 => 'Camera' },
     154        Writable => 'int32u',
     155        PrintHex => 1,
     156        PrintConv => {
     157            0x100101c => 'NX10',
     158            0x1001226 => 'HMX-S10BP',
     159            0x1001226 => 'HMX-S15BP',
     160            0x1001233 => 'HMX-Q10',
     161            0x1001234 => 'HMX-H300',
     162            0x1001234 => 'HMX-H304',
     163            0x100130c => 'NX100',
     164            0x1001327 => 'NX11',
     165            0x170104b => 'ES65, ES67 / VLUU ES65, ES67 / SL50',
     166            0x170104e => 'ES70, ES71 / VLUU ES70, ES71 / SL600',
     167            0x1701052 => 'ES73 / VLUU ES73 / SL605',
     168            0x1701055 => 'ES25, ES27 / VLUU ES25, ES27 / SL45',
     169            0x1701300 => 'ES28 / VLUU ES28',
     170            0x1701303 => 'ES74,ES75,ES78 / VLUU ES75,ES78',
     171            0x2001046 => 'PL150 / VLUU PL150 / TL210 / PL151',
     172            0x2001048 => 'PL100 / TL205 / VLUU PL100 / PL101',
     173            0x2001311 => 'PL120,PL121 / VLUU PL120,PL121',
     174            0x2001315 => 'PL170,PL171 / VLUUPL170,PL171',
     175            0x200131e => 'PL210, PL211 / VLUU PL210, PL211',
     176            0x2701317 => 'PL20,PL21 / VLUU PL20,PL21',
     177            0x2a0001b => 'WP10 / VLUU WP10 / AQ100',
     178            0x3000000 => 'Various Models (0x3000000)',
     179           #0x3000000 => 'DV150F / DV151F / DV155F',
     180           #0x3000000 => 'NX mini',
     181           #0x3000000 => 'NX3000',
     182           #0x3000000 => 'NX3300',
     183           #0x3000000 => 'ST150F / ST151F / ST152F',
     184           #0x3000000 => 'WB200F / WB201F / WB202F',
     185           #0x3000000 => 'WB250F / WB251F / WB252F',
     186           #0x3000000 => 'WB30F / WB31F / WB32F',
     187           #0x3000000 => 'WB350F / WB351F / WB352F',
     188           #0x3000000 => 'WB800F',
     189            0x3a00018 => 'Various Models (0x3a00018)',
     190           #0x3a00018 => 'ES30 / VLUU ES30',
     191           #0x3a00018 => 'ES80 / ES81',
     192           #0x3a00018 => 'ES9 / ES8',
     193           #0x3a00018 => 'PL200 / VLUU PL200',
     194           #0x3a00018 => 'PL80 / VLUU PL80 / SL630 / PL81',
     195           #0x3a00018 => 'PL90 / VLUU PL90',
     196           #0x3a00018 => 'WB1100F / WB1101F / WB1102F',
     197           #0x3a00018 => 'WB2200F',
     198            0x400101f => 'ST1000 / ST1100 / VLUU ST1000 / CL65',
     199            0x4001022 => 'ST550 / VLUU ST550 / TL225',
     200            0x4001025 => 'Various Models (0x4001025)',
     201           #0x4001025 => 'DV300 / DV300F / DV305F',
     202           #0x4001025 => 'ST500 / VLUU ST500 / TL220',
     203           #0x4001025 => 'ST200 / ST200F / ST201 / ST201F / ST205F',
     204            0x400103e => 'VLUU ST5500, ST5500, CL80',
     205            0x4001041 => 'VLUU ST5000, ST5000, TL240',
     206            0x4001043 => 'ST70 / VLUU ST70 / ST71',
     207            0x400130a => 'Various Models (0x400130a)',
     208           #0x400130a => 'VLUU ST100, ST100',
     209           #0x400130a => 'VLUU ST600, ST600',
     210           #0x400130a => 'VLUU ST80, ST80',
     211            0x400130e => 'ST90,ST91 / VLUU ST90,ST91',
     212            0x4001313 => 'VLUU ST95, ST95',
     213            0x4a00015 => 'VLUU ST60',
     214            0x4a0135b => 'ST30, ST65 / VLUU ST65 / ST67',
     215            0x5000000 => 'Various Models (0x5000000)',
     216           #0x5000000 => 'EX2F',
     217           #0x5000000 => 'NX1000',
     218           #0x5000000 => 'NX20',
     219           #0x5000000 => 'NX200',
     220           #0x5000000 => 'NX210',
     221           #0x5000000 => 'ST96',
     222           #0x5000000 => 'WB750',
     223           #0x5000000 => 'ST700',
     224            0x5001038 => 'Various Models (0x5001038)',
     225           #0x5001038 => 'EK-GN120',
     226           #0x5001038 => 'HMX-E10',
     227           #0x5001038 => 'NX1',
     228           #0x5001038 => 'NX2000',
     229           #0x5001038 => 'NX30',
     230           #0x5001038 => 'NX300',
     231           #0x5001038 => 'NX500',
     232           #0x5001038 => 'SM-C200',
     233           #0x5001038 => 'WB2000',
     234            0x500103a => 'WB650 / VLUU WB650 / WB660',
     235            0x500103c => 'WB600 / VLUU WB600 / WB610',
     236            0x500133e => 'WB150 / WB150F / WB152 / WB152F / WB151',
     237            0x5a0000f => 'WB5000 / HZ25W',
     238            0x5a0001e => 'WB5500 / VLUU WB5500 / HZ50W',
     239            0x6001036 => 'EX1',
     240            0x700131c => 'VLUU SH100, SH100',
     241            0x27127002 => 'SMX-C20N',
     242        },
     243    },
     244    # 0x0004 - undef[x] (SamsungContentsID?)
     245    # 0x000a - int32u (ContinuousShotMode?)
     246    # 0x000b - int16u (BestPhotoMode?)
     247    # 0x000c - int32u ? values: 0,1
     248    # 0x000e - int32u[2] (SoundMultiPicture?)
     249    # 0x0010 - rational64u ? values: undef,inf
     250    0x0011 => { #6
     251        Name => 'OrientationInfo',
     252        SubDirectory => { TagTable => 'Image::ExifTool::Samsung::OrientationInfo' },
     253    },
     254    0x0020 => [{ #forum7685
     255        Name => 'SmartAlbumColor',
     256        Condition => '$$valPt =~ /^\0{4}/',
     257        Writable => 'int16u',
     258        Count => 2,
     259        PrintConv => {
     260            '0 0' => 'n/a',
     261        },
     262    },{
     263        Name => 'SmartAlbumColor',
     264        Writable => 'int16u',
     265        Count => 2,
     266        PrintConv => [{
     267            0 => 'Red',
     268            1 => 'Yellow',
     269            2 => 'Green',
     270            3 => 'Blue',
     271            4 => 'Magenta',
     272            5 => 'Black',
     273            6 => 'White',
     274            7 => 'Various',
     275        }],
     276    }],
    77277    0x0021 => { #1
    78278        Name => 'PictureWizard',
    79279        Writable => 'int16u',
    80         Count => 5,
    81         PrintConv => q{
    82             my @a = split ' ', $val;
    83             return $val unless @a == 5;
    84             sprintf("Mode: %d, Col: %d, Sat: %d, Sha: %d, Con: %d",
    85                     $a[0], $a[1], $a[2]-4, $a[3]-4, $a[4]-4);
    86         },
    87         PrintConvInv => q{
    88             my @a = ($val =~ /[+-]?\d+/g);
    89             return $val unless @a >= 5;
    90             sprintf("%d %d %d %d %d", $a[0], $a[1], $a[2]+4, $a[3]+4, $a[4]+4);
    91         },
    92     },
    93     # 0x0023 - string: "0123456789" (PH)
     280        SubDirectory => { TagTable => 'Image::ExifTool::Samsung::PictureWizard' },
     281    },
     282    # 0x0022 - int32u (CaptureMode?) (Gamma? eg. 65538 = 1.2, ref forum7720)
     283    # 0x0023 - string: "0123456789" (PH) (placeholder for SerialNumber?)
     284    # 0x0025 - int32u (ImageCount?)
     285    # 0x002a - undef[4] (SNSDirectShare?)
     286    # 0x002f - string (GPSInfo01?)
    94287    0x0030 => { #1 (NX100 with GPS)
    95288        Name => 'LocalLocationName',
     289        Groups => { 2 => 'Location' },
    96290        Writable => 'string',
    97291        Format => 'undef',
     
    103297    0x0031 => { #1 (NX100 with GPS)
    104298        Name => 'LocationName',
     299        Groups => { 2 => 'Location' },
    105300        Writable => 'string',
    106301    },
    107     0x0035 => {
     302    # 0x0032 - string (GPSInfo03)
     303    # 0x0033 - string (GPSInfo04)
     304    # 0x0034 - string (GPSInfo05)
     305    0x0035 => [{
     306        Name => 'PreviewIFD',
     307        Condition => '$$self{TIFF_TYPE} eq "SRW" and $$self{Model} ne "EK-GN120"', # (not an IFD in JPEG images)
     308        Groups => { 1 => 'PreviewIFD' },
     309        Flags => 'SubIFD',
     310        SubDirectory => {
     311            TagTable => 'Image::ExifTool::Nikon::PreviewIFD',
     312            ByteOrder => 'Unknown',
     313            Start => '$val',
     314        },
     315    },{
    108316        Name => 'PreviewIFD',
    109317        Condition => '$$self{TIFF_TYPE} eq "SRW"', # (not an IFD in JPEG images)
     
    113321            TagTable => 'Image::ExifTool::Nikon::PreviewIFD',
    114322            ByteOrder => 'Unknown',
    115             Start => '$val',
     323            Start => '$val - 36',
     324        },
     325    }],
     326    # 0x003a - int16u[2] (SmartLensInfo?)
     327    # 0x003b - int16u[2] (PhotoStyleSelectInfo?)
     328    # 0x003c - int16u (SmartRange?)
     329    # 0x003d - int16u[5] (SmartCropInfo?)
     330    # 0x003e - int32u (DualCapture?)
     331    # 0x003f - int16u[2] (SGIFInfo?)
     332    0x0040 => { #forum7432
     333        Name => 'RawDataByteOrder',
     334        PrintConv => {
     335            0 => 'Little-endian (Intel, II)',
     336            1 => 'Big-endian (Motorola, MM)', #(NC)
     337        },
     338    },
     339    0x0041 => { #forum7684
     340        Name => 'WhiteBalanceSetup',
     341        Writable => 'int32u',
     342        PrintConv => {
     343            0 => 'Auto',
     344            1 => 'Manual',
    116345        },
    117346    },
     
    121350        Writable => 'rational64s',
    122351        # (DPreview samples all 0.2 C --> pre-production model)
    123         PrintConv => '"$val C"',
     352        PrintConv => '$val =~ /\d/ ? "$val C" : $val',
    124353        PrintConvInv => '$val=~s/ ?C//; $val',
    125354    },
    126     # 0x00a0 - undef[8192]: white balance information (ref 1):
     355    # 0x0045 => { Name => 'RawCompressionMode', Writable => 'int32u' }, # (related to ExposureMode, not raw compresison? ref forum7432)
     356    # 0x004a - int32u[7] (ImageVerification?)
     357    # 0x004b - int32u[2] (RewindInfo?)
     358    # 0x0050 - int32u (ColorSpace? - inconsistent) values: 1 (related to compression mode, ref forum7432)
     359    0x0050 => { #forum7432
     360        Name => 'RawDataCFAPattern',
     361        PrintConv => {
     362            0 => 'Unchanged',
     363            1 => 'Swap',
     364            65535 => 'Roll',
     365        },
     366    },
     367    # 0x0054 - int16u[2] (WeatherInfo?)
     368    # 0x0060 - undef (AEInfo?)
     369    # 0x0080 - undef (AFInfo?)
     370    # 0x00a0 - undef[8192] (AWBInfo1): white balance information (ref 1):
    127371    #   At byte 5788, the WBAdjust: "Adjust\0\X\0\Y\0\Z\xee\xea\xce\xab", where
    128372    #   Y = BA adjust (0=Blue7, 7=0, 14=Amber7), Z = MG (0=Magenta7, 7=0, 14=Green7)
     373    # 0x00a1 - undef (AWBInfo2?)
     374    # 0x00c0 - undef (IPCInfo?)
     375    # 0x00c7 - undef (SmartFunctionInfo?)
     376    # 0x00e0 - int16u (SceneResult?)
     377    # 0x00e1 - int16u[8] (SADebugInfo01?)
     378    # 0x00e1 - int16u[x] (SADebugInfo02?)
     379    0x0100 => {
     380        Name => 'FaceDetect',
     381        Writable => 'int16u',
     382        PrintConv => { 0 => 'Off', 1 => 'On' }, #(NC)
     383    },
     384    # 0x0101 - int16u[6] (FaceDetectInfo?)
     385    # 0x0102 - int16u[x] (FaceDetectInfo?)
     386    0x0120 => {
     387        Name => 'FaceRecognition',
     388        Writable => 'int32u',
     389        PrintConv => { 0 => 'Off', 1 => 'On' }, #(NC)
     390    },
     391    0x0123 => { Name => 'FaceName', Writable => 'string' },
     392    # 0x140 - undef (LensInfo?)
    129393#
    130394# the following tags found only in SRW images
    131395#
    132     # 0xa000 - rational64u: 1 or 1.1 (ref PH)
     396    # 0xa000 - rational64u: 1 or 1.1 (ref PH) (MakerNoteVersion?)
    133397    0xa001 => { #1
    134398        Name => 'FirmwareName',
     
    136400        Writable => 'string',
    137401    },
    138     # 0xa002 - string[30]: '0' or 'DY049P000000' (ref PH)
     402    0xa002 => { #PH/IB
     403        Name => 'SerialNumber',
     404        Condition => '$$valPt =~ /^\w{5}/', # should be at least 5 characters long
     405        Groups => { 2 => 'Camera' },
     406        Writable => 'string',
     407    },
    139408    0xa003 => { #1 (SRW images only)
    140409        Name => 'LensType',
    141410        Groups => { 2 => 'Camera' },
    142411        Writable => 'int16u',
    143         PrintConv => {
    144             0 => 'Built-in', #PH (EX1, WB2000)
    145             1 => 'Samsung 30mm F2 Pancake',
    146             2 => 'Samsung Zoom 18-55mm F3.5-5.6 OIS',
    147             3 => 'Samsung Zoom 50-200mm F4-5.6 ED OIS',
    148             # what about the non-OIS version of the 18-55,
    149             # which was supposed to be available before the 20-50?
    150             4 => 'Samsung 20-50mm F3.5-5.6 Compact Zoom', #PH
    151             5 => 'Samsung 20mm F2.8 Pancake', #PH (guess)
    152         },
     412        Count => -1,
     413        PrintConv => [ \%samsungLensTypes ],
    153414    },
    154415    0xa004 => { #1
     
    157418        Writable => 'string',
    158419    },
    159     # 0xa005 - string[30]: constant for a given lens? Not the printed serial number (ref 1)
     420    0xa005 => {
     421        Name => 'InternalLensSerialNumber', # Not the printed serial number (ref 1)
     422        Groups => { 2 => 'Camera' },
     423        Writable => 'string',
     424    },
    160425    0xa010 => { #1
    161426        Name => 'SensorAreas',
     
    190455        Writable => 'rational64u',
    191456        PrintConv => 'Image::ExifTool::Exif::PrintExposureTime($val)',
    192         PrintConvInv => 'Image::ExifTool::Exif::ConvertFraction($val)',
     457        PrintConvInv => '$val',
    193458    },
    194459    0xa019 => { #1
    195460        Name => 'FNumber',
     461        Priority => 0,
    196462        Writable => 'rational64u',
    197463        PrintConv => 'sprintf("%.1f",$val)',
     
    201467        Name => 'FocalLengthIn35mmFormat',
    202468        Groups => { 2 => 'Camera' },
     469        Priority => 0,
    203470        Format => 'int32u',
    204471        ValueConv => '$val / 10',
     
    207474        PrintConvInv => '$val=~s/\s*mm$//;$val',
    208475    },
     476    # 0xa01b - int32u (ImageCount?)
     477    # 0xa01b - int16u (LDCLens?)
    209478    0xa020 => { #1
    210479        Name => 'EncryptionKey',
     
    246515        RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,1)',
    247516    },
    248     #this doesn't seem correct
    249     #0xa025 => { #PH/1
    250     #    Name => 'ColorTemperatureAuto',
    251     #    Writable => 'int32u',
    252     #    RawConv    => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,6)',
    253     #    RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-6)',
    254     #},
     517    0xa025 => { # (PostAEGain?)
     518        Name => 'DigitalGain', #IB
     519        Writable => 'int32u',
     520        RawConv    => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,6)',
     521        RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-6)',
     522    },
     523    0xa025 => { #IB
     524        Name => 'HighlightLinearityLimit',
     525        Writable => 'int32u',
     526    },
    255527    0xa028 => { #2/PH
    256528        Name => 'WB_RGGBLevelsBlack',
     
    282554    },
    283555    0xa033 => { #1
    284         Name => 'Samsung_Type2_0xa033',
    285         Unknown => 1,
    286         Hidden => 1,
     556        Name => 'CbCrMatrixDefault',
    287557        Writable => 'int32s',
    288558        Count => 4,
     
    291561    },
    292562    0xa034 => { #1
    293         Name => 'Samsung_Type2_0xa034',
    294         Unknown => 1,
    295         Hidden => 1,
     563        Name => 'CbCrMatrix',
    296564        Writable => 'int32s',
    297565        Count => 4,
     
    300568    },
    301569    0xa035 => { #1
    302         Name => 'Samsung_Type2_0xa035',
    303         Unknown => 1,
    304         Hidden => 1,
     570        Name => 'CbCrGainDefault',
    305571        Writable => 'int32u',
    306572        Count => 2,
     
    309575    },
    310576    0xa036 => { #1
    311         Name => 'Samsung_Type2_0xa036',
    312         Unknown => 1,
    313         Hidden => 1,
     577        Name => 'CbCrGain',
    314578        Writable => 'int32u',
    315579        Count => 2,
     
    318582    },
    319583    0xa040 => { #1
    320         Name => 'ToneCurve1',
     584        Name => 'ToneCurveSRGBDefault',
    321585        Writable =>  'int32u',
    322586        Count => 23,
     
    329593    },
    330594    0xa041 => { #1
    331         Name => 'ToneCurve2',
     595        Name => 'ToneCurveAdobeRGBDefault',
    332596        Writable =>  'int32u',
    333597        Count => 23,
     
    336600    },
    337601    0xa042 => { #1
    338         Name => 'ToneCurve3',
     602        Name => 'ToneCurveSRGB',
    339603        Writable =>  'int32u',
    340604        Count => 23,
     
    343607    },
    344608    0xa043 => { #1
    345         Name => 'ToneCurve4',
     609        Name => 'ToneCurveAdobeRGB',
    346610        Writable =>  'int32u',
    347611        Count => 23,
     
    350614    },
    351615    0xa048 => { #1
    352         Name => 'Samsung_Type2_0xa048',
     616        Name => 'RawData',
    353617        Unknown => 1,
    354         Hidden => 1,
    355618        Writable => 'int32s',
    356619        Count => 12,
     
    358621        RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,"-0")',
    359622    },
    360     0xa050 => { #1 (vignette curve?)
    361         Name => 'Samsung_Type2_0xa050',
     623    0xa050 => { #1
     624        Name => 'Distortion',
    362625        Unknown => 1,
    363         Hidden => 1,
    364626        Writable => 'int32s',
    365627        Count => 8,
     
    368630    },
    369631    0xa051 => { #1
    370         Name => 'Samsung_Type2_0xa051',
     632        Name => 'ChromaticAberration',
    371633        Unknown => 1,
    372         Hidden => 1,
    373634        Writable => 'int16u',
    374635        Count => 22,
     
    376637        RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,0,7,3)',
    377638    },
    378     0xa052 => { #1 (vignette curve?)
    379         Name => 'Samsung_Type2_0xa052',
     639    0xa052 => { #1
     640        Name => 'Vignetting',
    380641        Unknown => 1,
    381         Hidden => 1,
    382642        Writable => 'int16u',
    383643        Count => 15,
     
    386646    },
    387647    0xa053 => { #1
    388         Name => 'Samsung_Type2_0xa053',
     648        Name => 'VignettingCorrection',
    389649        Unknown => 1,
    390         Hidden => 1,
    391650        Writable => 'int16u',
    392651        Count => 15,
     
    395654    },
    396655    0xa054 => { #1
    397         Name => 'Samsung_Type2_0xa054',
     656        Name => 'VignettingSetting',
    398657        Unknown => 1,
    399         Hidden => 1,
    400658        Writable => 'int16u',
    401659        Count => 15,
     
    404662    },
    405663    0xa055 => { #1
    406         Name => 'Samsung_Type2_0xa055',
     664        Name => 'Samsung_Type2_0xa055', # (DistortionCamera1st?)
    407665        Unknown => 1,
    408666        Hidden => 1,
     
    413671    },
    414672    0xa056 => { #1
    415         Name => 'Samsung_Type2_0xa056',
     673        Name => 'Samsung_Type2_0xa056', # (DistortionCamera2nd?)
    416674        Unknown => 1,
    417675        Hidden => 1,
     
    422680    },
    423681    0xa057 => { #1
    424         Name => 'Samsung_Type2_0xa057',
     682        Name => 'Samsung_Type2_0xa057', # (DistortionCameraSetting?)
    425683        Unknown => 1,
    426684        Hidden => 1,
     
    429687        RawConv    => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,2)',
    430688        RawConvInv => 'Image::ExifTool::Samsung::Crypt($self,$val,$tagInfo,-2)',
     689    },
     690    # 0xa060 - rational64u (CISTemperature?)
     691    # 0xa061 - int16u (Compression?)
     692);
     693
     694# orientation information (ref 6)
     695%Image::ExifTool::Samsung::OrientationInfo = (
     696    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     697    WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
     698    CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
     699    WRITABLE => 1,
     700    FORMAT => 'rational64s',
     701    FIRST_ENTRY => 0,
     702    GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
     703    NOTES => 'Camera orientation information written by the Gear 360 (SM-C200).',
     704    0 => {
     705        Name => 'YawAngle', #(NC)
     706        Unknown => 1,
     707        Notes => 'always zero',
     708    },
     709    1 => {
     710        Name => 'PitchAngle',
     711        Notes => 'upward tilt of rear camera in degrees',
     712    },
     713    2 => {
     714        Name => 'RollAngle',
     715        Notes => 'clockwise rotation of rear camera in degrees',
     716    },
     717);
     718
     719# Picture Wizard information (ref 1)
     720%Image::ExifTool::Samsung::PictureWizard = (
     721    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     722    WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
     723    CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
     724    WRITABLE => 1,
     725    FORMAT => 'int16u',
     726    FIRST_ENTRY => 0,
     727    GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
     728    0 => {
     729        Name => 'PictureWizardMode',
     730        PrintConvColumns => 3,
     731        PrintConv => { #3
     732             0 => 'Standard',
     733             1 => 'Vivid',
     734             2 => 'Portrait',
     735             3 => 'Landscape',
     736             4 => 'Forest',
     737             5 => 'Retro',
     738             6 => 'Cool',
     739             7 => 'Calm',
     740             8 => 'Classic',
     741             9 => 'Custom1',
     742            10 => 'Custom2',
     743            11 => 'Custom3',
     744           255 => 'n/a', #PH
     745        },
     746    },
     747    1 => 'PictureWizardColor',
     748    2 => {
     749        Name => 'PictureWizardSaturation',
     750        ValueConv => '$val - 4',
     751        ValueConvInv => '$val + 4',
     752    },
     753    3 => {
     754        Name => 'PictureWizardSharpness',
     755        ValueConv => '$val - 4',
     756        ValueConvInv => '$val + 4',
     757    },
     758    4 => {
     759        Name => 'PictureWizardContrast',
     760        ValueConv => '$val - 4',
     761        ValueConvInv => '$val + 4',
    431762    },
    432763);
     
    465796        Format => 'string[16]',
    466797    },
    467     0x2e => { # (NC)
     798    0x2e => { #(NC)
    468799        Name => 'ExposureTime',
    469800        Format => 'int32u',
     
    476807        PrintConv => 'sprintf("%.1f",$val)',
    477808    },
    478     0x3a => { # (NC)
     809    0x3a => { #(NC)
    479810        Name => 'ExposureCompensation',
    480811        Format => 'rational64s',
     
    488819        Name => 'Software',
    489820        Format => 'string[32]',
    490         # (these tags are not at a constant offset for Sanyo videos,
     821        # (these tags are not at a constant offset for Olympus/Sanyo videos,
    491822        #  so just to be safe use this to validate subsequent tags)
    492823        RawConv => q{
     
    496827        },
    497828    },
    498     0xf8 => {
    499         Name => 'ThumbnailWidth',
     829    0xf4 => {
     830        Name => 'Thumbnail',
    500831        Condition => '$$self{SamsungMP4}',
    501         Format => 'int32u',
    502     },
    503     0xfc => {
    504         Name => 'ThumbnailHeight',
    505         Condition => '$$self{SamsungMP4}',
    506         Format => 'int32u',
    507     },
    508     0x100 => {
    509         Name => 'ThumbnailLength',
    510         Condition => '$$self{SamsungMP4}',
    511         Format => 'int32u',
    512     },
    513     0x104 => {
    514         Name => 'ThumbnailOffset',
    515         Condition => '$$self{SamsungMP4}',
    516         IsOffset => 1,
    517         Format => 'int32u',
    518         RawConv => '$val + 0xf4',
    519     },
     832        SubDirectory => {
     833            TagTable => 'Image::ExifTool::Samsung::Thumbnail',
     834            Base => '$start',
     835        },
     836    },
     837);
     838
     839# thumbnail image information found in MP4 videos (similar in Olympus,Samsung,Sanyo)
     840%Image::ExifTool::Samsung::Thumbnail = (
     841    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     842    GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
     843    FIRST_ENTRY => 0,
     844    FORMAT => 'int32u',
     845    1 => 'ThumbnailWidth',
     846    2 => 'ThumbnailHeight',
     847    3 => 'ThumbnailLength',
     848    4 => { Name => 'ThumbnailOffset', IsOffset => 1 },
     849);
     850
     851# Samsung MP4 @sec information (PH - from WB30F sample)
     852%Image::ExifTool::Samsung::sec = (
     853    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     854    GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
     855    NOTES => q{
     856        This information is found in the @sec atom of Samsung MP4 videos from models
     857        such as the WB30F.
     858    },
     859    0x00 => {
     860        Name => 'Make',
     861        Format => 'string[32]',
     862        PrintConv => 'ucfirst(lc($val))',
     863    },
     864    0x20 => {
     865        Name => 'Model',
     866        Description => 'Camera Model Name',
     867        Format => 'string[32]',
     868    },
     869    0x200 => { Name => 'ThumbnailWidth',  Format => 'int32u' },
     870    0x204 => { Name => 'ThumbnailHeight', Format => 'int32u' },
     871    0x208 => { Name => 'ThumbnailLength', Format => 'int32u' }, # (2 bytes too long in my sample)
     872    0x20c => {
     873        Name => 'ThumbnailImage',
     874        Groups => { 2 => 'Preview' },
     875        Format => 'undef[$val{0x208}]',
     876        Notes => 'the THM image, embedded metadata is extracted as the first sub-document',
     877        SetBase => 1,
     878        RawConv => q{
     879            my $pt = $self->ValidateImage(\$val, $tag);
     880            if ($pt) {
     881                $$self{BASE} += 0x20c;
     882                $$self{DOC_NUM} = ++$$self{DOC_COUNT};
     883                $self->ExtractInfo($pt, { ReEntry => 1 });
     884                $$self{DOC_NUM} = 0;
     885            }
     886            return $pt;
     887        },
     888    },
     889);
     890
     891# Samsung MP4 smta information (PH - from SM-C101 sample)
     892%Image::ExifTool::Samsung::smta = (
     893    GROUPS => { 0 => 'MakerNotes', 2 => 'Video' },
     894    NOTES => q{
     895        This information is found in the smta atom of Samsung MP4 videos from models
     896        such as the Galaxy S4.
     897    },
     898    svss => {
     899        Name => 'SamsungSvss',
     900        SubDirectory => { TagTable => 'Image::ExifTool::Samsung::svss' },
     901    },
     902    # swtr - 4 bytes, all zero
     903    # scid - 8 bytes, all zero
     904    # saut - 4 bytes, all zero
     905);
     906
     907# Samsung MP4 svss information (PH - from SM-C101 sample)
     908%Image::ExifTool::Samsung::svss = (
     909    GROUPS => { 0 => 'MakerNotes', 2 => 'Video' },
     910    NOTES => q{
     911        This information is found in the svss atom of Samsung MP4 videos from models
     912        such as the Galaxy S4.
     913    },
     914    # junk - 10240 bytes, all zero
     915);
     916
     917# thumbnail image information found in some MP4 videos
     918%Image::ExifTool::Samsung::Thumbnail2 = (
     919    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     920    GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
     921    FIRST_ENTRY => 0,
     922    FORMAT => 'int32u',
     923    1 => 'ThumbnailWidth',
     924    2 => 'ThumbnailHeight',
     925    3 => 'ThumbnailLength',
     926    4 => { Name => 'ThumbnailOffset', IsOffset => 1 },
     927);
     928
     929# information extracted from "ssuniqueid\0" APP5 (ref PH)
     930%Image::ExifTool::Samsung::APP5 = (
     931    GROUPS => { 0 => 'MakerNotes', 2 => 'Camera' },
     932    ssuniqueid => {
     933        Name => 'UniqueID',
     934        # 32 bytes - some sort of serial number?
     935        ValueConv => 'unpack("H*",$val)',
     936    },
     937);
     938
     939# information extracted from Samsung trailer (ie. Samsung SM-T805 "Sound & Shot" JPEG) (ref PH)
     940%Image::ExifTool::Samsung::Trailer = (
     941    GROUPS => { 0 => 'MakerNotes', 2 => 'Other' },
     942    VARS => { NO_ID => 1, HEX_ID => 0 },
     943    NOTES => q{
     944        Tags extracted from the trailer of JPEG images written when using certain
     945        features (such as "Sound & Shot" or "Shot & More") from Samsung models such
     946        as the Galaxy S4 and Tab S.
     947    },
     948    '0x0001-name' => 'EmbeddedImageName', # ("DualShot_1","DualShot_2")
     949    '0x0001' => { Name => 'EmbeddedImage', Groups => { 2 => 'Preview' }, Binary => 1 },
     950    '0x0100-name' => 'EmbeddedAudioFileName', # ("SoundShot_000")
     951    '0x0100' => { Name => 'EmbeddedAudioFile', Groups => { 2 => 'Audio' }, Binary => 1 },
     952    '0x0201-name' => 'SurroundShotVideoName', # ("Interactive_Panorama_000")
     953    '0x0201' => { Name => 'SurroundShotVideo', Groups => { 2 => 'Video' }, Binary => 1 },
     954   # 0x0800-name - seen 'SoundShot_Meta_Info'
     955   # 0x0800 - unknown (29 bytes) (contains already-extracted EmbeddedAudioFileName)
     956   # 0x0830-name - seen '1165724808.pre'
     957   # 0x0830 - unknown (164004 bytes)
     958   # 0x08d0-name - seen 'Interactive_Panorama_Info'
     959   # 0x08d0 - unknown (7984 bytes)
     960   # 0x08e0-name - seen 'Panorama_Shot_Info'
     961   # 0x08e0 - string, seen 'PanoramaShot'
     962   # 0x08e1-name - seen 'Motion_Panorama_Info'
     963   # 0x0910-name - seen 'Front_Cam_Selfie_Info'
     964   # 0x0910 - string, seen 'Front_Cam_Selfie_Info'
     965   # 0x09e0-name - seen 'Burst_Shot_Info'
     966   # 0x09e0 - string, seen '489489125'
     967   # 0x0a01-name - seen 'Image_UTC_Data'
     968    '0x0a01' => { #forum7161
     969        Name => 'TimeStamp',
     970        Groups => { 2 => 'Time' },
     971        ValueConv => 'ConvertUnixTime($val / 1e3, 1)',
     972        PrintConv => '$self->ConvertDateTime($val)',
     973    },
     974    '0x0a20-name' => 'DualCameraImageName', # ("FlipPhoto_002")
     975    '0x0a20' => { Name => 'DualCameraImage', Groups => { 2 => 'Preview' }, Binary => 1 },
     976    '0x0a30-name' => 'EmbeddedVideoType', # ("MotionPhoto_Data")
     977    '0x0a30' => { Name => 'EmbeddedVideoFile', Groups => { 2 => 'Video' }, Binary => 1 }, #forum7161
     978   # 0x0aa1-name - seen 'MCC_Data'
     979   # 0x0aa1 - seen '234','222','429'
     980   # 0x0ab0-name - seen 'DualShot_Meta_Info'
     981    '0x0ab1-name' => 'DepthMapName', # seen 'DualShot_DepthMap_1' (SM-N950U)
     982    '0x0ab1' => { Name => 'DepthMapData', Binary => 1 },
     983   # 0x0ab3-name - seen 'DualShot_Extra_Info' (SM-N950U)
     984    '0x0ab3' => { # (SM-N950U)
     985        Name => 'DualShotExtra',
     986        SubDirectory => { TagTable => 'Image::ExifTool::Samsung::DualShotExtra' },
     987     },
     988   # 0x0ac0-name - seen 'ZoomInOut_Info' (SM-N950U)
     989   # 0x0ac0 - 2048 bytes of interesting stuff including firmware version? (SM-N950U)
     990    '0x0b40' => { # (SM-N975X front camera)
     991        Name => 'SingleShotMeta',
     992        SubDirectory => { TagTable => 'Image::ExifTool::Samsung::SingleShotMeta' },
     993     },
     994   # 0x0b41-name - seen 'SingeShot_DepthMap_1' (Yes, "Singe") (SM-N975X front camera)
     995    '0x0b41' => { Name => 'SingleShotDepthMap', Binary => 1 },
     996   # 0xa050-name - seen 'Jpeg360_2D_Info' (Samsung Gear 360)
     997   # 0xa050 - seen 'Jpeg3602D' (Samsung Gear 360)
     998);
     999
     1000# DualShot Extra Info (ref PH)
     1001%Image::ExifTool::Samsung::DualShotExtra = (
     1002    PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
     1003    GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
     1004    FIRST_ENTRY => 0,
     1005    FORMAT => 'int32u',
     1006    # This is a pain, but the DepthMapWidth/Height move around in this record.
     1007    # In all of my samples so far, the bytes "01 00 ff ff" precede these tags.
     1008    # I have seen this byte sequence at offsets 32, 60, 64 and 68, so look for
     1009    # it in bytes 32-95, and use its location to adjust the tag positions
     1010    8 => {
     1011        Name => 'DualShotDummy',
     1012        Format => 'undef[64]',
     1013        Hidden => 1,
     1014        Hook => q{
     1015            if ($size >= 96) {
     1016                my $tmp = substr($$dataPt, $pos, 64);
     1017                if ($tmp =~ /\x01\0\xff\xff/g and not pos($tmp) % 4) {
     1018                    $$self{DepthMapTagPos} = pos($tmp);
     1019                    $varSize += $$self{DepthMapTagPos} - 32;
     1020                }
     1021            }
     1022        },
     1023        RawConv => 'undef', # not a real tag
     1024    },
     1025    16 => {
     1026        Name => 'DepthMapWidth',
     1027        Condition => '$$self{DepthMapTagPos}',
     1028        Notes => 'index varies depending on model',
     1029    },
     1030    17 => {
     1031        Name => 'DepthMapHeight',
     1032        Condition => '$$self{DepthMapTagPos}',
     1033        Notes => 'index varies depending on model',
     1034    },
     1035);
     1036
     1037# SingleShot Meta Info (ref PH) (SM-N975X front camera)
     1038%Image::ExifTool::Samsung::SingleShotMeta = (
     1039    PROCESS_PROC => \&ProcessSamsungMeta,
     1040    GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
     1041    inputWidth          => { },
     1042    inputHeight         => { },
     1043    outputWidth         => { },
     1044    outputHeight        => { },
     1045    segWidth            => { },
     1046    segHeight           => { },
     1047    depthSWWidth        => { },
     1048    depthSWHeight       => { },
     1049    depthHWWidth        => { },
     1050    depthHWHeight       => { },
     1051    flipStatus          => { },
     1052    lensFacing          => { },
     1053    deviceOrientation   => { },
     1054    objectOrientation   => { },
     1055    isArtBokeh          => { },
     1056    beautyRetouchLevel  => { },
     1057    beautyColorLevel    => { },
     1058    effectType          => { },
     1059    effectStrength      => { },
     1060    blurStrength        => { },
     1061    spinStrength        => { },
     1062    zoomStrength        => { },
     1063    colorpopStrength    => { },
     1064    monoStrength        => { },
     1065    sidelightStrength   => { },
     1066    vintageStrength     => { },
     1067    bokehShape          => { },
     1068    perfMode            => { },
    5201069);
    5211070
     
    5331082            $a[$_] -= $b[$_] foreach 0..$#a;
    5341083            return "@a";
     1084        },
     1085    },
     1086    DepthMapTiff => {
     1087        Require => {
     1088            0 => 'DepthMapData',
     1089            1 => 'DepthMapWidth',
     1090            2 => 'DepthMapHeight',
     1091        },
     1092        ValueConv => q{
     1093            return undef unless length ${$val[0]} == $val[1] * $val[2];
     1094            my $tiff = MakeTiffHeader($val[1],$val[2],1,8) . ${$val[0]};
     1095            return \$tiff;
     1096        },
     1097    },
     1098    SingleShotDepthMapTiff => {
     1099        Require => {
     1100            0 => 'SingleShotDepthMap',
     1101            1 => 'SegWidth',
     1102            2 => 'SegHeight',
     1103        },
     1104        ValueConv => q{
     1105            return undef unless length ${$val[0]} == $val[1] * $val[2];
     1106            my $tiff = MakeTiffHeader($val[1],$val[2],1,8) . ${$val[0]};
     1107            return \$tiff;
    5351108        },
    5361109    },
     
    5511124sub Crypt($$$@)
    5521125{
    553     my ($exifTool, $val, $tagInfo, @salt) = @_;
    554     my $key = $$exifTool{EncryptionKey} or return undef;
     1126    my ($et, $val, $tagInfo, @salt) = @_;
     1127    my $key = $$et{EncryptionKey} or return undef;
    5551128    my $format = $$tagInfo{Writable} || $$tagInfo{Format} or return undef;
    5561129    return undef unless $formatMinMax{$format};
     
    5831156sub ProcessINFO($$$)
    5841157{
    585     my ($exifTool, $dirInfo, $tagTablePtr) = @_;
     1158    my ($et, $dirInfo, $tagTablePtr) = @_;
    5861159    my $dataPt = $$dirInfo{DataPt};
    5871160    my $pos = $$dirInfo{DirStart};
    5881161    my $len = $$dirInfo{DirLen};
    5891162    my $end = $pos + $len;
    590     $exifTool->VerboseDir('INFO', undef, $len);
     1163    $et->VerboseDir('INFO', undef, $len);
    5911164    while ($pos + 8 <= $end) {
    5921165        my $tag = substr($$dataPt, $pos, 4);
     
    5951168            my $name = "Samsung_INFO_$tag";
    5961169            $name =~ tr/-_0-9a-zA-Z//dc;
    597             Image::ExifTool::AddTagToTable($tagTablePtr, $tag, { Name => $name }) if $name;
     1170            AddTagToTable($tagTablePtr, $tag, { Name => $name }) if $name;
    5981171        }
    599         $exifTool->HandleTag($tagTablePtr, $tag, $val);
     1172        $et->HandleTag($tagTablePtr, $tag, $val);
    6001173        $pos += 8;
    6011174    }
    6021175    return 1;
     1176}
     1177
     1178#------------------------------------------------------------------------------
     1179# Read Samsung Meta Info from trailer
     1180# Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref
     1181# Returns: true on success
     1182sub ProcessSamsungMeta($$$)
     1183{
     1184    my ($et, $dirInfo, $tagTablePtr) = @_;
     1185    my $dirName = $$dirInfo{DirName};
     1186    my $dataPt = $$dirInfo{DataPt};
     1187    my $pos = $$dirInfo{DirStart};
     1188    my $end = $$dirInfo{DirLen} + $pos;
     1189    unless ($pos + 8 <= $end and substr($$dataPt, $pos, 4) eq 'DOFS') {
     1190        $et->Warn("Unrecognized $dirName data");
     1191        return 0;
     1192    }
     1193    my $ver = Get32u($dataPt, $pos + 4);
     1194    if ($ver == 3) {
     1195        unless ($pos + 18 <= $end and Get32u($dataPt, $pos + 12) == $$dirInfo{DirLen}) {
     1196            $et->Warn("Unrecognized $dirName version $ver data");
     1197            return 0;
     1198        }
     1199        my $num = Get16u($dataPt, $pos + 16);
     1200        $et->VerboseDir("$dirName version $ver", $num);
     1201        $pos += 18;
     1202        my ($i, $val);
     1203        for ($i=0; $i<$num; ++$i) {
     1204            last if $pos + 2 > $end;
     1205            my ($x, $n) = unpack("x${pos}CC", $$dataPt);
     1206            $pos += 2;
     1207            last if $pos + $n + 2 > $end;
     1208            my $tag = substr($$dataPt, $pos, $n);
     1209            my $len = Get16u($dataPt, $pos + $n);
     1210            $pos += $n + 2;
     1211            last if $pos + $len > $end;
     1212            if ($len == 4) {
     1213                $val = Get32u($dataPt, $pos);
     1214            } else {
     1215                my $tmp = substr($$dataPt, $pos, $len);
     1216                $val = \$pos;
     1217            }
     1218            $et->HandleTag($tagTablePtr, $tag, $val);
     1219            $pos += $len;
     1220        }
     1221        $et->Warn("Unexpected end of $dirName version $ver $i $num data") if $i < $num;
     1222    }
     1223    return 1;
     1224}
     1225
     1226#------------------------------------------------------------------------------
     1227# Inputs: 0) ExifTool object ref, 1) source dirInfo ref, 2) tag table ref
     1228# Returns: true on success
     1229sub ProcessSamsungIFD($$$)
     1230{
     1231    my ($et, $dirInfo, $tagTablePtr) = @_;
     1232    my $len = $$dirInfo{DataLen};
     1233    my $pos = $$dirInfo{DirStart};
     1234    return 0 unless $pos + 4 < $len;
     1235    my $dataPt = $$dirInfo{DataPt};
     1236    my $buff = substr($$dataPt, $pos, 4);
     1237    # this is not an IFD for many models
     1238    # (the string "Park Byeongchan" is often found here)
     1239    return 0 unless $buff =~ s/^([^\0])\0\0\0/$1\0$1\0/s;
     1240    my $numEntries = ord $1;
     1241    if ($$et{HTML_DUMP}) {
     1242        my $pt = $$dirInfo{DirStart} + $$dirInfo{DataPos} + $$dirInfo{Base};
     1243        $et->HDump($pt-44, 44, "MakerNotes header", 'Samsung');
     1244        $et->HDump($pt, 4, "MakerNotes entries", "Format: int32u\nEntry count: $numEntries");
     1245        $$dirInfo{NoDumpEntryCount} = 1;
     1246    }
     1247    substr($$dataPt, $pos, 4) = $buff;      # insert bogus 2-byte entry count
     1248    # offset base is at end of IFD
     1249    my $shift = $$dirInfo{DirStart} + 4 + $numEntries * 12 + 4;
     1250    $$dirInfo{Base} += $shift;
     1251    $$dirInfo{DataPos} -= $shift;
     1252    $$dirInfo{DirStart} += 2;       # start at bogus entry count
     1253    $$dirInfo{ZeroOffsetOK} = 1;    # disable check for zero offset
     1254    delete $$et{NO_UNKNOWN};  # (set for BinaryData, but not for EXIF IFD's)
     1255    my $rtn = Image::ExifTool::Exif::ProcessExif($et, $dirInfo, $tagTablePtr);
     1256    substr($$dataPt, $pos + 2, 1) = "\0";   # remove bogus count
     1257    return $rtn;
     1258}
     1259
     1260#------------------------------------------------------------------------------
     1261# Read/write Samsung trailer (ie. "Sound & Shot" written by Galaxy Tab S (SM-T805))
     1262# Inputs: 0) ExifTool object reference, 1) dirInfo reference
     1263# Returns: 1 on success, 0 not valid Samsung trailer, or -1 error writing
     1264# - updates DataPos to point to start of Samsung trailer
     1265# - updates DirLen to existing trailer length
     1266sub ProcessSamsung($$$)
     1267{
     1268    my ($et, $dirInfo) = @_;
     1269    my $raf = $$dirInfo{RAF};
     1270    my $offset = $$dirInfo{Offset} || 0;
     1271    my $outfile = $$dirInfo{OutFile};
     1272    my $verbose = $et->Options('Verbose');
     1273    my $unknown = $et->Options('Unknown');
     1274    my ($buff, $buf2, $index, $offsetPos, $audioNOff, $audioSize);
     1275
     1276    return 0 unless $raf->Seek(-6-$offset, 2) and $raf->Read($buff, 6) == 6 and
     1277                    ($buff eq 'QDIOBS' or $buff eq "\0\0SEFT");
     1278    my $endPos = $raf->Tell();
     1279    $raf->Seek(-2, 1) or return 0 if $buff eq 'QDIOBS'; # rewind to before 'BS'
     1280    my $blockEnd = $raf->Tell();
     1281    SetByteOrder('II');
     1282
     1283    # read blocks backward until we find the SEFH/SEFT block
     1284    # (the only other block I have seen is QDIO/QDIO)
     1285SamBlock:
     1286    for (;;) {
     1287        last unless $raf->Seek($blockEnd-8, 0) and $raf->Read($buff, 8) == 8;
     1288        my $type = substr($buff, 4);
     1289        last unless $type =~ /^\w+$/;
     1290        my $len = Get32u(\$buff, 0);
     1291        last unless $len < 0x10000 and $len >= 4 and $len + 8 < $blockEnd;
     1292        last unless $raf->Seek(-8-$len, 1) and $raf->Read($buff, $len) == $len;
     1293        $blockEnd -= $len + 8;
     1294        unless ($type eq 'SEFT') {  # look for directory block (ends with "SEFT")
     1295            next unless $outfile and $type eq 'QDIO';
     1296            # QDIO block format:
     1297            #   0 - 'QDIO'
     1298            #   4 - int32u: 101 (version)
     1299            #   8 - int32u: 1
     1300            #  12 - int32u: absolute offset of audio file start (augh!!)
     1301            #  16 - int32u: absolute offset of audio file end (augh!!)
     1302            #  20 - int32u: 20 (QDIO block length minus 8)
     1303            #  24 - 'QDIO'
     1304            if ($len == 20) {
     1305                # save position of audio file offset in QDIO block
     1306                $offsetPos = $endPos - $raf->Tell() + $len - 12;
     1307            } else {
     1308                $et->Error('Unsupported Samsung trailer QDIO block', 1);
     1309            }
     1310            next;
     1311        }
     1312        last unless $buff =~ /^SEFH/ and $len >= 12;   # validate SEFH header
     1313        my $dirPos = $raf->Tell() - $len;
     1314        # my $ver = Get32u(\$buff, 0x04);  # version (=101)
     1315        my $count = Get32u(\$buff, 0x08);
     1316        last if 12 + 12 * $count > $len;
     1317        my $tagTablePtr = GetTagTable('Image::ExifTool::Samsung::Trailer');
     1318
     1319        # scan ahead quickly to look for the block where the data comes first
     1320        # (have only seen this to be the first in the directory, but just in case)
     1321        my $firstBlock = 0;
     1322        for ($index=0; $index<$count; ++$index) {
     1323            my $entry = 12 + 12 * $index;
     1324            my $noff = Get32u(\$buff, $entry + 4);  # negative offset
     1325            $firstBlock = $noff if $firstBlock < $noff;
     1326        }
     1327        # save trailer position and length
     1328        my $dataPos = $$dirInfo{DataPos} = $dirPos - $firstBlock;
     1329        my $dirLen = $$dirInfo{DirLen} = $endPos - $dataPos;
     1330        if (($verbose or $$et{HTML_DUMP}) and not $outfile) {
     1331            $et->DumpTrailer($dirInfo);
     1332            return 1 if $$et{HTML_DUMP};
     1333        }
     1334        # read through the SEFH/SEFT directory entries
     1335        for ($index=0; $index<$count; ++$index) {
     1336            my $entry = 12 + 12 * $index;
     1337            # first 2 bytes always 0 (may be part of block type)
     1338            my $type = Get16u(\$buff, $entry + 2);  # block type
     1339            my $noff = Get32u(\$buff, $entry + 4);  # negative offset
     1340            my $size = Get32u(\$buff, $entry + 8);  # block size
     1341            last SamBlock if $noff > $dirPos or $size > $noff or $size < 8;
     1342            $firstBlock = $noff if $firstBlock < $noff;
     1343            if ($outfile) {
     1344                next unless $type == 0x0100 and not $audioNOff;
     1345                # save offset and length of first audio file for QDIO block
     1346                last unless $raf->Seek($dirPos-$noff, 0) and $raf->Read($buf2, 8) == 8;
     1347                $len = Get32u(\$buf2, 4);
     1348                $audioNOff = $noff - 8 - $len;   # negative offset to start of audio data
     1349                $audioSize = $size - 8 - $len;
     1350                next;
     1351            }
     1352            # add unknown tags if necessary
     1353            my $tag = sprintf("0x%.4x", $type);
     1354            unless ($$tagTablePtr{$tag}) {
     1355                next unless $unknown or $verbose;
     1356                my %tagInfo = (
     1357                    Name        => "SamsungTrailer_$tag",
     1358                    Description => "Samsung Trailer $tag",
     1359                    Unknown     => 1,
     1360                    Binary      => 1,
     1361                );
     1362                AddTagToTable($tagTablePtr, $tag, \%tagInfo);
     1363            }
     1364            unless ($$tagTablePtr{"$tag-name"}) {
     1365                my %tagInfo2 = (
     1366                    Name        => "SamsungTrailer_${tag}Name",
     1367                    Description => "Samsung Trailer $tag Name",
     1368                    Unknown     => 1,
     1369                );
     1370                AddTagToTable($tagTablePtr, "$tag-name", \%tagInfo2);
     1371            }
     1372            last unless $raf->Seek($dirPos-$noff, 0) and $raf->Read($buf2, $size) == $size;
     1373            # (could validate the first 4 bytes of the block because they
     1374            # are the same as the first 4 bytes of the directory entry)
     1375            $len = Get32u(\$buf2, 4);
     1376            last if $len + 8 > $size;
     1377            # extract tag name and value
     1378            $et->HandleTag($tagTablePtr, "$tag-name", undef,
     1379                DataPt  => \$buf2,
     1380                DataPos => $dirPos - $noff,
     1381                Start   => 8,
     1382                Size    => $len,
     1383            );
     1384            $et->HandleTag($tagTablePtr, $tag, undef,
     1385                DataPt  => \$buf2,
     1386                DataPos => $dirPos - $noff,
     1387                Start   => 8 + $len,
     1388                Size    => $size - (8 + $len),
     1389            );
     1390        }
     1391        if ($outfile) {
     1392            last unless $raf->Seek($dataPos, 0) and $raf->Read($buff, $dirLen) == $dirLen;
     1393            # adjust the absolute offset in the QDIO block if necessary
     1394            if ($offsetPos and $audioNOff) {
     1395                # initialize the audio file start/end position in the QDIO block
     1396                my $newPos = Tell($outfile) + $dirPos - $audioNOff - $dataPos;
     1397                Set32u($newPos, \$buff, length($buff) - $offsetPos);
     1398                Set32u($newPos + $audioSize, \$buff, length($buff) - $offsetPos + 4);
     1399                # add a fixup so the calling routine can apply further shifts if necessary
     1400                require Image::ExifTool::Fixup;
     1401                my $fixup = $$dirInfo{Fixup};
     1402                $fixup or $fixup = $$dirInfo{Fixup} = new Image::ExifTool::Fixup;
     1403                $fixup->AddFixup(length($buff) - $offsetPos);
     1404                $fixup->AddFixup(length($buff) - $offsetPos + 4);
     1405            }
     1406            $et->VPrint(0, "Writing Samsung trailer ($dirLen bytes)\n") if $verbose;
     1407            Write($$dirInfo{OutFile}, $buff) or return -1;
     1408            return 1;
     1409        }
     1410        return 1;
     1411    }
     1412    $et->Warn('Error processing Samsung trailer',1);
     1413    return 0;
    6031414}
    6041415
     
    6091420sub WriteSTMN($$$)
    6101421{
    611     my ($exifTool, $dirInfo, $tagTablePtr) = @_;
     1422    my ($et, $dirInfo, $tagTablePtr) = @_;
    6121423    # create a Fixup for the PreviewImage
    6131424    $$dirInfo{Fixup} = new Image::ExifTool::Fixup;
    614     my $val = Image::ExifTool::WriteBinaryData($exifTool, $dirInfo, $tagTablePtr);
     1425    my $val = Image::ExifTool::WriteBinaryData($et, $dirInfo, $tagTablePtr);
    6151426    # force PreviewImage into the trailer even if it fits in EXIF segment
    616     $$exifTool{PREVIEW_INFO}{IsTrailer} = 1 if $$exifTool{PREVIEW_INFO};
     1427    $$et{PREVIEW_INFO}{IsTrailer} = 1 if $$et{PREVIEW_INFO};
    6171428    return $val;
    6181429}
     
    6371448=head1 AUTHOR
    6381449
    639 Copyright 2003-2011, Phil Harvey (phil at owl.phy.queensu.ca)
     1450Copyright 2003-2021, Phil Harvey (philharvey66 at gmail.com)
    6401451
    6411452This library is free software; you can redistribute it and/or modify it
    6421453under the same terms as Perl itself.
    6431454
     1455=head1 REFERENCES
     1456
     1457=over 4
     1458
     1459=item L<http://www.cybercom.net/~dcoffin/dcraw/>
     1460
     1461=back
     1462
    6441463=head1 ACKNOWLEDGEMENTS
    6451464
    646 Thanks to Tae-Sun Park for decoding a number of tags.
     1465Thanks to Tae-Sun Park for decoding a number of tags, Pascal de Bruijn for
     1466the PictureWizard values, and everyone else who helped by discovering new
     1467Samsung information.
    6471468
    6481469=head1 SEE ALSO
Note: See TracChangeset for help on using the changeset viewer.