content: /*
   * Copyright 2002-2019 Drew Noakes and contributors
   *
   *    Licensed under the Apache License, Version 2.0 (the "License");
   *    you may not use this file except in compliance with the License.
   *    You may obtain a copy of the License at
   *
   *        https://www.apache.org/licenses/LICENSE-2.0
   *
   *    Unless required by applicable law or agreed to in writing, software
   *    distributed under the License is distributed on an "AS IS" BASIS,
   *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   *    See the License for the specific language governing permissions and
   *    limitations under the License.
   *
   * More information about this project is available at:
   *
   *    https://drewnoakes.com/code/exif/
   *    https://github.com/drewnoakes/metadata-extractor
   */
  package com.drew.metadata.exif.makernotes;
  
  import com.drew.lang.annotations.Nullable;
  import com.drew.lang.annotations.NotNull;
  import com.drew.metadata.Directory;
  
  import java.util.HashMap;
  
  /**
   * Describes tags specific to Nikon (type 2) cameras.  Type-2 applies to the E990 and D-series cameras such as the E990, D1,
   * D70 and D100.
   * <p>
   * Thanks to Fabrizio Giudici for publishing his reverse-engineering of the D100 makernote data.
   * https://www.timelesswanderings.net/equipment/D100/NEF.html
   * <p>
   * Note that the camera implements image protection (locking images) via the file's 'readonly' attribute.  Similarly
   * image hiding uses the 'hidden' attribute (observed on the D70).  Consequently, these values are not available here.
   * <p>
   * Additional sample images have been observed, and their tag values recorded in javadoc comments for each tag's field.
   * New tags have subsequently been added since Fabrizio's observations.
   * <p>
   * In earlier models (such as the E990 and D1), this directory begins at the first byte of the makernote IFD.  In
   * later models, the IFD was given the standard prefix to indicate the camera models (most other manufacturers also
   * provide this prefix to aid in software decoding).
   *
   * @author Drew Noakes https://drewnoakes.com
   */
  @SuppressWarnings("WeakerAccess")
  public class NikonType2MakernoteDirectory extends Directory
  {
      /**
       * Values observed
       * - 0200 (D70)
       * - 0200 (D1X)
       */
      public static final int TAG_FIRMWARE_VERSION = 0x0001;
  
      /**
       * Values observed
       * - 0 250
       * - 0 400
       */
      public static final int TAG_ISO_1 = 0x0002;
  
      /**
       * The camera's color mode, as an uppercase string.  Examples include:
       * <ul>
       * <li><code>B &amp; W</code></li>
       * <li><code>COLOR</code></li>
       * <li><code>COOL</code></li>
       * <li><code>SEPIA</code></li>
       * <li><code>VIVID</code></li>
       * </ul>
       */
      public static final int TAG_COLOR_MODE = 0x0003;
  
      /**
       * The camera's quality setting, as an uppercase string.  Examples include:
       * <ul>
       * <li><code>BASIC</code></li>
       * <li><code>FINE</code></li>
       * <li><code>NORMAL</code></li>
       * <li><code>RAW</code></li>
       * <li><code>RAW2.7M</code></li>
       * </ul>
       */
      public static final int TAG_QUALITY_AND_FILE_FORMAT = 0x0004;
  
      /**
       * The camera's white balance setting, as an uppercase string.  Examples include:
       *
       * <ul>
       * <li><code>AUTO</code></li>
       * <li><code>CLOUDY</code></li>
       * <li><code>FLASH</code></li>
       * <li><code>FLUORESCENT</code></li>
       * <li><code>INCANDESCENT</code></li>
       * <li><code>PRESET</code></li>
       * <li><code>PRESET0</code></li>
       * <li><code>PRESET1</code></li>
       * <li><code>PRESET3</code></li>
       * <li><code>SUNNY</code></li>
       * <li><code>WHITE PRESET</code></li>
       * <li><code>4350K</code></li>
       * <li><code>5000K</code></li>
       * <li><code>DAY WHITE FL</code></li>
       * <li><code>SHADE</code></li>
       * </ul>
       */
      public static final int TAG_CAMERA_WHITE_BALANCE  = 0x0005;
  
      /**
       * The camera's sharpening setting, as an uppercase string.  Examples include:
       *
       * <ul>
       * <li><code>AUTO</code></li>
       * <li><code>HIGH</code></li>
       * <li><code>LOW</code></li>
       * <li><code>NONE</code></li>
       * <li><code>NORMAL</code></li>
       * <li><code>MED.H</code></li>
       * <li><code>MED.L</code></li>
       * </ul>
       */
      public static final int TAG_CAMERA_SHARPENING = 0x0006;
  
      /**
       * The camera's auto-focus mode, as an uppercase string.  Examples include:
       *
       * <ul>
       * <li><code>AF-C</code></li>
       * <li><code>AF-S</code></li>
       * <li><code>MANUAL</code></li>
       * <li><code>AF-A</code></li>
       * </ul>
       */
      public static final int TAG_AF_TYPE = 0x0007;
  
      /**
       * The camera's flash setting, as an uppercase string.  Examples include:
       *
       * <ul>
       * <li><code></code></li>
       * <li><code>NORMAL</code></li>
       * <li><code>RED-EYE</code></li>
       * <li><code>SLOW</code></li>
       * <li><code>NEW_TTL</code></li>
       * <li><code>REAR</code></li>
       * <li><code>REAR SLOW</code></li>
       * </ul>
       * Note: when TAG_AUTO_FLASH_MODE is blank (whitespace), Nikon Browser displays "Flash Sync Mode: Not Attached"
       */
      public static final int TAG_FLASH_SYNC_MODE = 0x0008;
  
      /**
       * The type of flash used in the photograph, as a string.  Examples include:
       *
       * <ul>
       * <li><code></code></li>
       * <li><code>Built-in,TTL</code></li>
       * <li><code>NEW_TTL</code> Nikon Browser interprets as "D-TTL"</li>
       * <li><code>Built-in,M</code></li>
       * <li><code>Optional,TTL</code> with speedlight SB800, flash sync mode as "NORMAL"</li>
       * </ul>
       */
      public static final int TAG_AUTO_FLASH_MODE = 0x0009;
  
      /**
       * An unknown tag, as a rational.  Several values given here:
       * https://gvsoft.homedns.org/exif/makernote-nikon-type2.html#0x000b
       */
      public static final int TAG_UNKNOWN_34 = 0x000A;
  
      /**
       * The camera's white balance bias setting, as an uint16 array having either one or two elements.
       *
       * <ul>
       * <li><code>0</code></li>
       * <li><code>1</code></li>
       * <li><code>-3</code></li>
       * <li><code>-2</code></li>
       * <li><code>-1</code></li>
       * <li><code>0,0</code></li>
       * <li><code>1,0</code></li>
       * <li><code>5,-5</code></li>
       * </ul>
       */
      public static final int TAG_CAMERA_WHITE_BALANCE_FINE = 0x000B;
  
      /**
       * The first two numbers are coefficients to multiply red and blue channels according to white balance as set in the
       * camera. The meaning of the third and the fourth numbers is unknown.
       *
       * Values observed
       * - 2.25882352 1.76078431 0.0 0.0
       * - 10242/1 34305/1 0/1 0/1
       * - 234765625/100000000 1140625/1000000 1/1 1/1
       */
      public static final int TAG_CAMERA_WHITE_BALANCE_RB_COEFF = 0x000C;
  
      /**
       * The camera's program shift setting, as an array of four integers.
       * The value, in EV, is calculated as <code>a*b/c</code>.
       *
       * <ul>
       * <li><code>0,1,3,0</code> = 0 EV</li>
       * <li><code>1,1,3,0</code> = 0.33 EV</li>
       * <li><code>-3,1,3,0</code> = -1 EV</li>
       * <li><code>1,1,2,0</code> = 0.5 EV</li>
       * <li><code>2,1,6,0</code> = 0.33 EV</li>
       * </ul>
       */
      public static final int TAG_PROGRAM_SHIFT = 0x000D;
  
      /**
       * The exposure difference, as an array of four integers.
       * The value, in EV, is calculated as <code>a*b/c</code>.
       *
       * <ul>
       * <li><code>-105,1,12,0</code> = -8.75 EV</li>
       * <li><code>-72,1,12,0</code> = -6.00 EV</li>
       * <li><code>-11,1,12,0</code> = -0.92 EV</li>
       * </ul>
       */
      public static final int TAG_EXPOSURE_DIFFERENCE = 0x000E;
  
      /**
       * The camera's ISO mode, as an uppercase string.
       *
       * <ul>
       * <li><code>AUTO</code></li>
       * <li><code>MANUAL</code></li>
       * </ul>
       */
      public static final int TAG_ISO_MODE = 0x000F;
  
      /**
       * Added during merge of Type2 &amp; Type3.  May apply to earlier models, such as E990 and D1.
       */
      public static final int TAG_DATA_DUMP = 0x0010;
  
      /**
       * Preview to another IFD (?)
       * <p>
       * Details here: https://gvsoft.homedns.org/exif/makernote-nikon-2-tag0x0011.html
       * // TODO if this is another IFD, decode it
       */
      public static final int TAG_PREVIEW_IFD = 0x0011;
  
      /**
       * The flash compensation, as an array of four integers.
       * The value, in EV, is calculated as <code>a*b/c</code>.
       *
       * <ul>
       * <li><code>-18,1,6,0</code> = -3 EV</li>
       * <li><code>4,1,6,0</code> = 0.67 EV</li>
       * <li><code>6,1,6,0</code> = 1 EV</li>
       * </ul>
       */
      public static final int TAG_AUTO_FLASH_COMPENSATION = 0x0012;
  
      /**
       * The requested ISO value, as an array of two integers.
       *
       * <ul>
       * <li><code>0,0</code></li>
       * <li><code>0,125</code></li>
       * <li><code>1,2500</code></li>
       * </ul>
       */
      public static final int TAG_ISO_REQUESTED = 0x0013;
  
      /**
       * Defines the photo corner coordinates, in 8 bytes.  Treated as four 16-bit integers, they
       * decode as: top-left (x,y); bot-right (x,y)
       * - 0 0 49163 53255
       * - 0 0 3008 2000 (the image dimensions were 3008x2000) (D70)
       * <ul>
       * <li><code>0,0,4288,2848</code> The max resolution of the D300 camera</li>
       * <li><code>0,0,3008,2000</code> The max resolution of the D70 camera</li>
       * <li><code>0,0,4256,2832</code> The max resolution of the D3 camera</li>
       * </ul>
       */
      public static final int TAG_IMAGE_BOUNDARY = 0x0016;
  
      /**
       * The flash exposure compensation, as an array of four integers.
       * The value, in EV, is calculated as <code>a*b/c</code>.
       *
       * <ul>
       * <li><code>0,0,0,0</code> = 0 EV</li>
       * <li><code>0,1,6,0</code> = 0 EV</li>
       * <li><code>4,1,6,0</code> = 0.67 EV</li>
       * </ul>
       */
      public static final int TAG_FLASH_EXPOSURE_COMPENSATION = 0x0017;
  
      /**
       * The flash bracket compensation, as an array of four integers.
       * The value, in EV, is calculated as <code>a*b/c</code>.
       *
       * <ul>
       * <li><code>0,0,0,0</code> = 0 EV</li>
       * <li><code>0,1,6,0</code> = 0 EV</li>
       * <li><code>4,1,6,0</code> = 0.67 EV</li>
       * </ul>
       */
      public static final int TAG_FLASH_BRACKET_COMPENSATION = 0x0018;
  
      /**
       * The AE bracket compensation, as a rational number.
       *
       * <ul>
       * <li><code>0/0</code></li>
       * <li><code>0/1</code></li>
       * <li><code>0/6</code></li>
       * <li><code>4/6</code></li>
       * <li><code>6/6</code></li>
       * </ul>
       */
      public static final int TAG_AE_BRACKET_COMPENSATION = 0x0019;
  
      /**
       * Flash mode, as a string.
       *
       * <ul>
       * <li><code></code></li>
       * <li><code>Red Eye Reduction</code></li>
       * <li><code>D-Lighting</code></li>
       * <li><code>Distortion control</code></li>
       * </ul>
       */
      public static final int TAG_FLASH_MODE = 0x001a;
  
      public static final int TAG_CROP_HIGH_SPEED = 0x001b;
      public static final int TAG_EXPOSURE_TUNING = 0x001c;
  
      /**
       * The camera's serial number, as a string.
       * Note that D200 is always blank, and D50 is always <code>"D50"</code>.
       */
      public static final int TAG_CAMERA_SERIAL_NUMBER = 0x001d;
  
      /**
       * The camera's color space setting.
       *
       * <ul>
       * <li><code>1</code> sRGB</li>
       * <li><code>2</code> Adobe RGB</li>
       * </ul>
       */
      public static final int TAG_COLOR_SPACE = 0x001e;
      public static final int TAG_VR_INFO = 0x001f;
      public static final int TAG_IMAGE_AUTHENTICATION = 0x0020;
      public static final int TAG_FACE_DETECT = 0x0021;
  
      /**
       * The active D-Lighting setting.
       *
       * <ul>
       * <li><code>0</code> Off</li>
       * <li><code>1</code> Low</li>
       * <li><code>3</code> Normal</li>
       * <li><code>5</code> High</li>
       * <li><code>7</code> Extra High</li>
       * <li><code>65535</code> Auto</li>
       * </ul>
       */
      public static final int TAG_ACTIVE_D_LIGHTING = 0x0022;
      public static final int TAG_PICTURE_CONTROL = 0x0023;
      public static final int TAG_WORLD_TIME = 0x0024;
      public static final int TAG_ISO_INFO = 0x0025;
      public static final int TAG_UNKNOWN_36 = 0x0026;
      public static final int TAG_UNKNOWN_37 = 0x0027;
      public static final int TAG_UNKNOWN_38 = 0x0028;
      public static final int TAG_UNKNOWN_39 = 0x0029;
  
      /**
       * The camera's vignette control setting.
       *
       * <ul>
       * <li><code>0</code> Off</li>
       * <li><code>1</code> Low</li>
       * <li><code>3</code> Normal</li>
       * <li><code>5</code> High</li>
       * </ul>
       */
      public static final int TAG_VIGNETTE_CONTROL = 0x002a;
      public static final int TAG_DISTORT_INFO = 0x002b;
      public static final int TAG_UNKNOWN_41 = 0x002c;
      public static final int TAG_UNKNOWN_42 = 0x002d;
      public static final int TAG_UNKNOWN_43 = 0x002e;
      public static final int TAG_UNKNOWN_44 = 0x002f;
      public static final int TAG_UNKNOWN_45 = 0x0030;
      public static final int TAG_UNKNOWN_46 = 0x0031;
  
      /**
       * The camera's image adjustment setting, as a string.
       *
       * <ul>
       * <li><code>AUTO</code></li>
       * <li><code>CONTRAST(+)</code></li>
       * <li><code>CONTRAST(-)</code></li>
       * <li><code>NORMAL</code></li>
       * <li><code>B &amp; W</code></li>
       * <li><code>BRIGHTNESS(+)</code></li>
       * <li><code>BRIGHTNESS(-)</code></li>
       * <li><code>SEPIA</code></li>
       * </ul>
       */
      public static final int TAG_IMAGE_ADJUSTMENT = 0x0080;
  
      /**
       * The camera's tone compensation setting, as a string.
       *
       * <ul>
       * <li><code>NORMAL</code></li>
       * <li><code>LOW</code></li>
       * <li><code>MED.L</code></li>
       * <li><code>MED.H</code></li>
       * <li><code>HIGH</code></li>
       * <li><code>AUTO</code></li>
       * </ul>
       */
      public static final int TAG_CAMERA_TONE_COMPENSATION = 0x0081;
  
      /**
       * A description of any auxiliary lens, as a string.
       *
       * <ul>
       * <li><code>OFF</code></li>
       * <li><code>FISHEYE 1</code></li>
       * <li><code>FISHEYE 2</code></li>
       * <li><code>TELEPHOTO 2</code></li>
       * <li><code>WIDE ADAPTER</code></li>
       * </ul>
       */
      public static final int TAG_ADAPTER = 0x0082;
  
      /**
       * The type of lens used, as a byte.
       *
       * <ul>
       * <li><code>0x00</code> AF</li>
       * <li><code>0x01</code> MF</li>
       * <li><code>0x02</code> D</li>
       * <li><code>0x06</code> G, D</li>
       * <li><code>0x08</code> VR</li>
       * <li><code>0x0a</code> VR, D</li>
       * <li><code>0x0e</code> VR, G, D</li>
       * </ul>
       */
      public static final int TAG_LENS_TYPE = 0x0083;
  
      /**
       * A pair of focal/max-fstop values that describe the lens used.
       *
       * Values observed
       * - 180.0,180.0,2.8,2.8 (D100)
       * - 240/10 850/10 35/10 45/10
       * - 18-70mm f/3.5-4.5 (D70)
       * - 17-35mm f/2.8-2.8 (D1X)
       * - 70-200mm f/2.8-2.8 (D70)
       *
       * Nikon Browser identifies the lens as "18-70mm F/3.5-4.5 G" which
       * is identical to metadata extractor, except for the "G".  This must
       * be coming from another tag...
       */
      public static final int TAG_LENS = 0x0084;
  
      /**
       * Added during merge of Type2 &amp; Type3.  May apply to earlier models, such as E990 and D1.
       */
      public static final int TAG_MANUAL_FOCUS_DISTANCE = 0x0085;
  
      /**
       * The amount of digital zoom used.
       */
      public static final int TAG_DIGITAL_ZOOM = 0x0086;
  
      /**
       * Whether the flash was used in this image.
       *
       * <ul>
       * <li><code>0</code> Flash Not Used</li>
       * <li><code>1</code> Manual Flash</li>
       * <li><code>3</code> Flash Not Ready</li>
       * <li><code>7</code> External Flash</li>
       * <li><code>8</code> Fired, Commander Mode</li>
       * <li><code>9</code> Fired, TTL Mode</li>
       * </ul>
       */
      public static final int TAG_FLASH_USED = 0x0087;
  
      /**
       * The position of the autofocus target.
       */
      public static final int TAG_AF_FOCUS_POSITION = 0x0088;
  
      /**
       * The camera's shooting mode.
       * <p>
       * A bit-array with:
       * <ul>
       * <li><code>0</code> Single Frame</li>
       * <li><code>1</code> Continuous</li>
       * <li><code>2</code> Delay</li>
       * <li><code>8</code> PC Control</li>
       * <li><code>16</code> Exposure Bracketing</li>
       * <li><code>32</code> Auto ISO</li>
       * <li><code>64</code> White-Balance Bracketing</li>
       * <li><code>128</code> IR Control</li>
       * </ul>
       */
      public static final int TAG_SHOOTING_MODE = 0x0089;
  
      public static final int TAG_UNKNOWN_20 = 0x008A;
  
      /**
       * Lens stops, as an array of four integers.
       * The value, in EV, is calculated as <code>a*b/c</code>.
       *
       * <ul>
       * <li><code>64,1,12,0</code> = 5.33 EV</li>
       * <li><code>72,1,12,0</code> = 6 EV</li>
       * </ul>
       */
      public static final int TAG_LENS_STOPS = 0x008B;
  
      public static final int TAG_CONTRAST_CURVE = 0x008C;
  
      /**
       * The color space as set in the camera, as a string.
       *
       * <ul>
       * <li><code>MODE1</code> = Mode 1 (sRGB)</li>
       * <li><code>MODE1a</code> = Mode 1 (sRGB)</li>
       * <li><code>MODE2</code> = Mode 2 (Adobe RGB)</li>
       * <li><code>MODE3</code> = Mode 2 (sRGB): Higher Saturation</li>
       * <li><code>MODE3a</code> = Mode 2 (sRGB): Higher Saturation</li>
       * <li><code>B &amp; W</code> = B &amp; W</li>
       * </ul>
       */
      public static final int TAG_CAMERA_COLOR_MODE = 0x008D;
      public static final int TAG_UNKNOWN_47 = 0x008E;
  
      /**
       * The camera's scene mode, as a string.  Examples include:
       * <ul>
       * <li><code>BEACH/SNOW</code></li>
       * <li><code>CLOSE UP</code></li>
       * <li><code>NIGHT PORTRAIT</code></li>
       * <li><code>PORTRAIT</code></li>
       * <li><code>ANTI-SHAKE</code></li>
       * <li><code>BACK LIGHT</code></li>
       * <li><code>BEST FACE</code></li>
       * <li><code>BEST</code></li>
       * <li><code>COPY</code></li>
       * <li><code>DAWN/DUSK</code></li>
       * <li><code>FACE-PRIORITY</code></li>
       * <li><code>FIREWORKS</code></li>
       * <li><code>FOOD</code></li>
       * <li><code>HIGH SENS.</code></li>
       * <li><code>LAND SCAPE</code></li>
       * <li><code>MUSEUM</code></li>
       * <li><code>PANORAMA ASSIST</code></li>
       * <li><code>PARTY/INDOOR</code></li>
       * <li><code>SCENE AUTO</code></li>
       * <li><code>SMILE</code></li>
       * <li><code>SPORT</code></li>
       * <li><code>SPORT CONT.</code></li>
       * <li><code>SUNSET</code></li>
       * </ul>
       */
      public static final int TAG_SCENE_MODE = 0x008F;
  
      /**
       * The lighting type, as a string.  Examples include:
       * <ul>
       * <li><code></code></li>
       * <li><code>NATURAL</code></li>
       * <li><code>SPEEDLIGHT</code></li>
       * <li><code>COLORED</code></li>
       * <li><code>MIXED</code></li>
       * <li><code>NORMAL</code></li>
       * </ul>
       */
      public static final int TAG_LIGHT_SOURCE = 0x0090;
  
      /**
       * Advertised as ASCII, but actually isn't.  A variable number of bytes (eg. 18 to 533).  Actual number of bytes
       * appears fixed for a given camera model.
       */
      public static final int TAG_SHOT_INFO = 0x0091;
  
      /**
       * The hue adjustment as set in the camera.  Values observed are either 0 or 3.
       */
      public static final int TAG_CAMERA_HUE_ADJUSTMENT = 0x0092;
      /**
       * The NEF (RAW) compression.  Examples include:
       * <ul>
       * <li><code>1</code> Lossy (Type 1)</li>
       * <li><code>2</code> Uncompressed</li>
       * <li><code>3</code> Lossless</li>
       * <li><code>4</code> Lossy (Type 2)</li>
       * </ul>
       */
      public static final int TAG_NEF_COMPRESSION = 0x0093;
  
      /**
       * The saturation level, as a signed integer.  Examples include:
       * <ul>
       * <li><code>+3</code></li>
       * <li><code>+2</code></li>
       * <li><code>+1</code></li>
       * <li><code>0</code> Normal</li>
       * <li><code>-1</code></li>
       * <li><code>-2</code></li>
       * <li><code>-3</code> (B&amp;W)</li>
       * </ul>
       */
      public static final int TAG_SATURATION = 0x0094;
  
      /**
       * The type of noise reduction, as a string.  Examples include:
       * <ul>
       * <li><code>OFF</code></li>
       * <li><code>FPNR</code></li>
       * </ul>
       */
      public static final int TAG_NOISE_REDUCTION = 0x0095;
      public static final int TAG_LINEARIZATION_TABLE = 0x0096;
      public static final int TAG_COLOR_BALANCE = 0x0097;
      public static final int TAG_LENS_DATA = 0x0098;
  
      /** The NEF (RAW) thumbnail size, as an integer array with two items representing [width,height]. */
      public static final int TAG_NEF_THUMBNAIL_SIZE = 0x0099;
  
      /** The sensor pixel size, as a pair of rational numbers. */
      public static final int TAG_SENSOR_PIXEL_SIZE = 0x009A;
      public static final int TAG_UNKNOWN_10 = 0x009B;
      public static final int TAG_SCENE_ASSIST = 0x009C;
      public static final int TAG_DATE_STAMP_MODE = 0x009D;
      public static final int TAG_RETOUCH_HISTORY = 0x009E;
      public static final int TAG_UNKNOWN_12 = 0x009F;
  
      /**
       * The camera serial number, as a string.
       * <ul>
       * <li><code>NO= 00002539</code></li>
       * <li><code>NO= -1000d71</code></li>
       * <li><code>PKG597230621263</code></li>
       * <li><code>PKG5995671330625116</code></li>
       * <li><code>PKG49981281631130677</code></li>
       * <li><code>BU672230725063</code></li>
       * <li><code>NO= 200332c7</code></li>
       * <li><code>NO= 30045efe</code></li>
       * </ul>
       */
      public static final int TAG_CAMERA_SERIAL_NUMBER_2 = 0x00A0;
  
      public static final int TAG_IMAGE_DATA_SIZE = 0x00A2;
  
      public static final int TAG_UNKNOWN_27 = 0x00A3;
      public static final int TAG_UNKNOWN_28 = 0x00A4;
      public static final int TAG_IMAGE_COUNT = 0x00A5;
      public static final int TAG_DELETED_IMAGE_COUNT = 0x00A6;
  
      /** The number of total shutter releases.  This value increments for each exposure (observed on D70). */
      public static final int TAG_EXPOSURE_SEQUENCE_NUMBER = 0x00A7;
  
      public static final int TAG_FLASH_INFO = 0x00A8;
      /**
       * The camera's image optimisation, as a string.
       * <ul>
       *     <li><code></code></li>
       *     <li><code>NORMAL</code></li>
       *     <li><code>CUSTOM</code></li>
       *     <li><code>BLACK AND WHITE</code></li>
       *     <li><code>LAND SCAPE</code></li>
       *     <li><code>MORE VIVID</code></li>
       *     <li><code>PORTRAIT</code></li>
       *     <li><code>SOFT</code></li>
       *     <li><code>VIVID</code></li>
       * </ul>
       */
      public static final int TAG_IMAGE_OPTIMISATION = 0x00A9;
  
      /**
       * The camera's saturation level, as a string.
       * <ul>
       *     <li><code></code></li>
       *     <li><code>NORMAL</code></li>
       *     <li><code>AUTO</code></li>
       *     <li><code>ENHANCED</code></li>
       *     <li><code>MODERATE</code></li>
       * </ul>
       */
      public static final int TAG_SATURATION_2 = 0x00AA;
  
      /**
       * The camera's digital vari-program setting, as a string.
       * <ul>
       *     <li><code></code></li>
       *     <li><code>AUTO</code></li>
       *     <li><code>AUTO(FLASH OFF)</code></li>
       *     <li><code>CLOSE UP</code></li>
       *     <li><code>LANDSCAPE</code></li>
       *     <li><code>NIGHT PORTRAIT</code></li>
       *     <li><code>PORTRAIT</code></li>
       *     <li><code>SPORT</code></li>
       * </ul>
       */
      public static final int TAG_DIGITAL_VARI_PROGRAM = 0x00AB;
  
      /**
       * The camera's digital vari-program setting, as a string.
       * <ul>
       *     <li><code></code></li>
       *     <li><code>VR-ON</code></li>
       *     <li><code>VR-OFF</code></li>
       *     <li><code>VR-HYBRID</code></li>
       *     <li><code>VR-ACTIVE</code></li>
       * </ul>
       */
      public static final int TAG_IMAGE_STABILISATION = 0x00AC;
  
      /**
       * The camera's digital vari-program setting, as a string.
       * <ul>
       *     <li><code></code></li>
       *     <li><code>HYBRID</code></li>
       *     <li><code>STANDARD</code></li>
       * </ul>
       */
      public static final int TAG_AF_RESPONSE = 0x00AD;
      public static final int TAG_UNKNOWN_29 = 0x00AE;
      public static final int TAG_UNKNOWN_30 = 0x00AF;
      public static final int TAG_MULTI_EXPOSURE = 0x00B0;
  
      /**
       * The camera's high ISO noise reduction setting, as an integer.
       * <ul>
       *     <li><code>0</code> Off</li>
       *     <li><code>1</code> Minimal</li>
       *     <li><code>2</code> Low</li>
       *     <li><code>4</code> Normal</li>
       *     <li><code>6</code> High</li>
       * </ul>
       */
      public static final int TAG_HIGH_ISO_NOISE_REDUCTION = 0x00B1;
      public static final int TAG_UNKNOWN_31 = 0x00B2;
      public static final int TAG_TONING_EFFECT = 0x00B3;
      public static final int TAG_UNKNOWN_33 = 0x00B4;
      public static final int TAG_UNKNOWN_48 = 0x00B5;
      public static final int TAG_POWER_UP_TIME = 0x00B6;
      public static final int TAG_AF_INFO_2 = 0x00B7;
      public static final int TAG_FILE_INFO = 0x00B8;
      public static final int TAG_AF_TUNE = 0x00B9;
      public static final int TAG_RETOUCH_INFO = 0x00BB;
      public static final int TAG_PICTURE_CONTROL_2 = 0x00BD;
      public static final int TAG_UNKNOWN_51 = 0x0103;
      public static final int TAG_PRINT_IMAGE_MATCHING_INFO = 0x0E00;
  
      /**
       * Data about changes set by Nikon Capture Editor.
       *
       * Values observed
       */
      public static final int TAG_NIKON_CAPTURE_DATA = 0x0E01;
      public static final int TAG_UNKNOWN_52 = 0x0E05;
      public static final int TAG_UNKNOWN_53 = 0x0E08;
      public static final int TAG_NIKON_CAPTURE_VERSION = 0x0E09;
      public static final int TAG_NIKON_CAPTURE_OFFSETS = 0x0E0E;
      public static final int TAG_NIKON_SCAN = 0x0E10;
      public static final int TAG_UNKNOWN_54 = 0x0E19;
      public static final int TAG_NEF_BIT_DEPTH = 0x0E22;
      public static final int TAG_UNKNOWN_55 = 0x0E23;
  
      @NotNull
      private static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
  
      static
      {
          _tagNameMap.put(TAG_FIRMWARE_VERSION, "Firmware Version");
          _tagNameMap.put(TAG_ISO_1, "ISO");
          _tagNameMap.put(TAG_QUALITY_AND_FILE_FORMAT, "Quality & File Format");
          _tagNameMap.put(TAG_CAMERA_WHITE_BALANCE, "White Balance");
          _tagNameMap.put(TAG_CAMERA_SHARPENING, "Sharpening");
          _tagNameMap.put(TAG_AF_TYPE, "AF Type");
          _tagNameMap.put(TAG_CAMERA_WHITE_BALANCE_FINE, "White Balance Fine");
          _tagNameMap.put(TAG_CAMERA_WHITE_BALANCE_RB_COEFF, "White Balance RB Coefficients");
          _tagNameMap.put(TAG_ISO_REQUESTED, "ISO");
          _tagNameMap.put(TAG_ISO_MODE, "ISO Mode");
          _tagNameMap.put(TAG_DATA_DUMP, "Data Dump");
  
          _tagNameMap.put(TAG_PROGRAM_SHIFT, "Program Shift");
          _tagNameMap.put(TAG_EXPOSURE_DIFFERENCE, "Exposure Difference");
          _tagNameMap.put(TAG_PREVIEW_IFD, "Preview IFD");
          _tagNameMap.put(TAG_LENS_TYPE, "Lens Type");
          _tagNameMap.put(TAG_FLASH_USED, "Flash Used");
          _tagNameMap.put(TAG_AF_FOCUS_POSITION, "AF Focus Position");
          _tagNameMap.put(TAG_SHOOTING_MODE, "Shooting Mode");
          _tagNameMap.put(TAG_LENS_STOPS, "Lens Stops");
          _tagNameMap.put(TAG_CONTRAST_CURVE, "Contrast Curve");
          _tagNameMap.put(TAG_LIGHT_SOURCE, "Light source");
          _tagNameMap.put(TAG_SHOT_INFO, "Shot Info");
          _tagNameMap.put(TAG_COLOR_BALANCE, "Color Balance");
          _tagNameMap.put(TAG_LENS_DATA, "Lens Data");
          _tagNameMap.put(TAG_NEF_THUMBNAIL_SIZE, "NEF Thumbnail Size");
          _tagNameMap.put(TAG_SENSOR_PIXEL_SIZE, "Sensor Pixel Size");
          _tagNameMap.put(TAG_UNKNOWN_10, "Unknown 10");
          _tagNameMap.put(TAG_SCENE_ASSIST, "Scene Assist");
          _tagNameMap.put(TAG_DATE_STAMP_MODE, "Date Stamp Mode");
          _tagNameMap.put(TAG_RETOUCH_HISTORY, "Retouch History");
          _tagNameMap.put(TAG_UNKNOWN_12, "Unknown 12");
          _tagNameMap.put(TAG_FLASH_SYNC_MODE, "Flash Sync Mode");
          _tagNameMap.put(TAG_AUTO_FLASH_MODE, "Auto Flash Mode");
          _tagNameMap.put(TAG_AUTO_FLASH_COMPENSATION, "Auto Flash Compensation");
          _tagNameMap.put(TAG_EXPOSURE_SEQUENCE_NUMBER, "Exposure Sequence Number");
          _tagNameMap.put(TAG_COLOR_MODE, "Color Mode");
  
          _tagNameMap.put(TAG_UNKNOWN_20, "Unknown 20");
          _tagNameMap.put(TAG_IMAGE_BOUNDARY, "Image Boundary");
          _tagNameMap.put(TAG_FLASH_EXPOSURE_COMPENSATION, "Flash Exposure Compensation");
          _tagNameMap.put(TAG_FLASH_BRACKET_COMPENSATION, "Flash Bracket Compensation");
          _tagNameMap.put(TAG_AE_BRACKET_COMPENSATION, "AE Bracket Compensation");
          _tagNameMap.put(TAG_FLASH_MODE, "Flash Mode");
          _tagNameMap.put(TAG_CROP_HIGH_SPEED, "Crop High Speed");
          _tagNameMap.put(TAG_EXPOSURE_TUNING, "Exposure Tuning");
          _tagNameMap.put(TAG_CAMERA_SERIAL_NUMBER, "Camera Serial Number");
          _tagNameMap.put(TAG_COLOR_SPACE, "Color Space");
          _tagNameMap.put(TAG_VR_INFO, "VR Info");
          _tagNameMap.put(TAG_IMAGE_AUTHENTICATION, "Image Authentication");
          _tagNameMap.put(TAG_FACE_DETECT, "Face Detect");
          _tagNameMap.put(TAG_ACTIVE_D_LIGHTING, "Active D-Lighting");
          _tagNameMap.put(TAG_PICTURE_CONTROL, "Picture Control");
          _tagNameMap.put(TAG_WORLD_TIME, "World Time");
          _tagNameMap.put(TAG_ISO_INFO, "ISO Info");
          _tagNameMap.put(TAG_UNKNOWN_36, "Unknown 36");
          _tagNameMap.put(TAG_UNKNOWN_37, "Unknown 37");
          _tagNameMap.put(TAG_UNKNOWN_38, "Unknown 38");
          _tagNameMap.put(TAG_UNKNOWN_39, "Unknown 39");
          _tagNameMap.put(TAG_VIGNETTE_CONTROL, "Vignette Control");
          _tagNameMap.put(TAG_DISTORT_INFO, "Distort Info");
          _tagNameMap.put(TAG_UNKNOWN_41, "Unknown 41");
          _tagNameMap.put(TAG_UNKNOWN_42, "Unknown 42");
          _tagNameMap.put(TAG_UNKNOWN_43, "Unknown 43");
          _tagNameMap.put(TAG_UNKNOWN_44, "Unknown 44");
          _tagNameMap.put(TAG_UNKNOWN_45, "Unknown 45");
          _tagNameMap.put(TAG_UNKNOWN_46, "Unknown 46");
          _tagNameMap.put(TAG_UNKNOWN_47, "Unknown 47");
          _tagNameMap.put(TAG_SCENE_MODE, "Scene Mode");
  
          _tagNameMap.put(TAG_CAMERA_SERIAL_NUMBER_2, "Camera Serial Number");
          _tagNameMap.put(TAG_IMAGE_DATA_SIZE, "Image Data Size");
          _tagNameMap.put(TAG_UNKNOWN_27, "Unknown 27");
          _tagNameMap.put(TAG_UNKNOWN_28, "Unknown 28");
          _tagNameMap.put(TAG_IMAGE_COUNT, "Image Count");
          _tagNameMap.put(TAG_DELETED_IMAGE_COUNT, "Deleted Image Count");
          _tagNameMap.put(TAG_SATURATION_2, "Saturation");
          _tagNameMap.put(TAG_DIGITAL_VARI_PROGRAM, "Digital Vari Program");
          _tagNameMap.put(TAG_IMAGE_STABILISATION, "Image Stabilisation");
          _tagNameMap.put(TAG_AF_RESPONSE, "AF Response");
          _tagNameMap.put(TAG_UNKNOWN_29, "Unknown 29");
          _tagNameMap.put(TAG_UNKNOWN_30, "Unknown 30");
          _tagNameMap.put(TAG_MULTI_EXPOSURE, "Multi Exposure");
          _tagNameMap.put(TAG_HIGH_ISO_NOISE_REDUCTION, "High ISO Noise Reduction");
          _tagNameMap.put(TAG_UNKNOWN_31, "Unknown 31");
          _tagNameMap.put(TAG_TONING_EFFECT, "Toning Effect");
          _tagNameMap.put(TAG_UNKNOWN_33, "Unknown 33");
          _tagNameMap.put(TAG_UNKNOWN_48, "Unknown 48");
          _tagNameMap.put(TAG_POWER_UP_TIME, "Power Up Time");
          _tagNameMap.put(TAG_AF_INFO_2, "AF Info 2");
          _tagNameMap.put(TAG_FILE_INFO, "File Info");
          _tagNameMap.put(TAG_AF_TUNE, "AF Tune");
          _tagNameMap.put(TAG_FLASH_INFO, "Flash Info");
          _tagNameMap.put(TAG_IMAGE_OPTIMISATION, "Image Optimisation");
  
          _tagNameMap.put(TAG_IMAGE_ADJUSTMENT, "Image Adjustment");
          _tagNameMap.put(TAG_CAMERA_TONE_COMPENSATION, "Tone Compensation");
          _tagNameMap.put(TAG_ADAPTER, "Adapter");
          _tagNameMap.put(TAG_LENS, "Lens");
          _tagNameMap.put(TAG_MANUAL_FOCUS_DISTANCE, "Manual Focus Distance");
          _tagNameMap.put(TAG_DIGITAL_ZOOM, "Digital Zoom");
          _tagNameMap.put(TAG_CAMERA_COLOR_MODE, "Colour Mode");
          _tagNameMap.put(TAG_CAMERA_HUE_ADJUSTMENT, "Camera Hue Adjustment");
          _tagNameMap.put(TAG_NEF_COMPRESSION, "NEF Compression");
          _tagNameMap.put(TAG_SATURATION, "Saturation");
          _tagNameMap.put(TAG_NOISE_REDUCTION, "Noise Reduction");
          _tagNameMap.put(TAG_LINEARIZATION_TABLE, "Linearization Table");
          _tagNameMap.put(TAG_NIKON_CAPTURE_DATA, "Nikon Capture Data");
          _tagNameMap.put(TAG_RETOUCH_INFO, "Retouch Info");
          _tagNameMap.put(TAG_PICTURE_CONTROL_2, "Picture Control 2");
          _tagNameMap.put(TAG_UNKNOWN_51, "Unknown 51");
          _tagNameMap.put(TAG_PRINT_IMAGE_MATCHING_INFO, "Print IM");
          _tagNameMap.put(TAG_UNKNOWN_52, "Unknown 52");
          _tagNameMap.put(TAG_UNKNOWN_53, "Unknown 53");
          _tagNameMap.put(TAG_NIKON_CAPTURE_VERSION, "Nikon Capture Version");
          _tagNameMap.put(TAG_NIKON_CAPTURE_OFFSETS, "Nikon Capture Offsets");
          _tagNameMap.put(TAG_NIKON_SCAN, "Nikon Scan");
          _tagNameMap.put(TAG_UNKNOWN_54, "Unknown 54");
          _tagNameMap.put(TAG_NEF_BIT_DEPTH, "NEF Bit Depth");
          _tagNameMap.put(TAG_UNKNOWN_55, "Unknown 55");
      }
  
      public NikonType2MakernoteDirectory()
      {
          this.setDescriptor(new NikonType2MakernoteDescriptor(this));
      }
  
      @Override
      @NotNull
      public String getName()
      {
          return "Nikon Makernote";
      }
  
      @Override
      @NotNull
      protected HashMap<Integer, String> getTagNameMap()
      {
          return _tagNameMap;
      }
  
  	/** Nikon decryption tables used in exiftool */
      private static final int[] _decTable1 =   {0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d,
                                                 0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d,
                                                 0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f,
                                                 0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f,
                                                 0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1,
                                                 0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17,
                                                 0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89,
                                                 0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f,
                                                 0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b,
                                                 0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb,
                                                 0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3,
                                                 0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f,
                                                 0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35,
                                                 0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43,
                                                 0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5,
                                                 0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7 };
      private static final int[] _decTable2 = { 0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c,
                                                 0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34,
                                                 0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad,
                                                 0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05,
                                                 0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee,
                                                 0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d,
                                                 0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b,
                                                 0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b,
                                                 0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc,
                                                 0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33,
                                                 0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8,
                                                 0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6,
                                                 0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c,
                                                 0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49,
                                                 0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb,
                                                 0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f };
  
  
      /** decryption algorithm adapted from exiftool */
      @Nullable
      public int[] getDecryptedIntArray(int tagType)
      {
          int[] data = getIntArray(tagType);
          Integer serial = getInteger(TAG_CAMERA_SERIAL_NUMBER);
          Integer count = getInteger(TAG_EXPOSURE_SEQUENCE_NUMBER);
  
          if (data == null || serial == null || count == null)
              return null;
  
          int key = 0;
          for (int i = 0; i < 4; i++)
              key ^= (count >> (i * 8)) & 0xff;
  
          int ci = _decTable1[serial & 0xff];
          int cj = _decTable2[key];
          int ck = 0x60;
  
          for (int i = 4; i < data.length; i++)
          {
              cj = (cj + ci * ck) & 0xff;
              ck = (ck + 1) & 0xff;
              data[i] ^= cj;
          }
  
          return data;
      }
  }
  