<html><head><meta name="color-scheme" content="light dark"></head><body><pre style="word-wrap: break-word; white-space: pre-wrap;">#------------------------------------------------------------------------------
# File:         NikonCapture.pm
#
# Description:  Read/write Nikon Capture information
#
# Revisions:    11/08/2005 - P. Harvey Created
#               10/10/2008 - P. Harvey Updated for Capture NX 2
#               16/04/2011 - P. Harvey Decode NikonCaptureEditVersions
#
# References:   1) http://www.cybercom.net/~dcoffin/dcraw/
#               IB) Iliah Borg private communication (LibRaw)
#------------------------------------------------------------------------------

package Image::ExifTool::NikonCapture;

use strict;
use vars qw($VERSION);
use Image::ExifTool qw(:DataAccess :Utils);
use Image::ExifTool::Exif;

$VERSION = '1.14';

sub ProcessNikonCapture($$$);

# common print conversions
my %offOn = ( 0 =&gt; 'Off', 1 =&gt; 'On' );
my %noYes = ( 0 =&gt; 'No', 1 =&gt; 'Yes' );
my %unsharpColor = (
    0 =&gt; 'RGB',
    1 =&gt; 'Red',
    2 =&gt; 'Green',
    3 =&gt; 'Blue',
    4 =&gt; 'Yellow',
    5 =&gt; 'Magenta',
    6 =&gt; 'Cyan',
);

# Nikon Capture data (ref PH)
%Image::ExifTool::NikonCapture::Main = (
    PROCESS_PROC =&gt; \&amp;ProcessNikonCapture,
    WRITE_PROC =&gt; \&amp;WriteNikonCapture,
    CHECK_PROC =&gt; \&amp;Image::ExifTool::Exif::CheckExif,
    GROUPS =&gt; { 0 =&gt; 'MakerNotes', 2 =&gt; 'Image' },
    NOTES =&gt; q{
        This information is written by the Nikon Capture software in tag 0x0e01 of
        the maker notes of NEF images.
    },
    # 0x007ddc9d contains contrast information
    0x008ae85e =&gt; {
        Name =&gt; 'LCHEditor',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%offOn,
    },
    0x0c89224b =&gt; {
        Name =&gt; 'ColorAberrationControl',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%offOn,
    },
    0x116fea21 =&gt; {
        Name =&gt; 'HighlightData',
        SubDirectory =&gt; {
            TagTable =&gt; 'Image::ExifTool::NikonCapture::HighlightData',
        },
    },
    0x2175eb78 =&gt; {
        Name =&gt; 'D-LightingHQ',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%offOn,
    },
    0x2fc08431 =&gt; {
        Name =&gt; 'StraightenAngle',
        Writable =&gt; 'double',
    },
    0x374233e0 =&gt; {
        Name =&gt; 'CropData',
        SubDirectory =&gt; {
            TagTable =&gt; 'Image::ExifTool::NikonCapture::CropData',
        },
    },
    0x39c456ac =&gt; {
        Name =&gt; 'PictureCtrl',
        SubDirectory =&gt; {
            TagTable =&gt; 'Image::ExifTool::NikonCapture::PictureCtrl',
        },
    },
    0x3cfc73c6 =&gt; {
        Name =&gt; 'RedEyeData',
        SubDirectory =&gt; {
            TagTable =&gt; 'Image::ExifTool::NikonCapture::RedEyeData',
        },
    },
    0x3d136244 =&gt; {
        Name =&gt; 'EditVersionName',
        Writable =&gt; 'string', # (null terminated)
    },
    # 0x3e726567 added when I rotated by 90 degrees
    0x416391c6 =&gt; {
        Name =&gt; 'QuickFix',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%offOn,
    },
    0x56a54260 =&gt; {
        Name =&gt; 'Exposure',
        SubDirectory =&gt; {
            TagTable =&gt; 'Image::ExifTool::NikonCapture::Exposure',
        },
    },
    0x5f0e7d23 =&gt; {
        Name =&gt; 'ColorBooster',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%offOn,
    },
    0x6a6e36b6 =&gt; {
        Name =&gt; 'D-LightingHQSelected',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%noYes,
    },
    0x753dcbc0 =&gt; {
        Name =&gt; 'NoiseReduction',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%offOn,
    },
    0x76a43200 =&gt; {
        Name =&gt; 'UnsharpMask',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%offOn,
    },
    0x76a43201 =&gt; {
        Name =&gt; 'Curves',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%offOn,
    },
    0x76a43202 =&gt; {
        Name =&gt; 'ColorBalanceAdj',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%offOn,
    },
    0x76a43203 =&gt; {
        Name =&gt; 'AdvancedRaw',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%offOn,
    },
    0x76a43204 =&gt; {
        Name =&gt; 'WhiteBalanceAdj',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%offOn,
    },
    0x76a43205 =&gt; {
        Name =&gt; 'VignetteControl',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%offOn,
    },
    0x76a43206 =&gt; {
        Name =&gt; 'FlipHorizontal',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%noYes,
    },
    0x76a43207 =&gt; { # rotation angle in degrees
        Name =&gt; 'Rotation',
        Writable =&gt; 'int16u',
    },
    0x083a1a25 =&gt; {
        Name =&gt; 'HistogramXML',
        Writable =&gt; 'undef',
        Binary =&gt; 1,
        AdjustSize =&gt; 4,    # patch Nikon bug
    },
    0x84589434 =&gt; {
        Name =&gt; 'BrightnessData',
        SubDirectory =&gt; {
            TagTable =&gt; 'Image::ExifTool::NikonCapture::Brightness',
        },
    },
  # 0x88f55e48 - related to QuickFix
    0x890ff591 =&gt; {
        Name =&gt; 'D-LightingHQData',
        SubDirectory =&gt; {
            TagTable =&gt; 'Image::ExifTool::NikonCapture::DLightingHQ',
        },
    },
    0x926f13e0 =&gt; {
        Name =&gt; 'NoiseReductionData',
        SubDirectory =&gt; {
            TagTable =&gt; 'Image::ExifTool::NikonCapture::NoiseReduction',
        },
    },
    0x9ef5f6e0 =&gt; {
        Name =&gt; 'IPTCData',
        SubDirectory =&gt; {
            TagTable =&gt; 'Image::ExifTool::IPTC::Main',
        },
    },
  # 0xa7264a72 - related to QuickFix
    0xab5eca5e =&gt; {
        Name =&gt; 'PhotoEffects',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%offOn,
    },
    0xac6bd5c0 =&gt; {
        Name =&gt; 'VignetteControlIntensity',
        Writable =&gt; 'int16s',
    },
    0xb0384e1e =&gt; {
        Name =&gt; 'PhotoEffectsData',
        SubDirectory =&gt; {
            TagTable =&gt; 'Image::ExifTool::NikonCapture::PhotoEffects',
        },
    },
    0xb999a36f =&gt; {
        Name =&gt; 'ColorBoostData',
        SubDirectory =&gt; {
            TagTable =&gt; 'Image::ExifTool::NikonCapture::ColorBoost',
        },
    },
    0xbf3c6c20 =&gt; {
        Name =&gt; 'WBAdjData',
        SubDirectory =&gt; {
            TagTable =&gt; 'Image::ExifTool::NikonCapture::WBAdjData',
        },
    },
    0xce5554aa =&gt; {
        Name =&gt; 'D-LightingHS',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%offOn,
    },
    0xe2173c47 =&gt; {
        Name =&gt; 'PictureControl',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%offOn,
    },
    0xe37b4337 =&gt; {
        Name =&gt; 'D-LightingHSData',
        SubDirectory =&gt; {
            TagTable =&gt; 'Image::ExifTool::NikonCapture::DLightingHS',
        },
    },
    0xe42b5161 =&gt; {
        Name =&gt; 'UnsharpData',
        SubDirectory =&gt; {
            TagTable =&gt; 'Image::ExifTool::NikonCapture::UnsharpData',
        },
    },
    0xe9651831 =&gt; {
        Name =&gt; 'PhotoEffectHistoryXML',
        Binary =&gt; 1,
        Writable =&gt; 'undef',
    },
    0xfe28a44f =&gt; {
        Name =&gt; 'AutoRedEye',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%offOn, # (have seen a value of 28 here for older software?)
    },
    0xfe443a45 =&gt; {
        Name =&gt; 'ImageDustOff',
        Writable =&gt; 'int8u',
        PrintConv =&gt; \%offOn,
    },
);

%Image::ExifTool::NikonCapture::UnsharpData = (
    PROCESS_PROC =&gt; \&amp;Image::ExifTool::ProcessBinaryData,
    WRITE_PROC =&gt; \&amp;Image::ExifTool::WriteBinaryData,
    CHECK_PROC =&gt; \&amp;Image::ExifTool::CheckBinaryData,
    WRITABLE =&gt; 1,
    FORMAT =&gt; 'int8u',
    FIRST_ENTRY =&gt; 0,
    GROUPS =&gt; { 0 =&gt; 'MakerNotes', 2 =&gt; 'Image' },
    0 =&gt; 'UnsharpCount',
    19 =&gt; { Name =&gt; 'Unsharp1Color', Format =&gt; 'int16u', PrintConv =&gt; \%unsharpColor },
    23 =&gt; { Name =&gt; 'Unsharp1Intensity', Format =&gt; 'int16u' },
    25 =&gt; { Name =&gt; 'Unsharp1HaloWidth', Format =&gt; 'int16u' },
    27 =&gt; 'Unsharp1Threshold',
    46 =&gt; { Name =&gt; 'Unsharp2Color', Format =&gt; 'int16u', PrintConv =&gt; \%unsharpColor },
    50 =&gt; { Name =&gt; 'Unsharp2Intensity', Format =&gt; 'int16u' },
    52 =&gt; { Name =&gt; 'Unsharp2HaloWidth', Format =&gt; 'int16u' },
    54 =&gt; 'Unsharp2Threshold',
    73 =&gt; { Name =&gt; 'Unsharp3Color', Format =&gt; 'int16u', PrintConv =&gt; \%unsharpColor },
    77 =&gt; { Name =&gt; 'Unsharp3Intensity', Format =&gt; 'int16u' },
    79 =&gt; { Name =&gt; 'Unsharp3HaloWidth', Format =&gt; 'int16u' },
    81 =&gt; 'Unsharp3Threshold',
    100 =&gt; { Name =&gt; 'Unsharp4Color', Format =&gt; 'int16u', PrintConv =&gt; \%unsharpColor },
    104 =&gt; { Name =&gt; 'Unsharp4Intensity', Format =&gt; 'int16u' },
    106 =&gt; { Name =&gt; 'Unsharp4HaloWidth', Format =&gt; 'int16u' },
    108 =&gt; 'Unsharp4Threshold',
    # there could be more, but I grow bored of this... :P
);

%Image::ExifTool::NikonCapture::DLightingHS = (
    PROCESS_PROC =&gt; \&amp;Image::ExifTool::ProcessBinaryData,
    WRITE_PROC =&gt; \&amp;Image::ExifTool::WriteBinaryData,
    CHECK_PROC =&gt; \&amp;Image::ExifTool::CheckBinaryData,
    WRITABLE =&gt; 1,
    FORMAT =&gt; 'int32u',
    FIRST_ENTRY =&gt; 0,
    GROUPS =&gt; { 0 =&gt; 'MakerNotes', 2 =&gt; 'Image' },
    0 =&gt; 'D-LightingHSAdjustment',
    1 =&gt; 'D-LightingHSColorBoost',
);

%Image::ExifTool::NikonCapture::DLightingHQ = (
    PROCESS_PROC =&gt; \&amp;Image::ExifTool::ProcessBinaryData,
    WRITE_PROC =&gt; \&amp;Image::ExifTool::WriteBinaryData,
    CHECK_PROC =&gt; \&amp;Image::ExifTool::CheckBinaryData,
    WRITABLE =&gt; 1,
    FORMAT =&gt; 'int32u',
    FIRST_ENTRY =&gt; 0,
    GROUPS =&gt; { 0 =&gt; 'MakerNotes', 2 =&gt; 'Image' },
    0 =&gt; 'D-LightingHQShadow',
    1 =&gt; 'D-LightingHQHighlight',
    2 =&gt; 'D-LightingHQColorBoost',
);

%Image::ExifTool::NikonCapture::ColorBoost = (
    PROCESS_PROC =&gt; \&amp;Image::ExifTool::ProcessBinaryData,
    WRITE_PROC =&gt; \&amp;Image::ExifTool::WriteBinaryData,
    CHECK_PROC =&gt; \&amp;Image::ExifTool::CheckBinaryData,
    WRITABLE =&gt; 1,
    FORMAT =&gt; 'int8u',
    FIRST_ENTRY =&gt; 0,
    GROUPS =&gt; { 0 =&gt; 'MakerNotes', 2 =&gt; 'Image' },
    0 =&gt; {
        Name =&gt; 'ColorBoostType',
        PrintConv =&gt; {
            0 =&gt; 'Nature',
            1 =&gt; 'People',
        },
    },
    1 =&gt; {
        Name =&gt; 'ColorBoostLevel',
        Format =&gt; 'int32u',
    },
);

%Image::ExifTool::NikonCapture::WBAdjData = (
    PROCESS_PROC =&gt; \&amp;Image::ExifTool::ProcessBinaryData,
    WRITE_PROC =&gt; \&amp;Image::ExifTool::WriteBinaryData,
    CHECK_PROC =&gt; \&amp;Image::ExifTool::CheckBinaryData,
    WRITABLE =&gt; 1,
    FORMAT =&gt; 'int8u',
    FIRST_ENTRY =&gt; 0,
    GROUPS =&gt; { 0 =&gt; 'MakerNotes', 2 =&gt; 'Image' },
    0x00 =&gt; {
        Name =&gt; 'WBAdjRedBalance',
        Format =&gt; 'double',
    },
    0x08 =&gt; {
        Name =&gt; 'WBAdjBlueBalance',
        Format =&gt; 'double',
    },
    0x10 =&gt; {
        Name =&gt; 'WBAdjMode',
        PrintConv =&gt; {
            1 =&gt; 'Use Gray Point',
            2 =&gt; 'Recorded Value',
            3 =&gt; 'Use Temperature',
            4 =&gt; 'Calculate Automatically',
            5 =&gt; 'Auto2', #IB
            6 =&gt; 'Underwater', #IB
            7 =&gt; 'Auto1',
        },
    },
    0x14 =&gt; { #IB
        Name =&gt; 'WBAdjLighting',
        Format =&gt; 'int16u',
        PrintHex =&gt; 1,
        PrintConv =&gt; {
            0x000 =&gt; 'None',
            0x100 =&gt; 'Incandescent',
            0x200 =&gt; 'Daylight (direct sunlight)',
            0x201 =&gt; 'Daylight (shade)',
            0x202 =&gt; 'Daylight (cloudy)',
            0x300 =&gt; 'Standard Fluorescent (warm white)',
            0x301 =&gt; 'Standard Fluorescent (3700K)',
            0x302 =&gt; 'Standard Fluorescent (cool white)',
            0x303 =&gt; 'Standard Fluorescent (5000K)',
            0x304 =&gt; 'Standard Fluorescent (daylight)',
            0x305 =&gt; 'Standard Fluorescent (high temperature mercury vapor)',
            0x400 =&gt; 'High Color Rendering Fluorescent (warm white)',
            0x401 =&gt; 'High Color Rendering Fluorescent (3700K)',
            0x402 =&gt; 'High Color Rendering Fluorescent (cool white)',
            0x403 =&gt; 'High Color Rendering Fluorescent (5000K)',
            0x404 =&gt; 'High Color Rendering Fluorescent (daylight)',
            0x500 =&gt; 'Flash',
            0x501 =&gt; 'Flash (FL-G1 filter)',
            0x502 =&gt; 'Flash (FL-G2 filter)',
            0x503 =&gt; 'Flash (TN-A1 filter)',
            0x504 =&gt; 'Flash (TN-A2 filter)',
            0x600 =&gt; 'Sodium Vapor Lamps',
            # 0x1002 =&gt; seen for WBAdjMode modes of Underwater and Calculate Automatically
        },
    },
    0x18 =&gt; {
        Name =&gt; 'WBAdjTemperature',
        Format =&gt; 'int16u',
    },
    0x25 =&gt; {
        Name =&gt; 'WBAdjTint',
        Format =&gt; 'int32s',
    },
);

%Image::ExifTool::NikonCapture::PhotoEffects = (
    PROCESS_PROC =&gt; \&amp;Image::ExifTool::ProcessBinaryData,
    WRITE_PROC =&gt; \&amp;Image::ExifTool::WriteBinaryData,
    CHECK_PROC =&gt; \&amp;Image::ExifTool::CheckBinaryData,
    WRITABLE =&gt; 1,
    FORMAT =&gt; 'int8u',
    FIRST_ENTRY =&gt; 0,
    GROUPS =&gt; { 0 =&gt; 'MakerNotes', 2 =&gt; 'Image' },
    0 =&gt; {
        Name =&gt; 'PhotoEffectsType',
        PrintConv =&gt; {
            0 =&gt; 'None',
            1 =&gt; 'B&amp;W',
            2 =&gt; 'Sepia',
            3 =&gt; 'Tinted',
        },
    },
    4 =&gt; {
        Name =&gt; 'PhotoEffectsRed',
        Format =&gt; 'int16s',
    },
    6 =&gt; {
        Name =&gt; 'PhotoEffectsGreen',
        Format =&gt; 'int16s',
    },
    8 =&gt; {
        Name =&gt; 'PhotoEffectsBlue',
        Format =&gt; 'int16s',
    },
);

%Image::ExifTool::NikonCapture::Brightness = (
    PROCESS_PROC =&gt; \&amp;Image::ExifTool::ProcessBinaryData,
    WRITE_PROC =&gt; \&amp;Image::ExifTool::WriteBinaryData,
    CHECK_PROC =&gt; \&amp;Image::ExifTool::CheckBinaryData,
    WRITABLE =&gt; 1,
    FORMAT =&gt; 'int8u',
    FIRST_ENTRY =&gt; 0,
    GROUPS =&gt; { 0 =&gt; 'MakerNotes', 2 =&gt; 'Image' },
    0 =&gt; {
        Name =&gt; 'BrightnessAdj',
        Format =&gt; 'double',
        ValueConv =&gt; '$val * 50',
        ValueConvInv =&gt; '$val / 50',
    },
    8 =&gt; {
        Name =&gt; 'EnhanceDarkTones',
        PrintConv =&gt; \%offOn,
    },
);

%Image::ExifTool::NikonCapture::NoiseReduction = (
    PROCESS_PROC =&gt; \&amp;Image::ExifTool::ProcessBinaryData,
    WRITE_PROC =&gt; \&amp;Image::ExifTool::WriteBinaryData,
    CHECK_PROC =&gt; \&amp;Image::ExifTool::CheckBinaryData,
    WRITABLE =&gt; 1,
    FORMAT =&gt; 'int8u',
    FIRST_ENTRY =&gt; 0,
    GROUPS =&gt; { 0 =&gt; 'MakerNotes', 2 =&gt; 'Image' },
    0x04 =&gt; {
        Name =&gt; 'EdgeNoiseReduction',
        PrintConv =&gt; \%offOn,
    },
    0x05 =&gt; {
        Name =&gt; 'ColorMoireReductionMode',
        PrintConv =&gt; {
            0 =&gt; 'Off',
            1 =&gt; 'Low',
            2 =&gt; 'Medium',
            3 =&gt; 'High',
        },
    },
    0x09 =&gt; {
        Name =&gt; 'NoiseReductionIntensity',
        Format =&gt; 'int32u',
    },
    0x0d =&gt; {
        Name =&gt; 'NoiseReductionSharpness',
        Format =&gt; 'int32u',
    },
    0x11 =&gt; {
        Name =&gt; 'NoiseReductionMethod',
        Format =&gt; 'int16u',
        PrintConv =&gt; {
            0 =&gt; 'Faster',
            1 =&gt; 'Better Quality',
            2 =&gt; 'Better Quality 2013',
        },
    },
    0x15 =&gt; {
        Name =&gt; 'ColorMoireReduction',
        PrintConv =&gt; \%offOn,
    },
    0x17 =&gt; {
        Name =&gt; 'NoiseReduction',
        PrintConv =&gt; \%offOn,
    },
    0x18 =&gt; {
        Name =&gt; 'ColorNoiseReductionIntensity',
        Format =&gt; 'int32u',
    },
    0x1c =&gt; {
        Name =&gt; 'ColorNoiseReductionSharpness',
        Format =&gt; 'int32u',
    },
);

%Image::ExifTool::NikonCapture::CropData = (
    PROCESS_PROC =&gt; \&amp;Image::ExifTool::ProcessBinaryData,
    WRITE_PROC =&gt; \&amp;Image::ExifTool::WriteBinaryData,
    CHECK_PROC =&gt; \&amp;Image::ExifTool::CheckBinaryData,
    WRITABLE =&gt; 1,
    FORMAT =&gt; 'int8u',
    FIRST_ENTRY =&gt; 0,
    GROUPS =&gt; { 0 =&gt; 'MakerNotes', 2 =&gt; 'Image' },
    0x1e =&gt; {
        Name =&gt; 'CropLeft',
        Format =&gt; 'double',
        ValueConv =&gt; '$val / 2',
        ValueConvInv =&gt; '$val * 2',
    },
    0x26 =&gt; {
        Name =&gt; 'CropTop',
        Format =&gt; 'double',
        ValueConv =&gt; '$val / 2',
        ValueConvInv =&gt; '$val * 2',
    },
    0x2e =&gt; {
        Name =&gt; 'CropRight',
        Format =&gt; 'double',
        ValueConv =&gt; '$val / 2',
        ValueConvInv =&gt; '$val * 2',
    },
    0x36 =&gt; {
        Name =&gt; 'CropBottom',
        Format =&gt; 'double',
        ValueConv =&gt; '$val / 2',
        ValueConvInv =&gt; '$val * 2',
    },
    0x8e =&gt; {
        Name =&gt; 'CropOutputWidthInches',
        Format =&gt; 'double',
    },
    0x96 =&gt; {
        Name =&gt; 'CropOutputHeightInches',
        Format =&gt; 'double',
    },
    0x9e =&gt; {
        Name =&gt; 'CropScaledResolution',
        Format =&gt; 'double',
    },
    0xae =&gt; {
        Name =&gt; 'CropSourceResolution',
        Format =&gt; 'double',
        ValueConv =&gt; '$val / 2',
        ValueConvInv =&gt; '$val * 2',
    },
    0xb6 =&gt; {
        Name =&gt; 'CropOutputResolution',
        Format =&gt; 'double',
    },
    0xbe =&gt; {
        Name =&gt; 'CropOutputScale',
        Format =&gt; 'double',
    },
    0xc6 =&gt; {
        Name =&gt; 'CropOutputWidth',
        Format =&gt; 'double',
    },
    0xce =&gt; {
        Name =&gt; 'CropOutputHeight',
        Format =&gt; 'double',
    },
    0xd6 =&gt; {
        Name =&gt; 'CropOutputPixels',
        Format =&gt; 'double',
    },
);

%Image::ExifTool::NikonCapture::PictureCtrl = (
    PROCESS_PROC =&gt; \&amp;Image::ExifTool::ProcessBinaryData,
    WRITE_PROC =&gt; \&amp;Image::ExifTool::WriteBinaryData,
    CHECK_PROC =&gt; \&amp;Image::ExifTool::CheckBinaryData,
    WRITABLE =&gt; 1,
    FORMAT =&gt; 'int8u',
    FIRST_ENTRY =&gt; 0,
    GROUPS =&gt; { 0 =&gt; 'MakerNotes', 2 =&gt; 'Image' },
    0x00 =&gt; {
        Name =&gt; 'PictureControlActive',
        PrintConv =&gt; \%offOn,
    },
    0x13 =&gt; {
        Name =&gt; 'PictureControlMode',
        Format =&gt; 'string[16]',
    },
    # 0x29 changes with Hue and Sharpening
    0x2a =&gt; {
        Name =&gt; 'QuickAdjust',
        ValueConv =&gt; '$val - 128',
        ValueConvInv =&gt; '$val + 128',
    },
    0x2b =&gt; {
        Name =&gt; 'SharpeningAdj',
        ValueConv =&gt; '$val ? $val - 128 : "Auto"',
        ValueConvInv =&gt; '$val=~/\d/ ? $val + 128 : 0',
    },
    0x2c =&gt; {
        Name =&gt; 'ContrastAdj',
        ValueConv =&gt; '$val ? $val - 128 : "Auto"',
        ValueConvInv =&gt; '$val=~/\d/ ? $val + 128 : 0',
    },
    0x2d =&gt; {
        Name =&gt; 'BrightnessAdj',
        ValueConv =&gt; '$val ? $val - 128 : "Auto"', # no "Auto" mode (yet) for this setting
        ValueConvInv =&gt; '$val=~/\d/ ? $val + 128 : 0',
    },
    0x2e =&gt; {
        Name =&gt; 'SaturationAdj',
        ValueConv =&gt; '$val ? $val - 128 : "Auto"',
        ValueConvInv =&gt; '$val=~/\d/ ? $val + 128 : 0',
    },
    0x2f =&gt; {
        Name =&gt; 'HueAdj',
        ValueConv =&gt; '$val - 128',
        ValueConvInv =&gt; '$val + 128',
    },
    # 0x37 changed from 0 to 2 when Picture Control is enabled (and no active DLighting)
);

%Image::ExifTool::NikonCapture::RedEyeData = (
    PROCESS_PROC =&gt; \&amp;Image::ExifTool::ProcessBinaryData,
    WRITE_PROC =&gt; \&amp;Image::ExifTool::WriteBinaryData,
    CHECK_PROC =&gt; \&amp;Image::ExifTool::CheckBinaryData,
    WRITABLE =&gt; 1,
    FORMAT =&gt; 'int8u',
    FIRST_ENTRY =&gt; 0,
    GROUPS =&gt; { 0 =&gt; 'MakerNotes', 2 =&gt; 'Image' },
    0 =&gt; {
        Name =&gt; 'RedEyeCorrection',
        PrintConv =&gt; {
            0 =&gt; 'Off',
            1 =&gt; 'Automatic',
            2 =&gt; 'Click on Eyes',
        },
    },
);

%Image::ExifTool::NikonCapture::Exposure = (
    PROCESS_PROC =&gt; \&amp;Image::ExifTool::ProcessBinaryData,
    WRITE_PROC =&gt; \&amp;Image::ExifTool::WriteBinaryData,
    CHECK_PROC =&gt; \&amp;Image::ExifTool::CheckBinaryData,
    WRITABLE =&gt; 1,
    FORMAT =&gt; 'int8u',
    FIRST_ENTRY =&gt; 0,
    GROUPS =&gt; { 0 =&gt; 'MakerNotes', 2 =&gt; 'Image' },
    0x00 =&gt; {
        Name =&gt; 'ExposureAdj',
        Format =&gt; 'int16s',
        ValueConv =&gt; '$val / 100',
        ValueConvInv =&gt; '$val * 100',
    },
    0x12 =&gt; {
        Name =&gt; 'ExposureAdj2',
        Format =&gt; 'double',
        PrintConv =&gt; 'sprintf("%.4f", $val)',
        PrintConvInv =&gt; '$val',
    },
    0x24 =&gt; {
        Name =&gt; 'ActiveD-Lighting',
        PrintConv =&gt; \%offOn,
    },
    0x25 =&gt; {
        Name =&gt; 'ActiveD-LightingMode',
        PrintConv =&gt; {
            0 =&gt; 'Unchanged',
            1 =&gt; 'Off',
            2 =&gt; 'Low',
            3 =&gt; 'Normal',
            4 =&gt; 'High',
            6 =&gt; 'Extra High',
            7 =&gt; 'Extra High 1',
            8 =&gt; 'Extra High 2',
        },
    },
);

%Image::ExifTool::NikonCapture::HighlightData = (
    PROCESS_PROC =&gt; \&amp;Image::ExifTool::ProcessBinaryData,
    WRITE_PROC =&gt; \&amp;Image::ExifTool::WriteBinaryData,
    CHECK_PROC =&gt; \&amp;Image::ExifTool::CheckBinaryData,
    WRITABLE =&gt; 1,
    FORMAT =&gt; 'int8s',
    FIRST_ENTRY =&gt; 0,
    GROUPS =&gt; { 0 =&gt; 'MakerNotes', 2 =&gt; 'Image' },
    0 =&gt; 'ShadowProtection',
    1 =&gt; 'SaturationAdj',
    6 =&gt; 'HighlightProtection',
);

#------------------------------------------------------------------------------
# write Nikon Capture data (ref 1)
# Inputs: 0) ExifTool object reference, 1) reference to directory information
#         2) pointer to tag table
# Returns: 1 on success
sub WriteNikonCapture($$$)
{
    my ($et, $dirInfo, $tagTablePtr) = @_;
    $et or return 1;    # allow dummy access to autoload this package

    # no need to edit this information unless necessary
    unless ($$et{EDIT_DIRS}{MakerNotes} or $$et{EDIT_DIRS}{IPTC}) {
        return undef;
    }
    my $dataPt = $$dirInfo{DataPt};
    my $dirStart = $$dirInfo{DirStart};
    my $dirLen = $$dirInfo{DirLen};
    if ($dirLen &lt; 22) {
        $et-&gt;Warn('Short Nikon Capture Data',1);
        return undef;
    }
    # make sure the capture data is properly contained
    SetByteOrder('II');
    my $tagID = Get32u($dataPt, $dirStart);
    # sometimes size includes 18 header bytes, and other times it doesn't (eg. ViewNX 2.1.1)
    my $size = Get32u($dataPt, $dirStart + 18);
    my $pad = $dirLen - $size - 18;
    unless ($tagID == 0x7a86a940 and ($pad &gt;= 0 or $pad == -18)) {
        $et-&gt;Warn('Unrecognized Nikon Capture Data header');
        return undef;
    }
    # determine if there is any data after this block
    if ($pad &gt; 0) {
        $pad = substr($$dataPt, $dirStart + 18 + $size, $pad);
        $dirLen = $size + 18;
    } else {
        $pad = '';
    }
    my $outBuff = '';
    my $pos;
    my $newTags = $et-&gt;GetNewTagInfoHash($tagTablePtr);
    my $dirEnd = $dirStart + $dirLen;

    # loop through all entries in the Nikon Capture data
    for ($pos=$dirStart+22; $pos+22&lt;$dirEnd; $pos+=22+$size) {
        $tagID = Get32u($dataPt, $pos);
        $size = Get32u($dataPt, $pos + 18) - 4;
        last if $size &lt; 0 or $pos + 22 + $size &gt; $dirEnd;
        my $tagInfo = $et-&gt;GetTagInfo($tagTablePtr, $tagID);
        if ($tagInfo) {
            my $newVal;
            if ($$tagInfo{SubDirectory}) {
                # rewrite the subdirectory
                my %subdirInfo = (
                    DataPt =&gt; $dataPt,
                    DirStart =&gt; $pos + 22,
                    DirLen =&gt; $size,
                );
                my $subTable = GetTagTable($tagInfo-&gt;{SubDirectory}-&gt;{TagTable});
                # ignore minor errors in IPTC since there is typically trailing garbage
                my $oldSetting = $et-&gt;Options('IgnoreMinorErrors');
                $$tagInfo{Name} =~ /IPTC/ and $et-&gt;Options(IgnoreMinorErrors =&gt; 1);
                # rewrite the directory
                $newVal = $et-&gt;WriteDirectory(\%subdirInfo, $subTable);
                # restore our original options
                $et-&gt;Options(IgnoreMinorErrors =&gt; $oldSetting);
            } elsif ($$newTags{$tagID}) {
                # get new value for this tag if we are writing it
                my $format = $$tagInfo{Format} || $$tagInfo{Writable};
                my $oldVal = ReadValue($dataPt,$pos+22,$format,1,$size);
                my $nvHash = $et-&gt;GetNewValueHash($tagInfo);
                if ($et-&gt;IsOverwriting($nvHash, $oldVal)) {
                    my $val = $et-&gt;GetNewValue($tagInfo);
                    $newVal = WriteValue($val, $$tagInfo{Writable}) if defined $val;
                    if (defined $newVal and length $newVal) {
                        ++$$et{CHANGED};
                    } else {
                        undef $newVal;
                        $et-&gt;Warn("Can't delete $$tagInfo{Name}");
                    }
                }
            }
            if (defined $newVal) {
                next unless length $newVal; # don't write zero length information
                # write the new value
                $outBuff .= substr($$dataPt, $pos, 18);
                $outBuff .= Set32u(length($newVal) + 4);
                $outBuff .= $newVal;
                next;
            }
        }
        # rewrite the existing information
        $outBuff .= substr($$dataPt, $pos, 22 + $size);
    }
    unless ($pos == $dirEnd) {
        if ($pos == $dirEnd - 4) {
            # it seems that sometimes (NX2) the main block size is wrong by 4 bytes
            # (did they forget to include the size word?)
            $outBuff .= substr($$dataPt, $pos, 4);
        } else {
            $et-&gt;Warn('Nikon Capture Data improperly terminated',1);
            return undef;
        }
    }
    # add the header and return the new directory
    return substr($$dataPt, $dirStart, 18) .
           Set32u(length($outBuff) + 4) .
           $outBuff . $pad;
}

#------------------------------------------------------------------------------
# process Nikon Capture data (ref 1)
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
# Returns: 1 on success
sub ProcessNikonCaptureEditVersions($$$)
{
    my ($et, $dirInfo, $tagTablePtr) = @_;
    my $dataPt = $$dirInfo{DataPt};
    my $dirStart = $$dirInfo{DirStart};
    my $dirLen = $$dirInfo{DirLen};
    my $dirEnd = $dirStart + $dirLen;
    my $verbose = $et-&gt;Options('Verbose');
    SetByteOrder('II');
    return 0 unless $dirLen &gt; 4;
    my $num = Get32u($dataPt, $dirStart);
    my $pos = $dirStart + 4;
    $verbose and $et-&gt;VerboseDir('NikonCaptureEditVersions', $num);
    while ($num) {
        last if $pos + 4 &gt; $dirEnd;
        my $len = Get32u($dataPt, $pos);
        last if $pos + $len + 4 &gt; $dirEnd;
        my %dirInfo = (
            DirName  =&gt; 'NikonCapture',
            Parent   =&gt; 'NikonCaptureEditVersions',
            DataPt   =&gt; $dataPt,
            DirStart =&gt; $pos + 4,
            DirLen   =&gt; $len,
        );
        $$et{DOC_NUM} = ++$$et{DOC_COUNT};
        $et-&gt;ProcessDirectory(\%dirInfo, $tagTablePtr);
        --$num;
        $pos += $len + 4;
    }
    delete $$et{DOC_NUM};
    return 1;
}

#------------------------------------------------------------------------------
# process Nikon Capture data (ref 1)
# Inputs: 0) ExifTool object ref, 1) dirInfo ref, 2) tag table ref
# Returns: 1 on success
sub ProcessNikonCapture($$$)
{
    my ($et, $dirInfo, $tagTablePtr) = @_;
    my $dataPt = $$dirInfo{DataPt};
    my $dirStart = $$dirInfo{DirStart};
    my $dirLen = $$dirInfo{DirLen};
    my $dirEnd = $dirStart + $dirLen;
    my $verbose = $et-&gt;Options('Verbose');
    my $success = 0;
    SetByteOrder('II');
    $verbose and $et-&gt;VerboseDir('NikonCapture', 0, $dirLen);
    my $pos;
    for ($pos=$dirStart+22; $pos+22&lt;$dirEnd; ) {
        my $tagID = Get32u($dataPt, $pos);
        my $size = Get32u($dataPt, $pos + 18) - 4;
        $pos += 22;
        last if $size &lt; 0 or $pos + $size &gt; $dirEnd;
        my $tagInfo = $et-&gt;GetTagInfo($tagTablePtr, $tagID);
        if ($tagInfo or $verbose) {
            my ($format, $value);
            # (note that Writable will be 0 for Unknown tags)
            $tagInfo and $format = ($$tagInfo{Format} || $$tagInfo{Writable});
            # generate a reasonable default format type for short values
            if (not $format and ($size == 1 or $size == 2 or $size == 4)) {
                $format = 'int' . ($size * 8) . 'u';
            }
            if ($format) {
                my $count = 1;
                if ($format eq 'string' or $format eq 'undef') {
                    # patch Nikon bug in size of some values (HistogramXML)
                    $size += $$tagInfo{AdjustSize} if $tagInfo and $$tagInfo{AdjustSize};
                    $count = $size;
                }
                $value = ReadValue($dataPt,$pos,$format,$count,$size);
            } elsif ($size == 1) {
                $value = substr($$dataPt, $pos, $size);
            }
            $et-&gt;HandleTag($tagTablePtr, $tagID, $value,
                DataPt  =&gt; $dataPt,
                DataPos =&gt; $$dirInfo{DataPos},
                Base    =&gt; $$dirInfo{Base},
                Start   =&gt; $pos,
                Size    =&gt; $size,
            ) and $success = 1;
        }
        $pos += $size;
    }
    return $success;
}

1;  # end

__END__

=head1 NAME

Image::ExifTool::NikonCapture - Read/write Nikon Capture information

=head1 SYNOPSIS

This module is loaded automatically by Image::ExifTool when required.

=head1 DESCRIPTION

This module contains routines to read and write Nikon Capture information in
the maker notes of NEF images.

=head1 AUTHOR

Copyright 2003-2023, Phil Harvey (philharvey66 at gmail.com)

This library is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.

=head1 REFERENCES

=over 4

=item L&lt;http://www.cybercom.net/~dcoffin/dcraw/&gt;

=back

=head1 SEE ALSO

L&lt;Image::ExifTool::TagNames/NikonCapture Tags&gt;,
L&lt;Image::ExifTool::TagNames/Nikon Tags&gt;,
L&lt;Image::ExifTool(3pm)|Image::ExifTool&gt;

=cut
</pre></body></html>