123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940 |
- #------------------------------------------------------------------------------
- # 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/
- # 2) 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 => 'Off', 1 => 'On' );
- my %noYes = ( 0 => 'No', 1 => 'Yes' );
- my %unsharpColor = (
- 0 => 'RGB',
- 1 => 'Red',
- 2 => 'Green',
- 3 => 'Blue',
- 4 => 'Yellow',
- 5 => 'Magenta',
- 6 => 'Cyan',
- );
- # Nikon Capture data (ref PH)
- %Image::ExifTool::NikonCapture::Main = (
- PROCESS_PROC => \&ProcessNikonCapture,
- WRITE_PROC => \&WriteNikonCapture,
- CHECK_PROC => \&Image::ExifTool::Exif::CheckExif,
- GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
- NOTES => 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 => {
- Name => 'LCHEditor',
- Writable => 'int8u',
- PrintConv => \%offOn,
- },
- 0x0c89224b => {
- Name => 'ColorAberrationControl',
- Writable => 'int8u',
- PrintConv => \%offOn,
- },
- 0x116fea21 => {
- Name => 'HighlightData',
- SubDirectory => {
- TagTable => 'Image::ExifTool::NikonCapture::HighlightData',
- },
- },
- 0x2175eb78 => {
- Name => 'D-LightingHQ',
- Writable => 'int8u',
- PrintConv => \%offOn,
- },
- 0x2fc08431 => {
- Name => 'StraightenAngle',
- Writable => 'double',
- },
- 0x374233e0 => {
- Name => 'CropData',
- SubDirectory => {
- TagTable => 'Image::ExifTool::NikonCapture::CropData',
- },
- },
- 0x39c456ac => {
- Name => 'PictureCtrl',
- SubDirectory => {
- TagTable => 'Image::ExifTool::NikonCapture::PictureCtrl',
- },
- },
- 0x3cfc73c6 => {
- Name => 'RedEyeData',
- SubDirectory => {
- TagTable => 'Image::ExifTool::NikonCapture::RedEyeData',
- },
- },
- 0x3d136244 => {
- Name => 'EditVersionName',
- Writable => 'string', # (null terminated)
- },
- # 0x3e726567 added when I rotated by 90 degrees
- 0x416391c6 => {
- Name => 'QuickFix',
- Writable => 'int8u',
- PrintConv => \%offOn,
- },
- 0x56a54260 => {
- Name => 'Exposure',
- SubDirectory => {
- TagTable => 'Image::ExifTool::NikonCapture::Exposure',
- },
- },
- 0x5f0e7d23 => {
- Name => 'ColorBooster',
- Writable => 'int8u',
- PrintConv => \%offOn,
- },
- 0x6a6e36b6 => {
- Name => 'D-LightingHQSelected',
- Writable => 'int8u',
- PrintConv => \%noYes,
- },
- 0x753dcbc0 => {
- Name => 'NoiseReduction',
- Writable => 'int8u',
- PrintConv => \%offOn,
- },
- 0x76a43200 => {
- Name => 'UnsharpMask',
- Writable => 'int8u',
- PrintConv => \%offOn,
- },
- 0x76a43201 => {
- Name => 'Curves',
- Writable => 'int8u',
- PrintConv => \%offOn,
- },
- 0x76a43202 => {
- Name => 'ColorBalanceAdj',
- Writable => 'int8u',
- PrintConv => \%offOn,
- },
- 0x76a43203 => {
- Name => 'AdvancedRaw',
- Writable => 'int8u',
- PrintConv => \%offOn,
- },
- 0x76a43204 => {
- Name => 'WhiteBalanceAdj',
- Writable => 'int8u',
- PrintConv => \%offOn,
- },
- 0x76a43205 => {
- Name => 'VignetteControl',
- Writable => 'int8u',
- PrintConv => \%offOn,
- },
- 0x76a43206 => {
- Name => 'FlipHorizontal',
- Writable => 'int8u',
- PrintConv => \%noYes,
- },
- 0x76a43207 => { # rotation angle in degrees
- Name => 'Rotation',
- Writable => 'int16u',
- },
- 0x083a1a25 => {
- Name => 'HistogramXML',
- Writable => 'undef',
- Binary => 1,
- AdjustSize => 4, # patch Nikon bug
- },
- 0x84589434 => {
- Name => 'BrightnessData',
- SubDirectory => {
- TagTable => 'Image::ExifTool::NikonCapture::Brightness',
- },
- },
- # 0x88f55e48 - related to QuickFix
- 0x890ff591 => {
- Name => 'D-LightingHQData',
- SubDirectory => {
- TagTable => 'Image::ExifTool::NikonCapture::DLightingHQ',
- },
- },
- 0x926f13e0 => {
- Name => 'NoiseReductionData',
- SubDirectory => {
- TagTable => 'Image::ExifTool::NikonCapture::NoiseReduction',
- },
- },
- 0x9ef5f6e0 => {
- Name => 'IPTCData',
- SubDirectory => {
- TagTable => 'Image::ExifTool::IPTC::Main',
- },
- },
- # 0xa7264a72 - related to QuickFix
- 0xab5eca5e => {
- Name => 'PhotoEffects',
- Writable => 'int8u',
- PrintConv => \%offOn,
- },
- 0xac6bd5c0 => {
- Name => 'VignetteControlIntensity',
- Writable => 'int16s',
- },
- 0xb0384e1e => {
- Name => 'PhotoEffectsData',
- SubDirectory => {
- TagTable => 'Image::ExifTool::NikonCapture::PhotoEffects',
- },
- },
- 0xb999a36f => {
- Name => 'ColorBoostData',
- SubDirectory => {
- TagTable => 'Image::ExifTool::NikonCapture::ColorBoost',
- },
- },
- 0xbf3c6c20 => {
- Name => 'WBAdjData',
- SubDirectory => {
- TagTable => 'Image::ExifTool::NikonCapture::WBAdjData',
- },
- },
- 0xce5554aa => {
- Name => 'D-LightingHS',
- Writable => 'int8u',
- PrintConv => \%offOn,
- },
- 0xe2173c47 => {
- Name => 'PictureControl',
- Writable => 'int8u',
- PrintConv => \%offOn,
- },
- 0xe37b4337 => {
- Name => 'D-LightingHSData',
- SubDirectory => {
- TagTable => 'Image::ExifTool::NikonCapture::DLightingHS',
- },
- },
- 0xe42b5161 => {
- Name => 'UnsharpData',
- SubDirectory => {
- TagTable => 'Image::ExifTool::NikonCapture::UnsharpData',
- },
- },
- 0xe9651831 => {
- Name => 'PhotoEffectHistoryXML',
- Binary => 1,
- Writable => 'undef',
- },
- 0xfe28a44f => {
- Name => 'AutoRedEye',
- Writable => 'int8u',
- PrintConv => \%offOn, # (have seen a value of 28 here for older software?)
- },
- 0xfe443a45 => {
- Name => 'ImageDustOff',
- Writable => 'int8u',
- PrintConv => \%offOn,
- },
- );
- %Image::ExifTool::NikonCapture::UnsharpData = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
- CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
- WRITABLE => 1,
- FORMAT => 'int8u',
- FIRST_ENTRY => 0,
- GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
- 0 => 'UnsharpCount',
- 19 => { Name => 'Unsharp1Color', Format => 'int16u', PrintConv => \%unsharpColor },
- 23 => { Name => 'Unsharp1Intensity', Format => 'int16u' },
- 25 => { Name => 'Unsharp1HaloWidth', Format => 'int16u' },
- 27 => 'Unsharp1Threshold',
- 46 => { Name => 'Unsharp2Color', Format => 'int16u', PrintConv => \%unsharpColor },
- 50 => { Name => 'Unsharp2Intensity', Format => 'int16u' },
- 52 => { Name => 'Unsharp2HaloWidth', Format => 'int16u' },
- 54 => 'Unsharp2Threshold',
- 73 => { Name => 'Unsharp3Color', Format => 'int16u', PrintConv => \%unsharpColor },
- 77 => { Name => 'Unsharp3Intensity', Format => 'int16u' },
- 79 => { Name => 'Unsharp3HaloWidth', Format => 'int16u' },
- 81 => 'Unsharp3Threshold',
- 100 => { Name => 'Unsharp4Color', Format => 'int16u', PrintConv => \%unsharpColor },
- 104 => { Name => 'Unsharp4Intensity', Format => 'int16u' },
- 106 => { Name => 'Unsharp4HaloWidth', Format => 'int16u' },
- 108 => 'Unsharp4Threshold',
- # there could be more, but I grow bored of this... :P
- );
- %Image::ExifTool::NikonCapture::DLightingHS = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
- CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
- WRITABLE => 1,
- FORMAT => 'int32u',
- FIRST_ENTRY => 0,
- GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
- 0 => 'D-LightingHSAdjustment',
- 1 => 'D-LightingHSColorBoost',
- );
- %Image::ExifTool::NikonCapture::DLightingHQ = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
- CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
- WRITABLE => 1,
- FORMAT => 'int32u',
- FIRST_ENTRY => 0,
- GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
- 0 => 'D-LightingHQShadow',
- 1 => 'D-LightingHQHighlight',
- 2 => 'D-LightingHQColorBoost',
- );
- %Image::ExifTool::NikonCapture::ColorBoost = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
- CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
- WRITABLE => 1,
- FORMAT => 'int8u',
- FIRST_ENTRY => 0,
- GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
- 0 => {
- Name => 'ColorBoostType',
- PrintConv => {
- 0 => 'Nature',
- 1 => 'People',
- },
- },
- 1 => {
- Name => 'ColorBoostLevel',
- Format => 'int32u',
- },
- );
- %Image::ExifTool::NikonCapture::WBAdjData = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
- CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
- WRITABLE => 1,
- FORMAT => 'int8u',
- FIRST_ENTRY => 0,
- GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
- 0x00 => {
- Name => 'WBAdjRedBalance',
- Format => 'double',
- },
- 0x08 => {
- Name => 'WBAdjBlueBalance',
- Format => 'double',
- },
- 0x10 => {
- Name => 'WBAdjMode',
- PrintConv => {
- 1 => 'Use Gray Point',
- 2 => 'Recorded Value',
- 3 => 'Use Temperature',
- 4 => 'Calculate Automatically',
- 5 => 'Auto2', #2
- 6 => 'Underwater', #2
- 7 => 'Auto1',
- },
- },
- 0x14 => { #2
- Name => 'WBAdjLighting',
- Format => 'int16u',
- PrintHex => 1,
- PrintConv => {
- 0x000 => 'None',
- 0x100 => 'Incandescent',
- 0x200 => 'Daylight (direct sunlight)',
- 0x201 => 'Daylight (shade)',
- 0x202 => 'Daylight (cloudy)',
- 0x300 => 'Standard Fluorescent (warm white)',
- 0x301 => 'Standard Fluorescent (3700K)',
- 0x302 => 'Standard Fluorescent (cool white)',
- 0x303 => 'Standard Fluorescent (5000K)',
- 0x304 => 'Standard Fluorescent (daylight)',
- 0x305 => 'Standard Fluorescent (high temperature mercury vapor)',
- 0x400 => 'High Color Rendering Fluorescent (warm white)',
- 0x401 => 'High Color Rendering Fluorescent (3700K)',
- 0x402 => 'High Color Rendering Fluorescent (cool white)',
- 0x403 => 'High Color Rendering Fluorescent (5000K)',
- 0x404 => 'High Color Rendering Fluorescent (daylight)',
- 0x500 => 'Flash',
- 0x501 => 'Flash (FL-G1 filter)',
- 0x502 => 'Flash (FL-G2 filter)',
- 0x503 => 'Flash (TN-A1 filter)',
- 0x504 => 'Flash (TN-A2 filter)',
- 0x600 => 'Sodium Vapor Lamps',
- # 0x1002 => seen for WBAdjMode modes of Underwater and Calculate Automatically
- },
- },
- 0x18 => {
- Name => 'WBAdjTemperature',
- Format => 'int16u',
- },
- 0x25 => {
- Name => 'WBAdjTint',
- Format => 'int32s',
- },
- );
- %Image::ExifTool::NikonCapture::PhotoEffects = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
- CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
- WRITABLE => 1,
- FORMAT => 'int8u',
- FIRST_ENTRY => 0,
- GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
- 0 => {
- Name => 'PhotoEffectsType',
- PrintConv => {
- 0 => 'None',
- 1 => 'B&W',
- 2 => 'Sepia',
- 3 => 'Tinted',
- },
- },
- 4 => {
- Name => 'PhotoEffectsRed',
- Format => 'int16s',
- },
- 6 => {
- Name => 'PhotoEffectsGreen',
- Format => 'int16s',
- },
- 8 => {
- Name => 'PhotoEffectsBlue',
- Format => 'int16s',
- },
- );
- %Image::ExifTool::NikonCapture::Brightness = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
- CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
- WRITABLE => 1,
- FORMAT => 'int8u',
- FIRST_ENTRY => 0,
- GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
- 0 => {
- Name => 'BrightnessAdj',
- Format => 'double',
- ValueConv => '$val * 50',
- ValueConvInv => '$val / 50',
- },
- 8 => {
- Name => 'EnhanceDarkTones',
- PrintConv => \%offOn,
- },
- );
- %Image::ExifTool::NikonCapture::NoiseReduction = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
- CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
- WRITABLE => 1,
- FORMAT => 'int8u',
- FIRST_ENTRY => 0,
- GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
- 0x04 => {
- Name => 'EdgeNoiseReduction',
- PrintConv => \%offOn,
- },
- 0x05 => {
- Name => 'ColorMoireReductionMode',
- PrintConv => {
- 0 => 'Off',
- 1 => 'Low',
- 2 => 'Medium',
- 3 => 'High',
- },
- },
- 0x09 => {
- Name => 'NoiseReductionIntensity',
- Format => 'int32u',
- },
- 0x0d => {
- Name => 'NoiseReductionSharpness',
- Format => 'int32u',
- },
- 0x11 => {
- Name => 'NoiseReductionMethod',
- Format => 'int16u',
- PrintConv => {
- 0 => 'Faster',
- 1 => 'Better Quality',
- 2 => 'Better Quality 2013',
- },
- },
- 0x15 => {
- Name => 'ColorMoireReduction',
- PrintConv => \%offOn,
- },
- 0x17 => {
- Name => 'NoiseReduction',
- PrintConv => \%offOn,
- },
- 0x18 => {
- Name => 'ColorNoiseReductionIntensity',
- Format => 'int32u',
- },
- 0x1c => {
- Name => 'ColorNoiseReductionSharpness',
- Format => 'int32u',
- },
- );
- %Image::ExifTool::NikonCapture::CropData = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
- CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
- WRITABLE => 1,
- FORMAT => 'int8u',
- FIRST_ENTRY => 0,
- GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
- 0x1e => {
- Name => 'CropLeft',
- Format => 'double',
- ValueConv => '$val / 2',
- ValueConvInv => '$val * 2',
- },
- 0x26 => {
- Name => 'CropTop',
- Format => 'double',
- ValueConv => '$val / 2',
- ValueConvInv => '$val * 2',
- },
- 0x2e => {
- Name => 'CropRight',
- Format => 'double',
- ValueConv => '$val / 2',
- ValueConvInv => '$val * 2',
- },
- 0x36 => {
- Name => 'CropBottom',
- Format => 'double',
- ValueConv => '$val / 2',
- ValueConvInv => '$val * 2',
- },
- 0x8e => {
- Name => 'CropOutputWidthInches',
- Format => 'double',
- },
- 0x96 => {
- Name => 'CropOutputHeightInches',
- Format => 'double',
- },
- 0x9e => {
- Name => 'CropScaledResolution',
- Format => 'double',
- },
- 0xae => {
- Name => 'CropSourceResolution',
- Format => 'double',
- ValueConv => '$val / 2',
- ValueConvInv => '$val * 2',
- },
- 0xb6 => {
- Name => 'CropOutputResolution',
- Format => 'double',
- },
- 0xbe => {
- Name => 'CropOutputScale',
- Format => 'double',
- },
- 0xc6 => {
- Name => 'CropOutputWidth',
- Format => 'double',
- },
- 0xce => {
- Name => 'CropOutputHeight',
- Format => 'double',
- },
- 0xd6 => {
- Name => 'CropOutputPixels',
- Format => 'double',
- },
- );
- %Image::ExifTool::NikonCapture::PictureCtrl = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
- CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
- WRITABLE => 1,
- FORMAT => 'int8u',
- FIRST_ENTRY => 0,
- GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
- 0x00 => {
- Name => 'PictureControlActive',
- PrintConv => \%offOn,
- },
- 0x13 => {
- Name => 'PictureControlMode',
- Format => 'string[16]',
- },
- # 0x29 changes with Hue and Sharpening
- 0x2a => {
- Name => 'QuickAdjust',
- ValueConv => '$val - 128',
- ValueConvInv => '$val + 128',
- },
- 0x2b => {
- Name => 'SharpeningAdj',
- ValueConv => '$val ? $val - 128 : "Auto"',
- ValueConvInv => '$val=~/\d/ ? $val + 128 : 0',
- },
- 0x2c => {
- Name => 'ContrastAdj',
- ValueConv => '$val ? $val - 128 : "Auto"',
- ValueConvInv => '$val=~/\d/ ? $val + 128 : 0',
- },
- 0x2d => {
- Name => 'BrightnessAdj',
- ValueConv => '$val ? $val - 128 : "Auto"', # no "Auto" mode (yet) for this setting
- ValueConvInv => '$val=~/\d/ ? $val + 128 : 0',
- },
- 0x2e => {
- Name => 'SaturationAdj',
- ValueConv => '$val ? $val - 128 : "Auto"',
- ValueConvInv => '$val=~/\d/ ? $val + 128 : 0',
- },
- 0x2f => {
- Name => 'HueAdj',
- ValueConv => '$val - 128',
- ValueConvInv => '$val + 128',
- },
- # 0x37 changed from 0 to 2 when Picture Control is enabled (and no active DLighting)
- );
- %Image::ExifTool::NikonCapture::RedEyeData = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
- CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
- WRITABLE => 1,
- FORMAT => 'int8u',
- FIRST_ENTRY => 0,
- GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
- 0 => {
- Name => 'RedEyeCorrection',
- PrintConv => {
- 0 => 'Off',
- 1 => 'Automatic',
- 2 => 'Click on Eyes',
- },
- },
- );
- %Image::ExifTool::NikonCapture::Exposure = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
- CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
- WRITABLE => 1,
- FORMAT => 'int8u',
- FIRST_ENTRY => 0,
- GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
- 0x00 => {
- Name => 'ExposureAdj',
- Format => 'int16s',
- ValueConv => '$val / 100',
- ValueConvInv => '$val * 100',
- },
- 0x12 => {
- Name => 'ExposureAdj2',
- Format => 'double',
- PrintConv => 'sprintf("%.4f", $val)',
- PrintConvInv => '$val',
- },
- 0x24 => {
- Name => 'ActiveD-Lighting',
- PrintConv => \%offOn,
- },
- 0x25 => {
- Name => 'ActiveD-LightingMode',
- PrintConv => {
- 0 => 'Unchanged',
- 1 => 'Off',
- 2 => 'Low',
- 3 => 'Normal',
- 4 => 'High',
- 6 => 'Extra High',
- 7 => 'Extra High 1',
- 8 => 'Extra High 2',
- },
- },
- );
- %Image::ExifTool::NikonCapture::HighlightData = (
- PROCESS_PROC => \&Image::ExifTool::ProcessBinaryData,
- WRITE_PROC => \&Image::ExifTool::WriteBinaryData,
- CHECK_PROC => \&Image::ExifTool::CheckBinaryData,
- WRITABLE => 1,
- FORMAT => 'int8s',
- FIRST_ENTRY => 0,
- GROUPS => { 0 => 'MakerNotes', 2 => 'Image' },
- 0 => 'ShadowProtection',
- 1 => 'SaturationAdj',
- 6 => '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 < 22) {
- $et->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 >= 0 or $pad == -18)) {
- $et->Warn('Unrecognized Nikon Capture Data header');
- return undef;
- }
- # determine if there is any data after this block
- if ($pad > 0) {
- $pad = substr($$dataPt, $dirStart + 18 + $size, $pad);
- $dirLen = $size + 18;
- } else {
- $pad = '';
- }
- my $outBuff = '';
- my $pos;
- my $newTags = $et->GetNewTagInfoHash($tagTablePtr);
- my $dirEnd = $dirStart + $dirLen;
- # loop through all entries in the Nikon Capture data
- for ($pos=$dirStart+22; $pos+22<$dirEnd; $pos+=22+$size) {
- $tagID = Get32u($dataPt, $pos);
- $size = Get32u($dataPt, $pos + 18) - 4;
- last if $size < 0 or $pos + 22 + $size > $dirEnd;
- my $tagInfo = $et->GetTagInfo($tagTablePtr, $tagID);
- if ($tagInfo) {
- my $newVal;
- if ($$tagInfo{SubDirectory}) {
- # rewrite the subdirectory
- my %subdirInfo = (
- DataPt => $dataPt,
- DirStart => $pos + 22,
- DirLen => $size,
- );
- my $subTable = GetTagTable($tagInfo->{SubDirectory}->{TagTable});
- # ignore minor errors in IPTC since there is typically trailing garbage
- my $oldSetting = $et->Options('IgnoreMinorErrors');
- $$tagInfo{Name} =~ /IPTC/ and $et->Options(IgnoreMinorErrors => 1);
- # rewrite the directory
- $newVal = $et->WriteDirectory(\%subdirInfo, $subTable);
- # restore our original options
- $et->Options(IgnoreMinorErrors => $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->GetNewValueHash($tagInfo);
- if ($et->IsOverwriting($nvHash, $oldVal)) {
- my $val = $et->GetNewValue($tagInfo);
- $newVal = WriteValue($val, $$tagInfo{Writable}) if defined $val;
- if (defined $newVal and length $newVal) {
- ++$$et{CHANGED};
- } else {
- undef $newVal;
- $et->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->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->Options('Verbose');
- SetByteOrder('II');
- return 0 unless $dirLen > 4;
- my $num = Get32u($dataPt, $dirStart);
- my $pos = $dirStart + 4;
- $verbose and $et->VerboseDir('NikonCaptureEditVersions', $num);
- while ($num) {
- last if $pos + 4 > $dirEnd;
- my $len = Get32u($dataPt, $pos);
- last if $pos + $len + 4 > $dirEnd;
- my %dirInfo = (
- DirName => 'NikonCapture',
- Parent => 'NikonCaptureEditVersions',
- DataPt => $dataPt,
- DirStart => $pos + 4,
- DirLen => $len,
- );
- $$et{DOC_NUM} = ++$$et{DOC_COUNT};
- $et->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->Options('Verbose');
- my $success = 0;
- SetByteOrder('II');
- $verbose and $et->VerboseDir('NikonCapture', 0, $dirLen);
- my $pos;
- for ($pos=$dirStart+22; $pos+22<$dirEnd; ) {
- my $tagID = Get32u($dataPt, $pos);
- my $size = Get32u($dataPt, $pos + 18) - 4;
- $pos += 22;
- last if $size < 0 or $pos + $size > $dirEnd;
- my $tagInfo = $et->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->HandleTag($tagTablePtr, $tagID, $value,
- DataPt => $dataPt,
- DataPos => $$dirInfo{DataPos},
- Base => $$dirInfo{Base},
- Start => $pos,
- Size => $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-2016, Phil Harvey (phil at owl.phy.queensu.ca)
- 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<http://www.cybercom.net/~dcoffin/dcraw/>
- =back
- =head1 SEE ALSO
- L<Image::ExifTool::TagNames/NikonCapture Tags>,
- L<Image::ExifTool::TagNames/Nikon Tags>,
- L<Image::ExifTool(3pm)|Image::ExifTool>
- =cut
|