Index: trunk/src/com/drew/metadata/exif/ExifDescriptorBase.java
===================================================================
--- trunk/src/com/drew/metadata/exif/ExifDescriptorBase.java	(revision 15217)
+++ 	(revision )
@@ -1,1298 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.imaging.PhotographicConversions;
-import com.drew.lang.Rational;
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.lang.ByteArrayReader;
-import com.drew.metadata.Directory;
-import com.drew.metadata.TagDescriptor;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.text.DecimalFormat;
-
-import static com.drew.metadata.exif.ExifDirectoryBase.*;
-
-/**
- * Base class for several Exif format descriptor classes.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public abstract class ExifDescriptorBase<T extends Directory> extends TagDescriptor<T>
-{
-    /**
-     * Dictates whether rational values will be represented in decimal format in instances
-     * where decimal notation is elegant (such as 1/2 -> 0.5, but not 1/3).
-     */
-    private final boolean _allowDecimalRepresentationOfRationals = true;
-
-    // Note for the potential addition of brightness presentation in eV:
-    // Brightness of taken subject. To calculate Exposure(Ev) from BrightnessValue(Bv),
-    // you must add SensitivityValue(Sv).
-    // Ev=BV+Sv   Sv=log2(ISOSpeedRating/3.125)
-    // ISO100:Sv=5, ISO200:Sv=6, ISO400:Sv=7, ISO125:Sv=5.32.
-
-    public ExifDescriptorBase(@NotNull T directory)
-    {
-        super(directory);
-    }
-
-    @Nullable
-    @Override
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_INTEROP_INDEX:
-                return getInteropIndexDescription();
-            case TAG_INTEROP_VERSION:
-                return getInteropVersionDescription();
-            case TAG_NEW_SUBFILE_TYPE:
-                return getNewSubfileTypeDescription();
-            case TAG_SUBFILE_TYPE:
-                return getSubfileTypeDescription();
-            case TAG_IMAGE_WIDTH:
-                return getImageWidthDescription();
-            case TAG_IMAGE_HEIGHT:
-                return getImageHeightDescription();
-            case TAG_BITS_PER_SAMPLE:
-                return getBitsPerSampleDescription();
-            case TAG_COMPRESSION:
-                return getCompressionDescription();
-            case TAG_PHOTOMETRIC_INTERPRETATION:
-                return getPhotometricInterpretationDescription();
-            case TAG_THRESHOLDING:
-                return getThresholdingDescription();
-            case TAG_FILL_ORDER:
-                return getFillOrderDescription();
-            case TAG_ORIENTATION:
-                return getOrientationDescription();
-            case TAG_SAMPLES_PER_PIXEL:
-                return getSamplesPerPixelDescription();
-            case TAG_ROWS_PER_STRIP:
-                return getRowsPerStripDescription();
-            case TAG_STRIP_BYTE_COUNTS:
-                return getStripByteCountsDescription();
-            case TAG_X_RESOLUTION:
-                return getXResolutionDescription();
-            case TAG_Y_RESOLUTION:
-                return getYResolutionDescription();
-            case TAG_PLANAR_CONFIGURATION:
-                return getPlanarConfigurationDescription();
-            case TAG_RESOLUTION_UNIT:
-                return getResolutionDescription();
-            case TAG_JPEG_PROC:
-                return getJpegProcDescription();
-            case TAG_YCBCR_SUBSAMPLING:
-                return getYCbCrSubsamplingDescription();
-            case TAG_YCBCR_POSITIONING:
-                return getYCbCrPositioningDescription();
-            case TAG_REFERENCE_BLACK_WHITE:
-                return getReferenceBlackWhiteDescription();
-            case TAG_CFA_PATTERN_2:
-                return getCfaPattern2Description();
-            case TAG_EXPOSURE_TIME:
-                return getExposureTimeDescription();
-            case TAG_FNUMBER:
-                return getFNumberDescription();
-            case TAG_EXPOSURE_PROGRAM:
-                return getExposureProgramDescription();
-            case TAG_ISO_EQUIVALENT:
-                return getIsoEquivalentDescription();
-            case TAG_SENSITIVITY_TYPE:
-                return getSensitivityTypeRangeDescription();
-            case TAG_EXIF_VERSION:
-                return getExifVersionDescription();
-            case TAG_COMPONENTS_CONFIGURATION:
-                return getComponentConfigurationDescription();
-            case TAG_COMPRESSED_AVERAGE_BITS_PER_PIXEL:
-                return getCompressedAverageBitsPerPixelDescription();
-            case TAG_SHUTTER_SPEED:
-                return getShutterSpeedDescription();
-            case TAG_APERTURE:
-                return getApertureValueDescription();
-            case TAG_BRIGHTNESS_VALUE:
-                return getBrightnessValueDescription();
-            case TAG_EXPOSURE_BIAS:
-                return getExposureBiasDescription();
-            case TAG_MAX_APERTURE:
-                return getMaxApertureValueDescription();
-            case TAG_SUBJECT_DISTANCE:
-                return getSubjectDistanceDescription();
-            case TAG_METERING_MODE:
-                return getMeteringModeDescription();
-            case TAG_WHITE_BALANCE:
-                return getWhiteBalanceDescription();
-            case TAG_FLASH:
-                return getFlashDescription();
-            case TAG_FOCAL_LENGTH:
-                return getFocalLengthDescription();
-            case TAG_USER_COMMENT:
-                return getUserCommentDescription();
-            case TAG_TEMPERATURE:
-                return getTemperatureDescription();
-            case TAG_HUMIDITY:
-                return getHumidityDescription();
-            case TAG_PRESSURE:
-                return getPressureDescription();
-            case TAG_WATER_DEPTH:
-                return getWaterDepthDescription();
-            case TAG_ACCELERATION:
-                return getAccelerationDescription();
-            case TAG_CAMERA_ELEVATION_ANGLE:
-                return getCameraElevationAngleDescription();
-            case TAG_WIN_TITLE:
-                return getWindowsTitleDescription();
-            case TAG_WIN_COMMENT:
-                return getWindowsCommentDescription();
-            case TAG_WIN_AUTHOR:
-                return getWindowsAuthorDescription();
-            case TAG_WIN_KEYWORDS:
-                return getWindowsKeywordsDescription();
-            case TAG_WIN_SUBJECT:
-                return getWindowsSubjectDescription();
-            case TAG_FLASHPIX_VERSION:
-                return getFlashPixVersionDescription();
-            case TAG_COLOR_SPACE:
-                return getColorSpaceDescription();
-            case TAG_EXIF_IMAGE_WIDTH:
-                return getExifImageWidthDescription();
-            case TAG_EXIF_IMAGE_HEIGHT:
-                return getExifImageHeightDescription();
-            case TAG_FOCAL_PLANE_X_RESOLUTION:
-                return getFocalPlaneXResolutionDescription();
-            case TAG_FOCAL_PLANE_Y_RESOLUTION:
-                return getFocalPlaneYResolutionDescription();
-            case TAG_FOCAL_PLANE_RESOLUTION_UNIT:
-                return getFocalPlaneResolutionUnitDescription();
-            case TAG_SENSING_METHOD:
-                return getSensingMethodDescription();
-            case TAG_FILE_SOURCE:
-                return getFileSourceDescription();
-            case TAG_SCENE_TYPE:
-                return getSceneTypeDescription();
-            case TAG_CFA_PATTERN:
-                return getCfaPatternDescription();
-            case TAG_CUSTOM_RENDERED:
-                return getCustomRenderedDescription();
-            case TAG_EXPOSURE_MODE:
-                return getExposureModeDescription();
-            case TAG_WHITE_BALANCE_MODE:
-                return getWhiteBalanceModeDescription();
-            case TAG_DIGITAL_ZOOM_RATIO:
-                return getDigitalZoomRatioDescription();
-            case TAG_35MM_FILM_EQUIV_FOCAL_LENGTH:
-                return get35mmFilmEquivFocalLengthDescription();
-            case TAG_SCENE_CAPTURE_TYPE:
-                return getSceneCaptureTypeDescription();
-            case TAG_GAIN_CONTROL:
-                return getGainControlDescription();
-            case TAG_CONTRAST:
-                return getContrastDescription();
-            case TAG_SATURATION:
-                return getSaturationDescription();
-            case TAG_SHARPNESS:
-                return getSharpnessDescription();
-            case TAG_SUBJECT_DISTANCE_RANGE:
-                return getSubjectDistanceRangeDescription();
-            case TAG_LENS_SPECIFICATION:
-                return getLensSpecificationDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getInteropIndexDescription()
-    {
-        String value = _directory.getString(TAG_INTEROP_INDEX);
-
-        if (value == null)
-            return null;
-
-        return "R98".equalsIgnoreCase(value.trim())
-            ? "Recommended Exif Interoperability Rules (ExifR98)"
-            : "Unknown (" + value + ")";
-    }
-
-    @Nullable
-    public String getInteropVersionDescription()
-    {
-        return getVersionBytesDescription(TAG_INTEROP_VERSION, 2);
-    }
-
-    @Nullable
-    public String getNewSubfileTypeDescription()
-    {
-        return getIndexedDescription(TAG_NEW_SUBFILE_TYPE, 0,
-            "Full-resolution image",
-            "Reduced-resolution image",
-            "Single page of multi-page image",
-            "Single page of multi-page reduced-resolution image",
-            "Transparency mask",
-            "Transparency mask of reduced-resolution image",
-            "Transparency mask of multi-page image",
-            "Transparency mask of reduced-resolution multi-page image"
-        );
-    }
-
-    @Nullable
-    public String getSubfileTypeDescription()
-    {
-        return getIndexedDescription(TAG_SUBFILE_TYPE, 1,
-            "Full-resolution image",
-            "Reduced-resolution image",
-            "Single page of multi-page image"
-        );
-    }
-
-    @Nullable
-    public String getImageWidthDescription()
-    {
-        String value = _directory.getString(TAG_IMAGE_WIDTH);
-        return value == null ? null : value + " pixels";
-    }
-
-    @Nullable
-    public String getImageHeightDescription()
-    {
-        String value = _directory.getString(TAG_IMAGE_HEIGHT);
-        return value == null ? null : value + " pixels";
-    }
-
-    @Nullable
-    public String getBitsPerSampleDescription()
-    {
-        String value = _directory.getString(TAG_BITS_PER_SAMPLE);
-        return value == null ? null : value + " bits/component/pixel";
-    }
-
-    @Nullable
-    public String getCompressionDescription()
-    {
-        Integer value = _directory.getInteger(TAG_COMPRESSION);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 1: return "Uncompressed";
-            case 2: return "CCITT 1D";
-            case 3: return "T4/Group 3 Fax";
-            case 4: return "T6/Group 4 Fax";
-            case 5: return "LZW";
-            case 6: return "JPEG (old-style)";
-            case 7: return "JPEG";
-            case 8: return "Adobe Deflate";
-            case 9: return "JBIG B&W";
-            case 10: return "JBIG Color";
-            case 99: return "JPEG";
-            case 262: return "Kodak 262";
-            case 32766: return "Next";
-            case 32767: return "Sony ARW Compressed";
-            case 32769: return "Packed RAW";
-            case 32770: return "Samsung SRW Compressed";
-            case 32771: return "CCIRLEW";
-            case 32772: return "Samsung SRW Compressed 2";
-            case 32773: return "PackBits";
-            case 32809: return "Thunderscan";
-            case 32867: return "Kodak KDC Compressed";
-            case 32895: return "IT8CTPAD";
-            case 32896: return "IT8LW";
-            case 32897: return "IT8MP";
-            case 32898: return "IT8BL";
-            case 32908: return "PixarFilm";
-            case 32909: return "PixarLog";
-            case 32946: return "Deflate";
-            case 32947: return "DCS";
-            case 34661: return "JBIG";
-            case 34676: return "SGILog";
-            case 34677: return "SGILog24";
-            case 34712: return "JPEG 2000";
-            case 34713: return "Nikon NEF Compressed";
-            case 34715: return "JBIG2 TIFF FX";
-            case 34718: return "Microsoft Document Imaging (MDI) Binary Level Codec";
-            case 34719: return "Microsoft Document Imaging (MDI) Progressive Transform Codec";
-            case 34720: return "Microsoft Document Imaging (MDI) Vector";
-            case 34892: return "Lossy JPEG";
-            case 65000: return "Kodak DCR Compressed";
-            case 65535: return "Pentax PEF Compressed";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getPhotometricInterpretationDescription()
-    {
-        // Shows the color space of the image data components
-        Integer value = _directory.getInteger(TAG_PHOTOMETRIC_INTERPRETATION);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "WhiteIsZero";
-            case 1: return "BlackIsZero";
-            case 2: return "RGB";
-            case 3: return "RGB Palette";
-            case 4: return "Transparency Mask";
-            case 5: return "CMYK";
-            case 6: return "YCbCr";
-            case 8: return "CIELab";
-            case 9: return "ICCLab";
-            case 10: return "ITULab";
-            case 32803: return "Color Filter Array";
-            case 32844: return "Pixar LogL";
-            case 32845: return "Pixar LogLuv";
-            case 32892: return "Linear Raw";
-            default:
-                return "Unknown colour space";
-        }
-    }
-
-    @Nullable
-    public String getThresholdingDescription()
-    {
-        return getIndexedDescription(TAG_THRESHOLDING, 1,
-            "No dithering or halftoning",
-            "Ordered dither or halftone",
-            "Randomized dither"
-        );
-    }
-
-    @Nullable
-    public String getFillOrderDescription()
-    {
-        return getIndexedDescription(TAG_FILL_ORDER, 1,
-            "Normal",
-            "Reversed"
-        );
-    }
-
-    @Nullable
-    public String getOrientationDescription()
-    {
-        return super.getOrientationDescription(TAG_ORIENTATION);
-    }
-
-    @Nullable
-    public String getSamplesPerPixelDescription()
-    {
-        String value = _directory.getString(TAG_SAMPLES_PER_PIXEL);
-        return value == null ? null : value + " samples/pixel";
-    }
-
-    @Nullable
-    public String getRowsPerStripDescription()
-    {
-        final String value = _directory.getString(TAG_ROWS_PER_STRIP);
-        return value == null ? null : value + " rows/strip";
-    }
-
-    @Nullable
-    public String getStripByteCountsDescription()
-    {
-        final String value = _directory.getString(TAG_STRIP_BYTE_COUNTS);
-        return value == null ? null : value + " bytes";
-    }
-
-    @Nullable
-    public String getXResolutionDescription()
-    {
-        Rational value = _directory.getRational(TAG_X_RESOLUTION);
-        if (value == null)
-            return null;
-        final String unit = getResolutionDescription();
-        return String.format("%s dots per %s",
-            value.toSimpleString(_allowDecimalRepresentationOfRationals),
-            unit == null ? "unit" : unit.toLowerCase());
-    }
-
-    @Nullable
-    public String getYResolutionDescription()
-    {
-        Rational value = _directory.getRational(TAG_Y_RESOLUTION);
-        if (value==null)
-            return null;
-        final String unit = getResolutionDescription();
-        return String.format("%s dots per %s",
-            value.toSimpleString(_allowDecimalRepresentationOfRationals),
-            unit == null ? "unit" : unit.toLowerCase());
-    }
-
-    @Nullable
-    public String getPlanarConfigurationDescription()
-    {
-        // When image format is no compression YCbCr, this value shows byte aligns of YCbCr
-        // data. If value is '1', Y/Cb/Cr value is chunky format, contiguous for each subsampling
-        // pixel. If value is '2', Y/Cb/Cr value is separated and stored to Y plane/Cb plane/Cr
-        // plane format.
-        return getIndexedDescription(TAG_PLANAR_CONFIGURATION,
-            1,
-            "Chunky (contiguous for each subsampling pixel)",
-            "Separate (Y-plane/Cb-plane/Cr-plane format)"
-        );
-    }
-
-    @Nullable
-    public String getResolutionDescription()
-    {
-        // '1' means no-unit, '2' means inch, '3' means centimeter. Default value is '2'(inch)
-        return getIndexedDescription(TAG_RESOLUTION_UNIT, 1, "(No unit)", "Inch", "cm");
-    }
-
-    @Nullable
-    public String getJpegProcDescription()
-    {
-        Integer value = _directory.getInteger(TAG_JPEG_PROC);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 1: return "Baseline";
-            case 14: return "Lossless";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getYCbCrSubsamplingDescription()
-    {
-        int[] positions = _directory.getIntArray(TAG_YCBCR_SUBSAMPLING);
-        if (positions == null || positions.length < 2)
-            return null;
-        if (positions[0] == 2 && positions[1] == 1) {
-            return "YCbCr4:2:2";
-        } else if (positions[0] == 2 && positions[1] == 2) {
-            return "YCbCr4:2:0";
-        } else {
-            return "(Unknown)";
-        }
-    }
-
-    @Nullable
-    public String getYCbCrPositioningDescription()
-    {
-        return getIndexedDescription(TAG_YCBCR_POSITIONING, 1, "Center of pixel array", "Datum point");
-    }
-
-    @Nullable
-    public String getReferenceBlackWhiteDescription()
-    {
-        // For some reason, sometimes this is read as a long[] and
-        // getIntArray isn't able to deal with it
-        int[] ints = _directory.getIntArray(TAG_REFERENCE_BLACK_WHITE);
-        if (ints==null || ints.length < 6)
-        {
-            Object o = _directory.getObject(TAG_REFERENCE_BLACK_WHITE);
-            if (o != null && (o instanceof long[]))
-            {
-                long[] longs = (long[])o;
-                if (longs.length < 6)
-                    return null;
-
-                ints = new int[longs.length];
-                for (int i = 0; i < longs.length; i++)
-                    ints[i] = (int)longs[i];
-            }
-            else
-                return null;
-        }
-
-        int blackR = ints[0];
-        int whiteR = ints[1];
-        int blackG = ints[2];
-        int whiteG = ints[3];
-        int blackB = ints[4];
-        int whiteB = ints[5];
-        return String.format("[%d,%d,%d] [%d,%d,%d]", blackR, blackG, blackB, whiteR, whiteG, whiteB);
-    }
-
-    /// <summary>
-    /// String description of CFA Pattern
-    /// </summary>
-    /// <remarks>
-    /// Indicates the color filter array (CFA) geometric pattern of the image sensor when a one-chip color area sensor is used.
-    /// It does not apply to all sensing methods.
-    ///
-    /// ExifDirectoryBase.TAG_CFA_PATTERN_2 holds only the pixel pattern. ExifDirectoryBase.TAG_CFA_REPEAT_PATTERN_DIM is expected to exist and pass
-    /// some conditional tests.
-    /// </remarks>
-    @Nullable
-    public String getCfaPattern2Description()
-    {
-        byte[] values = _directory.getByteArray(TAG_CFA_PATTERN_2);
-        if (values == null)
-            return null;
-
-        int[] repeatPattern = _directory.getIntArray(TAG_CFA_REPEAT_PATTERN_DIM);
-        if (repeatPattern == null)
-            return String.format("Repeat Pattern not found for CFAPattern (%s)", super.getDescription(TAG_CFA_PATTERN_2));
-
-        if (repeatPattern.length == 2 && values.length == (repeatPattern[0] * repeatPattern[1]))
-        {
-            int[] intpattern = new int[2 + values.length];
-            intpattern[0] = repeatPattern[0];
-            intpattern[1] = repeatPattern[1];
-
-            for (int i = 0; i < values.length; i++)
-                intpattern[i + 2] = values[i] & 0xFF;   // convert the values[i] byte to unsigned
-
-            return formatCFAPattern(intpattern);
-        }
-
-        return String.format("Unknown Pattern (%s)", super.getDescription(TAG_CFA_PATTERN_2));
-    }
-
-    @Nullable
-    private static String formatCFAPattern(@Nullable int[] pattern)
-    {
-        if (pattern == null)
-            return null;
-        if (pattern.length < 2)
-            return "<truncated data>";
-        if (pattern[0] == 0 && pattern[1] == 0)
-            return "<zero pattern size>";
-
-        int end = 2 + pattern[0] * pattern[1];
-        if (end > pattern.length)
-            return "<invalid pattern size>";
-
-        String[] cfaColors = { "Red", "Green", "Blue", "Cyan", "Magenta", "Yellow", "White" };
-
-        StringBuilder ret = new StringBuilder();
-        ret.append("[");
-        for (int pos = 2; pos < end; pos++)
-        {
-            if (pattern[pos] <= cfaColors.length - 1)
-                ret.append(cfaColors[pattern[pos]]);
-            else
-                ret.append("Unknown");      // indicated pattern position is outside the array bounds
-
-            if ((pos - 2) % pattern[1] == 0)
-                ret.append(",");
-            else if(pos != end - 1)
-                ret.append("][");
-        }
-        ret.append("]");
-
-        return ret.toString();
-    }
-
-    @Nullable
-    public String getExposureTimeDescription()
-    {
-        String value = _directory.getString(TAG_EXPOSURE_TIME);
-        return value == null ? null : value + " sec";
-    }
-
-    @Nullable
-    public String getFNumberDescription()
-    {
-        Rational value = _directory.getRational(TAG_FNUMBER);
-        if (value == null)
-            return null;
-        return getFStopDescription(value.doubleValue());
-    }
-
-    @Nullable
-    public String getExposureProgramDescription()
-    {
-        return getIndexedDescription(TAG_EXPOSURE_PROGRAM,
-            1,
-            "Manual control",
-            "Program normal",
-            "Aperture priority",
-            "Shutter priority",
-            "Program creative (slow program)",
-            "Program action (high-speed program)",
-            "Portrait mode",
-            "Landscape mode"
-        );
-    }
-
-    @Nullable
-    public String getIsoEquivalentDescription()
-    {
-        // Have seen an exception here from files produced by ACDSEE that stored an int[] here with two values
-        Integer isoEquiv = _directory.getInteger(TAG_ISO_EQUIVALENT);
-        // There used to be a check here that multiplied ISO values < 50 by 200.
-        // Issue 36 shows a smart-phone image from a Samsung Galaxy S2 with ISO-40.
-        return isoEquiv != null
-            ? Integer.toString(isoEquiv)
-            : null;
-    }
-
-    @Nullable
-    public String getSensitivityTypeRangeDescription()
-    {
-        return getIndexedDescription(TAG_SENSITIVITY_TYPE,
-            "Unknown",
-            "Standard Output Sensitivity",
-            "Recommended Exposure Index",
-            "ISO Speed",
-            "Standard Output Sensitivity and Recommended Exposure Index",
-            "Standard Output Sensitivity and ISO Speed",
-            "Recommended Exposure Index and ISO Speed",
-            "Standard Output Sensitivity, Recommended Exposure Index and ISO Speed"
-        );
-    }
-
-    @Nullable
-    public String getExifVersionDescription()
-    {
-        return getVersionBytesDescription(TAG_EXIF_VERSION, 2);
-    }
-
-    @Nullable
-    public String getComponentConfigurationDescription()
-    {
-        int[] components = _directory.getIntArray(TAG_COMPONENTS_CONFIGURATION);
-        if (components == null)
-            return null;
-        String[] componentStrings = {"", "Y", "Cb", "Cr", "R", "G", "B"};
-        StringBuilder componentConfig = new StringBuilder();
-        for (int i = 0; i < Math.min(4, components.length); i++) {
-            int j = components[i];
-            if (j > 0 && j < componentStrings.length) {
-                componentConfig.append(componentStrings[j]);
-            }
-        }
-        return componentConfig.toString();
-    }
-
-    @Nullable
-    public String getCompressedAverageBitsPerPixelDescription()
-    {
-        Rational value = _directory.getRational(TAG_COMPRESSED_AVERAGE_BITS_PER_PIXEL);
-        if (value == null)
-            return null;
-        String ratio = value.toSimpleString(_allowDecimalRepresentationOfRationals);
-        return value.isInteger() && value.intValue() == 1
-            ? ratio + " bit/pixel"
-            : ratio + " bits/pixel";
-    }
-
-    @Nullable
-    public String getShutterSpeedDescription()
-    {
-        return super.getShutterSpeedDescription(TAG_SHUTTER_SPEED);
-    }
-
-    @Nullable
-    public String getApertureValueDescription()
-    {
-        Double aperture = _directory.getDoubleObject(TAG_APERTURE);
-        if (aperture == null)
-            return null;
-        double fStop = PhotographicConversions.apertureToFStop(aperture);
-        return getFStopDescription(fStop);
-    }
-
-    @Nullable
-    public String getBrightnessValueDescription()
-    {
-        Rational value = _directory.getRational(TAG_BRIGHTNESS_VALUE);
-        if (value == null)
-            return null;
-        if (value.getNumerator() == 0xFFFFFFFFL)
-            return "Unknown";
-        DecimalFormat formatter = new DecimalFormat("0.0##");
-        return formatter.format(value.doubleValue());
-    }
-
-    @Nullable
-    public String getExposureBiasDescription()
-    {
-        Rational value = _directory.getRational(TAG_EXPOSURE_BIAS);
-        if (value == null)
-            return null;
-        return value.toSimpleString(true) + " EV";
-    }
-
-    @Nullable
-    public String getMaxApertureValueDescription()
-    {
-        Double aperture = _directory.getDoubleObject(TAG_MAX_APERTURE);
-        if (aperture == null)
-            return null;
-        double fStop = PhotographicConversions.apertureToFStop(aperture);
-        return getFStopDescription(fStop);
-    }
-
-    @Nullable
-    public String getSubjectDistanceDescription()
-    {
-        Rational value = _directory.getRational(TAG_SUBJECT_DISTANCE);
-        if (value == null)
-            return null;
-        if (value.getNumerator() == 0xFFFFFFFFL)
-            return "Infinity";
-        if (value.getNumerator() == 0)
-            return "Unknown";
-        DecimalFormat formatter = new DecimalFormat("0.0##");
-        return formatter.format(value.doubleValue()) + " metres";
-    }
-
-    @Nullable
-    public String getMeteringModeDescription()
-    {
-        // '0' means unknown, '1' average, '2' center weighted average, '3' spot
-        // '4' multi-spot, '5' multi-segment, '6' partial, '255' other
-        Integer value = _directory.getInteger(TAG_METERING_MODE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "Unknown";
-            case 1: return "Average";
-            case 2: return "Center weighted average";
-            case 3: return "Spot";
-            case 4: return "Multi-spot";
-            case 5: return "Multi-segment";
-            case 6: return "Partial";
-            case 255: return "(Other)";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getWhiteBalanceDescription()
-    {
-        // See http://web.archive.org/web/20131018091152/http://exif.org/Exif2-2.PDF page 35
-        final Integer value = _directory.getInteger(TAG_WHITE_BALANCE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "Unknown";
-            case 1: return "Daylight";
-            case 2: return "Florescent";
-            case 3: return "Tungsten";
-            case 4: return "Flash";
-            case 9: return "Fine Weather";
-            case 10: return "Cloudy";
-            case 11: return "Shade";
-            case 12: return "Daylight Fluorescent";
-            case 13: return "Day White Fluorescent";
-            case 14: return "Cool White Fluorescent";
-            case 15: return "White Fluorescent";
-            case 16: return "Warm White Fluorescent";
-            case 17: return "Standard light";
-            case 18: return "Standard light (B)";
-            case 19: return "Standard light (C)";
-            case 20: return "D55";
-            case 21: return "D65";
-            case 22: return "D75";
-            case 23: return "D50";
-            case 24: return "Studio Tungsten";
-            case 255: return "(Other)";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getFlashDescription()
-    {
-        /*
-         * This is a bit mask.
-         * 0 = flash fired
-         * 1 = return detected
-         * 2 = return able to be detected
-         * 3 = unknown
-         * 4 = auto used
-         * 5 = unknown
-         * 6 = red eye reduction used
-         */
-
-        final Integer value = _directory.getInteger(TAG_FLASH);
-
-        if (value == null)
-            return null;
-
-        StringBuilder sb = new StringBuilder();
-
-        if ((value & 0x1) != 0)
-            sb.append("Flash fired");
-        else
-            sb.append("Flash did not fire");
-
-        // check if we're able to detect a return, before we mention it
-        if ((value & 0x4) != 0) {
-            if ((value & 0x2) != 0)
-                sb.append(", return detected");
-            else
-                sb.append(", return not detected");
-        }
-
-        // If 0x10 is set and the lowest byte is not zero - then flash is Auto
-        if ((value & 0x10) != 0 && (value & 0x0F) != 0)
-            sb.append(", auto");
-
-        if ((value & 0x40) != 0)
-            sb.append(", red-eye reduction");
-
-        return sb.toString();
-    }
-
-    @Nullable
-    public String getFocalLengthDescription()
-    {
-        Rational value = _directory.getRational(TAG_FOCAL_LENGTH);
-        return value == null ? null : getFocalLengthDescription(value.doubleValue());
-    }
-
-    @Nullable
-    public String getUserCommentDescription()
-    {
-        return getEncodedTextDescription(TAG_USER_COMMENT);
-    }
-
-    @Nullable
-    public String getTemperatureDescription()
-    {
-        Rational value = _directory.getRational(TAG_TEMPERATURE);
-        if (value == null)
-            return null;
-        if (value.getDenominator() == 0xFFFFFFFFL)
-            return "Unknown";
-        DecimalFormat formatter = new DecimalFormat("0.0");
-        return formatter.format(value.doubleValue()) + " °C";
-    }
-
-    @Nullable
-    public String getHumidityDescription()
-    {
-        Rational value = _directory.getRational(TAG_HUMIDITY);
-        if (value == null)
-            return null;
-        if (value.getDenominator() == 0xFFFFFFFFL)
-            return "Unknown";
-        DecimalFormat formatter = new DecimalFormat("0.0");
-        return formatter.format(value.doubleValue()) + " %";
-    }
-
-    @Nullable
-    public String getPressureDescription()
-    {
-        Rational value = _directory.getRational(TAG_PRESSURE);
-        if (value == null)
-            return null;
-        if (value.getDenominator() == 0xFFFFFFFFL)
-            return "Unknown";
-        DecimalFormat formatter = new DecimalFormat("0.0");
-        return formatter.format(value.doubleValue()) + " hPa";
-    }
-
-    @Nullable
-    public String getWaterDepthDescription()
-    {
-        Rational value = _directory.getRational(TAG_WATER_DEPTH);
-        if (value == null)
-            return null;
-        if (value.getDenominator() == 0xFFFFFFFFL)
-            return "Unknown";
-        DecimalFormat formatter = new DecimalFormat("0.0##");
-        return formatter.format(value.doubleValue()) + " metres";
-    }
-
-    @Nullable
-    public String getAccelerationDescription()
-    {
-        Rational value = _directory.getRational(TAG_ACCELERATION);
-        if (value == null)
-            return null;
-        if (value.getDenominator() == 0xFFFFFFFFL)
-            return "Unknown";
-        DecimalFormat formatter = new DecimalFormat("0.0##");
-        return formatter.format(value.doubleValue()) + " mGal";
-    }
-
-    @Nullable
-    public String getCameraElevationAngleDescription()
-    {
-        Rational value = _directory.getRational(TAG_CAMERA_ELEVATION_ANGLE);
-        if (value == null)
-            return null;
-        if (value.getDenominator() == 0xFFFFFFFFL)
-            return "Unknown";
-        DecimalFormat formatter = new DecimalFormat("0.##");
-        return formatter.format(value.doubleValue()) + " degrees";
-    }
-
-    /** The Windows specific tags uses plain Unicode. */
-    @Nullable
-    private String getUnicodeDescription(int tag)
-    {
-        byte[] bytes = _directory.getByteArray(tag);
-        if (bytes == null)
-            return null;
-        try {
-            // Decode the unicode string and trim the unicode zero "\0" from the end.
-            return new String(bytes, "UTF-16LE").trim();
-        } catch (UnsupportedEncodingException ex) {
-            return null;
-        }
-    }
-
-    @Nullable
-    public String getWindowsTitleDescription()
-    {
-        return getUnicodeDescription(TAG_WIN_TITLE);
-    }
-
-    @Nullable
-    public String getWindowsCommentDescription()
-    {
-        return getUnicodeDescription(TAG_WIN_COMMENT);
-    }
-
-    @Nullable
-    public String getWindowsAuthorDescription()
-    {
-        return getUnicodeDescription(TAG_WIN_AUTHOR);
-    }
-
-    @Nullable
-    public String getWindowsKeywordsDescription()
-    {
-        return getUnicodeDescription(TAG_WIN_KEYWORDS);
-    }
-
-    @Nullable
-    public String getWindowsSubjectDescription()
-    {
-        return getUnicodeDescription(TAG_WIN_SUBJECT);
-    }
-
-    @Nullable
-    public String getFlashPixVersionDescription()
-    {
-        return getVersionBytesDescription(TAG_FLASHPIX_VERSION, 2);
-    }
-
-    @Nullable
-    public String getColorSpaceDescription()
-    {
-        final Integer value = _directory.getInteger(TAG_COLOR_SPACE);
-        if (value == null)
-            return null;
-        if (value == 1)
-            return "sRGB";
-        if (value == 65535)
-            return "Undefined";
-        return "Unknown (" + value + ")";
-    }
-
-    @Nullable
-    public String getExifImageWidthDescription()
-    {
-        final Integer value = _directory.getInteger(TAG_EXIF_IMAGE_WIDTH);
-        return value == null ? null : value + " pixels";
-    }
-
-    @Nullable
-    public String getExifImageHeightDescription()
-    {
-        final Integer value = _directory.getInteger(TAG_EXIF_IMAGE_HEIGHT);
-        return value == null ? null : value + " pixels";
-    }
-
-    @Nullable
-    public String getFocalPlaneXResolutionDescription()
-    {
-        Rational rational = _directory.getRational(TAG_FOCAL_PLANE_X_RESOLUTION);
-        if (rational == null)
-            return null;
-        final String unit = getFocalPlaneResolutionUnitDescription();
-        return rational.getReciprocal().toSimpleString(_allowDecimalRepresentationOfRationals)
-            + (unit == null ? "" : " " + unit.toLowerCase());
-    }
-
-    @Nullable
-    public String getFocalPlaneYResolutionDescription()
-    {
-        Rational rational = _directory.getRational(TAG_FOCAL_PLANE_Y_RESOLUTION);
-        if (rational == null)
-            return null;
-        final String unit = getFocalPlaneResolutionUnitDescription();
-        return rational.getReciprocal().toSimpleString(_allowDecimalRepresentationOfRationals)
-            + (unit == null ? "" : " " + unit.toLowerCase());
-    }
-
-    @Nullable
-    public String getFocalPlaneResolutionUnitDescription()
-    {
-        // Unit of FocalPlaneXResolution/FocalPlaneYResolution.
-        // '1' means no-unit, '2' inch, '3' centimeter.
-        return getIndexedDescription(TAG_FOCAL_PLANE_RESOLUTION_UNIT,
-            1,
-            "(No unit)",
-            "Inches",
-            "cm"
-        );
-    }
-
-    @Nullable
-    public String getSensingMethodDescription()
-    {
-        // '1' Not defined, '2' One-chip color area sensor, '3' Two-chip color area sensor
-        // '4' Three-chip color area sensor, '5' Color sequential area sensor
-        // '7' Trilinear sensor '8' Color sequential linear sensor,  'Other' reserved
-        return getIndexedDescription(TAG_SENSING_METHOD,
-            1,
-            "(Not defined)",
-            "One-chip color area sensor",
-            "Two-chip color area sensor",
-            "Three-chip color area sensor",
-            "Color sequential area sensor",
-            null,
-            "Trilinear sensor",
-            "Color sequential linear sensor"
-        );
-    }
-
-    @Nullable
-    public String getFileSourceDescription()
-    {
-        return getIndexedDescription(TAG_FILE_SOURCE,
-            1,
-            "Film Scanner",
-            "Reflection Print Scanner",
-            "Digital Still Camera (DSC)"
-        );
-    }
-
-    @Nullable
-    public String getSceneTypeDescription()
-    {
-        return getIndexedDescription(TAG_SCENE_TYPE,
-            1,
-            "Directly photographed image"
-        );
-    }
-
-    /// <summary>
-    /// String description of CFA Pattern
-    /// </summary>
-    /// <remarks>
-    /// Converted from Exiftool version 10.33 created by Phil Harvey
-    /// http://www.sno.phy.queensu.ca/~phil/exiftool/
-    /// lib\Image\ExifTool\Exif.pm
-    ///
-    /// Indicates the color filter array (CFA) geometric pattern of the image sensor when a one-chip color area sensor is used.
-    /// It does not apply to all sensing methods.
-    /// </remarks>
-    @Nullable
-    public String getCfaPatternDescription()
-    {
-        return formatCFAPattern(decodeCfaPattern(TAG_CFA_PATTERN));
-    }
-
-    /// <summary>
-    /// Decode raw CFAPattern value
-    /// </summary>
-    /// <remarks>
-    /// Converted from Exiftool version 10.33 created by Phil Harvey
-    /// http://www.sno.phy.queensu.ca/~phil/exiftool/
-    /// lib\Image\ExifTool\Exif.pm
-    ///
-    /// The value consists of:
-    /// - Two short, being the grid width and height of the repeated pattern.
-    /// - Next, for every pixel in that pattern, an identification code.
-    /// </remarks>
-    @Nullable
-    private int[] decodeCfaPattern(int tagType)
-    {
-        int[] ret;
-
-        byte[] values = _directory.getByteArray(tagType);
-        if (values == null)
-            return null;
-
-        if (values.length < 4)
-        {
-            ret = new int[values.length];
-            for (int i = 0; i < values.length; i++)
-                ret[i] = values[i];
-            return ret;
-        }
-
-        ret = new int[values.length - 2];
-
-        try {
-            ByteArrayReader reader = new ByteArrayReader(values);
-
-            // first two values should be read as 16-bits (2 bytes)
-            short item0 = reader.getInt16(0);
-            short item1 = reader.getInt16(2);
-
-            Boolean copyArray = false;
-            int end = 2 + item0 * item1;
-            if (end > values.length) // sanity check in case of byte order problems; calculated 'end' should be <= length of the values
-            {
-                // try swapping byte order (I have seen this order different than in EXIF)
-                reader.setMotorolaByteOrder(!reader.isMotorolaByteOrder());
-                item0 = reader.getInt16(0);
-                item1 = reader.getInt16(2);
-
-                if (values.length >= (2 + item0 * item1))
-                    copyArray = true;
-            }
-            else
-                copyArray = true;
-
-            if(copyArray)
-            {
-                ret[0] = item0;
-                ret[1] = item1;
-
-                for (int i = 4; i < values.length; i++)
-                    ret[i - 2] = reader.getInt8(i);
-            }
-        } catch (IOException ex) {
-            _directory.addError("IO exception processing data: " + ex.getMessage());
-        }
-
-        return ret;
-    }
-
-    @Nullable
-    public String getCustomRenderedDescription()
-    {
-        return getIndexedDescription(TAG_CUSTOM_RENDERED,
-            "Normal process",
-            "Custom process"
-        );
-    }
-
-    @Nullable
-    public String getExposureModeDescription()
-    {
-        return getIndexedDescription(TAG_EXPOSURE_MODE,
-            "Auto exposure",
-            "Manual exposure",
-            "Auto bracket"
-        );
-    }
-
-    @Nullable
-    public String getWhiteBalanceModeDescription()
-    {
-        return getIndexedDescription(TAG_WHITE_BALANCE_MODE,
-            "Auto white balance",
-            "Manual white balance"
-        );
-    }
-
-    @Nullable
-    public String getDigitalZoomRatioDescription()
-    {
-        Rational value = _directory.getRational(TAG_DIGITAL_ZOOM_RATIO);
-        return value == null
-            ? null
-            : value.getNumerator() == 0
-                ? "Digital zoom not used"
-                : new DecimalFormat("0.#").format(value.doubleValue());
-    }
-
-    @Nullable
-    public String get35mmFilmEquivFocalLengthDescription()
-    {
-        Integer value = _directory.getInteger(TAG_35MM_FILM_EQUIV_FOCAL_LENGTH);
-        return value == null
-            ? null
-            : value == 0
-                ? "Unknown"
-                : getFocalLengthDescription(value);
-    }
-
-    @Nullable
-    public String getSceneCaptureTypeDescription()
-    {
-        return getIndexedDescription(TAG_SCENE_CAPTURE_TYPE,
-            "Standard",
-            "Landscape",
-            "Portrait",
-            "Night scene"
-        );
-    }
-
-    @Nullable
-    public String getGainControlDescription()
-    {
-        return getIndexedDescription(TAG_GAIN_CONTROL,
-            "None",
-            "Low gain up",
-            "Low gain down",
-            "High gain up",
-            "High gain down"
-        );
-    }
-
-    @Nullable
-    public String getContrastDescription()
-    {
-        return getIndexedDescription(TAG_CONTRAST,
-            "None",
-            "Soft",
-            "Hard"
-        );
-    }
-
-    @Nullable
-    public String getSaturationDescription()
-    {
-        return getIndexedDescription(TAG_SATURATION,
-            "None",
-            "Low saturation",
-            "High saturation"
-        );
-    }
-
-    @Nullable
-    public String getSharpnessDescription()
-    {
-        return getIndexedDescription(TAG_SHARPNESS,
-            "None",
-            "Low",
-            "Hard"
-        );
-    }
-
-    @Nullable
-    public String getSubjectDistanceRangeDescription()
-    {
-        return getIndexedDescription(TAG_SUBJECT_DISTANCE_RANGE,
-            "Unknown",
-            "Macro",
-            "Close view",
-            "Distant view"
-        );
-    }
-
-    @Nullable
-    public String getLensSpecificationDescription()
-    {
-        return getLensSpecificationDescription(TAG_LENS_SPECIFICATION);
-    }
-}
Index: trunk/src/com/drew/metadata/exif/ExifDirectoryBase.java
===================================================================
--- trunk/src/com/drew/metadata/exif/ExifDirectoryBase.java	(revision 15217)
+++ 	(revision )
@@ -1,786 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Base class for several Exif format tag directories.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public abstract class ExifDirectoryBase extends Directory
-{
-    public static final int TAG_INTEROP_INDEX = 0x0001;
-    public static final int TAG_INTEROP_VERSION = 0x0002;
-
-    /**
-     * The new subfile type tag.
-     * 0 = Full-resolution Image
-     * 1 = Reduced-resolution image
-     * 2 = Single page of multi-page image
-     * 3 = Single page of multi-page reduced-resolution image
-     * 4 = Transparency mask
-     * 5 = Transparency mask of reduced-resolution image
-     * 6 = Transparency mask of multi-page image
-     * 7 = Transparency mask of reduced-resolution multi-page image
-     */
-    public static final int TAG_NEW_SUBFILE_TYPE                  = 0x00FE;
-    /**
-     * The old subfile type tag.
-     * 1 = Full-resolution image (Main image)
-     * 2 = Reduced-resolution image (Thumbnail)
-     * 3 = Single page of multi-page image
-     */
-    public static final int TAG_SUBFILE_TYPE                      = 0x00FF;
-
-    public static final int TAG_IMAGE_WIDTH                       = 0x0100;
-    public static final int TAG_IMAGE_HEIGHT                      = 0x0101;
-
-    /**
-     * When image format is no compression, this value shows the number of bits
-     * per component for each pixel. Usually this value is '8,8,8'.
-     */
-    public static final int TAG_BITS_PER_SAMPLE                   = 0x0102;
-    public static final int TAG_COMPRESSION                       = 0x0103;
-
-    /**
-     * Shows the color space of the image data components.
-     * 0 = WhiteIsZero
-     * 1 = BlackIsZero
-     * 2 = RGB
-     * 3 = RGB Palette
-     * 4 = Transparency Mask
-     * 5 = CMYK
-     * 6 = YCbCr
-     * 8 = CIELab
-     * 9 = ICCLab
-     * 10 = ITULab
-     * 32803 = Color Filter Array
-     * 32844 = Pixar LogL
-     * 32845 = Pixar LogLuv
-     * 34892 = Linear Raw
-     */
-    public static final int TAG_PHOTOMETRIC_INTERPRETATION        = 0x0106;
-
-    /**
-     * 1 = No dithering or halftoning
-     * 2 = Ordered dither or halftone
-     * 3 = Randomized dither
-     */
-    public static final int TAG_THRESHOLDING                      = 0x0107;
-
-    /**
-     * 1 = Normal
-     * 2 = Reversed
-     */
-    public static final int TAG_FILL_ORDER                        = 0x010A;
-    public static final int TAG_DOCUMENT_NAME                     = 0x010D;
-
-    public static final int TAG_IMAGE_DESCRIPTION                 = 0x010E;
-
-    public static final int TAG_MAKE                              = 0x010F;
-    public static final int TAG_MODEL                             = 0x0110;
-    /** The position in the file of raster data. */
-    public static final int TAG_STRIP_OFFSETS                     = 0x0111;
-    public static final int TAG_ORIENTATION                       = 0x0112;
-    /** Each pixel is composed of this many samples. */
-    public static final int TAG_SAMPLES_PER_PIXEL                 = 0x0115;
-    /** The raster is codified by a single block of data holding this many rows. */
-    public static final int TAG_ROWS_PER_STRIP                    = 0x0116;
-    /** The size of the raster data in bytes. */
-    public static final int TAG_STRIP_BYTE_COUNTS                 = 0x0117;
-    public static final int TAG_MIN_SAMPLE_VALUE                  = 0x0118;
-    public static final int TAG_MAX_SAMPLE_VALUE                  = 0x0119;
-    public static final int TAG_X_RESOLUTION                      = 0x011A;
-    public static final int TAG_Y_RESOLUTION                      = 0x011B;
-    /**
-     * When image format is no compression YCbCr, this value shows byte aligns of
-     * YCbCr data. If value is '1', Y/Cb/Cr value is chunky format, contiguous for
-     * each subsampling pixel. If value is '2', Y/Cb/Cr value is separated and
-     * stored to Y plane/Cb plane/Cr plane format.
-     */
-    public static final int TAG_PLANAR_CONFIGURATION              = 0x011C;
-    public static final int TAG_PAGE_NAME                         = 0x011D;
-
-    public static final int TAG_RESOLUTION_UNIT                   = 0x0128;
-    public static final int TAG_PAGE_NUMBER                       = 0x0129;
-
-    public static final int TAG_TRANSFER_FUNCTION                 = 0x012D;
-    public static final int TAG_SOFTWARE                          = 0x0131;
-    public static final int TAG_DATETIME                          = 0x0132;
-    public static final int TAG_ARTIST                            = 0x013B;
-    public static final int TAG_HOST_COMPUTER                     = 0x013C;
-    public static final int TAG_PREDICTOR                         = 0x013D;
-    public static final int TAG_WHITE_POINT                       = 0x013E;
-    public static final int TAG_PRIMARY_CHROMATICITIES            = 0x013F;
-
-    public static final int TAG_TILE_WIDTH                        = 0x0142;
-    public static final int TAG_TILE_LENGTH                       = 0x0143;
-    public static final int TAG_TILE_OFFSETS                      = 0x0144;
-    public static final int TAG_TILE_BYTE_COUNTS                  = 0x0145;
-
-    /**
-     * Tag is a pointer to one or more sub-IFDs.
-     + Seems to be used exclusively by raw formats, referencing one or two IFDs.
-     */
-    public static final int TAG_SUB_IFD_OFFSET                    = 0x014a;
-
-    public static final int TAG_TRANSFER_RANGE                    = 0x0156;
-    public static final int TAG_JPEG_TABLES                       = 0x015B;
-    public static final int TAG_JPEG_PROC                         = 0x0200;
-
-    // 0x0201 can have all kinds of descriptions for thumbnail starting index
-    // 0x0202 can have all kinds of descriptions for thumbnail length
-    public static final int TAG_JPEG_RESTART_INTERVAL = 0x0203;
-    public static final int TAG_JPEG_LOSSLESS_PREDICTORS = 0x0205;
-    public static final int TAG_JPEG_POINT_TRANSFORMS = 0x0206;
-    public static final int TAG_JPEG_Q_TABLES = 0x0207;
-    public static final int TAG_JPEG_DC_TABLES = 0x0208;
-    public static final int TAG_JPEG_AC_TABLES = 0x0209;
-
-    public static final int TAG_YCBCR_COEFFICIENTS                = 0x0211;
-    public static final int TAG_YCBCR_SUBSAMPLING                 = 0x0212;
-    public static final int TAG_YCBCR_POSITIONING                 = 0x0213;
-    public static final int TAG_REFERENCE_BLACK_WHITE             = 0x0214;
-    public static final int TAG_STRIP_ROW_COUNTS                  = 0x022f;
-    public static final int TAG_APPLICATION_NOTES                 = 0x02bc;
-
-    public static final int TAG_RELATED_IMAGE_FILE_FORMAT         = 0x1000;
-    public static final int TAG_RELATED_IMAGE_WIDTH               = 0x1001;
-    public static final int TAG_RELATED_IMAGE_HEIGHT              = 0x1002;
-
-    public static final int TAG_RATING                            = 0x4746;
-
-    public static final int TAG_CFA_REPEAT_PATTERN_DIM            = 0x828D;
-    /** There are two definitions for CFA pattern, I don't know the difference... */
-    public static final int TAG_CFA_PATTERN_2                     = 0x828E;
-    public static final int TAG_BATTERY_LEVEL                     = 0x828F;
-    public static final int TAG_COPYRIGHT                         = 0x8298;
-    /**
-     * Exposure time (reciprocal of shutter speed). Unit is second.
-     */
-    public static final int TAG_EXPOSURE_TIME                     = 0x829A;
-    /**
-     * The actual F-number(F-stop) of lens when the image was taken.
-     */
-    public static final int TAG_FNUMBER                           = 0x829D;
-    public static final int TAG_IPTC_NAA                          = 0x83BB;
-    public static final int TAG_PHOTOSHOP_SETTINGS                = 0x8649;
-    public static final int TAG_INTER_COLOR_PROFILE               = 0x8773;
-    /**
-     * Exposure program that the camera used when image was taken. '1' means
-     * manual control, '2' program normal, '3' aperture priority, '4' shutter
-     * priority, '5' program creative (slow program), '6' program action
-     * (high-speed program), '7' portrait mode, '8' landscape mode.
-     */
-    public static final int TAG_EXPOSURE_PROGRAM                  = 0x8822;
-    public static final int TAG_SPECTRAL_SENSITIVITY              = 0x8824;
-    public static final int TAG_ISO_EQUIVALENT                    = 0x8827;
-    /**
-     * Indicates the Opto-Electric Conversion Function (OECF) specified in ISO 14524.
-     * <p>
-     * OECF is the relationship between the camera optical input and the image values.
-     * <p>
-     * The values are:
-     * <ul>
-     *   <li>Two shorts, indicating respectively number of columns, and number of rows.</li>
-     *   <li>For each column, the column name in a null-terminated ASCII string.</li>
-     *   <li>For each cell, an SRATIONAL value.</li>
-     * </ul>
-     */
-    public static final int TAG_OPTO_ELECTRIC_CONVERSION_FUNCTION = 0x8828;
-    public static final int TAG_INTERLACE                         = 0x8829;
-    public static final int TAG_TIME_ZONE_OFFSET_TIFF_EP          = 0x882A;
-    public static final int TAG_SELF_TIMER_MODE_TIFF_EP           = 0x882B;
-    /**
-     * Applies to ISO tag.
-     *
-     * 0 = Unknown
-     * 1 = Standard Output Sensitivity
-     * 2 = Recommended Exposure Index
-     * 3 = ISO Speed
-     * 4 = Standard Output Sensitivity and Recommended Exposure Index
-     * 5 = Standard Output Sensitivity and ISO Speed
-     * 6 = Recommended Exposure Index and ISO Speed
-     * 7 = Standard Output Sensitivity, Recommended Exposure Index and ISO Speed
-     */
-    public static final int TAG_SENSITIVITY_TYPE                  = 0x8830;
-    public static final int TAG_STANDARD_OUTPUT_SENSITIVITY       = 0x8831;
-    public static final int TAG_RECOMMENDED_EXPOSURE_INDEX        = 0x8832;
-    public static final int TAG_ISO_SPEED                         = 0x8833;
-    public static final int TAG_ISO_SPEED_LATITUDE_YYY            = 0x8834;
-    public static final int TAG_ISO_SPEED_LATITUDE_ZZZ            = 0x8835;
-
-    public static final int TAG_EXIF_VERSION                      = 0x9000;
-    public static final int TAG_DATETIME_ORIGINAL                 = 0x9003;
-    public static final int TAG_DATETIME_DIGITIZED                = 0x9004;
-    public static final int TAG_OFFSET_TIME                       = 0x9010;
-    public static final int TAG_OFFSET_TIME_ORIGINAL              = 0x9011;
-    public static final int TAG_OFFSET_TIME_DIGITIZED             = 0x9012;
-
-    public static final int TAG_COMPONENTS_CONFIGURATION          = 0x9101;
-    /**
-     * Average (rough estimate) compression level in JPEG bits per pixel.
-     * */
-    public static final int TAG_COMPRESSED_AVERAGE_BITS_PER_PIXEL = 0x9102;
-
-    /**
-     * Shutter speed by APEX value. To convert this value to ordinary 'Shutter Speed';
-     * calculate this value's power of 2, then reciprocal. For example, if the
-     * ShutterSpeedValue is '4', shutter speed is 1/(24)=1/16 second.
-     */
-    public static final int TAG_SHUTTER_SPEED                     = 0x9201;
-    /**
-     * The actual aperture value of lens when the image was taken. Unit is APEX.
-     * To convert this value to ordinary F-number (F-stop), calculate this value's
-     * power of root 2 (=1.4142). For example, if the ApertureValue is '5',
-     * F-number is 1.4142^5 = F5.6.
-     */
-    public static final int TAG_APERTURE                          = 0x9202;
-    public static final int TAG_BRIGHTNESS_VALUE                  = 0x9203;
-    public static final int TAG_EXPOSURE_BIAS                     = 0x9204;
-    /**
-     * Maximum aperture value of lens. You can convert to F-number by calculating
-     * power of root 2 (same process of ApertureValue:0x9202).
-     * The actual aperture value of lens when the image was taken. To convert this
-     * value to ordinary f-number(f-stop), calculate the value's power of root 2
-     * (=1.4142). For example, if the ApertureValue is '5', f-number is 1.41425^5 = F5.6.
-     */
-    public static final int TAG_MAX_APERTURE                      = 0x9205;
-    /**
-     * Indicates the distance the autofocus camera is focused to.  Tends to be less accurate as distance increases.
-     */
-    public static final int TAG_SUBJECT_DISTANCE                  = 0x9206;
-    /**
-     * Exposure metering method. '0' means unknown, '1' average, '2' center
-     * weighted average, '3' spot, '4' multi-spot, '5' multi-segment, '6' partial,
-     * '255' other.
-     */
-    public static final int TAG_METERING_MODE                     = 0x9207;
-
-    /**
-     * @deprecated use {@link com.drew.metadata.exif.ExifDirectoryBase#TAG_WHITE_BALANCE} instead.
-     */
-    @Deprecated
-    public static final int TAG_LIGHT_SOURCE                      = 0x9208;
-    /**
-     * White balance (aka light source). '0' means unknown, '1' daylight,
-     * '2' fluorescent, '3' tungsten, '10' flash, '17' standard light A,
-     * '18' standard light B, '19' standard light C, '20' D55, '21' D65,
-     * '22' D75, '255' other.
-     */
-    public static final int TAG_WHITE_BALANCE                     = 0x9208;
-    /**
-     * 0x0  = 0000000 = No Flash
-     * 0x1  = 0000001 = Fired
-     * 0x5  = 0000101 = Fired, Return not detected
-     * 0x7  = 0000111 = Fired, Return detected
-     * 0x9  = 0001001 = On
-     * 0xd  = 0001101 = On, Return not detected
-     * 0xf  = 0001111 = On, Return detected
-     * 0x10 = 0010000 = Off
-     * 0x18 = 0011000 = Auto, Did not fire
-     * 0x19 = 0011001 = Auto, Fired
-     * 0x1d = 0011101 = Auto, Fired, Return not detected
-     * 0x1f = 0011111 = Auto, Fired, Return detected
-     * 0x20 = 0100000 = No flash function
-     * 0x41 = 1000001 = Fired, Red-eye reduction
-     * 0x45 = 1000101 = Fired, Red-eye reduction, Return not detected
-     * 0x47 = 1000111 = Fired, Red-eye reduction, Return detected
-     * 0x49 = 1001001 = On, Red-eye reduction
-     * 0x4d = 1001101 = On, Red-eye reduction, Return not detected
-     * 0x4f = 1001111 = On, Red-eye reduction, Return detected
-     * 0x59 = 1011001 = Auto, Fired, Red-eye reduction
-     * 0x5d = 1011101 = Auto, Fired, Red-eye reduction, Return not detected
-     * 0x5f = 1011111 = Auto, Fired, Red-eye reduction, Return detected
-     *        6543210 (positions)
-     *
-     * This is a bitmask.
-     * 0 = flash fired
-     * 1 = return detected
-     * 2 = return able to be detected
-     * 3 = unknown
-     * 4 = auto used
-     * 5 = unknown
-     * 6 = red eye reduction used
-     */
-    public static final int TAG_FLASH                             = 0x9209;
-    /**
-     * Focal length of lens used to take image.  Unit is millimeter.
-     * Nice digital cameras actually save the focal length as a function of how far they are zoomed in.
-     */
-    public static final int TAG_FOCAL_LENGTH                      = 0x920A;
-
-    public static final int TAG_FLASH_ENERGY_TIFF_EP              = 0x920B;
-    public static final int TAG_SPATIAL_FREQ_RESPONSE_TIFF_EP     = 0x920C;
-    public static final int TAG_NOISE                             = 0x920D;
-    public static final int TAG_FOCAL_PLANE_X_RESOLUTION_TIFF_EP  = 0x920E;
-    public static final int TAG_FOCAL_PLANE_Y_RESOLUTION_TIFF_EP = 0x920F;
-    public static final int TAG_IMAGE_NUMBER                      = 0x9211;
-    public static final int TAG_SECURITY_CLASSIFICATION           = 0x9212;
-    public static final int TAG_IMAGE_HISTORY                     = 0x9213;
-    public static final int TAG_SUBJECT_LOCATION_TIFF_EP          = 0x9214;
-    public static final int TAG_EXPOSURE_INDEX_TIFF_EP            = 0x9215;
-    public static final int TAG_STANDARD_ID_TIFF_EP               = 0x9216;
-
-    /**
-     * This tag holds the Exif Makernote. Makernotes are free to be in any format, though they are often IFDs.
-     * To determine the format, we consider the starting bytes of the makernote itself and sometimes the
-     * camera model and make.
-     * <p>
-     * The component count for this tag includes all of the bytes needed for the makernote.
-     */
-    public static final int TAG_MAKERNOTE                         = 0x927C;
-
-    public static final int TAG_USER_COMMENT                      = 0x9286;
-
-    public static final int TAG_SUBSECOND_TIME                    = 0x9290;
-    public static final int TAG_SUBSECOND_TIME_ORIGINAL           = 0x9291;
-    public static final int TAG_SUBSECOND_TIME_DIGITIZED          = 0x9292;
-
-    public static final int TAG_TEMPERATURE                       = 0x9400;
-    public static final int TAG_HUMIDITY                          = 0x9401;
-    public static final int TAG_PRESSURE                          = 0x9402;
-    public static final int TAG_WATER_DEPTH                       = 0x9403;
-    public static final int TAG_ACCELERATION                      = 0x9404;
-    public static final int TAG_CAMERA_ELEVATION_ANGLE            = 0x9405;
-
-    /** The image title, as used by Windows XP. */
-    public static final int TAG_WIN_TITLE                         = 0x9C9B;
-    /** The image comment, as used by Windows XP. */
-    public static final int TAG_WIN_COMMENT                       = 0x9C9C;
-    /** The image author, as used by Windows XP (called Artist in the Windows shell). */
-    public static final int TAG_WIN_AUTHOR                        = 0x9C9D;
-    /** The image keywords, as used by Windows XP. */
-    public static final int TAG_WIN_KEYWORDS                      = 0x9C9E;
-    /** The image subject, as used by Windows XP. */
-    public static final int TAG_WIN_SUBJECT                       = 0x9C9F;
-
-    public static final int TAG_FLASHPIX_VERSION                  = 0xA000;
-    /**
-     * Defines Color Space. DCF image must use sRGB color space so value is
-     * always '1'. If the picture uses the other color space, value is
-     * '65535':Uncalibrated.
-     */
-    public static final int TAG_COLOR_SPACE                       = 0xA001;
-    public static final int TAG_EXIF_IMAGE_WIDTH                  = 0xA002;
-    public static final int TAG_EXIF_IMAGE_HEIGHT                 = 0xA003;
-    public static final int TAG_RELATED_SOUND_FILE                = 0xA004;
-
-    public static final int TAG_FLASH_ENERGY                      = 0xA20B;
-    public static final int TAG_SPATIAL_FREQ_RESPONSE             = 0xA20C;
-    public static final int TAG_FOCAL_PLANE_X_RESOLUTION          = 0xA20E;
-    public static final int TAG_FOCAL_PLANE_Y_RESOLUTION          = 0xA20F;
-    /**
-     * Unit of FocalPlaneXResolution/FocalPlaneYResolution. '1' means no-unit,
-     * '2' inch, '3' centimeter.
-     *
-     * Note: Some of Fujifilm's digicam(e.g.FX2700,FX2900,Finepix4700Z/40i etc)
-     * uses value '3' so it must be 'centimeter', but it seems that they use a
-     * '8.3mm?'(1/3in.?) to their ResolutionUnit. Fuji's BUG? Finepix4900Z has
-     * been changed to use value '2' but it doesn't match to actual value also.
-     */
-    public static final int TAG_FOCAL_PLANE_RESOLUTION_UNIT       = 0xA210;
-    public static final int TAG_SUBJECT_LOCATION                  = 0xA214;
-    public static final int TAG_EXPOSURE_INDEX                    = 0xA215;
-    public static final int TAG_SENSING_METHOD                    = 0xA217;
-
-    public static final int TAG_FILE_SOURCE                       = 0xA300;
-    public static final int TAG_SCENE_TYPE                        = 0xA301;
-    public static final int TAG_CFA_PATTERN                       = 0xA302;
-
-    /**
-     * This tag indicates the use of special processing on image data, such as rendering
-     * geared to output. When special processing is performed, the reader is expected to
-     * disable or minimize any further processing.
-     * Tag = 41985 (A401.H)
-     * Type = SHORT
-     * Count = 1
-     * Default = 0
-     *   0 = Normal process
-     *   1 = Custom process
-     *   Other = reserved
-     */
-    public static final int TAG_CUSTOM_RENDERED                   = 0xA401;
-    /**
-     * This tag indicates the exposure mode set when the image was shot. In auto-bracketing
-     * mode, the camera shoots a series of frames of the same scene at different exposure settings.
-     * Tag = 41986 (A402.H)
-     * Type = SHORT
-     * Count = 1
-     * Default = none
-     *   0 = Auto exposure
-     *   1 = Manual exposure
-     *   2 = Auto bracket
-     *   Other = reserved
-     */
-    public static final int TAG_EXPOSURE_MODE                     = 0xA402;
-    /**
-     * This tag indicates the white balance mode set when the image was shot.
-     * Tag = 41987 (A403.H)
-     * Type = SHORT
-     * Count = 1
-     * Default = none
-     *   0 = Auto white balance
-     *   1 = Manual white balance
-     *   Other = reserved
-     */
-    public static final int TAG_WHITE_BALANCE_MODE                = 0xA403;
-    /**
-     * This tag indicates the digital zoom ratio when the image was shot. If the
-     * numerator of the recorded value is 0, this indicates that digital zoom was
-     * not used.
-     * Tag = 41988 (A404.H)
-     * Type = RATIONAL
-     * Count = 1
-     * Default = none
-     */
-    public static final int TAG_DIGITAL_ZOOM_RATIO                = 0xA404;
-    /**
-     * This tag indicates the equivalent focal length assuming a 35mm film camera,
-     * in mm. A value of 0 means the focal length is unknown. Note that this tag
-     * differs from the FocalLength tag.
-     * Tag = 41989 (A405.H)
-     * Type = SHORT
-     * Count = 1
-     * Default = none
-     */
-    public static final int TAG_35MM_FILM_EQUIV_FOCAL_LENGTH      = 0xA405;
-    /**
-     * This tag indicates the type of scene that was shot. It can also be used to
-     * record the mode in which the image was shot. Note that this differs from
-     * the scene type (SceneType) tag.
-     * Tag = 41990 (A406.H)
-     * Type = SHORT
-     * Count = 1
-     * Default = 0
-     *   0 = Standard
-     *   1 = Landscape
-     *   2 = Portrait
-     *   3 = Night scene
-     *   Other = reserved
-     */
-    public static final int TAG_SCENE_CAPTURE_TYPE                = 0xA406;
-    /**
-     * This tag indicates the degree of overall image gain adjustment.
-     * Tag = 41991 (A407.H)
-     * Type = SHORT
-     * Count = 1
-     * Default = none
-     *   0 = None
-     *   1 = Low gain up
-     *   2 = High gain up
-     *   3 = Low gain down
-     *   4 = High gain down
-     *   Other = reserved
-     */
-    public static final int TAG_GAIN_CONTROL                      = 0xA407;
-    /**
-     * This tag indicates the direction of contrast processing applied by the camera
-     * when the image was shot.
-     * Tag = 41992 (A408.H)
-     * Type = SHORT
-     * Count = 1
-     * Default = 0
-     *   0 = Normal
-     *   1 = Soft
-     *   2 = Hard
-     *   Other = reserved
-     */
-    public static final int TAG_CONTRAST                          = 0xA408;
-    /**
-     * This tag indicates the direction of saturation processing applied by the camera
-     * when the image was shot.
-     * Tag = 41993 (A409.H)
-     * Type = SHORT
-     * Count = 1
-     * Default = 0
-     *   0 = Normal
-     *   1 = Low saturation
-     *   2 = High saturation
-     *   Other = reserved
-     */
-    public static final int TAG_SATURATION                        = 0xA409;
-    /**
-     * This tag indicates the direction of sharpness processing applied by the camera
-     * when the image was shot.
-     * Tag = 41994 (A40A.H)
-     * Type = SHORT
-     * Count = 1
-     * Default = 0
-     *   0 = Normal
-     *   1 = Soft
-     *   2 = Hard
-     *   Other = reserved
-     */
-    public static final int TAG_SHARPNESS                         = 0xA40A;
-    /**
-     * This tag indicates information on the picture-taking conditions of a particular
-     * camera model. The tag is used only to indicate the picture-taking conditions in
-     * the reader.
-     * Tag = 41995 (A40B.H)
-     * Type = UNDEFINED
-     * Count = Any
-     * Default = none
-     *
-     * The information is recorded in the format shown below. The data is recorded
-     * in Unicode using SHORT type for the number of display rows and columns and
-     * UNDEFINED type for the camera settings. The Unicode (UCS-2) string including
-     * Signature is NULL terminated. The specifics of the Unicode string are as given
-     * in ISO/IEC 10464-1.
-     *
-     *      Length  Type        Meaning
-     *      ------+-----------+------------------
-     *      2       SHORT       Display columns
-     *      2       SHORT       Display rows
-     *      Any     UNDEFINED   Camera setting-1
-     *      Any     UNDEFINED   Camera setting-2
-     *      :       :           :
-     *      Any     UNDEFINED   Camera setting-n
-     */
-    public static final int TAG_DEVICE_SETTING_DESCRIPTION        = 0xA40B;
-    /**
-     * This tag indicates the distance to the subject.
-     * Tag = 41996 (A40C.H)
-     * Type = SHORT
-     * Count = 1
-     * Default = none
-     *   0 = unknown
-     *   1 = Macro
-     *   2 = Close view
-     *   3 = Distant view
-     *   Other = reserved
-     */
-    public static final int TAG_SUBJECT_DISTANCE_RANGE            = 0xA40C;
-
-    /**
-     * This tag indicates an identifier assigned uniquely to each image. It is
-     * recorded as an ASCII string equivalent to hexadecimal notation and 128-bit
-     * fixed length.
-     * Tag = 42016 (A420.H)
-     * Type = ASCII
-     * Count = 33
-     * Default = none
-     */
-    public static final int TAG_IMAGE_UNIQUE_ID                   = 0xA420;
-    /** String. */
-    public static final int TAG_CAMERA_OWNER_NAME                 = 0xA430;
-    /** String. */
-    public static final int TAG_BODY_SERIAL_NUMBER                = 0xA431;
-    /** An array of four Rational64u numbers giving focal and aperture ranges. */
-    public static final int TAG_LENS_SPECIFICATION                = 0xA432;
-    /** String. */
-    public static final int TAG_LENS_MAKE                         = 0xA433;
-    /** String. */
-    public static final int TAG_LENS_MODEL                        = 0xA434;
-    /** String. */
-    public static final int TAG_LENS_SERIAL_NUMBER                = 0xA435;
-    /** Rational64u. */
-    public static final int TAG_GAMMA                             = 0xA500;
-
-    public static final int TAG_PRINT_IMAGE_MATCHING_INFO         = 0xC4A5;
-
-    public static final int TAG_PANASONIC_TITLE                   = 0xC6D2;
-    public static final int TAG_PANASONIC_TITLE_2                 = 0xC6D3;
-
-    public static final int TAG_PADDING                           = 0xEA1C;
-
-    public static final int TAG_LENS                              = 0xFDEA;
-
-    protected static void addExifTagNames(HashMap<Integer, String> map)
-    {
-        map.put(TAG_INTEROP_INDEX, "Interoperability Index");
-        map.put(TAG_INTEROP_VERSION, "Interoperability Version");
-        map.put(TAG_NEW_SUBFILE_TYPE, "New Subfile Type");
-        map.put(TAG_SUBFILE_TYPE, "Subfile Type");
-        map.put(TAG_IMAGE_WIDTH, "Image Width");
-        map.put(TAG_IMAGE_HEIGHT, "Image Height");
-        map.put(TAG_BITS_PER_SAMPLE, "Bits Per Sample");
-        map.put(TAG_COMPRESSION, "Compression");
-        map.put(TAG_PHOTOMETRIC_INTERPRETATION, "Photometric Interpretation");
-        map.put(TAG_THRESHOLDING, "Thresholding");
-        map.put(TAG_FILL_ORDER, "Fill Order");
-        map.put(TAG_DOCUMENT_NAME, "Document Name");
-        map.put(TAG_IMAGE_DESCRIPTION, "Image Description");
-        map.put(TAG_MAKE, "Make");
-        map.put(TAG_MODEL, "Model");
-        map.put(TAG_STRIP_OFFSETS, "Strip Offsets");
-        map.put(TAG_ORIENTATION, "Orientation");
-        map.put(TAG_SAMPLES_PER_PIXEL, "Samples Per Pixel");
-        map.put(TAG_ROWS_PER_STRIP, "Rows Per Strip");
-        map.put(TAG_STRIP_BYTE_COUNTS, "Strip Byte Counts");
-        map.put(TAG_MIN_SAMPLE_VALUE, "Minimum Sample Value");
-        map.put(TAG_MAX_SAMPLE_VALUE, "Maximum Sample Value");
-        map.put(TAG_X_RESOLUTION, "X Resolution");
-        map.put(TAG_Y_RESOLUTION, "Y Resolution");
-        map.put(TAG_PLANAR_CONFIGURATION, "Planar Configuration");
-        map.put(TAG_PAGE_NAME, "Page Name");
-        map.put(TAG_RESOLUTION_UNIT, "Resolution Unit");
-        map.put(TAG_PAGE_NUMBER, "Page Number");
-        map.put(TAG_TRANSFER_FUNCTION, "Transfer Function");
-        map.put(TAG_SOFTWARE, "Software");
-        map.put(TAG_DATETIME, "Date/Time");
-        map.put(TAG_ARTIST, "Artist");
-        map.put(TAG_PREDICTOR, "Predictor");
-        map.put(TAG_HOST_COMPUTER, "Host Computer");
-        map.put(TAG_WHITE_POINT, "White Point");
-        map.put(TAG_PRIMARY_CHROMATICITIES, "Primary Chromaticities");
-        map.put(TAG_TILE_WIDTH, "Tile Width");
-        map.put(TAG_TILE_LENGTH, "Tile Length");
-        map.put(TAG_TILE_OFFSETS, "Tile Offsets");
-        map.put(TAG_TILE_BYTE_COUNTS, "Tile Byte Counts");
-        map.put(TAG_SUB_IFD_OFFSET, "Sub IFD Pointer(s)");
-        map.put(TAG_TRANSFER_RANGE, "Transfer Range");
-        map.put(TAG_JPEG_TABLES, "JPEG Tables");
-        map.put(TAG_JPEG_PROC, "JPEG Proc");
-
-        map.put(TAG_JPEG_RESTART_INTERVAL, "JPEG Restart Interval");
-        map.put(TAG_JPEG_LOSSLESS_PREDICTORS, "JPEG Lossless Predictors");
-        map.put(TAG_JPEG_POINT_TRANSFORMS, "JPEG Point Transforms");
-        map.put(TAG_JPEG_Q_TABLES, "JPEGQ Tables");
-        map.put(TAG_JPEG_DC_TABLES, "JPEGDC Tables");
-        map.put(TAG_JPEG_AC_TABLES, "JPEGAC Tables");
-
-        map.put(TAG_YCBCR_COEFFICIENTS, "YCbCr Coefficients");
-        map.put(TAG_YCBCR_SUBSAMPLING, "YCbCr Sub-Sampling");
-        map.put(TAG_YCBCR_POSITIONING, "YCbCr Positioning");
-        map.put(TAG_REFERENCE_BLACK_WHITE, "Reference Black/White");
-        map.put(TAG_STRIP_ROW_COUNTS, "Strip Row Counts");
-        map.put(TAG_APPLICATION_NOTES, "Application Notes");
-        map.put(TAG_RELATED_IMAGE_FILE_FORMAT, "Related Image File Format");
-        map.put(TAG_RELATED_IMAGE_WIDTH, "Related Image Width");
-        map.put(TAG_RELATED_IMAGE_HEIGHT, "Related Image Height");
-        map.put(TAG_RATING, "Rating");
-        map.put(TAG_CFA_REPEAT_PATTERN_DIM, "CFA Repeat Pattern Dim");
-        map.put(TAG_CFA_PATTERN_2, "CFA Pattern");
-        map.put(TAG_BATTERY_LEVEL, "Battery Level");
-        map.put(TAG_COPYRIGHT, "Copyright");
-        map.put(TAG_EXPOSURE_TIME, "Exposure Time");
-        map.put(TAG_FNUMBER, "F-Number");
-        map.put(TAG_IPTC_NAA, "IPTC/NAA");
-        map.put(TAG_PHOTOSHOP_SETTINGS, "Photoshop Settings");
-        map.put(TAG_INTER_COLOR_PROFILE, "Inter Color Profile");
-        map.put(TAG_EXPOSURE_PROGRAM, "Exposure Program");
-        map.put(TAG_SPECTRAL_SENSITIVITY, "Spectral Sensitivity");
-        map.put(TAG_ISO_EQUIVALENT, "ISO Speed Ratings");
-        map.put(TAG_OPTO_ELECTRIC_CONVERSION_FUNCTION, "Opto-electric Conversion Function (OECF)");
-        map.put(TAG_INTERLACE, "Interlace");
-        map.put(TAG_TIME_ZONE_OFFSET_TIFF_EP, "Time Zone Offset");
-        map.put(TAG_SELF_TIMER_MODE_TIFF_EP, "Self Timer Mode");
-        map.put(TAG_SENSITIVITY_TYPE, "Sensitivity Type");
-        map.put(TAG_STANDARD_OUTPUT_SENSITIVITY, "Standard Output Sensitivity");
-        map.put(TAG_RECOMMENDED_EXPOSURE_INDEX, "Recommended Exposure Index");
-        map.put(TAG_ISO_SPEED, "ISO Speed");
-        map.put(TAG_ISO_SPEED_LATITUDE_YYY, "ISO Speed Latitude yyy");
-        map.put(TAG_ISO_SPEED_LATITUDE_ZZZ, "ISO Speed Latitude zzz");
-        map.put(TAG_EXIF_VERSION, "Exif Version");
-        map.put(TAG_DATETIME_ORIGINAL, "Date/Time Original");
-        map.put(TAG_DATETIME_DIGITIZED, "Date/Time Digitized");
-        map.put(TAG_OFFSET_TIME, "Offset Time");
-        map.put(TAG_OFFSET_TIME_ORIGINAL, "Offset Time Original");
-        map.put(TAG_OFFSET_TIME_DIGITIZED, "Offset Time Digitized");
-        map.put(TAG_COMPONENTS_CONFIGURATION, "Components Configuration");
-        map.put(TAG_COMPRESSED_AVERAGE_BITS_PER_PIXEL, "Compressed Bits Per Pixel");
-        map.put(TAG_SHUTTER_SPEED, "Shutter Speed Value");
-        map.put(TAG_APERTURE, "Aperture Value");
-        map.put(TAG_BRIGHTNESS_VALUE, "Brightness Value");
-        map.put(TAG_EXPOSURE_BIAS, "Exposure Bias Value");
-        map.put(TAG_MAX_APERTURE, "Max Aperture Value");
-        map.put(TAG_SUBJECT_DISTANCE, "Subject Distance");
-        map.put(TAG_METERING_MODE, "Metering Mode");
-        map.put(TAG_WHITE_BALANCE, "White Balance");
-        map.put(TAG_FLASH, "Flash");
-        map.put(TAG_FOCAL_LENGTH, "Focal Length");
-        map.put(TAG_FLASH_ENERGY_TIFF_EP, "Flash Energy");
-        map.put(TAG_SPATIAL_FREQ_RESPONSE_TIFF_EP, "Spatial Frequency Response");
-        map.put(TAG_NOISE, "Noise");
-        map.put(TAG_FOCAL_PLANE_X_RESOLUTION_TIFF_EP, "Focal Plane X Resolution");
-        map.put(TAG_FOCAL_PLANE_Y_RESOLUTION_TIFF_EP, "Focal Plane Y Resolution");
-        map.put(TAG_IMAGE_NUMBER, "Image Number");
-        map.put(TAG_SECURITY_CLASSIFICATION, "Security Classification");
-        map.put(TAG_IMAGE_HISTORY, "Image History");
-        map.put(TAG_SUBJECT_LOCATION_TIFF_EP, "Subject Location");
-        map.put(TAG_EXPOSURE_INDEX_TIFF_EP, "Exposure Index");
-        map.put(TAG_STANDARD_ID_TIFF_EP, "TIFF/EP Standard ID");
-        map.put(TAG_MAKERNOTE, "Makernote");
-        map.put(TAG_USER_COMMENT, "User Comment");
-        map.put(TAG_SUBSECOND_TIME, "Sub-Sec Time");
-        map.put(TAG_SUBSECOND_TIME_ORIGINAL, "Sub-Sec Time Original");
-        map.put(TAG_SUBSECOND_TIME_DIGITIZED, "Sub-Sec Time Digitized");
-        map.put(TAG_TEMPERATURE, "Temperature");
-        map.put(TAG_HUMIDITY, "Humidity");
-        map.put(TAG_PRESSURE, "Pressure");
-        map.put(TAG_WATER_DEPTH, "Water Depth");
-        map.put(TAG_ACCELERATION, "Acceleration");
-        map.put(TAG_CAMERA_ELEVATION_ANGLE, "Camera Elevation Angle");
-        map.put(TAG_WIN_TITLE, "Windows XP Title");
-        map.put(TAG_WIN_COMMENT, "Windows XP Comment");
-        map.put(TAG_WIN_AUTHOR, "Windows XP Author");
-        map.put(TAG_WIN_KEYWORDS, "Windows XP Keywords");
-        map.put(TAG_WIN_SUBJECT, "Windows XP Subject");
-        map.put(TAG_FLASHPIX_VERSION, "FlashPix Version");
-        map.put(TAG_COLOR_SPACE, "Color Space");
-        map.put(TAG_EXIF_IMAGE_WIDTH, "Exif Image Width");
-        map.put(TAG_EXIF_IMAGE_HEIGHT, "Exif Image Height");
-        map.put(TAG_RELATED_SOUND_FILE, "Related Sound File");
-        map.put(TAG_FLASH_ENERGY, "Flash Energy");
-        map.put(TAG_SPATIAL_FREQ_RESPONSE, "Spatial Frequency Response");
-        map.put(TAG_FOCAL_PLANE_X_RESOLUTION, "Focal Plane X Resolution");
-        map.put(TAG_FOCAL_PLANE_Y_RESOLUTION, "Focal Plane Y Resolution");
-        map.put(TAG_FOCAL_PLANE_RESOLUTION_UNIT, "Focal Plane Resolution Unit");
-        map.put(TAG_SUBJECT_LOCATION, "Subject Location");
-        map.put(TAG_EXPOSURE_INDEX, "Exposure Index");
-        map.put(TAG_SENSING_METHOD, "Sensing Method");
-        map.put(TAG_FILE_SOURCE, "File Source");
-        map.put(TAG_SCENE_TYPE, "Scene Type");
-        map.put(TAG_CFA_PATTERN, "CFA Pattern");
-        map.put(TAG_CUSTOM_RENDERED, "Custom Rendered");
-        map.put(TAG_EXPOSURE_MODE, "Exposure Mode");
-        map.put(TAG_WHITE_BALANCE_MODE, "White Balance Mode");
-        map.put(TAG_DIGITAL_ZOOM_RATIO, "Digital Zoom Ratio");
-        map.put(TAG_35MM_FILM_EQUIV_FOCAL_LENGTH, "Focal Length 35");
-        map.put(TAG_SCENE_CAPTURE_TYPE, "Scene Capture Type");
-        map.put(TAG_GAIN_CONTROL, "Gain Control");
-        map.put(TAG_CONTRAST, "Contrast");
-        map.put(TAG_SATURATION, "Saturation");
-        map.put(TAG_SHARPNESS, "Sharpness");
-        map.put(TAG_DEVICE_SETTING_DESCRIPTION, "Device Setting Description");
-        map.put(TAG_SUBJECT_DISTANCE_RANGE, "Subject Distance Range");
-        map.put(TAG_IMAGE_UNIQUE_ID, "Unique Image ID");
-        map.put(TAG_CAMERA_OWNER_NAME, "Camera Owner Name");
-        map.put(TAG_BODY_SERIAL_NUMBER, "Body Serial Number");
-        map.put(TAG_LENS_SPECIFICATION, "Lens Specification");
-        map.put(TAG_LENS_MAKE, "Lens Make");
-        map.put(TAG_LENS_MODEL, "Lens Model");
-        map.put(TAG_LENS_SERIAL_NUMBER, "Lens Serial Number");
-        map.put(TAG_GAMMA, "Gamma");
-        map.put(TAG_PRINT_IMAGE_MATCHING_INFO, "Print Image Matching (PIM) Info");
-        map.put(TAG_PANASONIC_TITLE, "Panasonic Title");
-        map.put(TAG_PANASONIC_TITLE_2, "Panasonic Title (2)");
-        map.put(TAG_PADDING, "Padding");
-        map.put(TAG_LENS, "Lens");
-    }
-}
Index: trunk/src/com/drew/metadata/exif/ExifIFD0Descriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/ExifIFD0Descriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,38 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link ExifIFD0Directory}.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class ExifIFD0Descriptor extends ExifDescriptorBase<ExifIFD0Directory>
-{
-    public ExifIFD0Descriptor(@NotNull ExifIFD0Directory directory)
-    {
-        super(directory);
-    }
-}
Index: trunk/src/com/drew/metadata/exif/ExifIFD0Directory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/ExifIFD0Directory.java	(revision 15217)
+++ 	(revision )
@@ -1,68 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-
-import java.util.HashMap;
-
-/**
- * Describes Exif tags from the IFD0 directory.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class ExifIFD0Directory extends ExifDirectoryBase
-{
-    /** This tag is a pointer to the Exif SubIFD. */
-    public static final int TAG_EXIF_SUB_IFD_OFFSET = 0x8769;
-
-    /** This tag is a pointer to the Exif GPS IFD. */
-    public static final int TAG_GPS_INFO_OFFSET = 0x8825;
-
-    public ExifIFD0Directory()
-    {
-        this.setDescriptor(new ExifIFD0Descriptor(this));
-    }
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        addExifTagNames(_tagNameMap);
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Exif IFD0";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/ExifImageDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/ExifImageDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,37 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link ExifImageDirectory}.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class ExifImageDescriptor extends ExifDescriptorBase<ExifImageDirectory>
-{
-    public ExifImageDescriptor(@NotNull ExifImageDirectory directory)
-    {
-        super(directory);
-    }
-}
Index: trunk/src/com/drew/metadata/exif/ExifImageDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/ExifImageDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,64 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-
-import java.util.HashMap;
-
-/**
- * Describes One of several Exif directories.
- *
- * Holds information about image IFD's in a chain after the first. The first page is stored in IFD0.
- * Currently, this only applied to multi-page TIFF images
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class ExifImageDirectory extends ExifDirectoryBase
-{
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        addExifTagNames(_tagNameMap);
-    }
-
-    public ExifImageDirectory()
-    {
-        this.setDescriptor(new ExifImageDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Exif Image";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/ExifInteropDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/ExifInteropDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,37 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link ExifInteropDirectory}.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class ExifInteropDescriptor extends ExifDescriptorBase<ExifInteropDirectory>
-{
-    public ExifInteropDescriptor(@NotNull ExifInteropDirectory directory)
-    {
-        super(directory);
-    }
-}
Index: trunk/src/com/drew/metadata/exif/ExifInteropDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/ExifInteropDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,61 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-
-import java.util.HashMap;
-
-/**
- * Describes Exif interoperability tags.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class ExifInteropDirectory extends ExifDirectoryBase
-{
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        addExifTagNames(_tagNameMap);
-    }
-
-    public ExifInteropDirectory()
-    {
-        this.setDescriptor(new ExifInteropDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Interoperability";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/ExifReader.java
===================================================================
--- trunk/src/com/drew/metadata/exif/ExifReader.java	(revision 15217)
+++ 	(revision )
@@ -1,102 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.imaging.jpeg.JpegSegmentMetadataReader;
-import com.drew.imaging.jpeg.JpegSegmentType;
-import com.drew.imaging.tiff.TiffProcessingException;
-import com.drew.imaging.tiff.TiffReader;
-import com.drew.lang.ByteArrayReader;
-import com.drew.lang.RandomAccessReader;
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.Directory;
-import com.drew.metadata.Metadata;
-
-import java.io.IOException;
-import java.util.Collections;
-
-/**
- * Decodes Exif binary data, populating a {@link Metadata} object with tag values in {@link ExifSubIFDDirectory},
- * {@link ExifThumbnailDirectory}, {@link ExifInteropDirectory}, {@link GpsDirectory} and one of the many camera
- * makernote directories.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class ExifReader implements JpegSegmentMetadataReader
-{
-    /** Exif data stored in JPEG files' APP1 segment are preceded by this six character preamble. */
-    public static final String JPEG_SEGMENT_PREAMBLE = "Exif\0\0";
-
-    @NotNull
-    public Iterable<JpegSegmentType> getSegmentTypes()
-    {
-        return Collections.singletonList(JpegSegmentType.APP1);
-    }
-
-    public void readJpegSegments(@NotNull final Iterable<byte[]> segments, @NotNull final Metadata metadata, @NotNull final JpegSegmentType segmentType)
-    {
-        assert(segmentType == JpegSegmentType.APP1);
-
-        for (byte[] segmentBytes : segments) {
-            // Filter any segments containing unexpected preambles
-            if (segmentBytes.length < JPEG_SEGMENT_PREAMBLE.length() || !new String(segmentBytes, 0, JPEG_SEGMENT_PREAMBLE.length()).equals(JPEG_SEGMENT_PREAMBLE))
-                continue;
-            extract(new ByteArrayReader(segmentBytes), metadata, JPEG_SEGMENT_PREAMBLE.length());
-        }
-    }
-
-    /** Reads TIFF formatted Exif data from start of the specified {@link RandomAccessReader}. */
-    public void extract(@NotNull final RandomAccessReader reader, @NotNull final Metadata metadata)
-    {
-        extract(reader, metadata, 0);
-    }
-
-    /** Reads TIFF formatted Exif data a specified offset within a {@link RandomAccessReader}. */
-    public void extract(@NotNull final RandomAccessReader reader, @NotNull final Metadata metadata, int readerOffset)
-    {
-        extract(reader, metadata, readerOffset, null);
-    }
-
-    /** Reads TIFF formatted Exif data at a specified offset within a {@link RandomAccessReader}. */
-    public void extract(@NotNull final RandomAccessReader reader, @NotNull final Metadata metadata, int readerOffset, @Nullable Directory parentDirectory)
-    {
-        ExifTiffHandler exifTiffHandler = new ExifTiffHandler(metadata, parentDirectory);
-
-        try {
-            // Read the TIFF-formatted Exif data
-            new TiffReader().processTiff(
-                reader,
-                exifTiffHandler,
-                readerOffset
-            );
-        } catch (TiffProcessingException e) {
-            exifTiffHandler.error("Exception processing TIFF data: " + e.getMessage());
-            // TODO what do to with this error state?
-            e.printStackTrace(System.err);
-        } catch (IOException e) {
-            exifTiffHandler.error("Exception processing TIFF data: " + e.getMessage());
-            // TODO what do to with this error state?
-            e.printStackTrace(System.err);
-        }
-    }
-}
Index: trunk/src/com/drew/metadata/exif/ExifSubIFDDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/ExifSubIFDDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,37 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link ExifSubIFDDirectory}.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class ExifSubIFDDescriptor extends ExifDescriptorBase<ExifSubIFDDirectory>
-{
-    public ExifSubIFDDescriptor(@NotNull ExifSubIFDDirectory directory)
-    {
-        super(directory);
-    }
-}
Index: trunk/src/com/drew/metadata/exif/ExifSubIFDDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/ExifSubIFDDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,177 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.Directory;
-
-import java.util.Date;
-import java.util.HashMap;
-import java.util.TimeZone;
-
-/**
- * Describes Exif tags from the SubIFD directory.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class ExifSubIFDDirectory extends ExifDirectoryBase
-{
-    /** This tag is a pointer to the Exif Interop IFD. */
-    public static final int TAG_INTEROP_OFFSET = 0xA005;
-
-    public ExifSubIFDDirectory()
-    {
-        this.setDescriptor(new ExifSubIFDDescriptor(this));
-    }
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        addExifTagNames(_tagNameMap);
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Exif SubIFD";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-
-    /**
-     * Parses the date/time tag, the subsecond tag and the time offset tag to obtain a single Date
-     * object with milliseconds representing the date and time when this image was modified.  If
-     * the time offset tag does not exist, attempts will be made to parse the values as though it is
-     * in the GMT {@link TimeZone}.
-     *
-     * @return A Date object representing when this image was modified, if possible, otherwise null
-     */
-    @Nullable
-    public Date getDateModified()
-    {
-        return getDateModified(null);
-    }
-
-    /**
-     * Parses the date/time tag, the subsecond tag and the time offset tag to obtain a single Date
-     * object with milliseconds representing the date and time when this image was modified.  If
-     * the time offset tag does not exist, attempts will be made to parse the values as though it is
-     * in the {@link TimeZone} represented by the {@code timeZone} parameter (if it is non-null).
-     *
-     * @param timeZone the time zone to use
-     * @return A Date object representing when this image was modified, if possible, otherwise null
-     */
-    @Nullable
-    public Date getDateModified(@Nullable TimeZone timeZone)
-    {
-        Directory parent = getParent();
-        if (parent instanceof ExifIFD0Directory) {
-            TimeZone timeZoneModified = getTimeZone(TAG_OFFSET_TIME);
-            return parent.getDate(TAG_DATETIME, getString(TAG_SUBSECOND_TIME),
-                (timeZoneModified != null) ? timeZoneModified : timeZone);
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * Parses the date/time tag, the subsecond tag and the time offset tag to obtain a single Date
-     * object with milliseconds representing the date and time when this image was captured.  If
-     * the time offset tag does not exist, attempts will be made to parse the values as though it is
-     * in the GMT {@link TimeZone}.
-     *
-     * @return A Date object representing when this image was captured, if possible, otherwise null
-     */
-    @Nullable
-    public Date getDateOriginal()
-    {
-        return getDateOriginal(null);
-    }
-
-    /**
-     * Parses the date/time tag, the subsecond tag and the time offset tag to obtain a single Date
-     * object with milliseconds representing the date and time when this image was captured.  If
-     * the time offset tag does not exist, attempts will be made to parse the values as though it is
-     * in the {@link TimeZone} represented by the {@code timeZone} parameter (if it is non-null).
-     *
-     * @param timeZone the time zone to use
-     * @return A Date object representing when this image was captured, if possible, otherwise null
-     */
-    @Nullable
-    public Date getDateOriginal(@Nullable TimeZone timeZone)
-    {
-        TimeZone timeZoneOriginal = getTimeZone(TAG_OFFSET_TIME_ORIGINAL);
-        return getDate(TAG_DATETIME_ORIGINAL, getString(TAG_SUBSECOND_TIME_ORIGINAL),
-            (timeZoneOriginal != null) ? timeZoneOriginal : timeZone);
-    }
-
-    /**
-     * Parses the date/time tag, the subsecond tag and the time offset tag to obtain a single Date
-     * object with milliseconds representing the date and time when this image was digitized.  If
-     * the time offset tag does not exist, attempts will be made to parse the values as though it is
-     * in the GMT {@link TimeZone}.
-     *
-     * @return A Date object representing when this image was digitized, if possible, otherwise null
-     */
-    @Nullable
-    public Date getDateDigitized()
-    {
-        return getDateDigitized(null);
-    }
-
-    /**
-     * Parses the date/time tag, the subsecond tag and the time offset tag to obtain a single Date
-     * object with milliseconds representing the date and time when this image was digitized.  If
-     * the time offset tag does not exist, attempts will be made to parse the values as though it is
-     * in the {@link TimeZone} represented by the {@code timeZone} parameter (if it is non-null).
-     *
-     * @param timeZone the time zone to use
-     * @return A Date object representing when this image was digitized, if possible, otherwise null
-     */
-    @Nullable
-    public Date getDateDigitized(@Nullable TimeZone timeZone)
-    {
-        TimeZone timeZoneDigitized = getTimeZone(TAG_OFFSET_TIME_DIGITIZED);
-        return getDate(TAG_DATETIME_DIGITIZED, getString(TAG_SUBSECOND_TIME_DIGITIZED),
-            (timeZoneDigitized != null) ? timeZoneDigitized : timeZone);
-    }
-
-    @Nullable
-    private TimeZone getTimeZone(int tagType)
-    {
-        String timeOffset = getString(tagType);
-        if (timeOffset != null && timeOffset.matches("[\\+\\-]\\d\\d:\\d\\d")) {
-            return TimeZone.getTimeZone("GMT" + timeOffset);
-        } else {
-            return null;
-        }
-    }
-}
Index: trunk/src/com/drew/metadata/exif/ExifThumbnailDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/ExifThumbnailDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,69 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-
-import static com.drew.metadata.exif.ExifThumbnailDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link ExifThumbnailDirectory}.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class ExifThumbnailDescriptor extends ExifDescriptorBase<ExifThumbnailDirectory>
-{
-    public ExifThumbnailDescriptor(@NotNull ExifThumbnailDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_THUMBNAIL_OFFSET:
-                return getThumbnailOffsetDescription();
-            case TAG_THUMBNAIL_LENGTH:
-                return getThumbnailLengthDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getThumbnailLengthDescription()
-    {
-        String value = _directory.getString(TAG_THUMBNAIL_LENGTH);
-        return value == null ? null : value + " bytes";
-    }
-
-    @Nullable
-    public String getThumbnailOffsetDescription()
-    {
-        String value = _directory.getString(TAG_THUMBNAIL_OFFSET);
-        return value == null ? null : value + " bytes";
-    }
-}
Index: trunk/src/com/drew/metadata/exif/ExifThumbnailDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/ExifThumbnailDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,80 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-
-import java.util.HashMap;
-
-/**
- * One of several Exif directories.  Otherwise known as IFD1, this directory holds information about an embedded thumbnail image.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class ExifThumbnailDirectory extends ExifDirectoryBase
-{
-    /**
-     * The offset to thumbnail image bytes.
-     */
-    public static final int TAG_THUMBNAIL_OFFSET = 0x0201;
-    /**
-     * The size of the thumbnail image data in bytes.
-     */
-    public static final int TAG_THUMBNAIL_LENGTH = 0x0202;
-
-    /**
-     * @deprecated use {@link com.drew.metadata.exif.ExifDirectoryBase#TAG_COMPRESSION} instead.
-     */
-    @Deprecated
-    public static final int TAG_THUMBNAIL_COMPRESSION = 0x0103;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        addExifTagNames(_tagNameMap);
-
-        _tagNameMap.put(TAG_THUMBNAIL_OFFSET, "Thumbnail Offset");
-        _tagNameMap.put(TAG_THUMBNAIL_LENGTH, "Thumbnail Length");
-    }
-
-    public ExifThumbnailDirectory()
-    {
-        this.setDescriptor(new ExifThumbnailDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Exif Thumbnail";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/ExifTiffHandler.java
===================================================================
--- trunk/src/com/drew/metadata/exif/ExifTiffHandler.java	(revision 15217)
+++ 	(revision )
@@ -1,859 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Set;
-
-import com.drew.imaging.jpeg.JpegMetadataReader;
-import com.drew.imaging.jpeg.JpegProcessingException;
-import com.drew.imaging.tiff.TiffProcessingException;
-import com.drew.imaging.tiff.TiffReader;
-import com.drew.lang.BufferBoundsException;
-import com.drew.lang.Charsets;
-import com.drew.lang.RandomAccessReader;
-import com.drew.lang.SequentialByteArrayReader;
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.Directory;
-import com.drew.metadata.Metadata;
-import com.drew.metadata.StringValue;
-import com.drew.metadata.exif.makernotes.AppleMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.CanonMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.CasioType1MakernoteDirectory;
-import com.drew.metadata.exif.makernotes.CasioType2MakernoteDirectory;
-import com.drew.metadata.exif.makernotes.FujifilmMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.KodakMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.KyoceraMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.LeicaMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.LeicaType5MakernoteDirectory;
-import com.drew.metadata.exif.makernotes.NikonType1MakernoteDirectory;
-import com.drew.metadata.exif.makernotes.NikonType2MakernoteDirectory;
-import com.drew.metadata.exif.makernotes.OlympusCameraSettingsMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.OlympusEquipmentMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.OlympusFocusInfoMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.OlympusImageProcessingMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.OlympusMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.OlympusRawDevelopment2MakernoteDirectory;
-import com.drew.metadata.exif.makernotes.OlympusRawDevelopmentMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.OlympusRawInfoMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.PanasonicMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.PentaxMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.ReconyxHyperFireMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.ReconyxUltraFireMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.RicohMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.SamsungType2MakernoteDirectory;
-import com.drew.metadata.exif.makernotes.SanyoMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.SigmaMakernoteDirectory;
-import com.drew.metadata.exif.makernotes.SonyType1MakernoteDirectory;
-import com.drew.metadata.exif.makernotes.SonyType6MakernoteDirectory;
-import com.drew.metadata.iptc.IptcReader;
-import com.drew.metadata.tiff.DirectoryTiffHandler;
-
-/**
- * Implementation of {@link com.drew.imaging.tiff.TiffHandler} used for handling TIFF tags according to the Exif
- * standard.
- * <p>
- * Includes support for camera manufacturer makernotes.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-public class ExifTiffHandler extends DirectoryTiffHandler
-{
-    public ExifTiffHandler(@NotNull Metadata metadata, @Nullable Directory parentDirectory)
-    {
-        super(metadata, parentDirectory);
-    }
-
-    public void setTiffMarker(int marker) throws TiffProcessingException
-    {
-        final int standardTiffMarker = 0x002A;
-        final int olympusRawTiffMarker = 0x4F52; // for ORF files
-        final int olympusRawTiffMarker2 = 0x5352; // for ORF files
-        final int panasonicRawTiffMarker = 0x0055; // for RW2 files
-
-        switch (marker) {
-            case standardTiffMarker:
-            case olympusRawTiffMarker:      // TODO implement an IFD0, if there is one
-            case olympusRawTiffMarker2:     // TODO implement an IFD0, if there is one
-                pushDirectory(ExifIFD0Directory.class);
-                break;
-            case panasonicRawTiffMarker:
-                pushDirectory(PanasonicRawIFD0Directory.class);
-                break;
-            default:
-                throw new TiffProcessingException(String.format("Unexpected TIFF marker: 0x%X", marker));
-        }
-    }
-
-    public boolean tryEnterSubIfd(int tagId)
-    {
-        if (tagId == ExifDirectoryBase.TAG_SUB_IFD_OFFSET) {
-            pushDirectory(ExifSubIFDDirectory.class);
-            return true;
-        }
-
-        if (_currentDirectory instanceof ExifIFD0Directory || _currentDirectory instanceof PanasonicRawIFD0Directory) {
-            if (tagId == ExifIFD0Directory.TAG_EXIF_SUB_IFD_OFFSET) {
-                pushDirectory(ExifSubIFDDirectory.class);
-                return true;
-            }
-
-            if (tagId == ExifIFD0Directory.TAG_GPS_INFO_OFFSET) {
-                pushDirectory(GpsDirectory.class);
-                return true;
-            }
-        }
-
-        if (_currentDirectory instanceof ExifSubIFDDirectory) {
-            if (tagId == ExifSubIFDDirectory.TAG_INTEROP_OFFSET) {
-                pushDirectory(ExifInteropDirectory.class);
-                return true;
-            }
-        }
-
-        if (_currentDirectory instanceof OlympusMakernoteDirectory) {
-            // Note: these also appear in customProcessTag because some are IFD pointers while others begin immediately
-            // for the same directories
-            switch(tagId) {
-                case OlympusMakernoteDirectory.TAG_EQUIPMENT:
-                    pushDirectory(OlympusEquipmentMakernoteDirectory.class);
-                    return true;
-                case OlympusMakernoteDirectory.TAG_CAMERA_SETTINGS:
-                    pushDirectory(OlympusCameraSettingsMakernoteDirectory.class);
-                    return true;
-                case OlympusMakernoteDirectory.TAG_RAW_DEVELOPMENT:
-                    pushDirectory(OlympusRawDevelopmentMakernoteDirectory.class);
-                    return true;
-                case OlympusMakernoteDirectory.TAG_RAW_DEVELOPMENT_2:
-                    pushDirectory(OlympusRawDevelopment2MakernoteDirectory.class);
-                    return true;
-                case OlympusMakernoteDirectory.TAG_IMAGE_PROCESSING:
-                    pushDirectory(OlympusImageProcessingMakernoteDirectory.class);
-                    return true;
-                case OlympusMakernoteDirectory.TAG_FOCUS_INFO:
-                    pushDirectory(OlympusFocusInfoMakernoteDirectory.class);
-                    return true;
-                case OlympusMakernoteDirectory.TAG_RAW_INFO:
-                    pushDirectory(OlympusRawInfoMakernoteDirectory.class);
-                    return true;
-                case OlympusMakernoteDirectory.TAG_MAIN_INFO:
-                    pushDirectory(OlympusMakernoteDirectory.class);
-                    return true;
-            }
-        }
-
-        return false;
-    }
-
-    public boolean hasFollowerIfd()
-    {
-        // In Exif, the only known 'follower' IFD is the thumbnail one, however this may not be the case.
-        // UPDATE: In multipage TIFFs, the 'follower' IFD points to the next image in the set
-        if (_currentDirectory instanceof ExifIFD0Directory || _currentDirectory instanceof ExifImageDirectory) {
-            // If the PageNumber tag is defined, assume this is a multipage TIFF or similar
-            // TODO: Find better ways to know which follower Directory should be used
-            if (_currentDirectory.containsTag(ExifDirectoryBase.TAG_PAGE_NUMBER))
-                pushDirectory(ExifImageDirectory.class);
-            else
-                pushDirectory(ExifThumbnailDirectory.class);
-            return true;
-        }
-
-        // The Canon EOS 7D (CR2) has three chained/following thumbnail IFDs
-        if (_currentDirectory instanceof ExifThumbnailDirectory)
-            return true;
-
-        // This should not happen, as Exif doesn't use follower IFDs apart from that above.
-        // NOTE have seen the CanonMakernoteDirectory IFD have a follower pointer, but it points to invalid data.
-        return false;
-    }
-
-    @Nullable
-    public Long tryCustomProcessFormat(final int tagId, final int formatCode, final long componentCount)
-    {
-        if (formatCode == 13)
-            return componentCount * 4;
-
-        // an unknown (0) formatCode needs to be potentially handled later as a highly custom directory tag
-        if (formatCode == 0)
-            return 0L;
-
-        return null;
-    }
-
-    public boolean customProcessTag(final int tagOffset,
-                                    final @NotNull Set<Integer> processedIfdOffsets,
-                                    final int tiffHeaderOffset,
-                                    final @NotNull RandomAccessReader reader,
-                                    final int tagId,
-                                    final int byteCount) throws IOException
-    {
-        assert(_currentDirectory != null);
-
-        // Some 0x0000 tags have a 0 byteCount. Determine whether it's bad.
-        if (tagId == 0) {
-            if (_currentDirectory.containsTag(tagId)) {
-                // Let it go through for now. Some directories handle it, some don't
-                return false;
-            }
-
-            // Skip over 0x0000 tags that don't have any associated bytes. No idea what it contains in this case, if anything.
-            if (byteCount == 0)
-                return true;
-        }
-
-        // Custom processing for the Makernote tag
-        if (tagId == ExifSubIFDDirectory.TAG_MAKERNOTE && _currentDirectory instanceof ExifSubIFDDirectory) {
-            return processMakernote(tagOffset, processedIfdOffsets, tiffHeaderOffset, reader);
-        }
-
-        // Custom processing for embedded IPTC data
-        if (tagId == ExifSubIFDDirectory.TAG_IPTC_NAA && _currentDirectory instanceof ExifIFD0Directory) {
-            // NOTE Adobe sets type 4 for IPTC instead of 7
-            if (reader.getInt8(tagOffset) == 0x1c) {
-                final byte[] iptcBytes = reader.getBytes(tagOffset, byteCount);
-                new IptcReader().extract(new SequentialByteArrayReader(iptcBytes), _metadata, iptcBytes.length, _currentDirectory);
-                return true;
-            }
-            return false;
-        }
-
-        if (handlePrintIM(_currentDirectory, tagId))
-        {
-            PrintIMDirectory printIMDirectory = new PrintIMDirectory();
-            printIMDirectory.setParent(_currentDirectory);
-            _metadata.addDirectory(printIMDirectory);
-            processPrintIM(printIMDirectory, tagOffset, reader, byteCount);
-            return true;
-        }
-
-        // Note: these also appear in tryEnterSubIfd because some are IFD pointers while others begin immediately
-        // for the same directories
-        if (_currentDirectory instanceof OlympusMakernoteDirectory) {
-            switch (tagId) {
-                case OlympusMakernoteDirectory.TAG_EQUIPMENT:
-                    pushDirectory(OlympusEquipmentMakernoteDirectory.class);
-                    TiffReader.processIfd(this, reader, processedIfdOffsets, tagOffset, tiffHeaderOffset);
-                    return true;
-                case OlympusMakernoteDirectory.TAG_CAMERA_SETTINGS:
-                    pushDirectory(OlympusCameraSettingsMakernoteDirectory.class);
-                    TiffReader.processIfd(this, reader, processedIfdOffsets, tagOffset, tiffHeaderOffset);
-                    return true;
-                case OlympusMakernoteDirectory.TAG_RAW_DEVELOPMENT:
-                    pushDirectory(OlympusRawDevelopmentMakernoteDirectory.class);
-                    TiffReader.processIfd(this, reader, processedIfdOffsets, tagOffset, tiffHeaderOffset);
-                    return true;
-                case OlympusMakernoteDirectory.TAG_RAW_DEVELOPMENT_2:
-                    pushDirectory(OlympusRawDevelopment2MakernoteDirectory.class);
-                    TiffReader.processIfd(this, reader, processedIfdOffsets, tagOffset, tiffHeaderOffset);
-                    return true;
-                case OlympusMakernoteDirectory.TAG_IMAGE_PROCESSING:
-                    pushDirectory(OlympusImageProcessingMakernoteDirectory.class);
-                    TiffReader.processIfd(this, reader, processedIfdOffsets, tagOffset, tiffHeaderOffset);
-                    return true;
-                case OlympusMakernoteDirectory.TAG_FOCUS_INFO:
-                    pushDirectory(OlympusFocusInfoMakernoteDirectory.class);
-                    TiffReader.processIfd(this, reader, processedIfdOffsets, tagOffset, tiffHeaderOffset);
-                    return true;
-                case OlympusMakernoteDirectory.TAG_RAW_INFO:
-                    pushDirectory(OlympusRawInfoMakernoteDirectory.class);
-                    TiffReader.processIfd(this, reader, processedIfdOffsets, tagOffset, tiffHeaderOffset);
-                    return true;
-                case OlympusMakernoteDirectory.TAG_MAIN_INFO:
-                    pushDirectory(OlympusMakernoteDirectory.class);
-                    TiffReader.processIfd(this, reader, processedIfdOffsets, tagOffset, tiffHeaderOffset);
-                    return true;
-            }
-        }
-
-        if (_currentDirectory instanceof PanasonicRawIFD0Directory) {
-            // these contain binary data with specific offsets, and can't be processed as regular ifd's.
-            // The binary data is broken into 'fake' tags and there is a pattern.
-            switch (tagId) {
-                case PanasonicRawIFD0Directory.TagWbInfo:
-                    PanasonicRawWbInfoDirectory dirWbInfo = new PanasonicRawWbInfoDirectory();
-                    dirWbInfo.setParent(_currentDirectory);
-                    _metadata.addDirectory(dirWbInfo);
-                    processBinary(dirWbInfo, tagOffset, reader, byteCount, false, 2);
-                    return true;
-                case PanasonicRawIFD0Directory.TagWbInfo2:
-                    PanasonicRawWbInfo2Directory dirWbInfo2 = new PanasonicRawWbInfo2Directory();
-                    dirWbInfo2.setParent(_currentDirectory);
-                    _metadata.addDirectory(dirWbInfo2);
-                    processBinary(dirWbInfo2, tagOffset, reader, byteCount, false, 3);
-                    return true;
-                case PanasonicRawIFD0Directory.TagDistortionInfo:
-                    PanasonicRawDistortionDirectory dirDistort = new PanasonicRawDistortionDirectory();
-                    dirDistort.setParent(_currentDirectory);
-                    _metadata.addDirectory(dirDistort);
-                    processBinary(dirDistort, tagOffset, reader, byteCount, true, 1);
-                    return true;
-            }
-        }
-
-        // Panasonic RAW sometimes contains an embedded version of the data as a JPG file.
-        if (tagId == PanasonicRawIFD0Directory.TagJpgFromRaw && _currentDirectory instanceof PanasonicRawIFD0Directory) {
-            byte[] jpegrawbytes = reader.getBytes(tagOffset, byteCount);
-
-            // Extract information from embedded image since it is metadata-rich
-            ByteArrayInputStream jpegmem = new ByteArrayInputStream(jpegrawbytes);
-            try {
-                Metadata jpegDirectory = JpegMetadataReader.readMetadata(jpegmem);
-                for (Directory directory : jpegDirectory.getDirectories()) {
-                    directory.setParent(_currentDirectory);
-                    _metadata.addDirectory(directory);
-                }
-                return true;
-            } catch (JpegProcessingException e) {
-                _currentDirectory.addError("Error processing JpgFromRaw: " + e.getMessage());
-            } catch (IOException e) {
-                _currentDirectory.addError("Error reading JpgFromRaw: " + e.getMessage());
-            }
-        }
-
-        return false;
-    }
-
-    private static void processBinary(@NotNull final Directory directory, final int tagValueOffset, @NotNull final RandomAccessReader reader, final int byteCount, final Boolean isSigned, final int arrayLength) throws IOException
-    {
-        // expects signed/unsigned int16 (for now)
-        //int byteSize = isSigned ? sizeof(short) : sizeof(ushort);
-        int byteSize = 2;
-
-        // 'directory' is assumed to contain tags that correspond to the byte position unless it's a set of bytes
-        for (int i = 0; i < byteCount; i++) {
-            if (directory.hasTagName(i)) {
-                // only process this tag if the 'next' integral tag exists. Otherwise, it's a set of bytes
-                if (i < byteCount - 1 && directory.hasTagName(i + 1)) {
-                    if (isSigned)
-                        directory.setObject(i, reader.getInt16(tagValueOffset + (i* byteSize)));
-                    else
-                        directory.setObject(i, reader.getUInt16(tagValueOffset + (i* byteSize)));
-                } else {
-                    // the next arrayLength bytes are a multi-byte value
-                    if (isSigned) {
-                        short[] val = new short[arrayLength];
-                        for (int j = 0; j<val.length; j++)
-                            val[j] = reader.getInt16(tagValueOffset + ((i + j) * byteSize));
-                        directory.setObjectArray(i, val);
-                    } else {
-                        int[] val = new int[arrayLength];
-                        for (int j = 0; j<val.length; j++)
-                            val[j] = reader.getUInt16(tagValueOffset + ((i + j) * byteSize));
-                        directory.setObjectArray(i, val);
-                    }
-
-                    i += arrayLength - 1;
-                }
-            }
-        }
-    }
-
-    /** Read a given number of bytes from the stream
-     *
-     * This method is employed to "suppress" attempts to read beyond end of the
-     * file as may happen at the beginning of processMakernote when we read
-     * increasingly longer camera makes.
-     *
-     * Instead of failing altogether in this context we return an empty string
-     * which will fail all sensible attempts to compare to makes while avoiding
-     * a full-on failure.
-     */
-    @NotNull
-    private static String getReaderString(final @NotNull RandomAccessReader reader, final int makernoteOffset, final int bytesRequested) throws IOException
-    {
-        try {
-            return reader.getString(makernoteOffset, bytesRequested, Charsets.UTF_8);
-        } catch(BufferBoundsException e) {
-            return "";
-        }
-    }
-
-    private boolean processMakernote(final int makernoteOffset,
-                                     final @NotNull Set<Integer> processedIfdOffsets,
-                                     final int tiffHeaderOffset,
-                                     final @NotNull RandomAccessReader reader) throws IOException
-    {
-        assert(_currentDirectory != null);
-
-        // Determine the camera model and makernote format.
-        Directory ifd0Directory = _metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
-
-        String cameraMake = ifd0Directory == null ? null : ifd0Directory.getString(ExifIFD0Directory.TAG_MAKE);
-
-        final String firstTwoChars    = getReaderString(reader, makernoteOffset, 2);
-        final String firstThreeChars  = getReaderString(reader, makernoteOffset, 3);
-        final String firstFourChars   = getReaderString(reader, makernoteOffset, 4);
-        final String firstFiveChars   = getReaderString(reader, makernoteOffset, 5);
-        final String firstSixChars    = getReaderString(reader, makernoteOffset, 6);
-        final String firstSevenChars  = getReaderString(reader, makernoteOffset, 7);
-        final String firstEightChars  = getReaderString(reader, makernoteOffset, 8);
-        final String firstNineChars   = getReaderString(reader, makernoteOffset, 9);
-        final String firstTenChars    = getReaderString(reader, makernoteOffset, 10);
-        final String firstTwelveChars = getReaderString(reader, makernoteOffset, 12);
-
-        boolean byteOrderBefore = reader.isMotorolaByteOrder();
-
-        if ("OLYMP\0".equals(firstSixChars) || "EPSON".equals(firstFiveChars) || "AGFA".equals(firstFourChars)) {
-            // Olympus Makernote
-            // Epson and Agfa use Olympus makernote standard: http://www.ozhiker.com/electronics/pjmt/jpeg_info/
-            pushDirectory(OlympusMakernoteDirectory.class);
-            TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 8, tiffHeaderOffset);
-        } else if ("OLYMPUS\0II".equals(firstTenChars)) {
-            // Olympus Makernote (alternate)
-            // Note that data is relative to the beginning of the makernote
-            // http://exiv2.org/makernote.html
-            pushDirectory(OlympusMakernoteDirectory.class);
-            TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 12, makernoteOffset);
-        } else if (cameraMake != null && cameraMake.toUpperCase().startsWith("MINOLTA")) {
-            // Cases seen with the model starting with MINOLTA in capitals seem to have a valid Olympus makernote
-            // area that commences immediately.
-            pushDirectory(OlympusMakernoteDirectory.class);
-            TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset, tiffHeaderOffset);
-        } else if (cameraMake != null && cameraMake.trim().toUpperCase().startsWith("NIKON")) {
-            if ("Nikon".equals(firstFiveChars)) {
-                /* There are two scenarios here:
-                 * Type 1:                  **
-                 * :0000: 4E 69 6B 6F 6E 00 01 00-05 00 02 00 02 00 06 00 Nikon...........
-                 * :0010: 00 00 EC 02 00 00 03 00-03 00 01 00 00 00 06 00 ................
-                 * Type 3:                  **
-                 * :0000: 4E 69 6B 6F 6E 00 02 00-00 00 4D 4D 00 2A 00 00 Nikon....MM.*...
-                 * :0010: 00 08 00 1E 00 01 00 07-00 00 00 04 30 32 30 30 ............0200
-                 */
-                switch (reader.getUInt8(makernoteOffset + 6)) {
-                    case 1:
-                        pushDirectory(NikonType1MakernoteDirectory.class);
-                        TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 8, tiffHeaderOffset);
-                        break;
-                    case 2:
-                        pushDirectory(NikonType2MakernoteDirectory.class);
-                        TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 18, makernoteOffset + 10);
-                        break;
-                    default:
-                        _currentDirectory.addError("Unsupported Nikon makernote data ignored.");
-                        break;
-                }
-            } else {
-                // The IFD begins with the first Makernote byte (no ASCII name).  This occurs with CoolPix 775, E990 and D1 models.
-                pushDirectory(NikonType2MakernoteDirectory.class);
-                TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset, tiffHeaderOffset);
-            }
-        } else if ("SONY CAM".equals(firstEightChars) || "SONY DSC".equals(firstEightChars)) {
-            pushDirectory(SonyType1MakernoteDirectory.class);
-            TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 12, tiffHeaderOffset);
-        // Do this check LAST after most other Sony checks
-        } else if (cameraMake != null && cameraMake.startsWith("SONY") &&
-                !Arrays.equals(reader.getBytes(makernoteOffset, 2), new byte[]{ 0x01, 0x00 }) ) {
-            // The IFD begins with the first Makernote byte (no ASCII name). Used in SR2 and ARW images
-            pushDirectory(SonyType1MakernoteDirectory.class);
-            TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset, tiffHeaderOffset);
-        } else if ("SEMC MS\u0000\u0000\u0000\u0000\u0000".equals(firstTwelveChars)) {
-            // force MM for this directory
-            reader.setMotorolaByteOrder(true);
-            // skip 12 byte header + 2 for "MM" + 6
-            pushDirectory(SonyType6MakernoteDirectory.class);
-            TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 20, tiffHeaderOffset);
-        } else if ("SIGMA\u0000\u0000\u0000".equals(firstEightChars) || "FOVEON\u0000\u0000".equals(firstEightChars)) {
-            pushDirectory(SigmaMakernoteDirectory.class);
-            TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 10, tiffHeaderOffset);
-        } else if ("KDK".equals(firstThreeChars)) {
-            reader.setMotorolaByteOrder(firstSevenChars.equals("KDK INFO"));
-            KodakMakernoteDirectory directory = new KodakMakernoteDirectory();
-            _metadata.addDirectory(directory);
-            processKodakMakernote(directory, makernoteOffset, reader);
-        } else if ("Canon".equalsIgnoreCase(cameraMake)) {
-            pushDirectory(CanonMakernoteDirectory.class);
-            TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset, tiffHeaderOffset);
-        } else if (cameraMake != null && cameraMake.toUpperCase().startsWith("CASIO")) {
-            if ("QVC\u0000\u0000\u0000".equals(firstSixChars)) {
-                pushDirectory(CasioType2MakernoteDirectory.class);
-                TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 6, tiffHeaderOffset);
-            } else {
-                pushDirectory(CasioType1MakernoteDirectory.class);
-                TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset, tiffHeaderOffset);
-            }
-        } else if ("FUJIFILM".equals(firstEightChars) || "Fujifilm".equalsIgnoreCase(cameraMake)) {
-            // Note that this also applies to certain Leica cameras, such as the Digilux-4.3
-            reader.setMotorolaByteOrder(false);
-            // the 4 bytes after "FUJIFILM" in the makernote point to the start of the makernote
-            // IFD, though the offset is relative to the start of the makernote, not the TIFF
-            // header (like everywhere else)
-            int ifdStart = makernoteOffset + reader.getInt32(makernoteOffset + 8);
-            pushDirectory(FujifilmMakernoteDirectory.class);
-            TiffReader.processIfd(this, reader, processedIfdOffsets, ifdStart, makernoteOffset);
-        } else if ("KYOCERA".equals(firstSevenChars)) {
-            // http://www.ozhiker.com/electronics/pjmt/jpeg_info/kyocera_mn.html
-            pushDirectory(KyoceraMakernoteDirectory.class);
-            TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 22, tiffHeaderOffset);
-        } else if ("LEICA".equals(firstFiveChars)) {
-            reader.setMotorolaByteOrder(false);
-
-            // used by the X1/X2/X VARIO/T
-            // (X1 starts with "LEICA\0\x01\0", Make is "LEICA CAMERA AG")
-            // (X2 starts with "LEICA\0\x05\0", Make is "LEICA CAMERA AG")
-            // (X VARIO starts with "LEICA\0\x04\0", Make is "LEICA CAMERA AG")
-            // (T (Typ 701) starts with "LEICA\0\0x6", Make is "LEICA CAMERA AG")
-            // (X (Typ 113) starts with "LEICA\0\0x7", Make is "LEICA CAMERA AG")
-
-            if ("LEICA\0\u0001\0".equals(firstEightChars) ||
-                "LEICA\0\u0004\0".equals(firstEightChars) ||
-                "LEICA\0\u0005\0".equals(firstEightChars) ||
-                "LEICA\0\u0006\0".equals(firstEightChars) ||
-                "LEICA\0\u0007\0".equals(firstEightChars))
-            {
-                pushDirectory(LeicaType5MakernoteDirectory.class);
-                TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 8, makernoteOffset);
-            } else if ("Leica Camera AG".equals(cameraMake)) {
-                pushDirectory(LeicaMakernoteDirectory.class);
-                TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 8, tiffHeaderOffset);
-            } else if ("LEICA".equals(cameraMake)) {
-                // Some Leica cameras use Panasonic makernote tags
-                pushDirectory(PanasonicMakernoteDirectory.class);
-                TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 8, tiffHeaderOffset);
-            } else {
-                return false;
-            }
-        } else if ("Panasonic\u0000\u0000\u0000".equals(firstTwelveChars)) {
-            // NON-Standard TIFF IFD Data using Panasonic Tags. There is no Next-IFD pointer after the IFD
-            // Offsets are relative to the start of the TIFF header at the beginning of the EXIF segment
-            // more information here: http://www.ozhiker.com/electronics/pjmt/jpeg_info/panasonic_mn.html
-            pushDirectory(PanasonicMakernoteDirectory.class);
-            TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 12, tiffHeaderOffset);
-        } else if ("AOC\u0000".equals(firstFourChars)) {
-            // NON-Standard TIFF IFD Data using Casio Type 2 Tags
-            // IFD has no Next-IFD pointer at end of IFD, and
-            // Offsets are relative to the start of the current IFD tag, not the TIFF header
-            // Observed for:
-            // - Pentax ist D
-            pushDirectory(CasioType2MakernoteDirectory.class);
-            TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 6, makernoteOffset);
-        } else if (cameraMake != null && (cameraMake.toUpperCase().startsWith("PENTAX") || cameraMake.toUpperCase().startsWith("ASAHI"))) {
-            // NON-Standard TIFF IFD Data using Pentax Tags
-            // IFD has no Next-IFD pointer at end of IFD, and
-            // Offsets are relative to the start of the current IFD tag, not the TIFF header
-            // Observed for:
-            // - PENTAX Optio 330
-            // - PENTAX Optio 430
-            pushDirectory(PentaxMakernoteDirectory.class);
-            TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset, makernoteOffset);
-//        } else if ("KC".equals(firstTwoChars) || "MINOL".equals(firstFiveChars) || "MLY".equals(firstThreeChars) || "+M+M+M+M".equals(firstEightChars)) {
-//            // This Konica data is not understood.  Header identified in accordance with information at this site:
-//            // http://www.ozhiker.com/electronics/pjmt/jpeg_info/minolta_mn.html
-//            // TODO add support for minolta/konica cameras
-//            exifDirectory.addError("Unsupported Konica/Minolta data ignored.");
-        } else if ("SANYO\0\1\0".equals(firstEightChars)) {
-            pushDirectory(SanyoMakernoteDirectory.class);
-            TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 8, makernoteOffset);
-        } else if (cameraMake != null && cameraMake.toLowerCase().startsWith("ricoh")) {
-            if (firstTwoChars.equals("Rv") || firstThreeChars.equals("Rev")) {
-                // This is a textual format, where the makernote bytes look like:
-                //   Rv0103;Rg1C;Bg18;Ll0;Ld0;Aj0000;Bn0473800;Fp2E00:������������������������������
-                //   Rv0103;Rg1C;Bg18;Ll0;Ld0;Aj0000;Bn0473800;Fp2D05:������������������������������
-                //   Rv0207;Sf6C84;Rg76;Bg60;Gg42;Ll0;Ld0;Aj0004;Bn0B02900;Fp10B8;Md6700;Ln116900086D27;Sv263:0000000000000000000000��
-                // This format is currently unsupported
-                return false;
-            } else if (firstFiveChars.equalsIgnoreCase("Ricoh")) {
-                // Always in Motorola byte order
-                reader.setMotorolaByteOrder(true);
-                pushDirectory(RicohMakernoteDirectory.class);
-                TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 8, makernoteOffset);
-            }
-        } else if (firstTenChars.equals("Apple iOS\0")) {
-            // Always in Motorola byte order
-            boolean orderBefore = reader.isMotorolaByteOrder();
-            reader.setMotorolaByteOrder(true);
-            pushDirectory(AppleMakernoteDirectory.class);
-            TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset + 14, makernoteOffset);
-            reader.setMotorolaByteOrder(orderBefore);
-        } else if (reader.getUInt16(makernoteOffset) == ReconyxHyperFireMakernoteDirectory.MAKERNOTE_VERSION) {
-            ReconyxHyperFireMakernoteDirectory directory = new ReconyxHyperFireMakernoteDirectory();
-            _metadata.addDirectory(directory);
-            processReconyxHyperFireMakernote(directory, makernoteOffset, reader);
-        } else if (firstNineChars.equalsIgnoreCase("RECONYXUF")) {
-            ReconyxUltraFireMakernoteDirectory directory = new ReconyxUltraFireMakernoteDirectory();
-            _metadata.addDirectory(directory);
-            processReconyxUltraFireMakernote(directory, makernoteOffset, reader);
-        } else if ("SAMSUNG".equals(cameraMake)) {
-            // Only handles Type2 notes correctly. Others aren't implemented, and it's complex to determine which ones to use
-            pushDirectory(SamsungType2MakernoteDirectory.class);
-            TiffReader.processIfd(this, reader, processedIfdOffsets, makernoteOffset, tiffHeaderOffset);
-        } else {
-            // The makernote is not comprehended by this library.
-            // If you are reading this and believe a particular camera's image should be processed, get in touch.
-            return false;
-        }
-
-        reader.setMotorolaByteOrder(byteOrderBefore);
-        return true;
-    }
-
-    private static boolean handlePrintIM(@NotNull final Directory directory, final int tagId)
-    {
-        if (tagId == ExifDirectoryBase.TAG_PRINT_IMAGE_MATCHING_INFO)
-            return true;
-
-        if (tagId == 0x0E00) {
-            // Tempting to say every tagid of 0x0E00 is a PIM tag, but can't be 100% sure
-            if (directory instanceof CasioType2MakernoteDirectory ||
-                directory instanceof KyoceraMakernoteDirectory ||
-                directory instanceof NikonType2MakernoteDirectory ||
-                directory instanceof OlympusMakernoteDirectory ||
-                directory instanceof PanasonicMakernoteDirectory ||
-                directory instanceof PentaxMakernoteDirectory ||
-                directory instanceof RicohMakernoteDirectory ||
-                directory instanceof SanyoMakernoteDirectory ||
-                directory instanceof SonyType1MakernoteDirectory)
-                return true;
-        }
-
-        return false;
-    }
-
-    /// <summary>
-    /// Process PrintIM IFD
-    /// </summary>
-    /// <remarks>
-    /// Converted from Exiftool version 10.33 created by Phil Harvey
-    /// http://www.sno.phy.queensu.ca/~phil/exiftool/
-    /// lib\Image\ExifTool\PrintIM.pm
-    /// </remarks>
-    private static void processPrintIM(@NotNull final PrintIMDirectory directory, final int tagValueOffset, @NotNull final RandomAccessReader reader, final int byteCount) throws IOException
-    {
-        Boolean resetByteOrder = null;
-
-        if (byteCount == 0) {
-            directory.addError("Empty PrintIM data");
-            return;
-        }
-
-        if (byteCount <= 15) {
-            directory.addError("Bad PrintIM data");
-            return;
-        }
-
-        String header = reader.getString(tagValueOffset, 12, Charsets.UTF_8);
-
-        if (!header.startsWith("PrintIM")) {
-            directory.addError("Invalid PrintIM header");
-            return;
-        }
-
-        // check size of PrintIM block
-        int num = reader.getUInt16(tagValueOffset + 14);
-
-        if (byteCount < 16 + num * 6) {
-            // size is too big, maybe byte ordering is wrong
-            resetByteOrder = reader.isMotorolaByteOrder();
-            reader.setMotorolaByteOrder(!reader.isMotorolaByteOrder());
-            num = reader.getUInt16(tagValueOffset + 14);
-            if (byteCount < 16 + num * 6) {
-                directory.addError("Bad PrintIM size");
-                return;
-            }
-        }
-
-        directory.setObject(PrintIMDirectory.TagPrintImVersion, header.substring(8, 12));
-
-        for (int n = 0; n < num; n++) {
-            int pos = tagValueOffset + 16 + n * 6;
-            int tag = reader.getUInt16(pos);
-            long val = reader.getUInt32(pos + 2);
-
-            directory.setObject(tag, val);
-        }
-
-        if (resetByteOrder != null)
-            reader.setMotorolaByteOrder(resetByteOrder);
-    }
-
-    private static void processKodakMakernote(@NotNull final KodakMakernoteDirectory directory, final int tagValueOffset, @NotNull final RandomAccessReader reader)
-    {
-        // Kodak's makernote is not in IFD format. It has values at fixed offsets.
-        int dataOffset = tagValueOffset + 8;
-        try {
-            directory.setStringValue(KodakMakernoteDirectory.TAG_KODAK_MODEL, reader.getStringValue(dataOffset, 8, Charsets.UTF_8));
-            directory.setInt(KodakMakernoteDirectory.TAG_QUALITY, reader.getUInt8(dataOffset + 9));
-            directory.setInt(KodakMakernoteDirectory.TAG_BURST_MODE, reader.getUInt8(dataOffset + 10));
-            directory.setInt(KodakMakernoteDirectory.TAG_IMAGE_WIDTH, reader.getUInt16(dataOffset + 12));
-            directory.setInt(KodakMakernoteDirectory.TAG_IMAGE_HEIGHT, reader.getUInt16(dataOffset + 14));
-            directory.setInt(KodakMakernoteDirectory.TAG_YEAR_CREATED, reader.getUInt16(dataOffset + 16));
-            directory.setByteArray(KodakMakernoteDirectory.TAG_MONTH_DAY_CREATED, reader.getBytes(dataOffset + 18, 2));
-            directory.setByteArray(KodakMakernoteDirectory.TAG_TIME_CREATED, reader.getBytes(dataOffset + 20, 4));
-            directory.setInt(KodakMakernoteDirectory.TAG_BURST_MODE_2, reader.getUInt16(dataOffset + 24));
-            directory.setInt(KodakMakernoteDirectory.TAG_SHUTTER_MODE, reader.getUInt8(dataOffset + 27));
-            directory.setInt(KodakMakernoteDirectory.TAG_METERING_MODE, reader.getUInt8(dataOffset + 28));
-            directory.setInt(KodakMakernoteDirectory.TAG_SEQUENCE_NUMBER, reader.getUInt8(dataOffset + 29));
-            directory.setInt(KodakMakernoteDirectory.TAG_F_NUMBER, reader.getUInt16(dataOffset + 30));
-            directory.setLong(KodakMakernoteDirectory.TAG_EXPOSURE_TIME, reader.getUInt32(dataOffset + 32));
-            directory.setInt(KodakMakernoteDirectory.TAG_EXPOSURE_COMPENSATION, reader.getInt16(dataOffset + 36));
-            directory.setInt(KodakMakernoteDirectory.TAG_FOCUS_MODE, reader.getUInt8(dataOffset + 56));
-            directory.setInt(KodakMakernoteDirectory.TAG_WHITE_BALANCE, reader.getUInt8(dataOffset + 64));
-            directory.setInt(KodakMakernoteDirectory.TAG_FLASH_MODE, reader.getUInt8(dataOffset + 92));
-            directory.setInt(KodakMakernoteDirectory.TAG_FLASH_FIRED, reader.getUInt8(dataOffset + 93));
-            directory.setInt(KodakMakernoteDirectory.TAG_ISO_SETTING, reader.getUInt16(dataOffset + 94));
-            directory.setInt(KodakMakernoteDirectory.TAG_ISO, reader.getUInt16(dataOffset + 96));
-            directory.setInt(KodakMakernoteDirectory.TAG_TOTAL_ZOOM, reader.getUInt16(dataOffset + 98));
-            directory.setInt(KodakMakernoteDirectory.TAG_DATE_TIME_STAMP, reader.getUInt16(dataOffset + 100));
-            directory.setInt(KodakMakernoteDirectory.TAG_COLOR_MODE, reader.getUInt16(dataOffset + 102));
-            directory.setInt(KodakMakernoteDirectory.TAG_DIGITAL_ZOOM, reader.getUInt16(dataOffset + 104));
-            directory.setInt(KodakMakernoteDirectory.TAG_SHARPNESS, reader.getInt8(dataOffset + 107));
-        } catch (IOException ex) {
-            directory.addError("Error processing Kodak makernote data: " + ex.getMessage());
-        }
-    }
-
-    private static void processReconyxHyperFireMakernote(@NotNull final ReconyxHyperFireMakernoteDirectory directory, final int makernoteOffset, @NotNull final RandomAccessReader reader) throws IOException
-    {
-        directory.setObject(ReconyxHyperFireMakernoteDirectory.TAG_MAKERNOTE_VERSION, reader.getUInt16(makernoteOffset));
-
-        int major = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_FIRMWARE_VERSION);
-        int minor = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_FIRMWARE_VERSION + 2);
-        int revision = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_FIRMWARE_VERSION + 4);
-        String buildYear = String.format("%04X", reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_FIRMWARE_VERSION + 6));
-        String buildDate = String.format("%04X", reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_FIRMWARE_VERSION + 8));
-        String buildYearAndDate = buildYear + buildDate;
-        Integer build;
-        try {
-            build = Integer.parseInt(buildYearAndDate);
-        } catch (NumberFormatException e) {
-            build = null;
-        }
-
-        if (build != null) {
-            directory.setString(ReconyxHyperFireMakernoteDirectory.TAG_FIRMWARE_VERSION, String.format("%d.%d.%d.%s", major, minor, revision, build));
-        } else {
-            directory.setString(ReconyxHyperFireMakernoteDirectory.TAG_FIRMWARE_VERSION, String.format("%d.%d.%d", major, minor, revision));
-            directory.addError("Error processing Reconyx HyperFire makernote data: build '" + buildYearAndDate + "' is not in the expected format and will be omitted from Firmware Version.");
-        }
-
-        directory.setString(ReconyxHyperFireMakernoteDirectory.TAG_TRIGGER_MODE, String.valueOf((char)reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_TRIGGER_MODE)));
-        directory.setIntArray(ReconyxHyperFireMakernoteDirectory.TAG_SEQUENCE,
-                      new int[]
-                      {
-                          reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_SEQUENCE),
-                          reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_SEQUENCE + 2)
-                      });
-
-        int eventNumberHigh = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_EVENT_NUMBER);
-        int eventNumberLow = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_EVENT_NUMBER + 2);
-        directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_EVENT_NUMBER, (eventNumberHigh << 16) + eventNumberLow);
-
-        int seconds = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL);
-        int minutes = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL + 2);
-        int hour = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL + 4);
-        int month = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL + 6);
-        int day = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL + 8);
-        int year = reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL + 10);
-
-        if ((seconds >= 0 && seconds < 60) &&
-            (minutes >= 0 && minutes < 60) &&
-            (hour >= 0 && hour < 24) &&
-            (month >= 1 && month < 13) &&
-            (day >= 1 && day < 32) &&
-            (year >= 1 && year <= 9999)) {
-            directory.setString(ReconyxHyperFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL,
-                    String.format("%4d:%2d:%2d %2d:%2d:%2d", year, month, day, hour, minutes, seconds));
-        } else {
-            directory.addError("Error processing Reconyx HyperFire makernote data: Date/Time Original " + year + "-" + month + "-" + day + " " + hour + ":" + minutes + ":" + seconds + " is not a valid date/time.");
-        }
-
-        directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_MOON_PHASE, reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_MOON_PHASE));
-        directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_AMBIENT_TEMPERATURE_FAHRENHEIT, reader.getInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_AMBIENT_TEMPERATURE_FAHRENHEIT));
-        directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_AMBIENT_TEMPERATURE, reader.getInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_AMBIENT_TEMPERATURE));
-        //directory.setByteArray(ReconyxHyperFireMakernoteDirectory.TAG_SERIAL_NUMBER, reader.getBytes(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_SERIAL_NUMBER, 28));
-        directory.setStringValue(ReconyxHyperFireMakernoteDirectory.TAG_SERIAL_NUMBER, new StringValue(reader.getBytes(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_SERIAL_NUMBER, 28), Charsets.UTF_16LE));
-        // two unread bytes: the serial number's terminating null
-
-        directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_CONTRAST, reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_CONTRAST));
-        directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_BRIGHTNESS, reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_BRIGHTNESS));
-        directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_SHARPNESS, reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_SHARPNESS));
-        directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_SATURATION, reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_SATURATION));
-        directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_INFRARED_ILLUMINATOR, reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_INFRARED_ILLUMINATOR));
-        directory.setInt(ReconyxHyperFireMakernoteDirectory.TAG_MOTION_SENSITIVITY, reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_MOTION_SENSITIVITY));
-        directory.setDouble(ReconyxHyperFireMakernoteDirectory.TAG_BATTERY_VOLTAGE, reader.getUInt16(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_BATTERY_VOLTAGE) / 1000.0);
-        directory.setString(ReconyxHyperFireMakernoteDirectory.TAG_USER_LABEL, reader.getNullTerminatedString(makernoteOffset + ReconyxHyperFireMakernoteDirectory.TAG_USER_LABEL, 44, Charsets.UTF_8));
-    }
-
-    private static void processReconyxUltraFireMakernote(@NotNull final ReconyxUltraFireMakernoteDirectory directory, final int makernoteOffset, @NotNull final RandomAccessReader reader) throws IOException
-    {
-        directory.setString(ReconyxUltraFireMakernoteDirectory.TAG_LABEL, reader.getString(makernoteOffset, 9, Charsets.UTF_8));
-        /*uint makernoteID = ByteConvert.FromBigEndianToNative(reader.GetUInt32(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagMakernoteID));
-        directory.Set(ReconyxUltraFireMakernoteDirectory.TagMakernoteID, makernoteID);
-        if (makernoteID != ReconyxUltraFireMakernoteDirectory.MAKERNOTE_ID) {
-            directory.addError("Error processing Reconyx UltraFire makernote data: unknown Makernote ID 0x" + makernoteID.ToString("x8"));
-            return;
-        }
-        directory.Set(ReconyxUltraFireMakernoteDirectory.TagMakernoteSize, ByteConvert.FromBigEndianToNative(reader.GetUInt32(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagMakernoteSize)));
-        uint makernotePublicID = ByteConvert.FromBigEndianToNative(reader.GetUInt32(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagMakernotePublicID));
-        directory.Set(ReconyxUltraFireMakernoteDirectory.TagMakernotePublicID, makernotePublicID);
-        if (makernotePublicID != ReconyxUltraFireMakernoteDirectory.MAKERNOTE_PUBLIC_ID) {
-            directory.addError("Error processing Reconyx UltraFire makernote data: unknown Makernote Public ID 0x" + makernotePublicID.ToString("x8"));
-            return;
-        }*/
-        //directory.Set(ReconyxUltraFireMakernoteDirectory.TagMakernotePublicSize, ByteConvert.FromBigEndianToNative(reader.GetUInt16(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagMakernotePublicSize)));
-
-        //directory.Set(ReconyxUltraFireMakernoteDirectory.TagCameraVersion, ProcessReconyxUltraFireVersion(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagCameraVersion, reader));
-        //directory.Set(ReconyxUltraFireMakernoteDirectory.TagUibVersion, ProcessReconyxUltraFireVersion(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagUibVersion, reader));
-        //directory.Set(ReconyxUltraFireMakernoteDirectory.TagBtlVersion, ProcessReconyxUltraFireVersion(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagBtlVersion, reader));
-        //directory.Set(ReconyxUltraFireMakernoteDirectory.TagPexVersion, ProcessReconyxUltraFireVersion(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagPexVersion, reader));
-
-        directory.setString(ReconyxUltraFireMakernoteDirectory.TAG_EVENT_TYPE, reader.getString(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_EVENT_TYPE, 1, Charsets.UTF_8));
-        directory.setIntArray(ReconyxUltraFireMakernoteDirectory.TAG_SEQUENCE,
-                      new int[]
-                      {
-                          reader.getByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_SEQUENCE),
-                          reader.getByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_SEQUENCE + 1)
-                      });
-        //directory.Set(ReconyxUltraFireMakernoteDirectory.TagEventNumber, ByteConvert.FromBigEndianToNative(reader.GetUInt32(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagEventNumber)));
-
-        byte seconds = reader.getByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL);
-        byte minutes = reader.getByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL + 1);
-        byte hour = reader.getByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL + 2);
-        byte day = reader.getByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL + 3);
-        byte month = reader.getByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL + 4);
-        /*ushort year = ByteConvert.FromBigEndianToNative(reader.GetUInt16(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagDateTimeOriginal + 5));
-        if ((seconds >= 0 && seconds < 60) &&
-            (minutes >= 0 && minutes < 60) &&
-            (hour >= 0 && hour < 24) &&
-            (month >= 1 && month < 13) &&
-            (day >= 1 && day < 32) &&
-            (year >= 1 && year <= 9999)) {
-            directory.Set(ReconyxUltraFireMakernoteDirectory.TAG_DATE_TIME_ORIGINAL, new DateTime(year, month, day, hour, minutes, seconds, DateTimeKind.Unspecified));
-        } else {
-            directory.addError("Error processing Reconyx UltraFire makernote data: Date/Time Original " + year + "-" + month + "-" + day + " " + hour + ":" + minutes + ":" + seconds + " is not a valid date/time.");
-        }*/
-        //directory.Set(ReconyxUltraFireMakernoteDirectory.TagDayOfWeek, reader.GetByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagDayOfWeek));
-
-        directory.setInt(ReconyxUltraFireMakernoteDirectory.TAG_MOON_PHASE, reader.getByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_MOON_PHASE));
-        //directory.Set(ReconyxUltraFireMakernoteDirectory.TagAmbientTemperatureFahrenheit, ByteConvert.FromBigEndianToNative(reader.GetInt16(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagAmbientTemperatureFahrenheit)));
-        //directory.Set(ReconyxUltraFireMakernoteDirectory.TagAmbientTemperature, ByteConvert.FromBigEndianToNative(reader.GetInt16(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagAmbientTemperature)));
-
-        directory.setInt(ReconyxUltraFireMakernoteDirectory.TAG_FLASH, reader.getByte(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_FLASH));
-        //directory.Set(ReconyxUltraFireMakernoteDirectory.TagBatteryVoltage, ByteConvert.FromBigEndianToNative(reader.GetUInt16(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TagBatteryVoltage)) / 1000.0);
-        directory.setStringValue(ReconyxUltraFireMakernoteDirectory.TAG_SERIAL_NUMBER, new StringValue(reader.getBytes(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_SERIAL_NUMBER, 14), Charsets.UTF_8));
-        // unread byte: the serial number's terminating null
-        directory.setString(ReconyxUltraFireMakernoteDirectory.TAG_USER_LABEL, reader.getNullTerminatedString(makernoteOffset + ReconyxUltraFireMakernoteDirectory.TAG_USER_LABEL, 20, Charsets.UTF_8));
-    }
-}
-
Index: trunk/src/com/drew/metadata/exif/GpsDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/GpsDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,338 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.GeoLocation;
-import com.drew.lang.Rational;
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import java.text.DecimalFormat;
-
-import static com.drew.metadata.exif.GpsDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link GpsDirectory}.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class GpsDescriptor extends TagDescriptor<GpsDirectory>
-{
-    public GpsDescriptor(@NotNull GpsDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_VERSION_ID:
-                return getGpsVersionIdDescription();
-            case TAG_ALTITUDE:
-                return getGpsAltitudeDescription();
-            case TAG_ALTITUDE_REF:
-                return getGpsAltitudeRefDescription();
-            case TAG_STATUS:
-                return getGpsStatusDescription();
-            case TAG_MEASURE_MODE:
-                return getGpsMeasureModeDescription();
-            case TAG_DOP:
-                return getGpsDopDescription();
-            case TAG_SPEED_REF:
-                return getGpsSpeedRefDescription();
-            case TAG_SPEED:
-                return getGpsSpeedDescription();
-            case TAG_TRACK_REF:
-            case TAG_IMG_DIRECTION_REF:
-            case TAG_DEST_BEARING_REF:
-                return getGpsDirectionReferenceDescription(tagType);
-            case TAG_TRACK:
-            case TAG_IMG_DIRECTION:
-            case TAG_DEST_BEARING:
-                return getGpsDirectionDescription(tagType);
-            case TAG_DEST_LATITUDE:
-                return getGpsDestLatitudeDescription();
-            case TAG_DEST_LONGITUDE:
-                return getGpsDestLongitudeDescription();
-            case TAG_DEST_DISTANCE_REF:
-                return getGpsDestinationReferenceDescription();
-            case TAG_DEST_DISTANCE:
-                return getGpsDestDistanceDescription();
-            case TAG_TIME_STAMP:
-                return getGpsTimeStampDescription();
-            case TAG_LONGITUDE:
-                // three rational numbers -- displayed in HH"MM"SS.ss
-                return getGpsLongitudeDescription();
-            case TAG_LATITUDE:
-                // three rational numbers -- displayed in HH"MM"SS.ss
-                return getGpsLatitudeDescription();
-            case TAG_PROCESSING_METHOD:
-                return getGpsProcessingMethodDescription();
-            case TAG_AREA_INFORMATION:
-                return getGpsAreaInformationDescription();
-            case TAG_DIFFERENTIAL:
-                return getGpsDifferentialDescription();
-            case TAG_H_POSITIONING_ERROR:
-                return getGpsHPositioningErrorDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    private String getGpsVersionIdDescription()
-    {
-        return getVersionBytesDescription(TAG_VERSION_ID, 1);
-    }
-
-    @Nullable
-    public String getGpsLatitudeDescription()
-    {
-        GeoLocation location = _directory.getGeoLocation();
-        return location == null ? null : GeoLocation.decimalToDegreesMinutesSecondsString(location.getLatitude());
-    }
-
-    @Nullable
-    public String getGpsLongitudeDescription()
-    {
-        GeoLocation location = _directory.getGeoLocation();
-        return location == null ? null : GeoLocation.decimalToDegreesMinutesSecondsString(location.getLongitude());
-    }
-
-    @Nullable
-    public String getGpsTimeStampDescription()
-    {
-        // time in hour, min, sec
-        Rational[] timeComponents = _directory.getRationalArray(TAG_TIME_STAMP);
-        DecimalFormat df = new DecimalFormat("00.000");
-        return timeComponents == null
-            ? null
-            : String.format("%02d:%02d:%s UTC",
-                timeComponents[0].intValue(),
-                timeComponents[1].intValue(),
-                df.format(timeComponents[2].doubleValue()));
-    }
-
-    @Nullable
-    public String getGpsDestLatitudeDescription()
-    {
-        Rational[] latitudes = _directory.getRationalArray(TAG_DEST_LATITUDE);
-        String latitudeRef = _directory.getString(TAG_DEST_LATITUDE_REF);
-
-        if (latitudes == null || latitudes.length != 3 || latitudeRef == null)
-            return null;
-
-        Double lat = GeoLocation.degreesMinutesSecondsToDecimal(
-            latitudes[0], latitudes[1], latitudes[2], latitudeRef.equalsIgnoreCase("S"));
-
-        return lat == null ? null : GeoLocation.decimalToDegreesMinutesSecondsString(lat);
-    }
-
-    @Nullable
-    public String getGpsDestLongitudeDescription()
-    {
-        Rational[] longitudes = _directory.getRationalArray(TAG_LONGITUDE);
-        String longitudeRef = _directory.getString(TAG_LONGITUDE_REF);
-
-        if (longitudes == null || longitudes.length != 3 || longitudeRef == null)
-            return null;
-
-        Double lon = GeoLocation.degreesMinutesSecondsToDecimal(
-            longitudes[0], longitudes[1], longitudes[2], longitudeRef.equalsIgnoreCase("W"));
-
-        return lon == null ? null : GeoLocation.decimalToDegreesMinutesSecondsString(lon);
-    }
-
-    @Nullable
-    public String getGpsDestinationReferenceDescription()
-    {
-        final String value = _directory.getString(TAG_DEST_DISTANCE_REF);
-        if (value == null)
-            return null;
-        String distanceRef = value.trim();
-        if ("K".equalsIgnoreCase(distanceRef)) {
-            return "kilometers";
-        } else if ("M".equalsIgnoreCase(distanceRef)) {
-            return "miles";
-        } else if ("N".equalsIgnoreCase(distanceRef)) {
-            return "knots";
-        } else {
-            return "Unknown (" + distanceRef + ")";
-        }
-    }
-
-    @Nullable
-    public String getGpsDestDistanceDescription()
-    {
-        final Rational value = _directory.getRational(TAG_DEST_DISTANCE);
-        if (value == null)
-            return null;
-        final String unit = getGpsDestinationReferenceDescription();
-        return String.format("%s %s",
-            new DecimalFormat("0.##").format(value.doubleValue()),
-            unit == null ? "unit" : unit.toLowerCase());
-    }
-
-    @Nullable
-    public String getGpsDirectionDescription(int tagType)
-    {
-        Rational angle = _directory.getRational(tagType);
-        // provide a decimal version of rational numbers in the description, to avoid strings like "35334/199 degrees"
-        String value = angle != null
-            ? new DecimalFormat("0.##").format(angle.doubleValue())
-            : _directory.getString(tagType);
-        return value == null || value.trim().length() == 0 ? null : value.trim() + " degrees";
-    }
-
-    @Nullable
-    public String getGpsDirectionReferenceDescription(int tagType)
-    {
-        final String value = _directory.getString(tagType);
-        if (value == null)
-            return null;
-        String gpsDistRef = value.trim();
-        if ("T".equalsIgnoreCase(gpsDistRef)) {
-            return "True direction";
-        } else if ("M".equalsIgnoreCase(gpsDistRef)) {
-            return "Magnetic direction";
-        } else {
-            return "Unknown (" + gpsDistRef + ")";
-        }
-    }
-
-    @Nullable
-    public String getGpsDopDescription()
-    {
-        final Rational value = _directory.getRational(TAG_DOP);
-        return value == null ? null : new DecimalFormat("0.##").format(value.doubleValue());
-    }
-
-    @Nullable
-    public String getGpsSpeedRefDescription()
-    {
-        final String value = _directory.getString(TAG_SPEED_REF);
-        if (value == null)
-            return null;
-        String gpsSpeedRef = value.trim();
-        if ("K".equalsIgnoreCase(gpsSpeedRef)) {
-            return "km/h";
-        } else if ("M".equalsIgnoreCase(gpsSpeedRef)) {
-            return "mph";
-        } else if ("N".equalsIgnoreCase(gpsSpeedRef)) {
-            return "knots";
-        } else {
-            return "Unknown (" + gpsSpeedRef + ")";
-        }
-    }
-
-    @Nullable
-    public String getGpsSpeedDescription()
-    {
-        final Rational value = _directory.getRational(TAG_SPEED);
-        if (value == null)
-            return null;
-        final String unit = getGpsSpeedRefDescription();
-        return String.format("%s %s",
-            new DecimalFormat("0.##").format(value.doubleValue()),
-            unit == null ? "unit" : unit.toLowerCase());
-    }
-
-    @Nullable
-    public String getGpsMeasureModeDescription()
-    {
-        final String value = _directory.getString(TAG_MEASURE_MODE);
-        if (value == null)
-            return null;
-        String gpsSpeedMeasureMode = value.trim();
-        if ("2".equalsIgnoreCase(gpsSpeedMeasureMode)) {
-            return "2-dimensional measurement";
-        } else if ("3".equalsIgnoreCase(gpsSpeedMeasureMode)) {
-            return "3-dimensional measurement";
-        } else {
-            return "Unknown (" + gpsSpeedMeasureMode + ")";
-        }
-    }
-
-    @Nullable
-    public String getGpsStatusDescription()
-    {
-        final String value = _directory.getString(TAG_STATUS);
-        if (value == null)
-            return null;
-        String gpsStatus = value.trim();
-        if ("A".equalsIgnoreCase(gpsStatus)) {
-            return "Active (Measurement in progress)";
-        } else if ("V".equalsIgnoreCase(gpsStatus)) {
-            return "Void (Measurement Interoperability)";
-        } else {
-            return "Unknown (" + gpsStatus + ")";
-        }
-    }
-
-    @Nullable
-    public String getGpsAltitudeRefDescription()
-    {
-        return getIndexedDescription(TAG_ALTITUDE_REF, "Sea level", "Below sea level");
-    }
-
-    @Nullable
-    public String getGpsAltitudeDescription()
-    {
-        final Rational value = _directory.getRational(TAG_ALTITUDE);
-        return value == null ? null : new DecimalFormat("0.##").format(value.doubleValue()) + " metres";
-    }
-
-    @Nullable
-    public String getGpsProcessingMethodDescription()
-    {
-        return getEncodedTextDescription(TAG_PROCESSING_METHOD);
-    }
-
-    @Nullable
-    public String getGpsAreaInformationDescription()
-    {
-        return getEncodedTextDescription(TAG_AREA_INFORMATION);
-    }
-
-    @Nullable
-    public String getGpsDifferentialDescription()
-    {
-        return getIndexedDescription(TAG_DIFFERENTIAL, "No Correction", "Differential Corrected");
-    }
-
-    @Nullable
-    public String getGpsHPositioningErrorDescription()
-    {
-        final Rational value = _directory.getRational(TAG_H_POSITIONING_ERROR);
-        return value == null ? null : new DecimalFormat("0.##").format(value.doubleValue()) + " metres";
-    }
-
-    @Nullable
-    public String getDegreesMinutesSecondsDescription()
-    {
-        GeoLocation location = _directory.getGeoLocation();
-        return location == null ? null : location.toDMSString();
-    }
-}
Index: trunk/src/com/drew/metadata/exif/GpsDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/GpsDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,227 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.GeoLocation;
-import com.drew.lang.Rational;
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Locale;
-
-/**
- * Describes Exif tags that contain Global Positioning System (GPS) data.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class GpsDirectory extends ExifDirectoryBase
-{
-    /** GPS tag version GPSVersionID 0 0 BYTE 4 */
-    public static final int TAG_VERSION_ID = 0x0000;
-    /** North or South Latitude GPSLatitudeRef 1 1 ASCII 2 */
-    public static final int TAG_LATITUDE_REF = 0x0001;
-    /** Latitude GPSLatitude 2 2 RATIONAL 3 */
-    public static final int TAG_LATITUDE = 0x0002;
-    /** East or West Longitude GPSLongitudeRef 3 3 ASCII 2 */
-    public static final int TAG_LONGITUDE_REF = 0x0003;
-    /** Longitude GPSLongitude 4 4 RATIONAL 3 */
-    public static final int TAG_LONGITUDE = 0x0004;
-    /** Altitude reference GPSAltitudeRef 5 5 BYTE 1 */
-    public static final int TAG_ALTITUDE_REF = 0x0005;
-    /** Altitude GPSAltitude 6 6 RATIONAL 1 */
-    public static final int TAG_ALTITUDE = 0x0006;
-    /** GPS time (atomic clock) GPSTimeStamp 7 7 RATIONAL 3 */
-    public static final int TAG_TIME_STAMP = 0x0007;
-    /** GPS satellites used for measurement GPSSatellites 8 8 ASCII Any */
-    public static final int TAG_SATELLITES = 0x0008;
-    /** GPS receiver status GPSStatus 9 9 ASCII 2 */
-    public static final int TAG_STATUS = 0x0009;
-    /** GPS measurement mode GPSMeasureMode 10 A ASCII 2 */
-    public static final int TAG_MEASURE_MODE = 0x000A;
-    /** Measurement precision GPSDOP 11 B RATIONAL 1 */
-    public static final int TAG_DOP = 0x000B;
-    /** Speed unit GPSSpeedRef 12 C ASCII 2 */
-    public static final int TAG_SPEED_REF = 0x000C;
-    /** Speed of GPS receiver GPSSpeed 13 D RATIONAL 1 */
-    public static final int TAG_SPEED = 0x000D;
-    /** Reference for direction of movement GPSTrackRef 14 E ASCII 2 */
-    public static final int TAG_TRACK_REF = 0x000E;
-    /** Direction of movement GPSTrack 15 F RATIONAL 1 */
-    public static final int TAG_TRACK = 0x000F;
-    /** Reference for direction of image GPSImgDirectionRef 16 10 ASCII 2 */
-    public static final int TAG_IMG_DIRECTION_REF = 0x0010;
-    /** Direction of image GPSImgDirection 17 11 RATIONAL 1 */
-    public static final int TAG_IMG_DIRECTION = 0x0011;
-    /** Geodetic survey data used GPSMapDatum 18 12 ASCII Any */
-    public static final int TAG_MAP_DATUM = 0x0012;
-    /** Reference for latitude of destination GPSDestLatitudeRef 19 13 ASCII 2 */
-    public static final int TAG_DEST_LATITUDE_REF = 0x0013;
-    /** Latitude of destination GPSDestLatitude 20 14 RATIONAL 3 */
-    public static final int TAG_DEST_LATITUDE = 0x0014;
-    /** Reference for longitude of destination GPSDestLongitudeRef 21 15 ASCII 2 */
-    public static final int TAG_DEST_LONGITUDE_REF = 0x0015;
-    /** Longitude of destination GPSDestLongitude 22 16 RATIONAL 3 */
-    public static final int TAG_DEST_LONGITUDE = 0x0016;
-    /** Reference for bearing of destination GPSDestBearingRef 23 17 ASCII 2 */
-    public static final int TAG_DEST_BEARING_REF = 0x0017;
-    /** Bearing of destination GPSDestBearing 24 18 RATIONAL 1 */
-    public static final int TAG_DEST_BEARING = 0x0018;
-    /** Reference for distance to destination GPSDestDistanceRef 25 19 ASCII 2 */
-    public static final int TAG_DEST_DISTANCE_REF = 0x0019;
-    /** Distance to destination GPSDestDistance 26 1A RATIONAL 1 */
-    public static final int TAG_DEST_DISTANCE = 0x001A;
-    /** Name of the method used for location finding GPSProcessingMethod 27 1B UNDEFINED Any */
-    public static final int TAG_PROCESSING_METHOD = 0x001B;
-    /** Name of the GPS area GPSAreaInformation 28 1C UNDEFINED Any */
-    public static final int TAG_AREA_INFORMATION = 0x001C;
-    /** Date and time GPSDateStamp 29 1D ASCII 11 */
-    public static final int TAG_DATE_STAMP = 0x001D;
-    /** Whether differential correction is applied GPSDifferential 30 1E SHORT 1 */
-    public static final int TAG_DIFFERENTIAL = 0x001E;
-    /** Horizontal positioning errors GPSHPositioningError 31 1F RATIONAL 1 */
-    public static final int TAG_H_POSITIONING_ERROR = 0x001F;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        addExifTagNames(_tagNameMap);
-
-        _tagNameMap.put(TAG_VERSION_ID, "GPS Version ID");
-        _tagNameMap.put(TAG_LATITUDE_REF, "GPS Latitude Ref");
-        _tagNameMap.put(TAG_LATITUDE, "GPS Latitude");
-        _tagNameMap.put(TAG_LONGITUDE_REF, "GPS Longitude Ref");
-        _tagNameMap.put(TAG_LONGITUDE, "GPS Longitude");
-        _tagNameMap.put(TAG_ALTITUDE_REF, "GPS Altitude Ref");
-        _tagNameMap.put(TAG_ALTITUDE, "GPS Altitude");
-        _tagNameMap.put(TAG_TIME_STAMP, "GPS Time-Stamp");
-        _tagNameMap.put(TAG_SATELLITES, "GPS Satellites");
-        _tagNameMap.put(TAG_STATUS, "GPS Status");
-        _tagNameMap.put(TAG_MEASURE_MODE, "GPS Measure Mode");
-        _tagNameMap.put(TAG_DOP, "GPS DOP");
-        _tagNameMap.put(TAG_SPEED_REF, "GPS Speed Ref");
-        _tagNameMap.put(TAG_SPEED, "GPS Speed");
-        _tagNameMap.put(TAG_TRACK_REF, "GPS Track Ref");
-        _tagNameMap.put(TAG_TRACK, "GPS Track");
-        _tagNameMap.put(TAG_IMG_DIRECTION_REF, "GPS Img Direction Ref");
-        _tagNameMap.put(TAG_IMG_DIRECTION, "GPS Img Direction");
-        _tagNameMap.put(TAG_MAP_DATUM, "GPS Map Datum");
-        _tagNameMap.put(TAG_DEST_LATITUDE_REF, "GPS Dest Latitude Ref");
-        _tagNameMap.put(TAG_DEST_LATITUDE, "GPS Dest Latitude");
-        _tagNameMap.put(TAG_DEST_LONGITUDE_REF, "GPS Dest Longitude Ref");
-        _tagNameMap.put(TAG_DEST_LONGITUDE, "GPS Dest Longitude");
-        _tagNameMap.put(TAG_DEST_BEARING_REF, "GPS Dest Bearing Ref");
-        _tagNameMap.put(TAG_DEST_BEARING, "GPS Dest Bearing");
-        _tagNameMap.put(TAG_DEST_DISTANCE_REF, "GPS Dest Distance Ref");
-        _tagNameMap.put(TAG_DEST_DISTANCE, "GPS Dest Distance");
-        _tagNameMap.put(TAG_PROCESSING_METHOD, "GPS Processing Method");
-        _tagNameMap.put(TAG_AREA_INFORMATION, "GPS Area Information");
-        _tagNameMap.put(TAG_DATE_STAMP, "GPS Date Stamp");
-        _tagNameMap.put(TAG_DIFFERENTIAL, "GPS Differential");
-        _tagNameMap.put(TAG_H_POSITIONING_ERROR, "GPS H Positioning Error");
-    }
-
-    public GpsDirectory()
-    {
-        this.setDescriptor(new GpsDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "GPS";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-
-    /**
-     * Parses various tags in an attempt to obtain a single object representing the latitude and longitude
-     * at which this image was captured.
-     *
-     * @return The geographical location of this image, if possible, otherwise null
-     */
-    @Nullable
-    public GeoLocation getGeoLocation()
-    {
-        Rational[] latitudes = getRationalArray(TAG_LATITUDE);
-        Rational[] longitudes = getRationalArray(TAG_LONGITUDE);
-        String latitudeRef = getString(TAG_LATITUDE_REF);
-        String longitudeRef = getString(TAG_LONGITUDE_REF);
-
-        // Make sure we have the required values
-        if (latitudes == null || latitudes.length != 3)
-            return null;
-        if (longitudes == null || longitudes.length != 3)
-            return null;
-        if (latitudeRef == null || longitudeRef == null)
-            return null;
-
-        Double lat = GeoLocation.degreesMinutesSecondsToDecimal(latitudes[0], latitudes[1], latitudes[2], latitudeRef.equalsIgnoreCase("S"));
-        Double lon = GeoLocation.degreesMinutesSecondsToDecimal(longitudes[0], longitudes[1], longitudes[2], longitudeRef.equalsIgnoreCase("W"));
-
-        // This can return null, in cases where the conversion was not possible
-        if (lat == null || lon == null)
-            return null;
-
-        return new GeoLocation(lat, lon);
-    }
-
-    /**
-     * Parses the date stamp tag and the time stamp tag to obtain a single Date object representing the
-     * date and time when this image was captured.
-     *
-     * @return A Date object representing when this image was captured, if possible, otherwise null
-     */
-    @Nullable
-    public Date getGpsDate()
-    {
-        String date = getString(TAG_DATE_STAMP);
-        Rational[] timeComponents = getRationalArray(TAG_TIME_STAMP);
-
-        // Make sure we have the required values
-        if (date == null)
-            return null;
-        if (timeComponents == null || timeComponents.length != 3)
-            return null;
-
-        String dateTime = String.format(Locale.US, "%s %02d:%02d:%02.3f UTC",
-            date, timeComponents[0].intValue(), timeComponents[1].intValue(), timeComponents[2].doubleValue());
-        try {
-            DateFormat parser = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss.S z");
-            return parser.parse(dateTime);
-        } catch (ParseException e) {
-            return null;
-        }
-    }
-}
Index: trunk/src/com/drew/metadata/exif/PanasonicRawDistortionDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/PanasonicRawDistortionDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,159 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.Rational;
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.PanasonicRawDistortionDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link PanasonicRawDistortionDirectory}.
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class PanasonicRawDistortionDescriptor extends TagDescriptor<PanasonicRawDistortionDirectory>
-{
-    public PanasonicRawDistortionDescriptor(@NotNull PanasonicRawDistortionDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TagDistortionParam02:
-                return getDistortionParam02Description();
-            case TagDistortionParam04:
-                return getDistortionParam04Description();
-            case TagDistortionScale:
-                return getDistortionScaleDescription();
-            case TagDistortionCorrection:
-                return getDistortionCorrectionDescription();
-            case TagDistortionParam08:
-                return getDistortionParam08Description();
-            case TagDistortionParam09:
-                return getDistortionParam09Description();
-            case TagDistortionParam11:
-                return getDistortionParam11Description();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getWbTypeDescription(int tagType)
-    {
-        Integer wbtype = _directory.getInteger(tagType);
-        if (wbtype == null)
-            return null;
-
-        return super.getLightSourceDescription(wbtype.shortValue());
-    }
-
-    @Nullable
-    public String getDistortionParam02Description()
-    {
-        Integer value = _directory.getInteger(TagDistortionParam02);
-        if (value == null)
-            return null;
-
-        return new Rational(value, 32678).toString();
-    }
-
-    @Nullable
-    public String getDistortionParam04Description()
-    {
-        Integer value = _directory.getInteger(TagDistortionParam04);
-        if (value == null)
-            return null;
-
-        return new Rational(value, 32678).toString();
-    }
-
-    @Nullable
-    public String getDistortionScaleDescription()
-    {
-        Integer value = _directory.getInteger(TagDistortionScale);
-        if (value == null)
-            return null;
-
-        //return (1 / (1 + value / 32768)).toString();
-        return Integer.toString(1 / (1 + value / 32768));
-    }
-
-    @Nullable
-    public String getDistortionCorrectionDescription()
-    {
-        Integer value = _directory.getInteger(TagDistortionCorrection);
-        if (value == null)
-            return null;
-
-        // (have seen the upper 4 bits set for GF5 and GX1, giving a value of -4095 - PH)
-        int mask = 0x000f;
-        switch (value & mask)
-        {
-            case 0:
-                return "Off";
-            case 1:
-                return "On";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getDistortionParam08Description()
-    {
-        Integer value = _directory.getInteger(TagDistortionParam08);
-        if (value == null)
-            return null;
-
-        return new Rational(value, 32678).toString();
-    }
-
-    @Nullable
-    public String getDistortionParam09Description()
-    {
-        Integer value = _directory.getInteger(TagDistortionParam09);
-        if (value == null)
-            return null;
-
-        return new Rational(value, 32678).toString();
-    }
-
-    @Nullable
-    public String getDistortionParam11Description()
-    {
-        Integer value = _directory.getInteger(TagDistortionParam11);
-        if (value == null)
-            return null;
-
-        return new Rational(value, 32678).toString();
-    }
-}
Index: trunk/src/com/drew/metadata/exif/PanasonicRawDistortionDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/PanasonicRawDistortionDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,86 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * These tags can be found in Panasonic/Leica RAW, RW2 and RWL images. The index values are 'fake' but
- * chosen specifically to make processing easier
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class PanasonicRawDistortionDirectory extends Directory
-{
-    // 0 and 1 are checksums
-
-    public static final int TagDistortionParam02 = 2;
-
-    public static final int TagDistortionParam04 = 4;
-    public static final int TagDistortionScale = 5;
-
-    public static final int TagDistortionCorrection = 7;
-    public static final int TagDistortionParam08 = 8;
-    public static final int TagDistortionParam09 = 9;
-
-    public static final int TagDistortionParam11 = 11;
-    public static final int TagDistortionN = 12;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TagDistortionParam02, "Distortion Param 2");
-        _tagNameMap.put(TagDistortionParam04, "Distortion Param 4");
-        _tagNameMap.put(TagDistortionScale, "Distortion Scale");
-        _tagNameMap.put(TagDistortionCorrection, "Distortion Correction");
-        _tagNameMap.put(TagDistortionParam08, "Distortion Param 8");
-        _tagNameMap.put(TagDistortionParam09, "Distortion Param 9");
-        _tagNameMap.put(TagDistortionParam11, "Distortion Param 11");
-        _tagNameMap.put(TagDistortionN, "Distortion N");
-    }
-
-    public PanasonicRawDistortionDirectory()
-    {
-        this.setDescriptor(new PanasonicRawDistortionDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "PanasonicRaw DistortionInfo";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/PanasonicRawIFD0Descriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/PanasonicRawIFD0Descriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,58 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.PanasonicRawIFD0Directory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link PanasonicRawIFD0Directory}.
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class PanasonicRawIFD0Descriptor extends TagDescriptor<PanasonicRawIFD0Directory>
-{
-    public PanasonicRawIFD0Descriptor(@NotNull PanasonicRawIFD0Directory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType)
-        {
-            case TagPanasonicRawVersion:
-                return getVersionBytesDescription(TagPanasonicRawVersion, 2);
-            case TagOrientation:
-                return getOrientationDescription(TagOrientation);
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-}
Index: trunk/src/com/drew/metadata/exif/PanasonicRawIFD0Directory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/PanasonicRawIFD0Directory.java	(revision 15217)
+++ 	(revision )
@@ -1,153 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * These tags are found in IFD0 of Panasonic/Leica RAW, RW2 and RWL images.
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class PanasonicRawIFD0Directory extends Directory
-{
-    public static final int TagPanasonicRawVersion = 0x0001;
-    public static final int TagSensorWidth = 0x0002;
-    public static final int TagSensorHeight = 0x0003;
-    public static final int TagSensorTopBorder = 0x0004;
-    public static final int TagSensorLeftBorder = 0x0005;
-    public static final int TagSensorBottomBorder = 0x0006;
-    public static final int TagSensorRightBorder = 0x0007;
-
-    public static final int TagBlackLevel1 = 0x0008;
-    public static final int TagBlackLevel2 = 0x0009;
-    public static final int TagBlackLevel3 = 0x000a;
-    public static final int TagLinearityLimitRed = 0x000e;
-    public static final int TagLinearityLimitGreen = 0x000f;
-    public static final int TagLinearityLimitBlue = 0x0010;
-    public static final int TagRedBalance = 0x0011;
-    public static final int TagBlueBalance = 0x0012;
-    public static final int TagWbInfo = 0x0013;
-
-    public static final int TagIso = 0x0017;
-    public static final int TagHighIsoMultiplierRed = 0x0018;
-    public static final int TagHighIsoMultiplierGreen = 0x0019;
-    public static final int TagHighIsoMultiplierBlue = 0x001a;
-    public static final int TagBlackLevelRed = 0x001c;
-    public static final int TagBlackLevelGreen = 0x001d;
-    public static final int TagBlackLevelBlue = 0x001e;
-    public static final int TagWbRedLevel = 0x0024;
-    public static final int TagWbGreenLevel = 0x0025;
-    public static final int TagWbBlueLevel = 0x0026;
-
-    public static final int TagWbInfo2 = 0x0027;
-
-    public static final int TagJpgFromRaw = 0x002e;
-
-    public static final int TagCropTop = 0x002f;
-    public static final int TagCropLeft = 0x0030;
-    public static final int TagCropBottom = 0x0031;
-    public static final int TagCropRight = 0x0032;
-
-    public static final int TagMake = 0x010f;
-    public static final int TagModel = 0x0110;
-    public static final int TagStripOffsets = 0x0111;
-    public static final int TagOrientation = 0x0112;
-    public static final int TagRowsPerStrip = 0x0116;
-    public static final int TagStripByteCounts = 0x0117;
-    public static final int TagRawDataOffset = 0x0118;
-
-    public static final int TagDistortionInfo = 0x0119;
-
-    public PanasonicRawIFD0Directory()
-    {
-        this.setDescriptor(new PanasonicRawIFD0Descriptor(this));
-    }
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TagPanasonicRawVersion, "Panasonic Raw Version");
-        _tagNameMap.put(TagSensorWidth, "Sensor Width");
-        _tagNameMap.put(TagSensorHeight, "Sensor Height");
-        _tagNameMap.put(TagSensorTopBorder, "Sensor Top Border");
-        _tagNameMap.put(TagSensorLeftBorder, "Sensor Left Border");
-        _tagNameMap.put(TagSensorBottomBorder, "Sensor Bottom Border");
-        _tagNameMap.put(TagSensorRightBorder, "Sensor Right Border");
-
-        _tagNameMap.put(TagBlackLevel1, "Black Level 1");
-        _tagNameMap.put(TagBlackLevel2, "Black Level 2");
-        _tagNameMap.put(TagBlackLevel3, "Black Level 3");
-        _tagNameMap.put(TagLinearityLimitRed, "Linearity Limit Red");
-        _tagNameMap.put(TagLinearityLimitGreen, "Linearity Limit Green");
-        _tagNameMap.put(TagLinearityLimitBlue, "Linearity Limit Blue");
-        _tagNameMap.put(TagRedBalance, "Red Balance");
-        _tagNameMap.put(TagBlueBalance, "Blue Balance");
-
-        _tagNameMap.put(TagIso, "ISO");
-        _tagNameMap.put(TagHighIsoMultiplierRed, "High ISO Multiplier Red");
-        _tagNameMap.put(TagHighIsoMultiplierGreen, "High ISO Multiplier Green");
-        _tagNameMap.put(TagHighIsoMultiplierBlue, "High ISO Multiplier Blue");
-        _tagNameMap.put(TagBlackLevelRed, "Black Level Red");
-        _tagNameMap.put(TagBlackLevelGreen, "Black Level Green");
-        _tagNameMap.put(TagBlackLevelBlue, "Black Level Blue");
-        _tagNameMap.put(TagWbRedLevel, "WB Red Level");
-        _tagNameMap.put(TagWbGreenLevel, "WB Green Level");
-        _tagNameMap.put(TagWbBlueLevel, "WB Blue Level");
-
-        _tagNameMap.put(TagJpgFromRaw, "Jpg From Raw");
-
-        _tagNameMap.put(TagCropTop, "Crop Top");
-        _tagNameMap.put(TagCropLeft, "Crop Left");
-        _tagNameMap.put(TagCropBottom, "Crop Bottom");
-        _tagNameMap.put(TagCropRight, "Crop Right");
-
-        _tagNameMap.put(TagMake, "Make");
-        _tagNameMap.put(TagModel, "Model");
-        _tagNameMap.put(TagStripOffsets, "Strip Offsets");
-        _tagNameMap.put(TagOrientation, "Orientation");
-        _tagNameMap.put(TagRowsPerStrip, "Rows Per Strip");
-        _tagNameMap.put(TagStripByteCounts, "Strip Byte Counts");
-        _tagNameMap.put(TagRawDataOffset, "Raw Data Offset");
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "PanasonicRaw Exif IFD0";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/PanasonicRawWbInfo2Descriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/PanasonicRawWbInfo2Descriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,71 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.PanasonicRawWbInfo2Directory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link PanasonicRawWbInfo2Directory}.
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class PanasonicRawWbInfo2Descriptor extends TagDescriptor<PanasonicRawWbInfo2Directory>
-{
-    public PanasonicRawWbInfo2Descriptor(@NotNull PanasonicRawWbInfo2Directory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TagWbType1:
-            case TagWbType2:
-            case TagWbType3:
-            case TagWbType4:
-            case TagWbType5:
-            case TagWbType6:
-            case TagWbType7:
-                return getWbTypeDescription(tagType);
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getWbTypeDescription(int tagType)
-    {
-        Integer wbtype = _directory.getInteger(tagType);
-        if (wbtype == null)
-            return null;
-
-        return super.getLightSourceDescription(wbtype.shortValue());
-    }
-}
Index: trunk/src/com/drew/metadata/exif/PanasonicRawWbInfo2Directory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/PanasonicRawWbInfo2Directory.java	(revision 15217)
+++ 	(revision )
@@ -1,103 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * These tags can be found in Panasonic/Leica RAW, RW2 and RWL images. The index values are 'fake' but
- * chosen specifically to make processing easier
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class PanasonicRawWbInfo2Directory extends Directory
-{
-    public static final int TagNumWbEntries = 0;
-
-    public static final int TagWbType1 = 1;
-    public static final int TagWbRgbLevels1 = 2;
-
-    public static final int TagWbType2 = 5;
-    public static final int TagWbRgbLevels2 = 6;
-
-    public static final int TagWbType3 = 9;
-    public static final int TagWbRgbLevels3 = 10;
-
-    public static final int TagWbType4 = 13;
-    public static final int TagWbRgbLevels4 = 14;
-
-    public static final int TagWbType5 = 17;
-    public static final int TagWbRgbLevels5 = 18;
-
-    public static final int TagWbType6 = 21;
-    public static final int TagWbRgbLevels6 = 22;
-
-    public static final int TagWbType7 = 25;
-    public static final int TagWbRgbLevels7 = 26;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TagNumWbEntries, "Num WB Entries");
-        _tagNameMap.put(TagNumWbEntries, "Num WB Entries");
-        _tagNameMap.put(TagWbType1, "WB Type 1");
-        _tagNameMap.put(TagWbRgbLevels1, "WB RGB Levels 1");
-        _tagNameMap.put(TagWbType2, "WB Type 2");
-        _tagNameMap.put(TagWbRgbLevels2, "WB RGB Levels 2");
-        _tagNameMap.put(TagWbType3, "WB Type 3");
-        _tagNameMap.put(TagWbRgbLevels3, "WB RGB Levels 3");
-        _tagNameMap.put(TagWbType4, "WB Type 4");
-        _tagNameMap.put(TagWbRgbLevels4, "WB RGB Levels 4");
-        _tagNameMap.put(TagWbType5, "WB Type 5");
-        _tagNameMap.put(TagWbRgbLevels5, "WB RGB Levels 5");
-        _tagNameMap.put(TagWbType6, "WB Type 6");
-        _tagNameMap.put(TagWbRgbLevels6, "WB RGB Levels 6");
-        _tagNameMap.put(TagWbType7, "WB Type 7");
-        _tagNameMap.put(TagWbRgbLevels7, "WB RGB Levels 7");
-    }
-
-    public PanasonicRawWbInfo2Directory()
-    {
-        this.setDescriptor(new PanasonicRawWbInfo2Descriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "PanasonicRaw WbInfo2";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/PanasonicRawWbInfoDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/PanasonicRawWbInfoDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,71 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.PanasonicRawWbInfoDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link PanasonicRawWbInfoDirectory}.
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class PanasonicRawWbInfoDescriptor extends TagDescriptor<PanasonicRawWbInfoDirectory>
-{
-    public PanasonicRawWbInfoDescriptor(@NotNull PanasonicRawWbInfoDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TagWbType1:
-            case TagWbType2:
-            case TagWbType3:
-            case TagWbType4:
-            case TagWbType5:
-            case TagWbType6:
-            case TagWbType7:
-                return getWbTypeDescription(tagType);
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getWbTypeDescription(int tagType)
-    {
-        Integer wbtype = _directory.getInteger(tagType);
-        if (wbtype == null)
-            return null;
-
-        return super.getLightSourceDescription(wbtype.shortValue());
-    }
-}
Index: trunk/src/com/drew/metadata/exif/PanasonicRawWbInfoDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/PanasonicRawWbInfoDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,102 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * These tags can be found in Panasonic/Leica RAW, RW2 and RWL images. The index values are 'fake' but
- * chosen specifically to make processing easier
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class PanasonicRawWbInfoDirectory extends Directory
-{
-    public static final int TagNumWbEntries = 0;
-
-    public static final int TagWbType1 = 1;
-    public static final int TagWbRbLevels1 = 2;
-
-    public static final int TagWbType2 = 4;
-    public static final int TagWbRbLevels2 = 5;
-
-    public static final int TagWbType3 = 7;
-    public static final int TagWbRbLevels3 = 8;
-
-    public static final int TagWbType4 = 10;
-    public static final int TagWbRbLevels4 = 11;
-
-    public static final int TagWbType5 = 13;
-    public static final int TagWbRbLevels5 = 14;
-
-    public static final int TagWbType6 = 16;
-    public static final int TagWbRbLevels6 = 17;
-
-    public static final int TagWbType7 = 19;
-    public static final int TagWbRbLevels7 = 20;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TagNumWbEntries, "Num WB Entries");
-        _tagNameMap.put(TagWbType1, "WB Type 1");
-        _tagNameMap.put(TagWbRbLevels1, "WB RGB Levels 1");
-        _tagNameMap.put(TagWbType2, "WB Type 2");
-        _tagNameMap.put(TagWbRbLevels2, "WB RGB Levels 2");
-        _tagNameMap.put(TagWbType3, "WB Type 3");
-        _tagNameMap.put(TagWbRbLevels3, "WB RGB Levels 3");
-        _tagNameMap.put(TagWbType4, "WB Type 4");
-        _tagNameMap.put(TagWbRbLevels4, "WB RGB Levels 4");
-        _tagNameMap.put(TagWbType5, "WB Type 5");
-        _tagNameMap.put(TagWbRbLevels5, "WB RGB Levels 5");
-        _tagNameMap.put(TagWbType6, "WB Type 6");
-        _tagNameMap.put(TagWbRbLevels6, "WB RGB Levels 6");
-        _tagNameMap.put(TagWbType7, "WB Type 7");
-        _tagNameMap.put(TagWbRbLevels7, "WB RGB Levels 7");
-    }
-
-    public PanasonicRawWbInfoDirectory()
-    {
-        this.setDescriptor(new PanasonicRawWbInfoDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "PanasonicRaw WbInfo";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/PrintIMDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/PrintIMDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,58 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.PrintIMDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link PrintIMDirectory}.
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class PrintIMDescriptor extends TagDescriptor<PrintIMDirectory>
-{
-    public PrintIMDescriptor(@NotNull PrintIMDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TagPrintImVersion:
-                return super.getDescription(tagType);
-            default:
-                Integer value = _directory.getInteger(tagType);
-                if (value == null)
-                    return null;
-                return String.format("0x%08x", value);
-        }
-    }
-}
Index: trunk/src/com/drew/metadata/exif/PrintIMDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/PrintIMDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,67 +1,0 @@
-/*
- * 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
- *
- *        http://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;
-
-import com.drew.lang.annotations.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * These tags can be found in Epson proprietary metadata. The index values are 'fake' but
- * chosen specifically to make processing easier
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class PrintIMDirectory extends Directory
-{
-    public static final int TagPrintImVersion = 0x0000;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TagPrintImVersion, "PrintIM Version");
-    }
-
-    public PrintIMDirectory()
-    {
-        this.setDescriptor(new PrintIMDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "PrintIM";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/AppleMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/AppleMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,59 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link AppleMakernoteDirectory}.
- * <p>
- * Using information from http://owl.phy.queensu.ca/~phil/exiftool/TagNames/Apple.html
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class AppleMakernoteDescriptor extends TagDescriptor<AppleMakernoteDirectory>
-{
-    public AppleMakernoteDescriptor(@NotNull AppleMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case AppleMakernoteDirectory.TAG_HDR_IMAGE_TYPE:
-                return getHdrImageTypeDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getHdrImageTypeDescription()
-    {
-        return getIndexedDescription(AppleMakernoteDirectory.TAG_HDR_IMAGE_TYPE, 3, "HDR Image", "Original Image");
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/AppleMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/AppleMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,70 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific to Apple cameras.
- * <p>
- * Using information from http://owl.phy.queensu.ca/~phil/exiftool/TagNames/Apple.html
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class AppleMakernoteDirectory extends Directory
-{
-    public static final int TAG_RUN_TIME = 0x0003;
-    public static final int TAG_HDR_IMAGE_TYPE = 0x000a;
-    public static final int TAG_BURST_UUID = 0x000b;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TAG_RUN_TIME, "Run Time");
-        _tagNameMap.put(TAG_HDR_IMAGE_TYPE, "HDR Image Type");
-        _tagNameMap.put(TAG_BURST_UUID, "Burst UUID");
-    }
-
-    public AppleMakernoteDirectory()
-    {
-        this.setDescriptor(new AppleMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Apple Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/CanonMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/CanonMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,1155 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import java.text.DecimalFormat;
-import java.util.HashMap;
-
-import static com.drew.metadata.exif.makernotes.CanonMakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link CanonMakernoteDirectory}.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class CanonMakernoteDescriptor extends TagDescriptor<CanonMakernoteDirectory>
-{
-    public CanonMakernoteDescriptor(@NotNull CanonMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_CANON_SERIAL_NUMBER:
-                return getSerialNumberDescription();
-            case CameraSettings.TAG_FLASH_ACTIVITY:
-                return getFlashActivityDescription();
-            case CameraSettings.TAG_FOCUS_TYPE:
-                return getFocusTypeDescription();
-            case CameraSettings.TAG_DIGITAL_ZOOM:
-                return getDigitalZoomDescription();
-            case CameraSettings.TAG_RECORD_MODE:
-                return getRecordModeDescription();
-            case CameraSettings.TAG_QUALITY:
-                return getQualityDescription();
-            case CameraSettings.TAG_MACRO_MODE:
-                return getMacroModeDescription();
-            case CameraSettings.TAG_SELF_TIMER_DELAY:
-                return getSelfTimerDelayDescription();
-            case CameraSettings.TAG_FLASH_MODE:
-                return getFlashModeDescription();
-            case CameraSettings.TAG_CONTINUOUS_DRIVE_MODE:
-                return getContinuousDriveModeDescription();
-            case CameraSettings.TAG_FOCUS_MODE_1:
-                return getFocusMode1Description();
-            case CameraSettings.TAG_IMAGE_SIZE:
-                return getImageSizeDescription();
-            case CameraSettings.TAG_EASY_SHOOTING_MODE:
-                return getEasyShootingModeDescription();
-            case CameraSettings.TAG_CONTRAST:
-                return getContrastDescription();
-            case CameraSettings.TAG_SATURATION:
-                return getSaturationDescription();
-            case CameraSettings.TAG_SHARPNESS:
-                return getSharpnessDescription();
-            case CameraSettings.TAG_ISO:
-                return getIsoDescription();
-            case CameraSettings.TAG_METERING_MODE:
-                return getMeteringModeDescription();
-            case CameraSettings.TAG_AF_POINT_SELECTED:
-                return getAfPointSelectedDescription();
-            case CameraSettings.TAG_EXPOSURE_MODE:
-                return getExposureModeDescription();
-            case CameraSettings.TAG_LENS_TYPE:
-                return getLensTypeDescription();
-            case CameraSettings.TAG_LONG_FOCAL_LENGTH:
-                return getLongFocalLengthDescription();
-            case CameraSettings.TAG_SHORT_FOCAL_LENGTH:
-                return getShortFocalLengthDescription();
-            case CameraSettings.TAG_FOCAL_UNITS_PER_MM:
-                return getFocalUnitsPerMillimetreDescription();
-            case CameraSettings.TAG_FLASH_DETAILS:
-                return getFlashDetailsDescription();
-            case CameraSettings.TAG_FOCUS_MODE_2:
-                return getFocusMode2Description();
-            case FocalLength.TAG_WHITE_BALANCE:
-                return getWhiteBalanceDescription();
-            case FocalLength.TAG_AF_POINT_USED:
-                return getAfPointUsedDescription();
-            case FocalLength.TAG_FLASH_BIAS:
-                return getFlashBiasDescription();
-            case AFInfo.TAG_AF_POINTS_IN_FOCUS:
-                return getTagAfPointsInFocus();
-            case CameraSettings.TAG_MAX_APERTURE:
-                return getMaxApertureDescription();
-            case CameraSettings.TAG_MIN_APERTURE:
-                return getMinApertureDescription();
-            case CameraSettings.TAG_FOCUS_CONTINUOUS:
-                return getFocusContinuousDescription();
-            case CameraSettings.TAG_AE_SETTING:
-                return getAESettingDescription();
-            case CanonMakernoteDirectory.CameraSettings.TAG_DISPLAY_APERTURE:
-                return getDisplayApertureDescription();
-            case CanonMakernoteDirectory.CameraSettings.TAG_SPOT_METERING_MODE:
-                return getSpotMeteringModeDescription();
-            case CanonMakernoteDirectory.CameraSettings.TAG_PHOTO_EFFECT:
-                return getPhotoEffectDescription();
-            case CanonMakernoteDirectory.CameraSettings.TAG_MANUAL_FLASH_OUTPUT:
-                return getManualFlashOutputDescription();
-            case CanonMakernoteDirectory.CameraSettings.TAG_COLOR_TONE:
-                return getColorToneDescription();
-            case CanonMakernoteDirectory.CameraSettings.TAG_SRAW_QUALITY:
-                return getSRawQualityDescription();
-
-            // It turns out that these values are dependent upon the camera model and therefore the below code was
-            // incorrect for some Canon models.  This needs to be revisited.
-
-//            case TAG_CANON_CUSTOM_FUNCTION_LONG_EXPOSURE_NOISE_REDUCTION:
-//                return getLongExposureNoiseReductionDescription();
-//            case TAG_CANON_CUSTOM_FUNCTION_SHUTTER_AUTO_EXPOSURE_LOCK_BUTTONS:
-//                return getShutterAutoExposureLockButtonDescription();
-//            case TAG_CANON_CUSTOM_FUNCTION_MIRROR_LOCKUP:
-//                return getMirrorLockupDescription();
-//            case TAG_CANON_CUSTOM_FUNCTION_TV_AV_AND_EXPOSURE_LEVEL:
-//                return getTvAndAvExposureLevelDescription();
-//            case TAG_CANON_CUSTOM_FUNCTION_AF_ASSIST_LIGHT:
-//                return getAutoFocusAssistLightDescription();
-//            case TAG_CANON_CUSTOM_FUNCTION_SHUTTER_SPEED_IN_AV_MODE:
-//                return getShutterSpeedInAvModeDescription();
-//            case TAG_CANON_CUSTOM_FUNCTION_BRACKETING:
-//                return getAutoExposureBracketingSequenceAndAutoCancellationDescription();
-//            case TAG_CANON_CUSTOM_FUNCTION_SHUTTER_CURTAIN_SYNC:
-//                return getShutterCurtainSyncDescription();
-//            case TAG_CANON_CUSTOM_FUNCTION_AF_STOP:
-//                return getLensAutoFocusStopButtonDescription();
-//            case TAG_CANON_CUSTOM_FUNCTION_FILL_FLASH_REDUCTION:
-//                return getFillFlashReductionDescription();
-//            case TAG_CANON_CUSTOM_FUNCTION_MENU_BUTTON_RETURN:
-//                return getMenuButtonReturnPositionDescription();
-//            case TAG_CANON_CUSTOM_FUNCTION_SET_BUTTON_FUNCTION:
-//                return getSetButtonFunctionWhenShootingDescription();
-//            case TAG_CANON_CUSTOM_FUNCTION_SENSOR_CLEANING:
-//                return getSensorCleaningDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getSerialNumberDescription()
-    {
-        // http://www.ozhiker.com/electronics/pjmt/jpeg_info/canon_mn.html
-        Integer value = _directory.getInteger(TAG_CANON_SERIAL_NUMBER);
-        if (value == null)
-            return null;
-        return String.format("%04X%05d", (value >> 8) & 0xFF, value & 0xFF);
-    }
-
-/*
-    @Nullable
-    public String getLongExposureNoiseReductionDescription()
-    {
-        Integer value = _directory.getInteger(TAG_CANON_CUSTOM_FUNCTION_LONG_EXPOSURE_NOISE_REDUCTION);
-        if (value==null)
-            return null;
-        switch (value) {
-            case 0:     return "Off";
-            case 1:     return "On";
-            default:    return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getShutterAutoExposureLockButtonDescription()
-    {
-        Integer value = _directory.getInteger(TAG_CANON_CUSTOM_FUNCTION_SHUTTER_AUTO_EXPOSURE_LOCK_BUTTONS);
-        if (value==null)
-            return null;
-        switch (value) {
-            case 0:     return "AF/AE lock";
-            case 1:     return "AE lock/AF";
-            case 2:     return "AF/AF lock";
-            case 3:     return "AE+release/AE+AF";
-            default:    return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getMirrorLockupDescription()
-    {
-        Integer value = _directory.getInteger(TAG_CANON_CUSTOM_FUNCTION_MIRROR_LOCKUP);
-        if (value==null)
-            return null;
-        switch (value) {
-            case 0:     return "Disabled";
-            case 1:     return "Enabled";
-            default:    return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getTvAndAvExposureLevelDescription()
-    {
-        Integer value = _directory.getInteger(TAG_CANON_CUSTOM_FUNCTION_TV_AV_AND_EXPOSURE_LEVEL);
-        if (value==null)
-            return null;
-        switch (value) {
-            case 0:     return "1/2 stop";
-            case 1:     return "1/3 stop";
-            default:    return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getAutoFocusAssistLightDescription()
-    {
-        Integer value = _directory.getInteger(TAG_CANON_CUSTOM_FUNCTION_AF_ASSIST_LIGHT);
-        if (value==null)
-            return null;
-        switch (value) {
-            case 0:     return "On (Auto)";
-            case 1:     return "Off";
-            default:    return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getShutterSpeedInAvModeDescription()
-    {
-        Integer value = _directory.getInteger(TAG_CANON_CUSTOM_FUNCTION_SHUTTER_SPEED_IN_AV_MODE);
-        if (value==null)
-            return null;
-        switch (value) {
-            case 0:     return "Automatic";
-            case 1:     return "1/200 (fixed)";
-            default:    return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getAutoExposureBracketingSequenceAndAutoCancellationDescription()
-    {
-        Integer value = _directory.getInteger(TAG_CANON_CUSTOM_FUNCTION_BRACKETING);
-        if (value==null)
-            return null;
-        switch (value) {
-            case 0:     return "0,-,+ / Enabled";
-            case 1:     return "0,-,+ / Disabled";
-            case 2:     return "-,0,+ / Enabled";
-            case 3:     return "-,0,+ / Disabled";
-            default:    return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getShutterCurtainSyncDescription()
-    {
-        Integer value = _directory.getInteger(TAG_CANON_CUSTOM_FUNCTION_SHUTTER_CURTAIN_SYNC);
-        if (value==null)
-            return null;
-        switch (value) {
-            case 0:     return "1st Curtain Sync";
-            case 1:     return "2nd Curtain Sync";
-            default:    return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getLensAutoFocusStopButtonDescription()
-    {
-        Integer value = _directory.getInteger(TAG_CANON_CUSTOM_FUNCTION_AF_STOP);
-        if (value==null)
-            return null;
-        switch (value) {
-            case 0:     return "AF stop";
-            case 1:     return "Operate AF";
-            case 2:     return "Lock AE and start timer";
-            default:    return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getFillFlashReductionDescription()
-    {
-        Integer value = _directory.getInteger(TAG_CANON_CUSTOM_FUNCTION_FILL_FLASH_REDUCTION);
-        if (value==null)
-            return null;
-        switch (value) {
-            case 0:     return "Enabled";
-            case 1:     return "Disabled";
-            default:    return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getMenuButtonReturnPositionDescription()
-    {
-        Integer value = _directory.getInteger(TAG_CANON_CUSTOM_FUNCTION_MENU_BUTTON_RETURN);
-        if (value==null)
-            return null;
-        switch (value) {
-            case 0:     return "Top";
-            case 1:     return "Previous (volatile)";
-            case 2:     return "Previous";
-            default:    return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getSetButtonFunctionWhenShootingDescription()
-    {
-        Integer value = _directory.getInteger(TAG_CANON_CUSTOM_FUNCTION_SET_BUTTON_FUNCTION);
-        if (value==null)
-            return null;
-        switch (value) {
-            case 0:     return "Not Assigned";
-            case 1:     return "Change Quality";
-            case 2:     return "Change ISO Speed";
-            case 3:     return "Select Parameters";
-            default:    return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getSensorCleaningDescription()
-    {
-        Integer value = _directory.getInteger(TAG_CANON_CUSTOM_FUNCTION_SENSOR_CLEANING);
-        if (value==null)
-            return null;
-        switch (value) {
-            case 0:     return "Disabled";
-            case 1:     return "Enabled";
-            default:    return "Unknown (" + value + ")";
-        }
-    }
-*/
-
-    @Nullable
-    public String getFlashBiasDescription()
-    {
-        Integer value = _directory.getInteger(FocalLength.TAG_FLASH_BIAS);
-
-        if (value == null)
-            return null;
-
-        boolean isNegative = false;
-        if (value > 0xF000) {
-            isNegative = true;
-            value = 0xFFFF - value;
-            value++;
-        }
-
-        // this tag is interesting in that the values returned are:
-        //  0, 0.375, 0.5, 0.626, 1
-        // not
-        //  0, 0.33,  0.5, 0.66,  1
-
-        return (isNegative ? "-" : "") + Float.toString(value / 32f) + " EV";
-    }
-
-    @Nullable
-    public String getAfPointUsedDescription()
-    {
-        Integer value = _directory.getInteger(FocalLength.TAG_AF_POINT_USED);
-        if (value == null)
-            return null;
-        if ((value & 0x7) == 0) {
-            return "Right";
-        } else if ((value & 0x7) == 1) {
-            return "Centre";
-        } else if ((value & 0x7) == 2) {
-            return "Left";
-        } else {
-            return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getTagAfPointsInFocus()
-    {
-        Integer value = _directory.getInteger(AFInfo.TAG_AF_POINTS_IN_FOCUS);
-        if (value == null)
-            return null;
-
-        StringBuilder sb = new StringBuilder();
-
-        for (int i = 0; i < 16; i++)
-        {
-            if ((value & 1 << i) != 0)
-            {
-                if (sb.length() != 0)
-                    sb.append(',');
-                sb.append(i);
-            }
-        }
-
-        return sb.length() == 0 ? "None" : sb.toString();
-    }
-
-    @Nullable
-    public String getWhiteBalanceDescription()
-    {
-        return getIndexedDescription(
-            FocalLength.TAG_WHITE_BALANCE,
-            "Auto",
-            "Sunny",
-            "Cloudy",
-            "Tungsten",
-            "Florescent",
-            "Flash",
-            "Custom"
-        );
-    }
-
-    @Nullable
-    public String getFocusMode2Description()
-    {
-        return getIndexedDescription(CameraSettings.TAG_FOCUS_MODE_2, "Single", "Continuous");
-    }
-
-    @Nullable
-    public String getFlashDetailsDescription()
-    {
-        Integer value = _directory.getInteger(CameraSettings.TAG_FLASH_DETAILS);
-        if (value == null)
-            return null;
-        if (((value >> 14) & 1) != 0) {
-            return "External E-TTL";
-        }
-        if (((value >> 13) & 1) != 0) {
-            return "Internal flash";
-        }
-        if (((value >> 11) & 1) != 0) {
-            return "FP sync used";
-        }
-        if (((value >> 4) & 1) != 0) {
-            return "FP sync enabled";
-        }
-        return "Unknown (" + value + ")";
-    }
-
-    @Nullable
-    public String getFocalUnitsPerMillimetreDescription()
-    {
-        Integer value = _directory.getInteger(CameraSettings.TAG_FOCAL_UNITS_PER_MM);
-        if (value == null)
-            return null;
-        if (value != 0) {
-            return Integer.toString(value);
-        } else {
-            return "";
-        }
-    }
-
-    @Nullable
-    public String getShortFocalLengthDescription()
-    {
-        Integer value = _directory.getInteger(CameraSettings.TAG_SHORT_FOCAL_LENGTH);
-        if (value == null)
-            return null;
-        String units = getFocalUnitsPerMillimetreDescription();
-        return Integer.toString(value) + " " + units;
-    }
-
-    @Nullable
-    public String getLongFocalLengthDescription()
-    {
-        Integer value = _directory.getInteger(CameraSettings.TAG_LONG_FOCAL_LENGTH);
-        if (value == null)
-            return null;
-        String units = getFocalUnitsPerMillimetreDescription();
-        return Integer.toString(value) + " " + units;
-    }
-
-    @Nullable
-    public String getExposureModeDescription()
-    {
-        return getIndexedDescription(
-            CameraSettings.TAG_EXPOSURE_MODE,
-            "Easy shooting",
-            "Program",
-            "Tv-priority",
-            "Av-priority",
-            "Manual",
-            "A-DEP"
-        );
-    }
-
-    @Nullable
-    public String getLensTypeDescription() {
-        Integer value = _directory.getInteger(CameraSettings.TAG_LENS_TYPE);
-        if (value == null)
-            return null;
-
-        return _lensTypeById.containsKey(value)
-            ? _lensTypeById.get(value)
-            : String.format("Unknown (%d)", value);
-    }
-
-    @Nullable
-    public String getMaxApertureDescription()
-    {
-        Integer value = _directory.getInteger(CameraSettings.TAG_MAX_APERTURE);
-        if (value == null)
-            return null;
-        if (value > 512)
-            return String.format("Unknown (%d)", value);
-        return getFStopDescription(Math.exp(decodeCanonEv(value) * Math.log(2.0) / 2.0));
-    }
-
-    @Nullable
-    public String getMinApertureDescription()
-    {
-        Integer value = _directory.getInteger(CameraSettings.TAG_MIN_APERTURE);
-        if (value == null)
-            return null;
-        if (value > 512)
-            return String.format("Unknown (%d)", value);
-        return getFStopDescription(Math.exp(decodeCanonEv(value) * Math.log(2.0) / 2.0));
-    }
-
-    @Nullable
-    public String getAfPointSelectedDescription()
-    {
-        return getIndexedDescription(
-            CameraSettings.TAG_AF_POINT_SELECTED,
-            0x3000,
-            "None (MF)",
-            "Auto selected",
-            "Right",
-            "Centre",
-            "Left"
-        );
-    }
-
-    @Nullable
-    public String getMeteringModeDescription()
-    {
-        return getIndexedDescription(
-            CameraSettings.TAG_METERING_MODE,
-            3,
-            "Evaluative",
-            "Partial",
-            "Centre weighted"
-        );
-    }
-
-    @Nullable
-    public String getIsoDescription()
-    {
-        Integer value = _directory.getInteger(CameraSettings.TAG_ISO);
-        if (value == null)
-            return null;
-
-        // Canon PowerShot S3 is special
-        int canonMask = 0x4000;
-        if ((value & canonMask) != 0)
-            return "" + (value & ~canonMask);
-
-        switch (value) {
-            case 0:
-                return "Not specified (see ISOSpeedRatings tag)";
-            case 15:
-                return "Auto";
-            case 16:
-                return "50";
-            case 17:
-                return "100";
-            case 18:
-                return "200";
-            case 19:
-                return "400";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getSharpnessDescription()
-    {
-        Integer value = _directory.getInteger(CameraSettings.TAG_SHARPNESS);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0xFFFF:
-                return "Low";
-            case 0x000:
-                return "Normal";
-            case 0x001:
-                return "High";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getSaturationDescription()
-    {
-        Integer value = _directory.getInteger(CameraSettings.TAG_SATURATION);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0xFFFF:
-                return "Low";
-            case 0x000:
-                return "Normal";
-            case 0x001:
-                return "High";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getContrastDescription()
-    {
-        Integer value = _directory.getInteger(CameraSettings.TAG_CONTRAST);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0xFFFF:
-                return "Low";
-            case 0x000:
-                return "Normal";
-            case 0x001:
-                return "High";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getEasyShootingModeDescription()
-    {
-        return getIndexedDescription(
-            CameraSettings.TAG_EASY_SHOOTING_MODE,
-            "Full auto",
-            "Manual",
-            "Landscape",
-            "Fast shutter",
-            "Slow shutter",
-            "Night",
-            "B&W",
-            "Sepia",
-            "Portrait",
-            "Sports",
-            "Macro / Closeup",
-            "Pan focus"
-        );
-    }
-
-    @Nullable
-    public String getImageSizeDescription()
-    {
-        return getIndexedDescription(
-            CameraSettings.TAG_IMAGE_SIZE,
-            "Large",
-            "Medium",
-            "Small"
-        );
-    }
-
-    @Nullable
-    public String getFocusMode1Description()
-    {
-        return getIndexedDescription(
-            CameraSettings.TAG_FOCUS_MODE_1,
-            "One-shot",
-            "AI Servo",
-            "AI Focus",
-            "Manual Focus",
-            // TODO should check field 32 here (FOCUS_MODE_2)
-            "Single",
-            "Continuous",
-            "Manual Focus"
-        );
-    }
-
-    @Nullable
-    public String getContinuousDriveModeDescription()
-    {
-        Integer value = _directory.getInteger(CameraSettings.TAG_CONTINUOUS_DRIVE_MODE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0:
-                final Integer delay = _directory.getInteger(CameraSettings.TAG_SELF_TIMER_DELAY);
-                if (delay != null)
-                    return delay == 0 ? "Single shot" : "Single shot with self-timer";
-            case 1:
-                return "Continuous";
-        }
-        return "Unknown (" + value + ")";
-    }
-
-    @Nullable
-    public String getFlashModeDescription()
-    {
-        Integer value = _directory.getInteger(CameraSettings.TAG_FLASH_MODE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0:
-                return "No flash fired";
-            case 1:
-                return "Auto";
-            case 2:
-                return "On";
-            case 3:
-                return "Red-eye reduction";
-            case 4:
-                return "Slow-synchro";
-            case 5:
-                return "Auto and red-eye reduction";
-            case 6:
-                return "On and red-eye reduction";
-            case 16:
-                // note: this value not set on Canon D30
-                return "External flash";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getSelfTimerDelayDescription()
-    {
-        Integer value = _directory.getInteger(CameraSettings.TAG_SELF_TIMER_DELAY);
-        if (value == null)
-            return null;
-        if (value == 0) {
-            return "Self timer not used";
-        } else {
-            DecimalFormat format = new DecimalFormat("0.##");
-            return format.format((double)value * 0.1d) + " sec";
-        }
-    }
-
-    @Nullable
-    public String getMacroModeDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_MACRO_MODE, 1, "Macro", "Normal");
-    }
-
-    @Nullable
-    public String getQualityDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_QUALITY, 2, "Normal", "Fine", null, "Superfine");
-    }
-
-    @Nullable
-    public String getDigitalZoomDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_DIGITAL_ZOOM, "No digital zoom", "2x", "4x");
-    }
-
-    @Nullable
-    public String getRecordModeDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_RECORD_MODE, 1, "JPEG", "CRW+THM", "AVI+THM", "TIF", "TIF+JPEG", "CR2", "CR2+JPEG", null, "MOV", "MP4");
-    }
-
-    @Nullable
-    public String getFocusTypeDescription()
-    {
-        Integer value = _directory.getInteger(CameraSettings.TAG_FOCUS_TYPE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0:
-                return "Manual";
-            case 1:
-                return "Auto";
-            case 3:
-                return "Close-up (Macro)";
-            case 8:
-                return "Locked (Pan Mode)";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getFlashActivityDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_FLASH_ACTIVITY, "Flash did not fire", "Flash fired");
-    }
-
-    @Nullable
-    public String getFocusContinuousDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_FOCUS_CONTINUOUS, 0,
-            "Single", "Continuous", null, null, null, null, null, null, "Manual");
-    }
-
-    @Nullable
-    public String getAESettingDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_AE_SETTING, 0,
-            "Normal AE", "Exposure Compensation", "AE Lock", "AE Lock + Exposure Comp.", "No AE");
-    }
-
-    @Nullable
-    public String getDisplayApertureDescription()
-    {
-        Integer value = _directory.getInteger(CameraSettings.TAG_DISPLAY_APERTURE);
-        if (value == null)
-            return null;
-
-        if (value == 0xFFFF)
-            return value.toString();
-        return getFStopDescription(value / 10f);
-    }
-
-    @Nullable
-    public String getSpotMeteringModeDescription()
-    {
-        return getIndexedDescription(CanonMakernoteDirectory.CameraSettings.TAG_SPOT_METERING_MODE, 0,
-            "Center", "AF Point");
-    }
-
-    @Nullable
-    public String getPhotoEffectDescription()
-    {
-        Integer value = _directory.getInteger(CameraSettings.TAG_PHOTO_EFFECT);
-        if (value == null)
-            return null;
-
-        switch (value)
-        {
-            case 0:
-                return "Off";
-            case 1:
-                return "Vivid";
-            case 2:
-                return "Neutral";
-            case 3:
-                return "Smooth";
-            case 4:
-                return "Sepia";
-            case 5:
-                return "B&W";
-            case 6:
-                return "Custom";
-            case 100:
-                return "My Color Data";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getManualFlashOutputDescription()
-    {
-        Integer value = _directory.getInteger(CameraSettings.TAG_MANUAL_FLASH_OUTPUT);
-        if (value == null)
-            return null;
-
-        switch (value)
-        {
-            case 0:
-                return "n/a";
-            case 0x500:
-                return "Full";
-            case 0x502:
-                return "Medium";
-            case 0x504:
-                return "Low";
-            case 0x7fff:
-                return "n/a";   // (EOS models)
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getColorToneDescription()
-    {
-        Integer value = _directory.getInteger(CameraSettings.TAG_COLOR_TONE);
-        if (value == null)
-            return null;
-
-        return value == 0x7fff ? "n/a" : value.toString();
-    }
-
-    @Nullable
-    public String getSRawQualityDescription()
-    {
-        return getIndexedDescription(CanonMakernoteDirectory.CameraSettings.TAG_SRAW_QUALITY, 0, "n/a", "sRAW1 (mRAW)", "sRAW2 (sRAW)");
-    }
-
-    /**
-     * Canon hex-based EV (modulo 0x20) to real number.
-     *
-     * Converted from Exiftool version 10.10 created by Phil Harvey
-     * http://www.sno.phy.queensu.ca/~phil/exiftool/
-     * lib\Image\ExifTool\Canon.pm
-     *
-     *         eg) 0x00 -> 0
-     *             0x0c -> 0.33333
-     *             0x10 -> 0.5
-     *             0x14 -> 0.66666
-     *             0x20 -> 1   ... etc
-     */
-    private double decodeCanonEv(int val)
-    {
-        int sign = 1;
-        if (val < 0)
-        {
-            val = -val;
-            sign = -1;
-        }
-
-        int frac = val & 0x1f;
-        val -= frac;
-
-        if (frac == 0x0c)
-            frac = 0x20 / 3;
-        else if (frac == 0x14)
-            frac = 0x40 / 3;
-
-        return sign * (val + frac) / (double)0x20;
-    }
-
-    /**
-     *  Map from <see cref="CanonMakernoteDirectory.CameraSettings.TagLensType"/> to string descriptions.
-     *
-     *  Data sourced from http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Canon.html#LensType
-     *
-     *  Note that only Canon lenses are listed. Lenses from other manufacturers may identify themselves to the camera
-     *  as being from this set, but in fact may be quite different. This limits the usefulness of this data,
-     *  unfortunately.
-     */
-    private static final HashMap<Integer, String> _lensTypeById = new HashMap<Integer, String>();
-
-    static {
-        _lensTypeById.put(1, "Canon EF 50mm f/1.8");
-        _lensTypeById.put(2, "Canon EF 28mm f/2.8");
-        _lensTypeById.put(3, "Canon EF 135mm f/2.8 Soft");
-        _lensTypeById.put(4, "Canon EF 35-105mm f/3.5-4.5 or Sigma Lens");
-        _lensTypeById.put(5, "Canon EF 35-70mm f/3.5-4.5");
-        _lensTypeById.put(6, "Canon EF 28-70mm f/3.5-4.5 or Sigma or Tokina Lens");
-        _lensTypeById.put(7, "Canon EF 100-300mm f/5.6L");
-        _lensTypeById.put(8, "Canon EF 100-300mm f/5.6 or Sigma or Tokina Lens");
-        _lensTypeById.put(9, "Canon EF 70-210mm f/4");
-        _lensTypeById.put(10, "Canon EF 50mm f/2.5 Macro or Sigma Lens");
-        _lensTypeById.put(11, "Canon EF 35mm f/2");
-        _lensTypeById.put(13, "Canon EF 15mm f/2.8 Fisheye");
-        _lensTypeById.put(14, "Canon EF 50-200mm f/3.5-4.5L");
-        _lensTypeById.put(15, "Canon EF 50-200mm f/3.5-4.5");
-        _lensTypeById.put(16, "Canon EF 35-135mm f/3.5-4.5");
-        _lensTypeById.put(17, "Canon EF 35-70mm f/3.5-4.5A");
-        _lensTypeById.put(18, "Canon EF 28-70mm f/3.5-4.5");
-        _lensTypeById.put(20, "Canon EF 100-200mm f/4.5A");
-        _lensTypeById.put(21, "Canon EF 80-200mm f/2.8L");
-        _lensTypeById.put(22, "Canon EF 20-35mm f/2.8L or Tokina Lens");
-        _lensTypeById.put(23, "Canon EF 35-105mm f/3.5-4.5");
-        _lensTypeById.put(24, "Canon EF 35-80mm f/4-5.6 Power Zoom");
-        _lensTypeById.put(25, "Canon EF 35-80mm f/4-5.6 Power Zoom");
-        _lensTypeById.put(26, "Canon EF 100mm f/2.8 Macro or Other Lens");
-        _lensTypeById.put(27, "Canon EF 35-80mm f/4-5.6");
-        _lensTypeById.put(28, "Canon EF 80-200mm f/4.5-5.6 or Tamron Lens");
-        _lensTypeById.put(29, "Canon EF 50mm f/1.8 II");
-        _lensTypeById.put(30, "Canon EF 35-105mm f/4.5-5.6");
-        _lensTypeById.put(31, "Canon EF 75-300mm f/4-5.6 or Tamron Lens");
-        _lensTypeById.put(32, "Canon EF 24mm f/2.8 or Sigma Lens");
-        _lensTypeById.put(33, "Voigtlander or Carl Zeiss Lens");
-        _lensTypeById.put(35, "Canon EF 35-80mm f/4-5.6");
-        _lensTypeById.put(36, "Canon EF 38-76mm f/4.5-5.6");
-        _lensTypeById.put(37, "Canon EF 35-80mm f/4-5.6 or Tamron Lens");
-        _lensTypeById.put(38, "Canon EF 80-200mm f/4.5-5.6");
-        _lensTypeById.put(39, "Canon EF 75-300mm f/4-5.6");
-        _lensTypeById.put(40, "Canon EF 28-80mm f/3.5-5.6");
-        _lensTypeById.put(41, "Canon EF 28-90mm f/4-5.6");
-        _lensTypeById.put(42, "Canon EF 28-200mm f/3.5-5.6 or Tamron Lens");
-        _lensTypeById.put(43, "Canon EF 28-105mm f/4-5.6");
-        _lensTypeById.put(44, "Canon EF 90-300mm f/4.5-5.6");
-        _lensTypeById.put(45, "Canon EF-S 18-55mm f/3.5-5.6 [II]");
-        _lensTypeById.put(46, "Canon EF 28-90mm f/4-5.6");
-        _lensTypeById.put(47, "Zeiss Milvus 35mm f/2 or 50mm f/2");
-        _lensTypeById.put(48, "Canon EF-S 18-55mm f/3.5-5.6 IS");
-        _lensTypeById.put(49, "Canon EF-S 55-250mm f/4-5.6 IS");
-        _lensTypeById.put(50, "Canon EF-S 18-200mm f/3.5-5.6 IS");
-        _lensTypeById.put(51, "Canon EF-S 18-135mm f/3.5-5.6 IS");
-        _lensTypeById.put(52, "Canon EF-S 18-55mm f/3.5-5.6 IS II");
-        _lensTypeById.put(53, "Canon EF-S 18-55mm f/3.5-5.6 III");
-        _lensTypeById.put(54, "Canon EF-S 55-250mm f/4-5.6 IS II");
-        _lensTypeById.put(94, "Canon TS-E 17mm f/4L");
-        _lensTypeById.put(95, "Canon TS-E 24.0mm f/3.5 L II");
-        _lensTypeById.put(124, "Canon MP-E 65mm f/2.8 1-5x Macro Photo");
-        _lensTypeById.put(125, "Canon TS-E 24mm f/3.5L");
-        _lensTypeById.put(126, "Canon TS-E 45mm f/2.8");
-        _lensTypeById.put(127, "Canon TS-E 90mm f/2.8");
-        _lensTypeById.put(129, "Canon EF 300mm f/2.8L");
-        _lensTypeById.put(130, "Canon EF 50mm f/1.0L");
-        _lensTypeById.put(131, "Canon EF 28-80mm f/2.8-4L or Sigma Lens");
-        _lensTypeById.put(132, "Canon EF 1200mm f/5.6L");
-        _lensTypeById.put(134, "Canon EF 600mm f/4L IS");
-        _lensTypeById.put(135, "Canon EF 200mm f/1.8L");
-        _lensTypeById.put(136, "Canon EF 300mm f/2.8L");
-        _lensTypeById.put(137, "Canon EF 85mm f/1.2L or Sigma or Tamron Lens");
-        _lensTypeById.put(138, "Canon EF 28-80mm f/2.8-4L");
-        _lensTypeById.put(139, "Canon EF 400mm f/2.8L");
-        _lensTypeById.put(140, "Canon EF 500mm f/4.5L");
-        _lensTypeById.put(141, "Canon EF 500mm f/4.5L");
-        _lensTypeById.put(142, "Canon EF 300mm f/2.8L IS");
-        _lensTypeById.put(143, "Canon EF 500mm f/4L IS or Sigma Lens");
-        _lensTypeById.put(144, "Canon EF 35-135mm f/4-5.6 USM");
-        _lensTypeById.put(145, "Canon EF 100-300mm f/4.5-5.6 USM");
-        _lensTypeById.put(146, "Canon EF 70-210mm f/3.5-4.5 USM");
-        _lensTypeById.put(147, "Canon EF 35-135mm f/4-5.6 USM");
-        _lensTypeById.put(148, "Canon EF 28-80mm f/3.5-5.6 USM");
-        _lensTypeById.put(149, "Canon EF 100mm f/2 USM");
-        _lensTypeById.put(150, "Canon EF 14mm f/2.8L or Sigma Lens");
-        _lensTypeById.put(151, "Canon EF 200mm f/2.8L");
-        _lensTypeById.put(152, "Canon EF 300mm f/4L IS or Sigma Lens");
-        _lensTypeById.put(153, "Canon EF 35-350mm f/3.5-5.6L or Sigma or Tamron Lens");
-        _lensTypeById.put(154, "Canon EF 20mm f/2.8 USM or Zeiss Lens");
-        _lensTypeById.put(155, "Canon EF 85mm f/1.8 USM");
-        _lensTypeById.put(156, "Canon EF 28-105mm f/3.5-4.5 USM or Tamron Lens");
-        _lensTypeById.put(160, "Canon EF 20-35mm f/3.5-4.5 USM or Tamron or Tokina Lens");
-        _lensTypeById.put(161, "Canon EF 28-70mm f/2.8L or Sigma or Tamron Lens");
-        _lensTypeById.put(162, "Canon EF 200mm f/2.8L");
-        _lensTypeById.put(163, "Canon EF 300mm f/4L");
-        _lensTypeById.put(164, "Canon EF 400mm f/5.6L");
-        _lensTypeById.put(165, "Canon EF 70-200mm f/2.8 L");
-        _lensTypeById.put(166, "Canon EF 70-200mm f/2.8 L + 1.4x");
-        _lensTypeById.put(167, "Canon EF 70-200mm f/2.8 L + 2x");
-        _lensTypeById.put(168, "Canon EF 28mm f/1.8 USM or Sigma Lens");
-        _lensTypeById.put(169, "Canon EF 17-35mm f/2.8L or Sigma Lens");
-        _lensTypeById.put(170, "Canon EF 200mm f/2.8L II");
-        _lensTypeById.put(171, "Canon EF 300mm f/4L");
-        _lensTypeById.put(172, "Canon EF 400mm f/5.6L or Sigma Lens");
-        _lensTypeById.put(173, "Canon EF 180mm Macro f/3.5L or Sigma Lens");
-        _lensTypeById.put(174, "Canon EF 135mm f/2L or Other Lens");
-        _lensTypeById.put(175, "Canon EF 400mm f/2.8L");
-        _lensTypeById.put(176, "Canon EF 24-85mm f/3.5-4.5 USM");
-        _lensTypeById.put(177, "Canon EF 300mm f/4L IS");
-        _lensTypeById.put(178, "Canon EF 28-135mm f/3.5-5.6 IS");
-        _lensTypeById.put(179, "Canon EF 24mm f/1.4L");
-        _lensTypeById.put(180, "Canon EF 35mm f/1.4L or Other Lens");
-        _lensTypeById.put(181, "Canon EF 100-400mm f/4.5-5.6L IS + 1.4x or Sigma Lens");
-        _lensTypeById.put(182, "Canon EF 100-400mm f/4.5-5.6L IS + 2x or Sigma Lens");
-        _lensTypeById.put(183, "Canon EF 100-400mm f/4.5-5.6L IS or Sigma Lens");
-        _lensTypeById.put(184, "Canon EF 400mm f/2.8L + 2x");
-        _lensTypeById.put(185, "Canon EF 600mm f/4L IS");
-        _lensTypeById.put(186, "Canon EF 70-200mm f/4L");
-        _lensTypeById.put(187, "Canon EF 70-200mm f/4L + 1.4x");
-        _lensTypeById.put(188, "Canon EF 70-200mm f/4L + 2x");
-        _lensTypeById.put(189, "Canon EF 70-200mm f/4L + 2.8x");
-        _lensTypeById.put(190, "Canon EF 100mm f/2.8 Macro USM");
-        _lensTypeById.put(191, "Canon EF 400mm f/4 DO IS");
-        _lensTypeById.put(193, "Canon EF 35-80mm f/4-5.6 USM");
-        _lensTypeById.put(194, "Canon EF 80-200mm f/4.5-5.6 USM");
-        _lensTypeById.put(195, "Canon EF 35-105mm f/4.5-5.6 USM");
-        _lensTypeById.put(196, "Canon EF 75-300mm f/4-5.6 USM");
-        _lensTypeById.put(197, "Canon EF 75-300mm f/4-5.6 IS USM");
-        _lensTypeById.put(198, "Canon EF 50mm f/1.4 USM or Zeiss Lens");
-        _lensTypeById.put(199, "Canon EF 28-80mm f/3.5-5.6 USM");
-        _lensTypeById.put(200, "Canon EF 75-300mm f/4-5.6 USM");
-        _lensTypeById.put(201, "Canon EF 28-80mm f/3.5-5.6 USM");
-        _lensTypeById.put(202, "Canon EF 28-80mm f/3.5-5.6 USM IV");
-        _lensTypeById.put(208, "Canon EF 22-55mm f/4-5.6 USM");
-        _lensTypeById.put(209, "Canon EF 55-200mm f/4.5-5.6");
-        _lensTypeById.put(210, "Canon EF 28-90mm f/4-5.6 USM");
-        _lensTypeById.put(211, "Canon EF 28-200mm f/3.5-5.6 USM");
-        _lensTypeById.put(212, "Canon EF 28-105mm f/4-5.6 USM");
-        _lensTypeById.put(213, "Canon EF 90-300mm f/4.5-5.6 USM or Tamron Lens");
-        _lensTypeById.put(214, "Canon EF-S 18-55mm f/3.5-5.6 USM");
-        _lensTypeById.put(215, "Canon EF 55-200mm f/4.5-5.6 II USM");
-        _lensTypeById.put(217, "Tamron AF 18-270mm f/3.5-6.3 Di II VC PZD");
-        _lensTypeById.put(224, "Canon EF 70-200mm f/2.8L IS");
-        _lensTypeById.put(225, "Canon EF 70-200mm f/2.8L IS + 1.4x");
-        _lensTypeById.put(226, "Canon EF 70-200mm f/2.8L IS + 2x");
-        _lensTypeById.put(227, "Canon EF 70-200mm f/2.8L IS + 2.8x");
-        _lensTypeById.put(228, "Canon EF 28-105mm f/3.5-4.5 USM");
-        _lensTypeById.put(229, "Canon EF 16-35mm f/2.8L");
-        _lensTypeById.put(230, "Canon EF 24-70mm f/2.8L");
-        _lensTypeById.put(231, "Canon EF 17-40mm f/4L");
-        _lensTypeById.put(232, "Canon EF 70-300mm f/4.5-5.6 DO IS USM");
-        _lensTypeById.put(233, "Canon EF 28-300mm f/3.5-5.6L IS");
-        _lensTypeById.put(234, "Canon EF-S 17-85mm f/4-5.6 IS USM or Tokina Lens");
-        _lensTypeById.put(235, "Canon EF-S 10-22mm f/3.5-4.5 USM");
-        _lensTypeById.put(236, "Canon EF-S 60mm f/2.8 Macro USM");
-        _lensTypeById.put(237, "Canon EF 24-105mm f/4L IS");
-        _lensTypeById.put(238, "Canon EF 70-300mm f/4-5.6 IS USM");
-        _lensTypeById.put(239, "Canon EF 85mm f/1.2L II");
-        _lensTypeById.put(240, "Canon EF-S 17-55mm f/2.8 IS USM");
-        _lensTypeById.put(241, "Canon EF 50mm f/1.2L");
-        _lensTypeById.put(242, "Canon EF 70-200mm f/4L IS");
-        _lensTypeById.put(243, "Canon EF 70-200mm f/4L IS + 1.4x");
-        _lensTypeById.put(244, "Canon EF 70-200mm f/4L IS + 2x");
-        _lensTypeById.put(245, "Canon EF 70-200mm f/4L IS + 2.8x");
-        _lensTypeById.put(246, "Canon EF 16-35mm f/2.8L II");
-        _lensTypeById.put(247, "Canon EF 14mm f/2.8L II USM");
-        _lensTypeById.put(248, "Canon EF 200mm f/2L IS or Sigma Lens");
-        _lensTypeById.put(249, "Canon EF 800mm f/5.6L IS");
-        _lensTypeById.put(250, "Canon EF 24mm f/1.4L II or Sigma Lens");
-        _lensTypeById.put(251, "Canon EF 70-200mm f/2.8L IS II USM");
-        _lensTypeById.put(252, "Canon EF 70-200mm f/2.8L IS II USM + 1.4x");
-        _lensTypeById.put(253, "Canon EF 70-200mm f/2.8L IS II USM + 2x");
-        _lensTypeById.put(254, "Canon EF 100mm f/2.8L Macro IS USM");
-        _lensTypeById.put(255, "Sigma 24-105mm f/4 DG OS HSM | A or Other Sigma Lens");
-        _lensTypeById.put(488, "Canon EF-S 15-85mm f/3.5-5.6 IS USM");
-        _lensTypeById.put(489, "Canon EF 70-300mm f/4-5.6L IS USM");
-        _lensTypeById.put(490, "Canon EF 8-15mm f/4L Fisheye USM");
-        _lensTypeById.put(491, "Canon EF 300mm f/2.8L IS II USM");
-        _lensTypeById.put(492, "Canon EF 400mm f/2.8L IS II USM");
-        _lensTypeById.put(493, "Canon EF 500mm f/4L IS II USM or EF 24-105mm f4L IS USM");
-        _lensTypeById.put(494, "Canon EF 600mm f/4.0L IS II USM");
-        _lensTypeById.put(495, "Canon EF 24-70mm f/2.8L II USM");
-        _lensTypeById.put(496, "Canon EF 200-400mm f/4L IS USM");
-        _lensTypeById.put(499, "Canon EF 200-400mm f/4L IS USM + 1.4x");
-        _lensTypeById.put(502, "Canon EF 28mm f/2.8 IS USM");
-        _lensTypeById.put(503, "Canon EF 24mm f/2.8 IS USM");
-        _lensTypeById.put(504, "Canon EF 24-70mm f/4L IS USM");
-        _lensTypeById.put(505, "Canon EF 35mm f/2 IS USM");
-        _lensTypeById.put(506, "Canon EF 400mm f/4 DO IS II USM");
-        _lensTypeById.put(507, "Canon EF 16-35mm f/4L IS USM");
-        _lensTypeById.put(508, "Canon EF 11-24mm f/4L USM");
-        _lensTypeById.put(747, "Canon EF 100-400mm f/4.5-5.6L IS II USM");
-        _lensTypeById.put(750, "Canon EF 35mm f/1.4L II USM");
-        _lensTypeById.put(4142, "Canon EF-S 18-135mm f/3.5-5.6 IS STM");
-        _lensTypeById.put(4143, "Canon EF-M 18-55mm f/3.5-5.6 IS STM or Tamron Lens");
-        _lensTypeById.put(4144, "Canon EF 40mm f/2.8 STM");
-        _lensTypeById.put(4145, "Canon EF-M 22mm f/2 STM");
-        _lensTypeById.put(4146, "Canon EF-S 18-55mm f/3.5-5.6 IS STM");
-        _lensTypeById.put(4147, "Canon EF-M 11-22mm f/4-5.6 IS STM");
-        _lensTypeById.put(4148, "Canon EF-S 55-250mm f/4-5.6 IS STM");
-        _lensTypeById.put(4149, "Canon EF-M 55-200mm f/4.5-6.3 IS STM");
-        _lensTypeById.put(4150, "Canon EF-S 10-18mm f/4.5-5.6 IS STM");
-        _lensTypeById.put(4152, "Canon EF 24-105mm f/3.5-5.6 IS STM");
-        _lensTypeById.put(4153, "Canon EF-M 15-45mm f/3.5-6.3 IS STM");
-        _lensTypeById.put(4154, "Canon EF-S 24mm f/2.8 STM");
-        _lensTypeById.put(4156, "Canon EF 50mm f/1.8 STM");
-        _lensTypeById.put(36912, "Canon EF-S 18-135mm f/3.5-5.6 IS USM");
-        _lensTypeById.put(65535, "N/A");
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/CanonMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/CanonMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,799 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific to Canon cameras.
- *
- * Thanks to Bill Richards for his contribution to this makernote directory.
- *
- * Many tag definitions explained here: http://www.ozhiker.com/electronics/pjmt/jpeg_info/canon_mn.html
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class CanonMakernoteDirectory extends Directory
-{
-    // These TAG_*_ARRAY Exif tags map to arrays of int16 values which are split out into separate 'fake' tags.
-    // When an attempt is made to set one of these on the directory, it is split and the corresponding offset added to the tagType.
-    // So the resulting tag is the offset + the index into the array.
-
-    private static final int TAG_CAMERA_SETTINGS_ARRAY          = 0x0001;
-    private static final int TAG_FOCAL_LENGTH_ARRAY             = 0x0002;
-//    private static final int TAG_FLASH_INFO                     = 0x0003;
-    private static final int TAG_SHOT_INFO_ARRAY                = 0x0004;
-    private static final int TAG_PANORAMA_ARRAY                 = 0x0005;
-
-    public static final int TAG_CANON_IMAGE_TYPE                = 0x0006;
-    public static final int TAG_CANON_FIRMWARE_VERSION          = 0x0007;
-    public static final int TAG_CANON_IMAGE_NUMBER              = 0x0008;
-    public static final int TAG_CANON_OWNER_NAME                = 0x0009;
-    public static final int TAG_CANON_SERIAL_NUMBER             = 0x000C;
-    public static final int TAG_CAMERA_INFO_ARRAY               = 0x000D; // depends upon model, so leave for now
-    public static final int TAG_CANON_FILE_LENGTH               = 0x000E;
-    public static final int TAG_CANON_CUSTOM_FUNCTIONS_ARRAY    = 0x000F; // depends upon model, so leave for now
-    public static final int TAG_MODEL_ID                        = 0x0010;
-    public static final int TAG_MOVIE_INFO_ARRAY                = 0x0011; // not currently decoded as not sure we see it in still images
-    private static final int TAG_AF_INFO_ARRAY                  = 0x0012; // not currently decoded
-    public static final int TAG_THUMBNAIL_IMAGE_VALID_AREA      = 0x0013;
-    public static final int TAG_SERIAL_NUMBER_FORMAT            = 0x0015;
-    public static final int TAG_SUPER_MACRO                     = 0x001A;
-    public static final int TAG_DATE_STAMP_MODE                 = 0x001C;
-    public static final int TAG_MY_COLORS                       = 0x001D;
-    public static final int TAG_FIRMWARE_REVISION               = 0x001E;
-    public static final int TAG_CATEGORIES                      = 0x0023;
-    public static final int TAG_FACE_DETECT_ARRAY_1             = 0x0024;
-    public static final int TAG_FACE_DETECT_ARRAY_2             = 0x0025;
-    public static final int TAG_AF_INFO_ARRAY_2                 = 0x0026;
-    public static final int TAG_IMAGE_UNIQUE_ID                 = 0x0028;
-
-    public static final int TAG_RAW_DATA_OFFSET                 = 0x0081;
-    public static final int TAG_ORIGINAL_DECISION_DATA_OFFSET   = 0x0083;
-
-    public static final int TAG_CUSTOM_FUNCTIONS_1D_ARRAY       = 0x0090; // not currently decoded
-    public static final int TAG_PERSONAL_FUNCTIONS_ARRAY        = 0x0091; // not currently decoded
-    public static final int TAG_PERSONAL_FUNCTION_VALUES_ARRAY  = 0x0092; // not currently decoded
-    public static final int TAG_FILE_INFO_ARRAY                 = 0x0093; // not currently decoded
-    public static final int TAG_AF_POINTS_IN_FOCUS_1D           = 0x0094;
-    public static final int TAG_LENS_MODEL                      = 0x0095;
-    public static final int TAG_SERIAL_INFO_ARRAY               = 0x0096; // not currently decoded
-    public static final int TAG_DUST_REMOVAL_DATA               = 0x0097;
-    public static final int TAG_CROP_INFO                       = 0x0098; // not currently decoded
-    public static final int TAG_CUSTOM_FUNCTIONS_ARRAY_2        = 0x0099; // not currently decoded
-    public static final int TAG_ASPECT_INFO_ARRAY               = 0x009A; // not currently decoded
-    public static final int TAG_PROCESSING_INFO_ARRAY           = 0x00A0; // not currently decoded
-    public static final int TAG_TONE_CURVE_TABLE                = 0x00A1;
-    public static final int TAG_SHARPNESS_TABLE                 = 0x00A2;
-    public static final int TAG_SHARPNESS_FREQ_TABLE            = 0x00A3;
-    public static final int TAG_WHITE_BALANCE_TABLE             = 0x00A4;
-    public static final int TAG_COLOR_BALANCE_ARRAY             = 0x00A9; // not currently decoded
-    public static final int TAG_MEASURED_COLOR_ARRAY            = 0x00AA; // not currently decoded
-    public static final int TAG_COLOR_TEMPERATURE               = 0x00AE;
-    public static final int TAG_CANON_FLAGS_ARRAY               = 0x00B0; // not currently decoded
-    public static final int TAG_MODIFIED_INFO_ARRAY             = 0x00B1; // not currently decoded
-    public static final int TAG_TONE_CURVE_MATCHING             = 0x00B2;
-    public static final int TAG_WHITE_BALANCE_MATCHING          = 0x00B3;
-    public static final int TAG_COLOR_SPACE                     = 0x00B4;
-    public static final int TAG_PREVIEW_IMAGE_INFO_ARRAY        = 0x00B6; // not currently decoded
-    public static final int TAG_VRD_OFFSET                      = 0x00D0;
-    public static final int TAG_SENSOR_INFO_ARRAY               = 0x00E0; // not currently decoded
-
-    public static final int TAG_COLOR_DATA_ARRAY_2              = 0x4001; // depends upon camera model, not currently decoded
-    public static final int TAG_CRW_PARAM                       = 0x4002; // depends upon camera model, not currently decoded
-    public static final int TAG_COLOR_INFO_ARRAY_2              = 0x4003; // not currently decoded
-    public static final int TAG_BLACK_LEVEL                     = 0x4008; // not currently decoded
-    public static final int TAG_CUSTOM_PICTURE_STYLE_FILE_NAME  = 0x4010;
-    public static final int TAG_COLOR_INFO_ARRAY                = 0x4013; // not currently decoded
-    public static final int TAG_VIGNETTING_CORRECTION_ARRAY_1   = 0x4015; // not currently decoded
-    public static final int TAG_VIGNETTING_CORRECTION_ARRAY_2   = 0x4016; // not currently decoded
-    public static final int TAG_LIGHTING_OPTIMIZER_ARRAY        = 0x4018; // not currently decoded
-    public static final int TAG_LENS_INFO_ARRAY                 = 0x4019; // not currently decoded
-    public static final int TAG_AMBIANCE_INFO_ARRAY             = 0x4020; // not currently decoded
-    public static final int TAG_FILTER_INFO_ARRAY               = 0x4024; // not currently decoded
-
-    public final static class CameraSettings
-    {
-        // These 'sub'-tag values have been created for consistency -- they don't exist within the exif segment
-        private static final int OFFSET = 0xC100;
-
-        /**
-         * 1 = Macro
-         * 2 = Normal
-         */
-        public static final int TAG_MACRO_MODE = OFFSET + 0x01;
-        public static final int TAG_SELF_TIMER_DELAY = OFFSET + 0x02;
-        /**
-         * 2 = Normal
-         * 3 = Fine
-         * 5 = Superfine
-         */
-        public static final int TAG_QUALITY = OFFSET + 0x03;
-        /**
-         * 0 = Flash Not Fired
-         * 1 = Auto
-         * 2 = On
-         * 3 = Red Eye Reduction
-         * 4 = Slow Synchro
-         * 5 = Auto + Red Eye Reduction
-         * 6 = On + Red Eye Reduction
-         * 16 = External Flash
-         */
-        public static final int TAG_FLASH_MODE = OFFSET + 0x04;
-        /**
-         * 0 = Single Frame or Timer Mode
-         * 1 = Continuous
-         */
-        public static final int TAG_CONTINUOUS_DRIVE_MODE = OFFSET + 0x05;
-        public static final int TAG_UNKNOWN_2 = OFFSET + 0x06;
-        /**
-         * 0 = One-Shot
-         * 1 = AI Servo
-         * 2 = AI Focus
-         * 3 = Manual Focus
-         * 4 = Single
-         * 5 = Continuous
-         * 6 = Manual Focus
-         */
-        public static final int TAG_FOCUS_MODE_1 = OFFSET + 0x07;
-        public static final int TAG_UNKNOWN_3 = OFFSET + 0x08;
-        public static final int TAG_RECORD_MODE = OFFSET + 0x09;
-        /**
-         * 0 = Large
-         * 1 = Medium
-         * 2 = Small
-         */
-        public static final int TAG_IMAGE_SIZE = OFFSET + 0x0A;
-        /**
-         * 0 = Full Auto
-         * 1 = Manual
-         * 2 = Landscape
-         * 3 = Fast Shutter
-         * 4 = Slow Shutter
-         * 5 = Night
-         * 6 = Black &amp; White
-         * 7 = Sepia
-         * 8 = Portrait
-         * 9 = Sports
-         * 10 = Macro / Close-Up
-         * 11 = Pan Focus
-         */
-        public static final int TAG_EASY_SHOOTING_MODE = OFFSET + 0x0B;
-        /**
-         * 0 = No Digital Zoom
-         * 1 = 2x
-         * 2 = 4x
-         */
-        public static final int TAG_DIGITAL_ZOOM = OFFSET + 0x0C;
-        /**
-         * 0 = Normal
-         * 1 = High
-         * 65535 = Low
-         */
-        public static final int TAG_CONTRAST = OFFSET + 0x0D;
-        /**
-         * 0 = Normal
-         * 1 = High
-         * 65535 = Low
-         */
-        public static final int TAG_SATURATION = OFFSET + 0x0E;
-        /**
-         * 0 = Normal
-         * 1 = High
-         * 65535 = Low
-         */
-        public static final int TAG_SHARPNESS = OFFSET + 0x0F;
-        /**
-         * 0 = Check ISOSpeedRatings EXIF tag for ISO Speed
-         * 15 = Auto ISO
-         * 16 = ISO 50
-         * 17 = ISO 100
-         * 18 = ISO 200
-         * 19 = ISO 400
-         */
-        public static final int TAG_ISO = OFFSET + 0x10;
-        /**
-         * 3 = Evaluative
-         * 4 = Partial
-         * 5 = Centre Weighted
-         */
-        public static final int TAG_METERING_MODE = OFFSET + 0x11;
-        /**
-         * 0 = Manual
-         * 1 = Auto
-         * 3 = Close-up (Macro)
-         * 8 = Locked (Pan Mode)
-         */
-        public static final int TAG_FOCUS_TYPE = OFFSET + 0x12;
-        /**
-         * 12288 = None (Manual Focus)
-         * 12289 = Auto Selected
-         * 12290 = Right
-         * 12291 = Centre
-         * 12292 = Left
-         */
-        public static final int TAG_AF_POINT_SELECTED = OFFSET + 0x13;
-        /**
-         * 0 = Easy Shooting (See Easy Shooting Mode)
-         * 1 = Program
-         * 2 = Tv-Priority
-         * 3 = Av-Priority
-         * 4 = Manual
-         * 5 = A-DEP
-         */
-        public static final int TAG_EXPOSURE_MODE = OFFSET + 0x14;
-        public static final int TAG_UNKNOWN_7 = OFFSET + 0x15;
-        public static final int TAG_LENS_TYPE = OFFSET + 0x16;
-        public static final int TAG_LONG_FOCAL_LENGTH = OFFSET + 0x17;
-        public static final int TAG_SHORT_FOCAL_LENGTH = OFFSET + 0x18;
-        public static final int TAG_FOCAL_UNITS_PER_MM = OFFSET + 0x19;
-        public static final int TAG_MAX_APERTURE = OFFSET + 0x1A;
-        public static final int TAG_MIN_APERTURE = OFFSET + 0x1B;
-        /**
-         * 0 = Flash Did Not Fire
-         * 1 = Flash Fired
-         */
-        public static final int TAG_FLASH_ACTIVITY = OFFSET + 0x1C;
-        public static final int TAG_FLASH_DETAILS = OFFSET + 0x1D;
-        public static final int TAG_FOCUS_CONTINUOUS = OFFSET + 0x1E;
-        public static final int TAG_AE_SETTING = OFFSET + 0x1F;
-        /**
-         * 0 = Focus Mode: Single
-         * 1 = Focus Mode: Continuous
-         */
-        public static final int TAG_FOCUS_MODE_2 = OFFSET + 0x20;
-
-        public static final int TAG_DISPLAY_APERTURE = OFFSET + 0x21;
-        public static final int TAG_ZOOM_SOURCE_WIDTH = OFFSET + 0x22;
-        public static final int TAG_ZOOM_TARGET_WIDTH = OFFSET + 0x23;
-
-        public static final int TAG_SPOT_METERING_MODE = OFFSET + 0x25;
-        public static final int TAG_PHOTO_EFFECT = OFFSET + 0x26;
-        public static final int TAG_MANUAL_FLASH_OUTPUT = OFFSET + 0x27;
-
-        public static final int TAG_COLOR_TONE = OFFSET + 0x29;
-        public static final int TAG_SRAW_QUALITY = OFFSET + 0x2D;
-    }
-
-    public final static class FocalLength
-    {
-        // These 'sub'-tag values have been created for consistency -- they don't exist within the exif segment
-
-        private static final int OFFSET = 0xC200;
-
-        /**
-         * 0 = Auto
-         * 1 = Sunny
-         * 2 = Cloudy
-         * 3 = Tungsten
-         * 4 = Florescent
-         * 5 = Flash
-         * 6 = Custom
-         */
-        public static final int TAG_WHITE_BALANCE = OFFSET + 0x07;
-        public static final int TAG_SEQUENCE_NUMBER = OFFSET + 0x09;
-        public static final int TAG_AF_POINT_USED = OFFSET + 0x0E;
-        /**
-         * The value of this tag may be translated into a flash bias value, in EV.
-         *
-         * 0xffc0 = -2 EV
-         * 0xffcc = -1.67 EV
-         * 0xffd0 = -1.5 EV
-         * 0xffd4 = -1.33 EV
-         * 0xffe0 = -1 EV
-         * 0xffec = -0.67 EV
-         * 0xfff0 = -0.5 EV
-         * 0xfff4 = -0.33 EV
-         * 0x0000 = 0 EV
-         * 0x000c = 0.33 EV
-         * 0x0010 = 0.5 EV
-         * 0x0014 = 0.67 EV
-         * 0x0020 = 1 EV
-         * 0x002c = 1.33 EV
-         * 0x0030 = 1.5 EV
-         * 0x0034 = 1.67 EV
-         * 0x0040 = 2 EV
-         */
-        public static final int TAG_FLASH_BIAS = OFFSET + 0x0F;
-        public static final int TAG_AUTO_EXPOSURE_BRACKETING = OFFSET + 0x10;
-        public static final int TAG_AEB_BRACKET_VALUE = OFFSET + 0x11;
-        public static final int TAG_SUBJECT_DISTANCE = OFFSET + 0x13;
-    }
-
-    public final static class ShotInfo
-    {
-        // These 'sub'-tag values have been created for consistency -- they don't exist within the exif segment
-
-        private static final int OFFSET = 0xC400;
-
-        public static final int TAG_AUTO_ISO = OFFSET + 1;
-        public static final int TAG_BASE_ISO = OFFSET + 2;
-        public static final int TAG_MEASURED_EV = OFFSET + 3;
-        public static final int TAG_TARGET_APERTURE = OFFSET + 4;
-        public static final int TAG_TARGET_EXPOSURE_TIME = OFFSET + 5;
-        public static final int TAG_EXPOSURE_COMPENSATION = OFFSET + 6;
-        public static final int TAG_WHITE_BALANCE = OFFSET + 7;
-        public static final int TAG_SLOW_SHUTTER = OFFSET + 8;
-        public static final int TAG_SEQUENCE_NUMBER = OFFSET + 9;
-        public static final int TAG_OPTICAL_ZOOM_CODE = OFFSET + 10;
-        public static final int TAG_CAMERA_TEMPERATURE = OFFSET + 12;
-        public static final int TAG_FLASH_GUIDE_NUMBER = OFFSET + 13;
-        public static final int TAG_AF_POINTS_IN_FOCUS = OFFSET + 14;
-        public static final int TAG_FLASH_EXPOSURE_BRACKETING = OFFSET + 15;
-        public static final int TAG_AUTO_EXPOSURE_BRACKETING = OFFSET + 16;
-        public static final int TAG_AEB_BRACKET_VALUE = OFFSET + 17;
-        public static final int TAG_CONTROL_MODE = OFFSET + 18;
-        public static final int TAG_FOCUS_DISTANCE_UPPER = OFFSET + 19;
-        public static final int TAG_FOCUS_DISTANCE_LOWER = OFFSET + 20;
-        public static final int TAG_F_NUMBER = OFFSET + 21;
-        public static final int TAG_EXPOSURE_TIME = OFFSET + 22;
-        public static final int TAG_MEASURED_EV_2 = OFFSET + 23;
-        public static final int TAG_BULB_DURATION = OFFSET + 24;
-        public static final int TAG_CAMERA_TYPE = OFFSET + 26;
-        public static final int TAG_AUTO_ROTATE = OFFSET + 27;
-        public static final int TAG_ND_FILTER = OFFSET + 28;
-        public static final int TAG_SELF_TIMER_2 = OFFSET + 29;
-        public static final int TAG_FLASH_OUTPUT = OFFSET + 33;
-    }
-
-    public final static class Panorama
-    {
-        // These 'sub'-tag values have been created for consistency -- they don't exist within the exif segment
-
-        private static final int OFFSET = 0xC500;
-
-        public static final int TAG_PANORAMA_FRAME_NUMBER = OFFSET + 2;
-        public static final int TAG_PANORAMA_DIRECTION = OFFSET + 5;
-    }
-
-    public final static class AFInfo
-    {
-        // These 'sub'-tag values have been created for consistency -- they don't exist within the exif segment
-
-        private static final int OFFSET = 0xD200;
-
-        public static final int TAG_NUM_AF_POINTS = OFFSET;
-        public static final int TAG_VALID_AF_POINTS = OFFSET + 1;
-        public static final int TAG_IMAGE_WIDTH = OFFSET + 2;
-        public static final int TAG_IMAGE_HEIGHT = OFFSET + 3;
-        public static final int TAG_AF_IMAGE_WIDTH = OFFSET + 4;
-        public static final int TAG_AF_IMAGE_HEIGHT = OFFSET + 5;
-        public static final int TAG_AF_AREA_WIDTH = OFFSET + 6;
-        public static final int TAG_AF_AREA_HEIGHT = OFFSET + 7;
-        public static final int TAG_AF_AREA_X_POSITIONS = OFFSET + 8;
-        public static final int TAG_AF_AREA_Y_POSITIONS = OFFSET + 9;
-        public static final int TAG_AF_POINTS_IN_FOCUS = OFFSET + 10;
-        public static final int TAG_PRIMARY_AF_POINT_1 = OFFSET + 11;
-        public static final int TAG_PRIMARY_AF_POINT_2 = OFFSET + 12; // not sure why there are two of these
-    }
-
-//    /**
-//     * Long Exposure Noise Reduction
-//     * 0 = Off
-//     * 1 = On
-//     */
-//    public static final int TAG_CANON_CUSTOM_FUNCTION_LONG_EXPOSURE_NOISE_REDUCTION = 0xC301;
-//
-//    /**
-//     * Shutter/Auto Exposure-lock buttons
-//     * 0 = AF/AE lock
-//     * 1 = AE lock/AF
-//     * 2 = AF/AF lock
-//     * 3 = AE+release/AE+AF
-//     */
-//    public static final int TAG_CANON_CUSTOM_FUNCTION_SHUTTER_AUTO_EXPOSURE_LOCK_BUTTONS = 0xC302;
-//
-//    /**
-//     * Mirror lockup
-//     * 0 = Disable
-//     * 1 = Enable
-//     */
-//    public static final int TAG_CANON_CUSTOM_FUNCTION_MIRROR_LOCKUP = 0xC303;
-//
-//    /**
-//     * Tv/Av and exposure level
-//     * 0 = 1/2 stop
-//     * 1 = 1/3 stop
-//     */
-//    public static final int TAG_CANON_CUSTOM_FUNCTION_TV_AV_AND_EXPOSURE_LEVEL = 0xC304;
-//
-//    /**
-//     * AF-assist light
-//     * 0 = On (Auto)
-//     * 1 = Off
-//     */
-//    public static final int TAG_CANON_CUSTOM_FUNCTION_AF_ASSIST_LIGHT = 0xC305;
-//
-//    /**
-//     * Shutter speed in Av mode
-//     * 0 = Automatic
-//     * 1 = 1/200 (fixed)
-//     */
-//    public static final int TAG_CANON_CUSTOM_FUNCTION_SHUTTER_SPEED_IN_AV_MODE = 0xC306;
-//
-//    /**
-//     * Auto-Exposure Bracketing sequence/auto cancellation
-//     * 0 = 0,-,+ / Enabled
-//     * 1 = 0,-,+ / Disabled
-//     * 2 = -,0,+ / Enabled
-//     * 3 = -,0,+ / Disabled
-//     */
-//    public static final int TAG_CANON_CUSTOM_FUNCTION_BRACKETING = 0xC307;
-//
-//    /**
-//     * Shutter Curtain Sync
-//     * 0 = 1st Curtain Sync
-//     * 1 = 2nd Curtain Sync
-//     */
-//    public static final int TAG_CANON_CUSTOM_FUNCTION_SHUTTER_CURTAIN_SYNC = 0xC308;
-//
-//    /**
-//     * Lens Auto-Focus stop button Function Switch
-//     * 0 = AF stop
-//     * 1 = Operate AF
-//     * 2 = Lock AE and start timer
-//     */
-//    public static final int TAG_CANON_CUSTOM_FUNCTION_AF_STOP = 0xC309;
-//
-//    /**
-//     * Auto reduction of fill flash
-//     * 0 = Enable
-//     * 1 = Disable
-//     */
-//    public static final int TAG_CANON_CUSTOM_FUNCTION_FILL_FLASH_REDUCTION = 0xC30A;
-//
-//    /**
-//     * Menu button return position
-//     * 0 = Top
-//     * 1 = Previous (volatile)
-//     * 2 = Previous
-//     */
-//    public static final int TAG_CANON_CUSTOM_FUNCTION_MENU_BUTTON_RETURN = 0xC30B;
-//
-//    /**
-//     * SET button function when shooting
-//     * 0 = Not Assigned
-//     * 1 = Change Quality
-//     * 2 = Change ISO Speed
-//     * 3 = Select Parameters
-//     */
-//    public static final int TAG_CANON_CUSTOM_FUNCTION_SET_BUTTON_FUNCTION = 0xC30C;
-//
-//    /**
-//     * Sensor cleaning
-//     * 0 = Disable
-//     * 1 = Enable
-//     */
-//    public static final int TAG_CANON_CUSTOM_FUNCTION_SENSOR_CLEANING = 0xC30D;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TAG_CANON_FIRMWARE_VERSION, "Firmware Version");
-        _tagNameMap.put(TAG_CANON_IMAGE_NUMBER, "Image Number");
-        _tagNameMap.put(TAG_CANON_IMAGE_TYPE, "Image Type");
-        _tagNameMap.put(TAG_CANON_OWNER_NAME, "Owner Name");
-        _tagNameMap.put(TAG_CANON_SERIAL_NUMBER, "Camera Serial Number");
-        _tagNameMap.put(TAG_CAMERA_INFO_ARRAY, "Camera Info Array");
-        _tagNameMap.put(TAG_CANON_FILE_LENGTH, "File Length");
-        _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTIONS_ARRAY, "Custom Functions");
-        _tagNameMap.put(TAG_MODEL_ID, "Canon Model ID");
-        _tagNameMap.put(TAG_MOVIE_INFO_ARRAY, "Movie Info Array");
-
-        _tagNameMap.put(CameraSettings.TAG_AF_POINT_SELECTED, "AF Point Selected");
-        _tagNameMap.put(CameraSettings.TAG_CONTINUOUS_DRIVE_MODE, "Continuous Drive Mode");
-        _tagNameMap.put(CameraSettings.TAG_CONTRAST, "Contrast");
-        _tagNameMap.put(CameraSettings.TAG_EASY_SHOOTING_MODE, "Easy Shooting Mode");
-        _tagNameMap.put(CameraSettings.TAG_EXPOSURE_MODE, "Exposure Mode");
-        _tagNameMap.put(CameraSettings.TAG_FLASH_DETAILS, "Flash Details");
-        _tagNameMap.put(CameraSettings.TAG_FLASH_MODE, "Flash Mode");
-        _tagNameMap.put(CameraSettings.TAG_FOCAL_UNITS_PER_MM, "Focal Units per mm");
-        _tagNameMap.put(CameraSettings.TAG_FOCUS_MODE_1, "Focus Mode");
-        _tagNameMap.put(CameraSettings.TAG_FOCUS_MODE_2, "Focus Mode");
-        _tagNameMap.put(CameraSettings.TAG_IMAGE_SIZE, "Image Size");
-        _tagNameMap.put(CameraSettings.TAG_ISO, "Iso");
-        _tagNameMap.put(CameraSettings.TAG_LONG_FOCAL_LENGTH, "Long Focal Length");
-        _tagNameMap.put(CameraSettings.TAG_MACRO_MODE, "Macro Mode");
-        _tagNameMap.put(CameraSettings.TAG_METERING_MODE, "Metering Mode");
-        _tagNameMap.put(CameraSettings.TAG_SATURATION, "Saturation");
-        _tagNameMap.put(CameraSettings.TAG_SELF_TIMER_DELAY, "Self Timer Delay");
-        _tagNameMap.put(CameraSettings.TAG_SHARPNESS, "Sharpness");
-        _tagNameMap.put(CameraSettings.TAG_SHORT_FOCAL_LENGTH, "Short Focal Length");
-        _tagNameMap.put(CameraSettings.TAG_QUALITY, "Quality");
-        _tagNameMap.put(CameraSettings.TAG_UNKNOWN_2, "Unknown Camera Setting 2");
-        _tagNameMap.put(CameraSettings.TAG_UNKNOWN_3, "Unknown Camera Setting 3");
-        _tagNameMap.put(CameraSettings.TAG_RECORD_MODE, "Record Mode");
-        _tagNameMap.put(CameraSettings.TAG_DIGITAL_ZOOM, "Digital Zoom");
-        _tagNameMap.put(CameraSettings.TAG_FOCUS_TYPE, "Focus Type");
-        _tagNameMap.put(CameraSettings.TAG_UNKNOWN_7, "Unknown Camera Setting 7");
-        _tagNameMap.put(CameraSettings.TAG_LENS_TYPE, "Lens Type");
-        _tagNameMap.put(CameraSettings.TAG_MAX_APERTURE, "Max Aperture");
-        _tagNameMap.put(CameraSettings.TAG_MIN_APERTURE, "Min Aperture");
-        _tagNameMap.put(CameraSettings.TAG_FLASH_ACTIVITY, "Flash Activity");
-        _tagNameMap.put(CameraSettings.TAG_FOCUS_CONTINUOUS, "Focus Continuous");
-        _tagNameMap.put(CameraSettings.TAG_AE_SETTING, "AE Setting");
-        _tagNameMap.put(CameraSettings.TAG_DISPLAY_APERTURE, "Display Aperture");
-        _tagNameMap.put(CameraSettings.TAG_ZOOM_SOURCE_WIDTH, "Zoom Source Width");
-        _tagNameMap.put(CameraSettings.TAG_ZOOM_TARGET_WIDTH, "Zoom Target Width");
-        _tagNameMap.put(CameraSettings.TAG_SPOT_METERING_MODE, "Spot Metering Mode");
-        _tagNameMap.put(CameraSettings.TAG_PHOTO_EFFECT, "Photo Effect");
-        _tagNameMap.put(CameraSettings.TAG_MANUAL_FLASH_OUTPUT, "Manual Flash Output");
-        _tagNameMap.put(CameraSettings.TAG_COLOR_TONE, "Color Tone");
-        _tagNameMap.put(CameraSettings.TAG_SRAW_QUALITY, "SRAW Quality");
-
-        _tagNameMap.put(FocalLength.TAG_WHITE_BALANCE, "White Balance");
-        _tagNameMap.put(FocalLength.TAG_SEQUENCE_NUMBER, "Sequence Number");
-        _tagNameMap.put(FocalLength.TAG_AF_POINT_USED, "AF Point Used");
-        _tagNameMap.put(FocalLength.TAG_FLASH_BIAS, "Flash Bias");
-        _tagNameMap.put(FocalLength.TAG_AUTO_EXPOSURE_BRACKETING, "Auto Exposure Bracketing");
-        _tagNameMap.put(FocalLength.TAG_AEB_BRACKET_VALUE, "AEB Bracket Value");
-        _tagNameMap.put(FocalLength.TAG_SUBJECT_DISTANCE, "Subject Distance");
-
-        _tagNameMap.put(ShotInfo.TAG_AUTO_ISO, "Auto ISO");
-        _tagNameMap.put(ShotInfo.TAG_BASE_ISO, "Base ISO");
-        _tagNameMap.put(ShotInfo.TAG_MEASURED_EV, "Measured EV");
-        _tagNameMap.put(ShotInfo.TAG_TARGET_APERTURE, "Target Aperture");
-        _tagNameMap.put(ShotInfo.TAG_TARGET_EXPOSURE_TIME, "Target Exposure Time");
-        _tagNameMap.put(ShotInfo.TAG_EXPOSURE_COMPENSATION, "Exposure Compensation");
-        _tagNameMap.put(ShotInfo.TAG_WHITE_BALANCE, "White Balance");
-        _tagNameMap.put(ShotInfo.TAG_SLOW_SHUTTER, "Slow Shutter");
-        _tagNameMap.put(ShotInfo.TAG_SEQUENCE_NUMBER, "Sequence Number");
-        _tagNameMap.put(ShotInfo.TAG_OPTICAL_ZOOM_CODE, "Optical Zoom Code");
-        _tagNameMap.put(ShotInfo.TAG_CAMERA_TEMPERATURE, "Camera Temperature");
-        _tagNameMap.put(ShotInfo.TAG_FLASH_GUIDE_NUMBER, "Flash Guide Number");
-        _tagNameMap.put(ShotInfo.TAG_AF_POINTS_IN_FOCUS, "AF Points in Focus");
-        _tagNameMap.put(ShotInfo.TAG_FLASH_EXPOSURE_BRACKETING, "Flash Exposure Compensation");
-        _tagNameMap.put(ShotInfo.TAG_AUTO_EXPOSURE_BRACKETING, "Auto Exposure Bracketing");
-        _tagNameMap.put(ShotInfo.TAG_AEB_BRACKET_VALUE, "AEB Bracket Value");
-        _tagNameMap.put(ShotInfo.TAG_CONTROL_MODE, "Control Mode");
-        _tagNameMap.put(ShotInfo.TAG_FOCUS_DISTANCE_UPPER, "Focus Distance Upper");
-        _tagNameMap.put(ShotInfo.TAG_FOCUS_DISTANCE_LOWER, "Focus Distance Lower");
-        _tagNameMap.put(ShotInfo.TAG_F_NUMBER, "F Number");
-        _tagNameMap.put(ShotInfo.TAG_EXPOSURE_TIME, "Exposure Time");
-        _tagNameMap.put(ShotInfo.TAG_MEASURED_EV_2, "Measured EV 2");
-        _tagNameMap.put(ShotInfo.TAG_BULB_DURATION, "Bulb Duration");
-        _tagNameMap.put(ShotInfo.TAG_CAMERA_TYPE, "Camera Type");
-        _tagNameMap.put(ShotInfo.TAG_AUTO_ROTATE, "Auto Rotate");
-        _tagNameMap.put(ShotInfo.TAG_ND_FILTER, "ND Filter");
-        _tagNameMap.put(ShotInfo.TAG_SELF_TIMER_2, "Self Timer 2");
-        _tagNameMap.put(ShotInfo.TAG_FLASH_OUTPUT, "Flash Output");
-
-        _tagNameMap.put(Panorama.TAG_PANORAMA_FRAME_NUMBER, "Panorama Frame Number");
-        _tagNameMap.put(Panorama.TAG_PANORAMA_DIRECTION, "Panorama Direction");
-
-        _tagNameMap.put(AFInfo.TAG_NUM_AF_POINTS, "AF Point Count");
-        _tagNameMap.put(AFInfo.TAG_VALID_AF_POINTS, "Valid AF Point Count");
-        _tagNameMap.put(AFInfo.TAG_IMAGE_WIDTH, "Image Width");
-        _tagNameMap.put(AFInfo.TAG_IMAGE_HEIGHT, "Image Height");
-        _tagNameMap.put(AFInfo.TAG_AF_IMAGE_WIDTH, "AF Image Width");
-        _tagNameMap.put(AFInfo.TAG_AF_IMAGE_HEIGHT, "AF Image Height");
-        _tagNameMap.put(AFInfo.TAG_AF_AREA_WIDTH, "AF Area Width");
-        _tagNameMap.put(AFInfo.TAG_AF_AREA_HEIGHT, "AF Area Height");
-        _tagNameMap.put(AFInfo.TAG_AF_AREA_X_POSITIONS, "AF Area X Positions");
-        _tagNameMap.put(AFInfo.TAG_AF_AREA_Y_POSITIONS, "AF Area Y Positions");
-        _tagNameMap.put(AFInfo.TAG_AF_POINTS_IN_FOCUS, "AF Points in Focus");
-        _tagNameMap.put(AFInfo.TAG_PRIMARY_AF_POINT_1, "Primary AF Point 1");
-        _tagNameMap.put(AFInfo.TAG_PRIMARY_AF_POINT_2, "Primary AF Point 2");
-
-//        _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_LONG_EXPOSURE_NOISE_REDUCTION, "Long Exposure Noise Reduction");
-//        _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_SHUTTER_AUTO_EXPOSURE_LOCK_BUTTONS, "Shutter/Auto Exposure-lock Buttons");
-//        _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_MIRROR_LOCKUP, "Mirror Lockup");
-//        _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_TV_AV_AND_EXPOSURE_LEVEL, "Tv/Av And Exposure Level");
-//        _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_AF_ASSIST_LIGHT, "AF-Assist Light");
-//        _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_SHUTTER_SPEED_IN_AV_MODE, "Shutter Speed in Av Mode");
-//        _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_BRACKETING, "Auto-Exposure Bracketing Sequence/Auto Cancellation");
-//        _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_SHUTTER_CURTAIN_SYNC, "Shutter Curtain Sync");
-//        _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_AF_STOP, "Lens Auto-Focus Stop Button Function Switch");
-//        _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_FILL_FLASH_REDUCTION, "Auto Reduction of Fill Flash");
-//        _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_MENU_BUTTON_RETURN, "Menu Button Return Position");
-//        _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_SET_BUTTON_FUNCTION, "SET Button Function When Shooting");
-//        _tagNameMap.put(TAG_CANON_CUSTOM_FUNCTION_SENSOR_CLEANING, "Sensor Cleaning");
-
-        _tagNameMap.put(TAG_THUMBNAIL_IMAGE_VALID_AREA, "Thumbnail Image Valid Area");
-        _tagNameMap.put(TAG_SERIAL_NUMBER_FORMAT, "Serial Number Format");
-        _tagNameMap.put(TAG_SUPER_MACRO, "Super Macro");
-        _tagNameMap.put(TAG_DATE_STAMP_MODE, "Date Stamp Mode");
-        _tagNameMap.put(TAG_MY_COLORS, "My Colors");
-        _tagNameMap.put(TAG_FIRMWARE_REVISION, "Firmware Revision");
-        _tagNameMap.put(TAG_CATEGORIES, "Categories");
-        _tagNameMap.put(TAG_FACE_DETECT_ARRAY_1, "Face Detect Array 1");
-        _tagNameMap.put(TAG_FACE_DETECT_ARRAY_2, "Face Detect Array 2");
-        _tagNameMap.put(TAG_AF_INFO_ARRAY_2, "AF Info Array 2");
-        _tagNameMap.put(TAG_IMAGE_UNIQUE_ID, "Image Unique ID");
-        _tagNameMap.put(TAG_RAW_DATA_OFFSET, "Raw Data Offset");
-        _tagNameMap.put(TAG_ORIGINAL_DECISION_DATA_OFFSET, "Original Decision Data Offset");
-        _tagNameMap.put(TAG_CUSTOM_FUNCTIONS_1D_ARRAY, "Custom Functions (1D) Array");
-        _tagNameMap.put(TAG_PERSONAL_FUNCTIONS_ARRAY, "Personal Functions Array");
-        _tagNameMap.put(TAG_PERSONAL_FUNCTION_VALUES_ARRAY, "Personal Function Values Array");
-        _tagNameMap.put(TAG_FILE_INFO_ARRAY, "File Info Array");
-        _tagNameMap.put(TAG_AF_POINTS_IN_FOCUS_1D, "AF Points in Focus (1D)");
-        _tagNameMap.put(TAG_LENS_MODEL, "Lens Model");
-        _tagNameMap.put(TAG_SERIAL_INFO_ARRAY, "Serial Info Array");
-        _tagNameMap.put(TAG_DUST_REMOVAL_DATA, "Dust Removal Data");
-        _tagNameMap.put(TAG_CROP_INFO, "Crop Info");
-        _tagNameMap.put(TAG_CUSTOM_FUNCTIONS_ARRAY_2, "Custom Functions Array 2");
-        _tagNameMap.put(TAG_ASPECT_INFO_ARRAY, "Aspect Information Array");
-        _tagNameMap.put(TAG_PROCESSING_INFO_ARRAY, "Processing Information Array");
-        _tagNameMap.put(TAG_TONE_CURVE_TABLE, "Tone Curve Table");
-        _tagNameMap.put(TAG_SHARPNESS_TABLE, "Sharpness Table");
-        _tagNameMap.put(TAG_SHARPNESS_FREQ_TABLE, "Sharpness Frequency Table");
-        _tagNameMap.put(TAG_WHITE_BALANCE_TABLE, "White Balance Table");
-        _tagNameMap.put(TAG_COLOR_BALANCE_ARRAY, "Color Balance Array");
-        _tagNameMap.put(TAG_MEASURED_COLOR_ARRAY, "Measured Color Array");
-        _tagNameMap.put(TAG_COLOR_TEMPERATURE, "Color Temperature");
-        _tagNameMap.put(TAG_CANON_FLAGS_ARRAY, "Canon Flags Array");
-        _tagNameMap.put(TAG_MODIFIED_INFO_ARRAY, "Modified Information Array");
-        _tagNameMap.put(TAG_TONE_CURVE_MATCHING, "Tone Curve Matching");
-        _tagNameMap.put(TAG_WHITE_BALANCE_MATCHING, "White Balance Matching");
-        _tagNameMap.put(TAG_COLOR_SPACE, "Color Space");
-        _tagNameMap.put(TAG_PREVIEW_IMAGE_INFO_ARRAY, "Preview Image Info Array");
-        _tagNameMap.put(TAG_VRD_OFFSET, "VRD Offset");
-        _tagNameMap.put(TAG_SENSOR_INFO_ARRAY, "Sensor Information Array");
-        _tagNameMap.put(TAG_COLOR_DATA_ARRAY_2, "Color Data Array 1");
-        _tagNameMap.put(TAG_CRW_PARAM, "CRW Parameters");
-        _tagNameMap.put(TAG_COLOR_INFO_ARRAY_2, "Color Data Array 2");
-        _tagNameMap.put(TAG_BLACK_LEVEL, "Black Level");
-        _tagNameMap.put(TAG_CUSTOM_PICTURE_STYLE_FILE_NAME, "Custom Picture Style File Name");
-        _tagNameMap.put(TAG_COLOR_INFO_ARRAY, "Color Info Array");
-        _tagNameMap.put(TAG_VIGNETTING_CORRECTION_ARRAY_1, "Vignetting Correction Array 1");
-        _tagNameMap.put(TAG_VIGNETTING_CORRECTION_ARRAY_2, "Vignetting Correction Array 2");
-        _tagNameMap.put(TAG_LIGHTING_OPTIMIZER_ARRAY, "Lighting Optimizer Array");
-        _tagNameMap.put(TAG_LENS_INFO_ARRAY, "Lens Info Array");
-        _tagNameMap.put(TAG_AMBIANCE_INFO_ARRAY, "Ambiance Info Array");
-        _tagNameMap.put(TAG_FILTER_INFO_ARRAY, "Filter Info Array");
-    }
-
-    public CanonMakernoteDirectory()
-    {
-        this.setDescriptor(new CanonMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Canon Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-
-    @Override
-    public void setObjectArray(int tagType, @NotNull Object array)
-    {
-        // TODO is there some way to drop out 'null' or 'zero' values that are present in the array to reduce the noise?
-
-        if (!(array instanceof int[])) {
-            // no special handling...
-            super.setObjectArray(tagType, array);
-            return;
-        }
-
-        // Certain Canon tags contain arrays of values that we split into 'fake' tags as each
-        // index in the array has its own meaning and decoding.
-        // Pick those tags out here and throw away the original array.
-        // Otherwise just add as usual.
-        switch (tagType) {
-            case TAG_CAMERA_SETTINGS_ARRAY: {
-                int[] ints = (int[])array;
-                for (int i = 0; i < ints.length; i++)
-                    setInt(CameraSettings.OFFSET + i, ints[i]);
-                break;
-            }
-            case TAG_FOCAL_LENGTH_ARRAY: {
-                int[] ints = (int[])array;
-                for (int i = 0; i < ints.length; i++)
-                    setInt(FocalLength.OFFSET + i, ints[i]);
-                break;
-            }
-            case TAG_SHOT_INFO_ARRAY: {
-                int[] ints = (int[])array;
-                for (int i = 0; i < ints.length; i++)
-                    setInt(ShotInfo.OFFSET + i, ints[i]);
-                break;
-            }
-            case TAG_PANORAMA_ARRAY: {
-                int[] ints = (int[])array;
-                for (int i = 0; i < ints.length; i++)
-                    setInt(Panorama.OFFSET + i, ints[i]);
-                break;
-            }
-            // TODO the interpretation of the custom functions tag depends upon the camera model
-//            case TAG_CANON_CUSTOM_FUNCTIONS_ARRAY:
-//                int subTagTypeBase = 0xC300;
-//                // we intentionally skip the first array member
-//                for (int i = 1; i < ints.length; i++)
-//                    setInt(subTagTypeBase + i + 1, ints[i] & 0x0F);
-//                break;
-            case TAG_AF_INFO_ARRAY: {
-                // Notes from Exiftool 10.10 by Phil Harvey, lib\Image\Exiftool\Canon.pm:
-                // Auto-focus information used by many older Canon models. The values in this
-                // record are sequential, and some have variable sizes based on the value of
-                // numafpoints (which may be 1,5,7,9,15,45, or 53). The AFArea coordinates are
-                // given in a system where the image has dimensions given by AFImageWidth and
-                // AFImageHeight, and 0,0 is the image center. The direction of the Y axis
-                // depends on the camera model, with positive Y upwards for EOS models, but
-                // apparently downwards for PowerShot models.
-
-                // AFInfo is another array with 'fake' tags. The first int of the array contains
-                // the number of AF points. Iterate through the array one byte at a time, generally
-                // assuming one byte corresponds to one tag UNLESS certain tag numbers are encountered.
-                // For these, read specific subsequent bytes from the array based on the tag type. The
-                // number of bytes read can vary.
-
-                int[] values = (int[])array;
-                int numafpoints = values[0];
-                int tagnumber = 0;
-                for (int i = 0; i < values.length; i++)
-                {
-                    // These two tags store 'numafpoints' bytes of data in the array
-                    if (AFInfo.OFFSET + tagnumber == AFInfo.TAG_AF_AREA_X_POSITIONS ||
-                        AFInfo.OFFSET + tagnumber == AFInfo.TAG_AF_AREA_Y_POSITIONS)
-                    {
-                        // There could be incorrect data in the array, so boundary check
-                        if (values.length - 1 >= (i + numafpoints))
-                        {
-                            short[] areaPositions = new short[numafpoints];
-                            for (int j = 0; j < areaPositions.length; j++)
-                                areaPositions[j] = (short)values[i + j];
-
-                            super.setObjectArray(AFInfo.OFFSET + tagnumber, areaPositions);
-                        }
-                        i += numafpoints - 1;   // assume these bytes are processed and skip
-                    }
-                    else if (AFInfo.OFFSET + tagnumber == AFInfo.TAG_AF_POINTS_IN_FOCUS)
-                    {
-                        short[] pointsInFocus = new short[((numafpoints + 15) / 16)];
-
-                        // There could be incorrect data in the array, so boundary check
-                        if (values.length - 1 >= (i + pointsInFocus.length))
-                        {
-                            for (int j = 0; j < pointsInFocus.length; j++)
-                                pointsInFocus[j] = (short)values[i + j];
-
-                            super.setObjectArray(AFInfo.OFFSET + tagnumber, pointsInFocus);
-                        }
-                        i += pointsInFocus.length - 1;  // assume these bytes are processed and skip
-                    }
-                    else
-                        super.setObjectArray(AFInfo.OFFSET + tagnumber, values[i]);
-                    tagnumber++;
-                }
-                break;
-            }
-            default: {
-                // no special handling...
-                super.setObjectArray(tagType, array);
-                break;
-            }
-        }
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/CasioType1MakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/CasioType1MakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,201 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.makernotes.CasioType1MakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link CasioType1MakernoteDirectory}.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class CasioType1MakernoteDescriptor extends TagDescriptor<CasioType1MakernoteDirectory>
-{
-    public CasioType1MakernoteDescriptor(@NotNull CasioType1MakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_RECORDING_MODE:
-                return getRecordingModeDescription();
-            case TAG_QUALITY:
-                return getQualityDescription();
-            case TAG_FOCUSING_MODE:
-                return getFocusingModeDescription();
-            case TAG_FLASH_MODE:
-                return getFlashModeDescription();
-            case TAG_FLASH_INTENSITY:
-                return getFlashIntensityDescription();
-            case TAG_OBJECT_DISTANCE:
-                return getObjectDistanceDescription();
-            case TAG_WHITE_BALANCE:
-                return getWhiteBalanceDescription();
-            case TAG_DIGITAL_ZOOM:
-                return getDigitalZoomDescription();
-            case TAG_SHARPNESS:
-                return getSharpnessDescription();
-            case TAG_CONTRAST:
-                return getContrastDescription();
-            case TAG_SATURATION:
-                return getSaturationDescription();
-            case TAG_CCD_SENSITIVITY:
-                return getCcdSensitivityDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getCcdSensitivityDescription()
-    {
-        Integer value = _directory.getInteger(TAG_CCD_SENSITIVITY);
-
-        if (value == null)
-            return null;
-
-        switch (value) {
-            // these four for QV3000
-            case 64: return "Normal";
-            case 125: return "+1.0";
-            case 250: return "+2.0";
-            case 244: return "+3.0";
-            // these two for QV8000/2000
-            case 80: return "Normal (ISO 80 equivalent)";
-            case 100: return "High";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getSaturationDescription()
-    {
-        return getIndexedDescription(TAG_SATURATION, "Normal", "Low", "High");
-    }
-
-    @Nullable
-    public String getContrastDescription()
-    {
-        return getIndexedDescription(TAG_CONTRAST, "Normal", "Low", "High");
-    }
-
-    @Nullable
-    public String getSharpnessDescription()
-    {
-        return getIndexedDescription(TAG_SHARPNESS, "Normal", "Soft", "Hard");
-    }
-
-    @Nullable
-    public String getDigitalZoomDescription()
-    {
-        Integer value = _directory.getInteger(TAG_DIGITAL_ZOOM);
-
-        if (value == null)
-            return null;
-
-        switch (value) {
-            case 0x10000: return "No digital zoom";
-            case 0x10001: return "2x digital zoom";
-            case 0x20000: return "2x digital zoom";
-            case 0x40000: return "4x digital zoom";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getWhiteBalanceDescription()
-    {
-        Integer value = _directory.getInteger(TAG_WHITE_BALANCE);
-
-        if (value == null)
-            return null;
-
-        switch (value) {
-            case 1: return "Auto";
-            case 2: return "Tungsten";
-            case 3: return "Daylight";
-            case 4: return "Florescent";
-            case 5: return "Shade";
-            case 129: return "Manual";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getObjectDistanceDescription()
-    {
-        Integer value = _directory.getInteger(TAG_OBJECT_DISTANCE);
-        return value == null ? null : getFocalLengthDescription(value);
-    }
-
-    @Nullable
-    public String getFlashIntensityDescription()
-    {
-        Integer value = _directory.getInteger(TAG_FLASH_INTENSITY);
-
-        if (value == null)
-            return null;
-
-        switch (value) {
-            case 11: return "Weak";
-            case 13: return "Normal";
-            case 15: return "Strong";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getFlashModeDescription()
-    {
-        return getIndexedDescription(TAG_FLASH_MODE, 1, "Auto", "On", "Off", "Red eye reduction");
-    }
-
-    @Nullable
-    public String getFocusingModeDescription()
-    {
-        return getIndexedDescription(TAG_FOCUSING_MODE, 2, "Macro", "Auto focus", "Manual focus", "Infinity");
-    }
-
-    @Nullable
-    public String getQualityDescription()
-    {
-        return getIndexedDescription(TAG_QUALITY, 1, "Economy", "Normal", "Fine");
-    }
-
-    @Nullable
-    public String getRecordingModeDescription()
-    {
-        return getIndexedDescription(TAG_RECORDING_MODE, 1, "Single shutter", "Panorama", "Night scene", "Portrait", "Landscape");
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/CasioType1MakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/CasioType1MakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,105 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific to Casio (type 1) cameras.
- *
- * A standard TIFF IFD directory but always uses Motorola (Big-Endian) Byte Alignment.
- * Makernote data begins immediately (no header).
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class CasioType1MakernoteDirectory extends Directory
-{
-    public static final int TAG_RECORDING_MODE = 0x0001;
-    public static final int TAG_QUALITY = 0x0002;
-    public static final int TAG_FOCUSING_MODE = 0x0003;
-    public static final int TAG_FLASH_MODE = 0x0004;
-    public static final int TAG_FLASH_INTENSITY = 0x0005;
-    public static final int TAG_OBJECT_DISTANCE = 0x0006;
-    public static final int TAG_WHITE_BALANCE = 0x0007;
-    public static final int TAG_UNKNOWN_1 = 0x0008;
-    public static final int TAG_UNKNOWN_2 = 0x0009;
-    public static final int TAG_DIGITAL_ZOOM = 0x000A;
-    public static final int TAG_SHARPNESS = 0x000B;
-    public static final int TAG_CONTRAST = 0x000C;
-    public static final int TAG_SATURATION = 0x000D;
-    public static final int TAG_UNKNOWN_3 = 0x000E;
-    public static final int TAG_UNKNOWN_4 = 0x000F;
-    public static final int TAG_UNKNOWN_5 = 0x0010;
-    public static final int TAG_UNKNOWN_6 = 0x0011;
-    public static final int TAG_UNKNOWN_7 = 0x0012;
-    public static final int TAG_UNKNOWN_8 = 0x0013;
-    public static final int TAG_CCD_SENSITIVITY = 0x0014;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TAG_CCD_SENSITIVITY, "CCD Sensitivity");
-        _tagNameMap.put(TAG_CONTRAST, "Contrast");
-        _tagNameMap.put(TAG_DIGITAL_ZOOM, "Digital Zoom");
-        _tagNameMap.put(TAG_FLASH_INTENSITY, "Flash Intensity");
-        _tagNameMap.put(TAG_FLASH_MODE, "Flash Mode");
-        _tagNameMap.put(TAG_FOCUSING_MODE, "Focusing Mode");
-        _tagNameMap.put(TAG_OBJECT_DISTANCE, "Object Distance");
-        _tagNameMap.put(TAG_QUALITY, "Quality");
-        _tagNameMap.put(TAG_RECORDING_MODE, "Recording Mode");
-        _tagNameMap.put(TAG_SATURATION, "Saturation");
-        _tagNameMap.put(TAG_SHARPNESS, "Sharpness");
-        _tagNameMap.put(TAG_UNKNOWN_1, "Makernote Unknown 1");
-        _tagNameMap.put(TAG_UNKNOWN_2, "Makernote Unknown 2");
-        _tagNameMap.put(TAG_UNKNOWN_3, "Makernote Unknown 3");
-        _tagNameMap.put(TAG_UNKNOWN_4, "Makernote Unknown 4");
-        _tagNameMap.put(TAG_UNKNOWN_5, "Makernote Unknown 5");
-        _tagNameMap.put(TAG_UNKNOWN_6, "Makernote Unknown 6");
-        _tagNameMap.put(TAG_UNKNOWN_7, "Makernote Unknown 7");
-        _tagNameMap.put(TAG_UNKNOWN_8, "Makernote Unknown 8");
-        _tagNameMap.put(TAG_WHITE_BALANCE, "White Balance");
-    }
-
-    public CasioType1MakernoteDirectory()
-    {
-        this.setDescriptor(new CasioType1MakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Casio Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/CasioType2MakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/CasioType2MakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,320 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.makernotes.CasioType2MakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link CasioType2MakernoteDirectory}.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class CasioType2MakernoteDescriptor extends TagDescriptor<CasioType2MakernoteDirectory>
-{
-    public CasioType2MakernoteDescriptor(@NotNull CasioType2MakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_THUMBNAIL_DIMENSIONS:
-                return getThumbnailDimensionsDescription();
-            case TAG_THUMBNAIL_SIZE:
-                return getThumbnailSizeDescription();
-            case TAG_THUMBNAIL_OFFSET:
-                return getThumbnailOffsetDescription();
-            case TAG_QUALITY_MODE:
-                return getQualityModeDescription();
-            case TAG_IMAGE_SIZE:
-                return getImageSizeDescription();
-            case TAG_FOCUS_MODE_1:
-                return getFocusMode1Description();
-            case TAG_ISO_SENSITIVITY:
-                return getIsoSensitivityDescription();
-            case TAG_WHITE_BALANCE_1:
-                return getWhiteBalance1Description();
-            case TAG_FOCAL_LENGTH:
-                return getFocalLengthDescription();
-            case TAG_SATURATION:
-                return getSaturationDescription();
-            case TAG_CONTRAST:
-                return getContrastDescription();
-            case TAG_SHARPNESS:
-                return getSharpnessDescription();
-            case TAG_PREVIEW_THUMBNAIL:
-                return getCasioPreviewThumbnailDescription();
-            case TAG_WHITE_BALANCE_BIAS:
-                return getWhiteBalanceBiasDescription();
-            case TAG_WHITE_BALANCE_2:
-                return getWhiteBalance2Description();
-            case TAG_OBJECT_DISTANCE:
-                return getObjectDistanceDescription();
-            case TAG_FLASH_DISTANCE:
-                return getFlashDistanceDescription();
-            case TAG_RECORD_MODE:
-                return getRecordModeDescription();
-            case TAG_SELF_TIMER:
-                return getSelfTimerDescription();
-            case TAG_QUALITY:
-                return getQualityDescription();
-            case TAG_FOCUS_MODE_2:
-                return getFocusMode2Description();
-            case TAG_TIME_ZONE:
-                return getTimeZoneDescription();
-            case TAG_CCD_ISO_SENSITIVITY:
-                return getCcdIsoSensitivityDescription();
-            case TAG_COLOUR_MODE:
-                return getColourModeDescription();
-            case TAG_ENHANCEMENT:
-                return getEnhancementDescription();
-            case TAG_FILTER:
-                return getFilterDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getFilterDescription()
-    {
-        return getIndexedDescription(TAG_FILTER, "Off");
-    }
-
-    @Nullable
-    public String getEnhancementDescription()
-    {
-        return getIndexedDescription(TAG_ENHANCEMENT, "Off");
-    }
-
-    @Nullable
-    public String getColourModeDescription()
-    {
-        return getIndexedDescription(TAG_COLOUR_MODE, "Off");
-    }
-
-    @Nullable
-    public String getCcdIsoSensitivityDescription()
-    {
-        return getIndexedDescription(TAG_CCD_ISO_SENSITIVITY, "Off", "On");
-    }
-
-    @Nullable
-    public String getTimeZoneDescription()
-    {
-        return _directory.getString(TAG_TIME_ZONE);
-    }
-
-    @Nullable
-    public String getFocusMode2Description()
-    {
-        Integer value = _directory.getInteger(TAG_FOCUS_MODE_2);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 1: return "Fixation";
-            case 6: return "Multi-Area Focus";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getQualityDescription()
-    {
-        return getIndexedDescription(TAG_QUALITY, 3, "Fine");
-    }
-
-    @Nullable
-    public String getSelfTimerDescription()
-    {
-        return getIndexedDescription(TAG_SELF_TIMER, 1, "Off");
-    }
-
-    @Nullable
-    public String getRecordModeDescription()
-    {
-        return getIndexedDescription(TAG_RECORD_MODE, 2, "Normal");
-    }
-
-    @Nullable
-    public String getFlashDistanceDescription()
-    {
-        return getIndexedDescription(TAG_FLASH_DISTANCE, "Off");
-    }
-
-    @Nullable
-    public String getObjectDistanceDescription()
-    {
-        Integer value = _directory.getInteger(TAG_OBJECT_DISTANCE);
-        if (value == null)
-            return null;
-        return Integer.toString(value) + " mm";
-    }
-
-    @Nullable
-    public String getWhiteBalance2Description()
-    {
-        Integer value = _directory.getInteger(TAG_WHITE_BALANCE_2);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "Manual";
-            case 1: return "Auto"; // unsure about this
-            case 4: return "Flash"; // unsure about this
-            case 12: return "Flash";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getWhiteBalanceBiasDescription()
-    {
-        return _directory.getString(TAG_WHITE_BALANCE_BIAS);
-    }
-
-    @Nullable
-    public String getCasioPreviewThumbnailDescription()
-    {
-        final byte[] bytes = _directory.getByteArray(TAG_PREVIEW_THUMBNAIL);
-        if (bytes == null)
-            return null;
-        return "<" + bytes.length + " bytes of image data>";
-    }
-
-    @Nullable
-    public String getSharpnessDescription()
-    {
-        return getIndexedDescription(TAG_SHARPNESS, "-1", "Normal", "+1");
-    }
-
-    @Nullable
-    public String getContrastDescription()
-    {
-        return getIndexedDescription(TAG_CONTRAST, "-1", "Normal", "+1");
-    }
-
-    @Nullable
-    public String getSaturationDescription()
-    {
-        return getIndexedDescription(TAG_SATURATION, "-1", "Normal", "+1");
-    }
-
-    @Nullable
-    public String getFocalLengthDescription()
-    {
-        Double value = _directory.getDoubleObject(TAG_FOCAL_LENGTH);
-        return value == null ? null : getFocalLengthDescription(value / 10d);
-    }
-
-    @Nullable
-    public String getWhiteBalance1Description()
-    {
-        return getIndexedDescription(
-            TAG_WHITE_BALANCE_1,
-            "Auto",
-            "Daylight",
-            "Shade",
-            "Tungsten",
-            "Florescent",
-            "Manual"
-        );
-    }
-
-    @Nullable
-    public String getIsoSensitivityDescription()
-    {
-        Integer value = _directory.getInteger(TAG_ISO_SENSITIVITY);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 3: return "50";
-            case 4: return "64";
-            case 6: return "100";
-            case 9: return "200";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getFocusMode1Description()
-    {
-        return getIndexedDescription(TAG_FOCUS_MODE_1, "Normal", "Macro");
-    }
-
-    @Nullable
-    public String getImageSizeDescription()
-    {
-        Integer value = _directory.getInteger(TAG_IMAGE_SIZE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "640 x 480 pixels";
-            case 4: return "1600 x 1200 pixels";
-            case 5: return "2048 x 1536 pixels";
-            case 20: return "2288 x 1712 pixels";
-            case 21: return "2592 x 1944 pixels";
-            case 22: return "2304 x 1728 pixels";
-            case 36: return "3008 x 2008 pixels";
-            default: return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getQualityModeDescription()
-    {
-        return getIndexedDescription(TAG_QUALITY_MODE, 1, "Fine", "Super Fine");
-    }
-
-    @Nullable
-    public String getThumbnailOffsetDescription()
-    {
-        return _directory.getString(TAG_THUMBNAIL_OFFSET);
-    }
-
-    @Nullable
-    public String getThumbnailSizeDescription()
-    {
-        Integer value = _directory.getInteger(TAG_THUMBNAIL_SIZE);
-        if (value == null)
-            return null;
-        return Integer.toString(value) + " bytes";
-    }
-
-    @Nullable
-    public String getThumbnailDimensionsDescription()
-    {
-        int[] dimensions = _directory.getIntArray(TAG_THUMBNAIL_DIMENSIONS);
-        if (dimensions == null || dimensions.length != 2)
-            return _directory.getString(TAG_THUMBNAIL_DIMENSIONS);
-        return dimensions[0] + " x " + dimensions[1] + " pixels";
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/CasioType2MakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/CasioType2MakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,233 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific to Casio (type 2) cameras.
- *
- * A standard TIFF IFD directory but always uses Motorola (Big-Endian) Byte Alignment.
- * Makernote data begins after a 6-byte header: "QVC\x00\x00\x00"
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class CasioType2MakernoteDirectory extends Directory
-{
-    /**
-     * 2 values - x,y dimensions in pixels.
-     */
-    public static final int TAG_THUMBNAIL_DIMENSIONS = 0x0002;
-    /**
-     * Size in bytes
-     */
-    public static final int TAG_THUMBNAIL_SIZE = 0x0003;
-    /**
-     * Offset of Preview Thumbnail
-     */
-    public static final int TAG_THUMBNAIL_OFFSET = 0x0004;
-    /**
-     * 1 = Fine
-     * 2 = Super Fine
-     */
-    public static final int TAG_QUALITY_MODE = 0x0008;
-    /**
-     * 0 = 640 x 480 pixels
-     * 4 = 1600 x 1200 pixels
-     * 5 = 2048 x 1536 pixels
-     * 20 = 2288 x 1712 pixels
-     * 21 = 2592 x 1944 pixels
-     * 22 = 2304 x 1728 pixels
-     * 36 = 3008 x 2008 pixels
-     */
-    public static final int TAG_IMAGE_SIZE = 0x0009;
-    /**
-     * 0 = Normal
-     * 1 = Macro
-     */
-    public static final int TAG_FOCUS_MODE_1 = 0x000D;
-    /**
-     * 3 = 50
-     * 4 = 64
-     * 6 = 100
-     * 9 = 200
-     */
-    public static final int TAG_ISO_SENSITIVITY = 0x0014;
-    /**
-     * 0 = Auto
-     * 1 = Daylight
-     * 2 = Shade
-     * 3 = Tungsten
-     * 4 = Fluorescent
-     * 5 = Manual
-     */
-    public static final int TAG_WHITE_BALANCE_1 = 0x0019;
-    /**
-     * Units are tenths of a millimetre
-     */
-    public static final int TAG_FOCAL_LENGTH = 0x001D;
-    /**
-     * 0 = -1
-     * 1 = Normal
-     * 2 = +1
-     */
-    public static final int TAG_SATURATION = 0x001F;
-    /**
-     * 0 = -1
-     * 1 = Normal
-     * 2 = +1
-     */
-    public static final int TAG_CONTRAST = 0x0020;
-    /**
-     * 0 = -1
-     * 1 = Normal
-     * 2 = +1
-     */
-    public static final int TAG_SHARPNESS = 0x0021;
-    /**
-     * See PIM specification here: http://www.ozhiker.com/electronics/pjmt/jpeg_info/pim.html
-     */
-    public static final int TAG_PRINT_IMAGE_MATCHING_INFO = 0x0E00;
-    /**
-     * Alternate thumbnail offset
-     */
-    public static final int TAG_PREVIEW_THUMBNAIL = 0x2000;
-    /**
-     *
-     */
-    public static final int TAG_WHITE_BALANCE_BIAS = 0x2011;
-    /**
-     * 12 = Flash
-     * 0 = Manual
-     * 1 = Auto?
-     * 4 = Flash?
-     */
-    public static final int TAG_WHITE_BALANCE_2 = 0x2012;
-    /**
-     * Units are millimetres
-     */
-    public static final int TAG_OBJECT_DISTANCE = 0x2022;
-    /**
-     * 0 = Off
-     */
-    public static final int TAG_FLASH_DISTANCE = 0x2034;
-    /**
-     * 2 = Normal Mode
-     */
-    public static final int TAG_RECORD_MODE = 0x3000;
-    /**
-     * 1 = Off?
-     */
-    public static final int TAG_SELF_TIMER = 0x3001;
-    /**
-     * 3 = Fine
-     */
-    public static final int TAG_QUALITY = 0x3002;
-    /**
-     * 1 = Fixation
-     * 6 = Multi-Area Auto Focus
-     */
-    public static final int TAG_FOCUS_MODE_2 = 0x3003;
-    /**
-     * (string)
-     */
-    public static final int TAG_TIME_ZONE = 0x3006;
-    /**
-     *
-     */
-    public static final int TAG_BESTSHOT_MODE = 0x3007;
-    /**
-     * 0 = Off
-     * 1 = On?
-     */
-    public static final int TAG_CCD_ISO_SENSITIVITY = 0x3014;
-    /**
-     * 0 = Off
-     */
-    public static final int TAG_COLOUR_MODE = 0x3015;
-    /**
-     * 0 = Off
-     */
-    public static final int TAG_ENHANCEMENT = 0x3016;
-    /**
-     * 0 = Off
-     */
-    public static final int TAG_FILTER = 0x3017;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        // TODO add missing names
-        _tagNameMap.put(TAG_THUMBNAIL_DIMENSIONS, "Thumbnail Dimensions");
-        _tagNameMap.put(TAG_THUMBNAIL_SIZE, "Thumbnail Size");
-        _tagNameMap.put(TAG_THUMBNAIL_OFFSET, "Thumbnail Offset");
-        _tagNameMap.put(TAG_QUALITY_MODE, "Quality Mode");
-        _tagNameMap.put(TAG_IMAGE_SIZE, "Image Size");
-        _tagNameMap.put(TAG_FOCUS_MODE_1, "Focus Mode");
-        _tagNameMap.put(TAG_ISO_SENSITIVITY, "ISO Sensitivity");
-        _tagNameMap.put(TAG_WHITE_BALANCE_1, "White Balance");
-        _tagNameMap.put(TAG_FOCAL_LENGTH, "Focal Length");
-        _tagNameMap.put(TAG_SATURATION, "Saturation");
-        _tagNameMap.put(TAG_CONTRAST, "Contrast");
-        _tagNameMap.put(TAG_SHARPNESS, "Sharpness");
-        _tagNameMap.put(TAG_PRINT_IMAGE_MATCHING_INFO, "Print Image Matching (PIM) Info");
-        _tagNameMap.put(TAG_PREVIEW_THUMBNAIL, "Casio Preview Thumbnail");
-        _tagNameMap.put(TAG_WHITE_BALANCE_BIAS, "White Balance Bias");
-        _tagNameMap.put(TAG_WHITE_BALANCE_2, "White Balance");
-        _tagNameMap.put(TAG_OBJECT_DISTANCE, "Object Distance");
-        _tagNameMap.put(TAG_FLASH_DISTANCE, "Flash Distance");
-        _tagNameMap.put(TAG_RECORD_MODE, "Record Mode");
-        _tagNameMap.put(TAG_SELF_TIMER, "Self Timer");
-        _tagNameMap.put(TAG_QUALITY, "Quality");
-        _tagNameMap.put(TAG_FOCUS_MODE_2, "Focus Mode");
-        _tagNameMap.put(TAG_TIME_ZONE, "Time Zone");
-        _tagNameMap.put(TAG_BESTSHOT_MODE, "BestShot Mode");
-        _tagNameMap.put(TAG_CCD_ISO_SENSITIVITY, "CCD ISO Sensitivity");
-        _tagNameMap.put(TAG_COLOUR_MODE, "Colour Mode");
-        _tagNameMap.put(TAG_ENHANCEMENT, "Enhancement");
-        _tagNameMap.put(TAG_FILTER, "Filter");
-    }
-
-    public CasioType2MakernoteDirectory()
-    {
-        this.setDescriptor(new CasioType2MakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Casio Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/FujifilmMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/FujifilmMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,469 +1,0 @@
-/*
- * 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
- *
- *        http://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.Rational;
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.makernotes.FujifilmMakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link FujifilmMakernoteDirectory}.
- * <p>
- * Fujifilm added their Makernote tag from the Year 2000's models (e.g.Finepix1400,
- * Finepix4700). It uses IFD format and start from ASCII character 'FUJIFILM', and next 4
- * bytes (value 0x000c) points the offset to first IFD entry.
- * <pre><code>
- * :0000: 46 55 4A 49 46 49 4C 4D-0C 00 00 00 0F 00 00 00 :0000: FUJIFILM........
- * :0010: 07 00 04 00 00 00 30 31-33 30 00 10 02 00 08 00 :0010: ......0130......
- * </code></pre>
- * There are two big differences to the other manufacturers.
- * <ul>
- * <li>Fujifilm's Exif data uses Motorola align, but Makernote ignores it and uses Intel align.</li>
- * <li>
- * The other manufacturer's Makernote counts the "offset to data" from the first byte of TIFF header
- * (same as the other IFD), but Fujifilm counts it from the first byte of Makernote itself.
- * </li>
- * </ul>
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class FujifilmMakernoteDescriptor extends TagDescriptor<FujifilmMakernoteDirectory>
-{
-    public FujifilmMakernoteDescriptor(@NotNull FujifilmMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_MAKERNOTE_VERSION:
-                return getMakernoteVersionDescription();
-            case TAG_SHARPNESS:
-                return getSharpnessDescription();
-            case TAG_WHITE_BALANCE:
-                return getWhiteBalanceDescription();
-            case TAG_COLOR_SATURATION:
-                return getColorSaturationDescription();
-            case TAG_TONE:
-                return getToneDescription();
-            case TAG_CONTRAST:
-                return getContrastDescription();
-            case TAG_NOISE_REDUCTION:
-                return getNoiseReductionDescription();
-            case TAG_HIGH_ISO_NOISE_REDUCTION:
-                return getHighIsoNoiseReductionDescription();
-            case TAG_FLASH_MODE:
-                return getFlashModeDescription();
-            case TAG_FLASH_EV:
-                return getFlashExposureValueDescription();
-            case TAG_MACRO:
-                return getMacroDescription();
-            case TAG_FOCUS_MODE:
-                return getFocusModeDescription();
-            case TAG_SLOW_SYNC:
-                return getSlowSyncDescription();
-            case TAG_PICTURE_MODE:
-                return getPictureModeDescription();
-            case TAG_EXR_AUTO:
-                return getExrAutoDescription();
-            case TAG_EXR_MODE:
-                return getExrModeDescription();
-            case TAG_AUTO_BRACKETING:
-                return getAutoBracketingDescription();
-            case TAG_FINE_PIX_COLOR:
-                return getFinePixColorDescription();
-            case TAG_BLUR_WARNING:
-                return getBlurWarningDescription();
-            case TAG_FOCUS_WARNING:
-                return getFocusWarningDescription();
-            case TAG_AUTO_EXPOSURE_WARNING:
-                return getAutoExposureWarningDescription();
-            case TAG_DYNAMIC_RANGE:
-                return getDynamicRangeDescription();
-            case TAG_FILM_MODE:
-                return getFilmModeDescription();
-            case TAG_DYNAMIC_RANGE_SETTING:
-                return getDynamicRangeSettingDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    private String getMakernoteVersionDescription()
-    {
-        return getVersionBytesDescription(TAG_MAKERNOTE_VERSION, 2);
-    }
-
-    @Nullable
-    public String getSharpnessDescription()
-    {
-        final Integer value = _directory.getInteger(TAG_SHARPNESS);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 1: return "Softest";
-            case 2: return "Soft";
-            case 3: return "Normal";
-            case 4: return "Hard";
-            case 5: return "Hardest";
-            case 0x82: return "Medium Soft";
-            case 0x84: return "Medium Hard";
-            case 0x8000: return "Film Simulation";
-            case 0xFFFF: return "N/A";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getWhiteBalanceDescription()
-    {
-        final Integer value = _directory.getInteger(TAG_WHITE_BALANCE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0x000: return "Auto";
-            case 0x100: return "Daylight";
-            case 0x200: return "Cloudy";
-            case 0x300: return "Daylight Fluorescent";
-            case 0x301: return "Day White Fluorescent";
-            case 0x302: return "White Fluorescent";
-            case 0x303: return "Warm White Fluorescent";
-            case 0x304: return "Living Room Warm White Fluorescent";
-            case 0x400: return "Incandescence";
-            case 0x500: return "Flash";
-            case 0xf00: return "Custom White Balance";
-            case 0xf01: return "Custom White Balance 2";
-            case 0xf02: return "Custom White Balance 3";
-            case 0xf03: return "Custom White Balance 4";
-            case 0xf04: return "Custom White Balance 5";
-            case 0xff0: return "Kelvin";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getColorSaturationDescription()
-    {
-        final Integer value = _directory.getInteger(TAG_COLOR_SATURATION);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0x000: return "Normal";
-            case 0x080: return "Medium High";
-            case 0x100: return "High";
-            case 0x180: return "Medium Low";
-            case 0x200: return "Low";
-            case 0x300: return "None (B&W)";
-            case 0x301: return "B&W Green Filter";
-            case 0x302: return "B&W Yellow Filter";
-            case 0x303: return "B&W Blue Filter";
-            case 0x304: return "B&W Sepia";
-            case 0x8000: return "Film Simulation";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getToneDescription()
-    {
-        final Integer value = _directory.getInteger(TAG_TONE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0x000: return "Normal";
-            case 0x080: return "Medium High";
-            case 0x100: return "High";
-            case 0x180: return "Medium Low";
-            case 0x200: return "Low";
-            case 0x300: return "None (B&W)";
-            case 0x8000: return "Film Simulation";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getContrastDescription()
-    {
-        final Integer value = _directory.getInteger(TAG_CONTRAST);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0x000: return "Normal";
-            case 0x100: return "High";
-            case 0x300: return "Low";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getNoiseReductionDescription()
-    {
-        final Integer value = _directory.getInteger(TAG_NOISE_REDUCTION);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0x040: return "Low";
-            case 0x080: return "Normal";
-            case 0x100: return "N/A";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getHighIsoNoiseReductionDescription()
-    {
-        final Integer value = _directory.getInteger(TAG_HIGH_ISO_NOISE_REDUCTION);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0x000: return "Normal";
-            case 0x100: return "Strong";
-            case 0x200: return "Weak";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getFlashModeDescription()
-    {
-        return getIndexedDescription(
-            TAG_FLASH_MODE,
-            "Auto",
-            "On",
-            "Off",
-            "Red-eye Reduction",
-            "External"
-        );
-    }
-
-    @Nullable
-    public String getFlashExposureValueDescription()
-    {
-        Rational value = _directory.getRational(TAG_FLASH_EV);
-        return value == null ? null : value.toSimpleString(false) + " EV (Apex)";
-    }
-
-    @Nullable
-    public String getMacroDescription()
-    {
-        return getIndexedDescription(TAG_MACRO, "Off", "On");
-    }
-
-    @Nullable
-    public String getFocusModeDescription()
-    {
-        return getIndexedDescription(TAG_FOCUS_MODE, "Auto Focus", "Manual Focus");
-    }
-
-    @Nullable
-    public String getSlowSyncDescription()
-    {
-        return getIndexedDescription(TAG_SLOW_SYNC, "Off", "On");
-    }
-
-    @Nullable
-    public String getPictureModeDescription()
-    {
-        final Integer value = _directory.getInteger(TAG_PICTURE_MODE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0x000: return "Auto";
-            case 0x001: return "Portrait scene";
-            case 0x002: return "Landscape scene";
-            case 0x003: return "Macro";
-            case 0x004: return "Sports scene";
-            case 0x005: return "Night scene";
-            case 0x006: return "Program AE";
-            case 0x007: return "Natural Light";
-            case 0x008: return "Anti-blur";
-            case 0x009: return "Beach & Snow";
-            case 0x00a: return "Sunset";
-            case 0x00b: return "Museum";
-            case 0x00c: return "Party";
-            case 0x00d: return "Flower";
-            case 0x00e: return "Text";
-            case 0x00f: return "Natural Light & Flash";
-            case 0x010: return "Beach";
-            case 0x011: return "Snow";
-            case 0x012: return "Fireworks";
-            case 0x013: return "Underwater";
-            case 0x014: return "Portrait with Skin Correction";
-            // skip 0x015
-            case 0x016: return "Panorama";
-            case 0x017: return "Night (Tripod)";
-            case 0x018: return "Pro Low-light";
-            case 0x019: return "Pro Focus";
-            // skip 0x01a
-            case 0x01b: return "Dog Face Detection";
-            case 0x01c: return "Cat Face Detection";
-            case 0x100: return "Aperture priority AE";
-            case 0x200: return "Shutter priority AE";
-            case 0x300: return "Manual exposure";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getExrAutoDescription()
-    {
-        return getIndexedDescription(TAG_EXR_AUTO, "Auto", "Manual");
-    }
-
-    @Nullable
-    public String getExrModeDescription()
-    {
-        final Integer value = _directory.getInteger(TAG_EXR_MODE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0x100: return "HR (High Resolution)";
-            case 0x200: return "SN (Signal to Noise Priority)";
-            case 0x300: return "DR (Dynamic Range Priority)";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getAutoBracketingDescription()
-    {
-        return getIndexedDescription(
-            TAG_AUTO_BRACKETING,
-            "Off",
-            "On",
-            "No Flash & Flash"
-        );
-    }
-
-    @Nullable
-    public String getFinePixColorDescription()
-    {
-        final Integer value = _directory.getInteger(TAG_FINE_PIX_COLOR);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0x00: return "Standard";
-            case 0x10: return "Chrome";
-            case 0x30: return "B&W";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getBlurWarningDescription()
-    {
-        return getIndexedDescription(
-            TAG_BLUR_WARNING,
-            "No Blur Warning",
-            "Blur warning"
-        );
-    }
-
-    @Nullable
-    public String getFocusWarningDescription()
-    {
-        return getIndexedDescription(
-            TAG_FOCUS_WARNING,
-            "Good Focus",
-            "Out Of Focus"
-        );
-    }
-
-    @Nullable
-    public String getAutoExposureWarningDescription()
-    {
-        return getIndexedDescription(
-            TAG_AUTO_EXPOSURE_WARNING,
-            "AE Good",
-            "Over Exposed"
-        );
-    }
-
-    @Nullable
-    public String getDynamicRangeDescription()
-    {
-        return getIndexedDescription(
-            TAG_DYNAMIC_RANGE,
-            1,
-            "Standard",
-            null,
-            "Wide"
-        );
-    }
-
-    @Nullable
-    public String getFilmModeDescription()
-    {
-        final Integer value = _directory.getInteger(TAG_FILM_MODE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0x000: return "F0/Standard (Provia) ";
-            case 0x100: return "F1/Studio Portrait";
-            case 0x110: return "F1a/Studio Portrait Enhanced Saturation";
-            case 0x120: return "F1b/Studio Portrait Smooth Skin Tone (Astia)";
-            case 0x130: return "F1c/Studio Portrait Increased Sharpness";
-            case 0x200: return "F2/Fujichrome (Velvia)";
-            case 0x300: return "F3/Studio Portrait Ex";
-            case 0x400: return "F4/Velvia";
-            case 0x500: return "Pro Neg. Std";
-            case 0x501: return "Pro Neg. Hi";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getDynamicRangeSettingDescription()
-    {
-        final Integer value = _directory.getInteger(TAG_DYNAMIC_RANGE_SETTING);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0x000: return "Auto (100-400%)";
-            case 0x001: return "Manual";
-            case 0x100: return "Standard (100%)";
-            case 0x200: return "Wide 1 (230%)";
-            case 0x201: return "Wide 2 (400%)";
-            case 0x8000: return "Film Simulation";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/FujifilmMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/FujifilmMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,179 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific to Fujifilm cameras.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class FujifilmMakernoteDirectory extends Directory
-{
-    public static final int TAG_MAKERNOTE_VERSION = 0x0000;
-    public static final int TAG_SERIAL_NUMBER = 0x0010;
-
-    public static final int TAG_QUALITY = 0x1000;
-    public static final int TAG_SHARPNESS = 0x1001;
-    public static final int TAG_WHITE_BALANCE = 0x1002;
-    public static final int TAG_COLOR_SATURATION = 0x1003;
-    public static final int TAG_TONE = 0x1004;
-    public static final int TAG_COLOR_TEMPERATURE = 0x1005;
-    public static final int TAG_CONTRAST = 0x1006;
-
-    public static final int TAG_WHITE_BALANCE_FINE_TUNE = 0x100a;
-    public static final int TAG_NOISE_REDUCTION = 0x100b;
-    public static final int TAG_HIGH_ISO_NOISE_REDUCTION = 0x100e;
-
-    public static final int TAG_FLASH_MODE = 0x1010;
-    public static final int TAG_FLASH_EV = 0x1011;
-
-    public static final int TAG_MACRO = 0x1020;
-    public static final int TAG_FOCUS_MODE = 0x1021;
-    public static final int TAG_FOCUS_PIXEL = 0x1023;
-
-    public static final int TAG_SLOW_SYNC = 0x1030;
-    public static final int TAG_PICTURE_MODE = 0x1031;
-    public static final int TAG_EXR_AUTO = 0x1033;
-    public static final int TAG_EXR_MODE = 0x1034;
-
-    public static final int TAG_AUTO_BRACKETING = 0x1100;
-    public static final int TAG_SEQUENCE_NUMBER = 0x1101;
-
-    public static final int TAG_FINE_PIX_COLOR = 0x1210;
-
-    public static final int TAG_BLUR_WARNING = 0x1300;
-    public static final int TAG_FOCUS_WARNING = 0x1301;
-    public static final int TAG_AUTO_EXPOSURE_WARNING = 0x1302;
-    public static final int TAG_GE_IMAGE_SIZE = 0x1304;
-
-    public static final int TAG_DYNAMIC_RANGE = 0x1400;
-    public static final int TAG_FILM_MODE = 0x1401;
-    public static final int TAG_DYNAMIC_RANGE_SETTING = 0x1402;
-    public static final int TAG_DEVELOPMENT_DYNAMIC_RANGE = 0x1403;
-    public static final int TAG_MIN_FOCAL_LENGTH = 0x1404;
-    public static final int TAG_MAX_FOCAL_LENGTH = 0x1405;
-    public static final int TAG_MAX_APERTURE_AT_MIN_FOCAL = 0x1406;
-    public static final int TAG_MAX_APERTURE_AT_MAX_FOCAL = 0x1407;
-
-    public static final int TAG_AUTO_DYNAMIC_RANGE = 0x140b;
-
-    public static final int TAG_FACES_DETECTED = 0x4100;
-    /**
-     * Left, top, right and bottom coordinates in full-sized image for each face detected.
-     */
-    public static final int TAG_FACE_POSITIONS = 0x4103;
-    public static final int TAG_FACE_REC_INFO = 0x4282;
-
-    public static final int TAG_FILE_SOURCE = 0x8000;
-    public static final int TAG_ORDER_NUMBER = 0x8002;
-    public static final int TAG_FRAME_NUMBER = 0x8003;
-
-    public static final int TAG_PARALLAX = 0xb211;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TAG_MAKERNOTE_VERSION, "Makernote Version");
-        _tagNameMap.put(TAG_SERIAL_NUMBER, "Serial Number");
-
-        _tagNameMap.put(TAG_QUALITY, "Quality");
-        _tagNameMap.put(TAG_SHARPNESS, "Sharpness");
-        _tagNameMap.put(TAG_WHITE_BALANCE, "White Balance");
-        _tagNameMap.put(TAG_COLOR_SATURATION, "Color Saturation");
-        _tagNameMap.put(TAG_TONE, "Tone (Contrast)");
-        _tagNameMap.put(TAG_COLOR_TEMPERATURE, "Color Temperature");
-        _tagNameMap.put(TAG_CONTRAST, "Contrast");
-
-        _tagNameMap.put(TAG_WHITE_BALANCE_FINE_TUNE, "White Balance Fine Tune");
-        _tagNameMap.put(TAG_NOISE_REDUCTION, "Noise Reduction");
-        _tagNameMap.put(TAG_HIGH_ISO_NOISE_REDUCTION, "High ISO Noise Reduction");
-
-        _tagNameMap.put(TAG_FLASH_MODE, "Flash Mode");
-        _tagNameMap.put(TAG_FLASH_EV, "Flash Strength");
-
-        _tagNameMap.put(TAG_MACRO, "Macro");
-        _tagNameMap.put(TAG_FOCUS_MODE, "Focus Mode");
-        _tagNameMap.put(TAG_FOCUS_PIXEL, "Focus Pixel");
-
-        _tagNameMap.put(TAG_SLOW_SYNC, "Slow Sync");
-        _tagNameMap.put(TAG_PICTURE_MODE, "Picture Mode");
-        _tagNameMap.put(TAG_EXR_AUTO, "EXR Auto");
-        _tagNameMap.put(TAG_EXR_MODE, "EXR Mode");
-
-        _tagNameMap.put(TAG_AUTO_BRACKETING, "Auto Bracketing");
-        _tagNameMap.put(TAG_SEQUENCE_NUMBER, "Sequence Number");
-
-        _tagNameMap.put(TAG_FINE_PIX_COLOR, "FinePix Color Setting");
-
-        _tagNameMap.put(TAG_BLUR_WARNING, "Blur Warning");
-        _tagNameMap.put(TAG_FOCUS_WARNING, "Focus Warning");
-        _tagNameMap.put(TAG_AUTO_EXPOSURE_WARNING, "AE Warning");
-        _tagNameMap.put(TAG_GE_IMAGE_SIZE, "GE Image Size");
-
-        _tagNameMap.put(TAG_DYNAMIC_RANGE, "Dynamic Range");
-        _tagNameMap.put(TAG_FILM_MODE, "Film Mode");
-        _tagNameMap.put(TAG_DYNAMIC_RANGE_SETTING, "Dynamic Range Setting");
-        _tagNameMap.put(TAG_DEVELOPMENT_DYNAMIC_RANGE, "Development Dynamic Range");
-        _tagNameMap.put(TAG_MIN_FOCAL_LENGTH, "Minimum Focal Length");
-        _tagNameMap.put(TAG_MAX_FOCAL_LENGTH, "Maximum Focal Length");
-        _tagNameMap.put(TAG_MAX_APERTURE_AT_MIN_FOCAL, "Maximum Aperture at Minimum Focal Length");
-        _tagNameMap.put(TAG_MAX_APERTURE_AT_MAX_FOCAL, "Maximum Aperture at Maximum Focal Length");
-
-        _tagNameMap.put(TAG_AUTO_DYNAMIC_RANGE, "Auto Dynamic Range");
-
-        _tagNameMap.put(TAG_FACES_DETECTED, "Faces Detected");
-        _tagNameMap.put(TAG_FACE_POSITIONS, "Face Positions");
-        _tagNameMap.put(TAG_FACE_REC_INFO, "Face Detection Data");
-
-        _tagNameMap.put(TAG_FILE_SOURCE, "File Source");
-        _tagNameMap.put(TAG_ORDER_NUMBER, "Order Number");
-        _tagNameMap.put(TAG_FRAME_NUMBER, "Frame Number");
-
-        _tagNameMap.put(TAG_PARALLAX, "Parallax");
-    }
-
-    public FujifilmMakernoteDirectory()
-    {
-        this.setDescriptor(new FujifilmMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Fujifilm Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/KodakMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/KodakMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,152 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.makernotes.KodakMakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link KodakMakernoteDirectory}.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class KodakMakernoteDescriptor extends TagDescriptor<KodakMakernoteDirectory>
-{
-    public KodakMakernoteDescriptor(@NotNull KodakMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_QUALITY:
-                return getQualityDescription();
-            case TAG_BURST_MODE:
-                return getBurstModeDescription();
-            case TAG_SHUTTER_MODE:
-                return getShutterModeDescription();
-            case TAG_FOCUS_MODE:
-                return getFocusModeDescription();
-            case TAG_WHITE_BALANCE:
-                return getWhiteBalanceDescription();
-            case TAG_FLASH_MODE:
-                return getFlashModeDescription();
-            case TAG_FLASH_FIRED:
-                return getFlashFiredDescription();
-            case TAG_COLOR_MODE:
-                return getColorModeDescription();
-            case TAG_SHARPNESS:
-                return getSharpnessDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getSharpnessDescription()
-    {
-        return getIndexedDescription(TAG_SHARPNESS, "Normal");
-    }
-
-    @Nullable
-    public String getColorModeDescription()
-    {
-        Integer value = _directory.getInteger(TAG_COLOR_MODE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0x001: case 0x2000: return "B&W";
-            case 0x002: case 0x4000: return "Sepia";
-            case 0x003: return "B&W Yellow Filter";
-            case 0x004: return "B&W Red Filter";
-            case 0x020: return "Saturated Color";
-            case 0x040: case 0x200: return "Neutral Color";
-            case 0x100: return "Saturated Color";
-            default: return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getFlashFiredDescription()
-    {
-        return getIndexedDescription(TAG_FLASH_FIRED, "No", "Yes");
-    }
-
-    @Nullable
-    public String getFlashModeDescription()
-    {
-        Integer value = _directory.getInteger(TAG_FLASH_MODE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0x00: return "Auto";
-            case 0x10: case 0x01: return "Fill Flash";
-            case 0x20: case 0x02: return "Off";
-            case 0x40: case 0x03: return "Red Eye";
-            default: return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getWhiteBalanceDescription()
-    {
-        return getIndexedDescription(TAG_WHITE_BALANCE, "Auto", "Flash", "Tungsten", "Daylight");
-    }
-
-    @Nullable
-    public String getFocusModeDescription()
-    {
-        return getIndexedDescription(TAG_FOCUS_MODE, "Normal", null, "Macro");
-    }
-
-    @Nullable
-    public String getShutterModeDescription()
-    {
-        Integer value = _directory.getInteger(TAG_SHUTTER_MODE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "Auto";
-            case 8: return "Aperture Priority";
-            case 32: return "Manual";
-            default: return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getBurstModeDescription()
-    {
-        return getIndexedDescription(TAG_BURST_MODE, "Off", "On");
-    }
-
-    @Nullable
-    public String getQualityDescription()
-    {
-        return getIndexedDescription(TAG_QUALITY, 1, "Fine", "Normal");
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/KodakMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/KodakMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,114 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific to Kodak cameras.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class KodakMakernoteDirectory extends Directory
-{
-    public final static int TAG_KODAK_MODEL = 0;
-    public final static int TAG_QUALITY = 9;
-    public final static int TAG_BURST_MODE = 10;
-    public final static int TAG_IMAGE_WIDTH = 12;
-    public final static int TAG_IMAGE_HEIGHT = 14;
-    public final static int TAG_YEAR_CREATED = 16;
-    public final static int TAG_MONTH_DAY_CREATED = 18;
-    public final static int TAG_TIME_CREATED = 20;
-    public final static int TAG_BURST_MODE_2 = 24;
-    public final static int TAG_SHUTTER_MODE = 27;
-    public final static int TAG_METERING_MODE = 28;
-    public final static int TAG_SEQUENCE_NUMBER = 29;
-    public final static int TAG_F_NUMBER = 30;
-    public final static int TAG_EXPOSURE_TIME = 32;
-    public final static int TAG_EXPOSURE_COMPENSATION = 36;
-    public final static int TAG_FOCUS_MODE = 56;
-    public final static int TAG_WHITE_BALANCE = 64;
-    public final static int TAG_FLASH_MODE = 92;
-    public final static int TAG_FLASH_FIRED = 93;
-    public final static int TAG_ISO_SETTING = 94;
-    public final static int TAG_ISO = 96;
-    public final static int TAG_TOTAL_ZOOM = 98;
-    public final static int TAG_DATE_TIME_STAMP = 100;
-    public final static int TAG_COLOR_MODE = 102;
-    public final static int TAG_DIGITAL_ZOOM = 104;
-    public final static int TAG_SHARPNESS = 107;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TAG_KODAK_MODEL, "Kodak Model");
-        _tagNameMap.put(TAG_QUALITY, "Quality");
-        _tagNameMap.put(TAG_BURST_MODE, "Burst Mode");
-        _tagNameMap.put(TAG_IMAGE_WIDTH, "Image Width");
-        _tagNameMap.put(TAG_IMAGE_HEIGHT, "Image Height");
-        _tagNameMap.put(TAG_YEAR_CREATED, "Year Created");
-        _tagNameMap.put(TAG_MONTH_DAY_CREATED, "Month/Day Created");
-        _tagNameMap.put(TAG_TIME_CREATED, "Time Created");
-        _tagNameMap.put(TAG_BURST_MODE_2, "Burst Mode 2");
-        _tagNameMap.put(TAG_SHUTTER_MODE, "Shutter Speed");
-        _tagNameMap.put(TAG_METERING_MODE, "Metering Mode");
-        _tagNameMap.put(TAG_SEQUENCE_NUMBER, "Sequence Number");
-        _tagNameMap.put(TAG_F_NUMBER, "F Number");
-        _tagNameMap.put(TAG_EXPOSURE_TIME, "Exposure Time");
-        _tagNameMap.put(TAG_EXPOSURE_COMPENSATION, "Exposure Compensation");
-        _tagNameMap.put(TAG_FOCUS_MODE, "Focus Mode");
-        _tagNameMap.put(TAG_WHITE_BALANCE, "White Balance");
-        _tagNameMap.put(TAG_FLASH_MODE, "Flash Mode");
-        _tagNameMap.put(TAG_FLASH_FIRED, "Flash Fired");
-        _tagNameMap.put(TAG_ISO_SETTING, "ISO Setting");
-        _tagNameMap.put(TAG_ISO, "ISO");
-        _tagNameMap.put(TAG_TOTAL_ZOOM, "Total Zoom");
-        _tagNameMap.put(TAG_DATE_TIME_STAMP, "Date/Time Stamp");
-        _tagNameMap.put(TAG_COLOR_MODE, "Color Mode");
-        _tagNameMap.put(TAG_DIGITAL_ZOOM, "Digital Zoom");
-        _tagNameMap.put(TAG_SHARPNESS, "Sharpness");
-    }
-
-    public KodakMakernoteDirectory()
-    {
-        this.setDescriptor(new KodakMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Kodak Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/KyoceraMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/KyoceraMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,66 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.makernotes.KyoceraMakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link KyoceraMakernoteDirectory}.
- * <p>
- * Some information about this makernote taken from here:
- * http://www.ozhiker.com/electronics/pjmt/jpeg_info/kyocera_mn.html
- * <p>
- * Most manufacturer's Makernote counts the "offset to data" from the first byte
- * of TIFF header (same as the other IFD), but Kyocera (along with Fujifilm) counts
- * it from the first byte of Makernote itself.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class KyoceraMakernoteDescriptor extends TagDescriptor<KyoceraMakernoteDirectory>
-{
-    public KyoceraMakernoteDescriptor(@NotNull KyoceraMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_PROPRIETARY_THUMBNAIL:
-                return getProprietaryThumbnailDataDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getProprietaryThumbnailDataDescription()
-    {
-        return getByteLengthDescription(TAG_PROPRIETARY_THUMBNAIL);
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/KyoceraMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/KyoceraMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,66 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific to Kyocera and Contax cameras.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class KyoceraMakernoteDirectory extends Directory
-{
-    public static final int TAG_PROPRIETARY_THUMBNAIL = 0x0001;
-    public static final int TAG_PRINT_IMAGE_MATCHING_INFO = 0x0E00;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TAG_PROPRIETARY_THUMBNAIL, "Proprietary Thumbnail Format Data");
-        _tagNameMap.put(TAG_PRINT_IMAGE_MATCHING_INFO, "Print Image Matching (PIM) Info");
-    }
-
-    public KyoceraMakernoteDirectory()
-    {
-        this.setDescriptor(new KyoceraMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Kyocera/Contax Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/LeicaMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/LeicaMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,128 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.makernotes.LeicaMakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link LeicaMakernoteDirectory}.
- * <p>
- * Tag reference from: http://gvsoft.homedns.org/exif/makernote-leica-type1.html
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class LeicaMakernoteDescriptor extends TagDescriptor<LeicaMakernoteDirectory>
-{
-    public LeicaMakernoteDescriptor(@NotNull LeicaMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_QUALITY:
-                return getQualityDescription();
-            case TAG_USER_PROFILE:
-                return getUserProfileDescription();
-//            case TAG_SERIAL:
-//                return getSerialNumberDescription();
-            case TAG_WHITE_BALANCE:
-                return getWhiteBalanceDescription();
-            case TAG_EXTERNAL_SENSOR_BRIGHTNESS_VALUE:
-                return getExternalSensorBrightnessValueDescription();
-            case TAG_MEASURED_LV:
-                return getMeasuredLvDescription();
-            case TAG_APPROXIMATE_F_NUMBER:
-                return getApproximateFNumberDescription();
-            case TAG_CAMERA_TEMPERATURE:
-                return getCameraTemperatureDescription();
-            case TAG_WB_RED_LEVEL:
-            case TAG_WB_BLUE_LEVEL:
-            case TAG_WB_GREEN_LEVEL:
-                return getSimpleRational(tagType);
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    private String getCameraTemperatureDescription()
-    {
-        return getFormattedInt(TAG_CAMERA_TEMPERATURE, "%d C");
-    }
-
-    @Nullable
-    private String getApproximateFNumberDescription()
-    {
-        return getSimpleRational(TAG_APPROXIMATE_F_NUMBER);
-    }
-
-    @Nullable
-    private String getMeasuredLvDescription()
-    {
-        return getSimpleRational(TAG_MEASURED_LV);
-    }
-
-    @Nullable
-    private String getExternalSensorBrightnessValueDescription()
-    {
-        return getSimpleRational(TAG_EXTERNAL_SENSOR_BRIGHTNESS_VALUE);
-    }
-
-    @Nullable
-    private String getWhiteBalanceDescription()
-    {
-        return getIndexedDescription(TAG_WHITE_BALANCE,
-            "Auto or Manual",
-            "Daylight",
-            "Fluorescent",
-            "Tungsten",
-            "Flash",
-            "Cloudy",
-            "Shadow"
-        );
-    }
-
-    @Nullable
-    private String getUserProfileDescription()
-    {
-        return getIndexedDescription(TAG_QUALITY, 1,
-            "User Profile 1",
-            "User Profile 2",
-            "User Profile 3",
-            "User Profile 0 (Dynamic)"
-        );
-    }
-
-    @Nullable
-    private String getQualityDescription()
-    {
-        return getIndexedDescription(TAG_QUALITY, 1, "Fine", "Basic");
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/LeicaMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/LeicaMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,108 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific to certain Leica cameras.
- * <p>
- * Tag reference from: http://gvsoft.homedns.org/exif/makernote-leica-type1.html
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class LeicaMakernoteDirectory extends Directory
-{
-    public static final int TAG_QUALITY = 0x0300;
-    public static final int TAG_USER_PROFILE = 0x0302;
-    public static final int TAG_SERIAL_NUMBER = 0x0303;
-    public static final int TAG_WHITE_BALANCE = 0x0304;
-
-    public static final int TAG_LENS_TYPE = 0x0310;
-    public static final int TAG_EXTERNAL_SENSOR_BRIGHTNESS_VALUE = 0x0311;
-    public static final int TAG_MEASURED_LV = 0x0312;
-    public static final int TAG_APPROXIMATE_F_NUMBER = 0x0313;
-
-    public static final int TAG_CAMERA_TEMPERATURE = 0x0320;
-    public static final int TAG_COLOR_TEMPERATURE = 0x0321;
-    public static final int TAG_WB_RED_LEVEL = 0x0322;
-    public static final int TAG_WB_GREEN_LEVEL = 0x0323;
-    public static final int TAG_WB_BLUE_LEVEL = 0x0324;
-
-    public static final int TAG_CCD_VERSION = 0x0330;
-    public static final int TAG_CCD_BOARD_VERSION = 0x0331;
-    public static final int TAG_CONTROLLER_BOARD_VERSION = 0x0332;
-    public static final int TAG_M16_C_VERSION = 0x0333;
-
-    public static final int TAG_IMAGE_ID_NUMBER = 0x0340;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TAG_QUALITY, "Quality");
-        _tagNameMap.put(TAG_USER_PROFILE, "User Profile");
-        _tagNameMap.put(TAG_SERIAL_NUMBER, "Serial Number");
-        _tagNameMap.put(TAG_WHITE_BALANCE, "White Balance");
-
-        _tagNameMap.put(TAG_LENS_TYPE, "Lens Type");
-        _tagNameMap.put(TAG_EXTERNAL_SENSOR_BRIGHTNESS_VALUE, "External Sensor Brightness Value");
-        _tagNameMap.put(TAG_MEASURED_LV, "Measured LV");
-        _tagNameMap.put(TAG_APPROXIMATE_F_NUMBER, "Approximate F Number");
-
-        _tagNameMap.put(TAG_CAMERA_TEMPERATURE, "Camera Temperature");
-        _tagNameMap.put(TAG_COLOR_TEMPERATURE, "Color Temperature");
-        _tagNameMap.put(TAG_WB_RED_LEVEL, "WB Red Level");
-        _tagNameMap.put(TAG_WB_GREEN_LEVEL, "WB Green Level");
-        _tagNameMap.put(TAG_WB_BLUE_LEVEL, "WB Blue Level");
-
-        _tagNameMap.put(TAG_CCD_VERSION, "CCD Version");
-        _tagNameMap.put(TAG_CCD_BOARD_VERSION, "CCD Board Version");
-        _tagNameMap.put(TAG_CONTROLLER_BOARD_VERSION, "Controller Board Version");
-        _tagNameMap.put(TAG_M16_C_VERSION, "M16 C Version");
-
-        _tagNameMap.put(TAG_IMAGE_ID_NUMBER, "Image ID Number");
-    }
-
-    public LeicaMakernoteDirectory()
-    {
-        this.setDescriptor(new LeicaMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Leica Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/LeicaType5MakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/LeicaType5MakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,79 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.makernotes.LeicaType5MakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link LeicaType5MakernoteDirectory}.
- * <p>
- * Tag reference from: http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Panasonic.html
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class LeicaType5MakernoteDescriptor extends TagDescriptor<LeicaType5MakernoteDirectory>
-{
-    public LeicaType5MakernoteDescriptor(@NotNull LeicaType5MakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TagExposureMode:
-                return getExposureModeDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getExposureModeDescription()
-    {
-        byte[] values = _directory.getByteArray(TagExposureMode);
-        if (values == null || values.length < 4)
-            return null;
-
-        String join = String.format("%d %d %d %d", values[0], values[1], values[2], values[3]);
-
-        if(join.equals("0 0 0 0"))
-            return "Program AE";
-        else if(join.equals("1 0 0 0"))
-            return "Aperture-priority AE";
-        else if(join.equals("1 1 0 0"))
-            return "Aperture-priority AE (1)";
-        else if(join.equals("2 0 0 0"))
-            return "Shutter speed priority AE";  // guess
-        else if(join.equals("3 0 0 0"))
-            return "Manual";
-        else
-            return String.format("Unknown (%s)", join);
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/LeicaType5MakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/LeicaType5MakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,79 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific to certain Leica cameras.
- * <p>
- * Tag reference from: http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Panasonic.html
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class LeicaType5MakernoteDirectory extends Directory
-{
-    public static final int TagLensModel = 0x0303;
-    public static final int TagOriginalFileName = 0x0407;
-    public static final int TagOriginalDirectory = 0x0408;
-    public static final int TagExposureMode = 0x040d;
-    public static final int TagShotInfo = 0x0410;
-    public static final int TagFilmMode = 0x0412;
-    public static final int TagWbRgbLevels = 0x0413;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TagLensModel, "Lens Model");
-        _tagNameMap.put(TagOriginalFileName, "Original File Name");
-        _tagNameMap.put(TagOriginalDirectory, "Original Directory");
-        _tagNameMap.put(TagExposureMode, "Exposure Mode");
-        _tagNameMap.put(TagShotInfo, "Shot Info" );
-        _tagNameMap.put(TagFilmMode, "Film Mode");
-        _tagNameMap.put(TagWbRgbLevels, "WB RGB Levels");
-    }
-
-    public LeicaType5MakernoteDirectory()
-    {
-        this.setDescriptor(new LeicaType5MakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Leica Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/NikonType1MakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/NikonType1MakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,170 +1,0 @@
-/*
- * 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
- *
- *        http://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.Rational;
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.makernotes.NikonType1MakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link NikonType1MakernoteDirectory}.
- * <p>
- * Type-1 is for E-Series cameras prior to (not including) E990.  For example: E700, E800, E900,
- * E900S, E910, E950.
- * <p>
- * Makernote starts from ASCII string "Nikon". Data format is the same as IFD, but it starts from
- * offset 0x08. This is the same as Olympus except start string. Example of actual data
- * structure is shown below.
- * <pre><code>
- * :0000: 4E 69 6B 6F 6E 00 01 00-05 00 02 00 02 00 06 00 Nikon...........
- * :0010: 00 00 EC 02 00 00 03 00-03 00 01 00 00 00 06 00 ................
- * </code></pre>
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class NikonType1MakernoteDescriptor extends TagDescriptor<NikonType1MakernoteDirectory>
-{
-    public NikonType1MakernoteDescriptor(@NotNull NikonType1MakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_QUALITY:
-                return getQualityDescription();
-            case TAG_COLOR_MODE:
-                return getColorModeDescription();
-            case TAG_IMAGE_ADJUSTMENT:
-                return getImageAdjustmentDescription();
-            case TAG_CCD_SENSITIVITY:
-                return getCcdSensitivityDescription();
-            case TAG_WHITE_BALANCE:
-                return getWhiteBalanceDescription();
-            case TAG_FOCUS:
-                return getFocusDescription();
-            case TAG_DIGITAL_ZOOM:
-                return getDigitalZoomDescription();
-            case TAG_CONVERTER:
-                return getConverterDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getConverterDescription()
-    {
-        return getIndexedDescription(TAG_CONVERTER, "None", "Fisheye converter");
-    }
-
-    @Nullable
-    public String getDigitalZoomDescription()
-    {
-        Rational value = _directory.getRational(TAG_DIGITAL_ZOOM);
-        return value == null
-            ? null
-            : value.getNumerator() == 0
-                ? "No digital zoom"
-                : value.toSimpleString(true) + "x digital zoom";
-    }
-
-    @Nullable
-    public String getFocusDescription()
-    {
-        Rational value = _directory.getRational(TAG_FOCUS);
-        return value == null
-            ? null
-            : value.getNumerator() == 1 && value.getDenominator() == 0
-                ? "Infinite"
-                : value.toSimpleString(true);
-    }
-
-    @Nullable
-    public String getWhiteBalanceDescription()
-    {
-        return getIndexedDescription(TAG_WHITE_BALANCE,
-            "Auto",
-            "Preset",
-            "Daylight",
-            "Incandescence",
-            "Florescence",
-            "Cloudy",
-            "SpeedLight"
-        );
-    }
-
-    @Nullable
-    public String getCcdSensitivityDescription()
-    {
-        return getIndexedDescription(TAG_CCD_SENSITIVITY,
-            "ISO80",
-            null,
-            "ISO160",
-            null,
-            "ISO320",
-            "ISO100"
-        );
-    }
-
-    @Nullable
-    public String getImageAdjustmentDescription()
-    {
-        return getIndexedDescription(TAG_IMAGE_ADJUSTMENT,
-            "Normal",
-            "Bright +",
-            "Bright -",
-            "Contrast +",
-            "Contrast -"
-        );
-    }
-
-    @Nullable
-    public String getColorModeDescription()
-    {
-        return getIndexedDescription(TAG_COLOR_MODE,
-            1,
-            "Color",
-            "Monochrome"
-        );
-    }
-
-    @Nullable
-    public String getQualityDescription()
-    {
-        return getIndexedDescription(TAG_QUALITY,
-            1,
-            "VGA Basic",
-            "VGA Normal",
-            "VGA Fine",
-            "SXGA Basic",
-            "SXGA Normal",
-            "SXGA Fine"
-        );
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/NikonType1MakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/NikonType1MakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,93 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific to Nikon (type 1) cameras.  Type-1 is for E-Series cameras prior to (not including) E990.
- *
- * There are 3 formats of Nikon's Makernote. Makernote of E700/E800/E900/E900S/E910/E950
- * starts from ASCII string "Nikon". Data format is the same as IFD, but it starts from
- * offset 0x08. This is the same as Olympus except start string. Example of actual data
- * structure is shown below.
- * <pre><code>
- * :0000: 4E 69 6B 6F 6E 00 01 00-05 00 02 00 02 00 06 00 Nikon...........
- * :0010: 00 00 EC 02 00 00 03 00-03 00 01 00 00 00 06 00 ................
- * </code></pre>
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class NikonType1MakernoteDirectory extends Directory
-{
-    public static final int TAG_UNKNOWN_1 = 0x0002;
-    public static final int TAG_QUALITY = 0x0003;
-    public static final int TAG_COLOR_MODE = 0x0004;
-    public static final int TAG_IMAGE_ADJUSTMENT = 0x0005;
-    public static final int TAG_CCD_SENSITIVITY = 0x0006;
-    public static final int TAG_WHITE_BALANCE = 0x0007;
-    public static final int TAG_FOCUS = 0x0008;
-    public static final int TAG_UNKNOWN_2 = 0x0009;
-    public static final int TAG_DIGITAL_ZOOM = 0x000A;
-    public static final int TAG_CONVERTER = 0x000B;
-    public static final int TAG_UNKNOWN_3 = 0x0F00;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TAG_CCD_SENSITIVITY, "CCD Sensitivity");
-        _tagNameMap.put(TAG_COLOR_MODE, "Color Mode");
-        _tagNameMap.put(TAG_DIGITAL_ZOOM, "Digital Zoom");
-        _tagNameMap.put(TAG_CONVERTER, "Fisheye Converter");
-        _tagNameMap.put(TAG_FOCUS, "Focus");
-        _tagNameMap.put(TAG_IMAGE_ADJUSTMENT, "Image Adjustment");
-        _tagNameMap.put(TAG_QUALITY, "Quality");
-        _tagNameMap.put(TAG_UNKNOWN_1, "Makernote Unknown 1");
-        _tagNameMap.put(TAG_UNKNOWN_2, "Makernote Unknown 2");
-        _tagNameMap.put(TAG_UNKNOWN_3, "Makernote Unknown 3");
-        _tagNameMap.put(TAG_WHITE_BALANCE, "White Balance");
-    }
-
-    public NikonType1MakernoteDirectory()
-    {
-        this.setDescriptor(new NikonType1MakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Nikon Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/NikonType2MakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/NikonType2MakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,380 +1,0 @@
-/*
- * 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
- *
- *        http://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.Rational;
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import java.nio.ByteBuffer;
-import java.text.DecimalFormat;
-
-import static com.drew.metadata.exif.makernotes.NikonType2MakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link NikonType2MakernoteDirectory}.
- *
- * Type-2 applies to the E990 and D-series cameras such as the D1, D70 and D100.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class NikonType2MakernoteDescriptor extends TagDescriptor<NikonType2MakernoteDirectory>
-{
-    public NikonType2MakernoteDescriptor(@NotNull NikonType2MakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType)
-        {
-            case TAG_PROGRAM_SHIFT:
-                return getProgramShiftDescription();
-            case TAG_EXPOSURE_DIFFERENCE:
-                return getExposureDifferenceDescription();
-            case TAG_LENS:
-                return getLensDescription();
-            case TAG_CAMERA_HUE_ADJUSTMENT:
-                return getHueAdjustmentDescription();
-            case TAG_CAMERA_COLOR_MODE:
-                return getColorModeDescription();
-            case TAG_AUTO_FLASH_COMPENSATION:
-                return getAutoFlashCompensationDescription();
-            case TAG_FLASH_EXPOSURE_COMPENSATION:
-                return getFlashExposureCompensationDescription();
-            case TAG_FLASH_BRACKET_COMPENSATION:
-                return getFlashBracketCompensationDescription();
-            case TAG_EXPOSURE_TUNING:
-                return getExposureTuningDescription();
-            case TAG_LENS_STOPS:
-                return getLensStopsDescription();
-            case TAG_COLOR_SPACE:
-                return getColorSpaceDescription();
-            case TAG_ACTIVE_D_LIGHTING:
-                return getActiveDLightingDescription();
-            case TAG_VIGNETTE_CONTROL:
-                return getVignetteControlDescription();
-            case TAG_ISO_1:
-                return getIsoSettingDescription();
-            case TAG_DIGITAL_ZOOM:
-                return getDigitalZoomDescription();
-            case TAG_FLASH_USED:
-                return getFlashUsedDescription();
-            case TAG_AF_FOCUS_POSITION:
-                return getAutoFocusPositionDescription();
-            case TAG_FIRMWARE_VERSION:
-                return getFirmwareVersionDescription();
-            case TAG_LENS_TYPE:
-                return getLensTypeDescription();
-            case TAG_SHOOTING_MODE:
-                return getShootingModeDescription();
-            case TAG_NEF_COMPRESSION:
-                return getNEFCompressionDescription();
-            case TAG_HIGH_ISO_NOISE_REDUCTION:
-                return getHighISONoiseReductionDescription();
-            case TAG_POWER_UP_TIME:
-                return getPowerUpTimeDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getPowerUpTimeDescription()
-    {
-        // this is generally a byte[] of length 8 directly representing a date and time.
-        // the format is : first 2 bytes together are the year, and then each byte after
-        //                 is month, day, hour, minute, second with the eighth byte unused
-        // e.g., 2011:04:25 01:54:58
-
-        byte[] values = _directory.getByteArray(TAG_POWER_UP_TIME);
-        short year = ByteBuffer.wrap(new byte[]{values[0], values[1]}).getShort();
-        return String.format("%04d:%02d:%02d %02d:%02d:%02d", year, values[2], values[3], 
-                                                        values[4], values[5], values[6]);
-    }
-
-    @Nullable
-    public String getHighISONoiseReductionDescription()
-    {
-        return getIndexedDescription(TAG_HIGH_ISO_NOISE_REDUCTION,
-            "Off",
-            "Minimal",
-            "Low",
-            null,
-            "Normal",
-            null,
-            "High"
-        );
-    }
-
-    @Nullable
-    public String getFlashUsedDescription()
-    {
-        return getIndexedDescription(TAG_FLASH_USED,
-            "Flash Not Used",
-            "Manual Flash",
-            null,
-            "Flash Not Ready",
-            null,
-            null,
-            null,
-            "External Flash",
-            "Fired, Commander Mode",
-            "Fired, TTL Mode"
-        );
-    }
-
-    @Nullable
-    public String getNEFCompressionDescription()
-    {
-        return getIndexedDescription(TAG_NEF_COMPRESSION,
-            1,
-            "Lossy (Type 1)",
-            null,
-            "Uncompressed",
-            null,
-            null,
-            null,
-            "Lossless",
-            "Lossy (Type 2)"
-        );
-    }
-
-    @Nullable
-    public String getShootingModeDescription()
-    {
-        return getBitFlagDescription(TAG_SHOOTING_MODE,
-            // LSB [low label, high label]
-            new String[]{"Single Frame", "Continuous"},
-            "Delay",
-            null,
-            "PC Control",
-            "Exposure Bracketing",
-            "Auto ISO",
-            "White-Balance Bracketing",
-            "IR Control"
-        );
-    }
-
-    @Nullable
-    public String getLensTypeDescription()
-    {
-        return getBitFlagDescription(TAG_LENS_TYPE,
-            // LSB [low label, high label]
-            new String[]{"AF", "MF"},
-            "D",
-            "G",
-            "VR"
-        );
-    }
-
-    @Nullable
-    public String getColorSpaceDescription()
-    {
-        return getIndexedDescription(TAG_COLOR_SPACE,
-            1,
-            "sRGB",
-            "Adobe RGB"
-        );
-    }
-
-    @Nullable
-    public String getActiveDLightingDescription()
-    {
-        Integer value = _directory.getInteger(TAG_ACTIVE_D_LIGHTING);
-        if (value==null)
-            return null;
-        switch (value) {
-            case 0: return "Off";
-            case 1: return "Light";
-            case 3: return "Normal";
-            case 5: return "High";
-            case 7: return "Extra High";
-            case 65535: return "Auto";
-            default: return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getVignetteControlDescription()
-    {
-        Integer value = _directory.getInteger(TAG_VIGNETTE_CONTROL);
-        if (value==null)
-            return null;
-        switch (value) {
-            case 0: return "Off";
-            case 1: return "Low";
-            case 3: return "Normal";
-            case 5: return "High";
-            default: return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getAutoFocusPositionDescription()
-    {
-        int[] values = _directory.getIntArray(TAG_AF_FOCUS_POSITION);
-        if (values==null)
-            return null;
-        if (values.length != 4 || values[0] != 0 || values[2] != 0 || values[3] != 0) {
-            return "Unknown (" + _directory.getString(TAG_AF_FOCUS_POSITION) + ")";
-        }
-        switch (values[1]) {
-            case 0:
-                return "Centre";
-            case 1:
-                return "Top";
-            case 2:
-                return "Bottom";
-            case 3:
-                return "Left";
-            case 4:
-                return "Right";
-            default:
-                return "Unknown (" + values[1] + ")";
-        }
-    }
-
-    @Nullable
-    public String getDigitalZoomDescription()
-    {
-        Rational value = _directory.getRational(TAG_DIGITAL_ZOOM);
-        if (value==null)
-            return null;
-        return value.intValue() == 1
-                ? "No digital zoom"
-                : value.toSimpleString(true) + "x digital zoom";
-    }
-
-    @Nullable
-    public String getProgramShiftDescription()
-    {
-        return getEVDescription(TAG_PROGRAM_SHIFT);
-    }
-
-    @Nullable
-    public String getExposureDifferenceDescription()
-    {
-        return getEVDescription(TAG_EXPOSURE_DIFFERENCE);
-    }
-
-    @Nullable
-    public String getAutoFlashCompensationDescription()
-    {
-        return getEVDescription(TAG_AUTO_FLASH_COMPENSATION);
-    }
-
-    @Nullable
-    public String getFlashExposureCompensationDescription()
-    {
-        return getEVDescription(TAG_FLASH_EXPOSURE_COMPENSATION);
-    }
-
-    @Nullable
-    public String getFlashBracketCompensationDescription()
-    {
-        return getEVDescription(TAG_FLASH_BRACKET_COMPENSATION);
-    }
-
-    @Nullable
-    public String getExposureTuningDescription()
-    {
-        return getEVDescription(TAG_EXPOSURE_TUNING);
-    }
-
-    @Nullable
-    public String getLensStopsDescription()
-    {
-        return getEVDescription(TAG_LENS_STOPS);
-    }
-
-    @Nullable
-    private String getEVDescription(int tagType)
-    {
-        int[] values = _directory.getIntArray(tagType);
-        if (values == null || values.length < 2)
-            return null;
-        if (values.length < 3 || values[2] == 0)
-            return null;
-        final DecimalFormat decimalFormat = new DecimalFormat("0.##");
-        double ev = values[0] * values[1] / (double)values[2];
-        return decimalFormat.format(ev) + " EV";
-    }
-
-    @Nullable
-    public String getIsoSettingDescription()
-    {
-        int[] values = _directory.getIntArray(TAG_ISO_1);
-        if (values == null)
-            return null;
-        if (values[0] != 0 || values[1] == 0)
-            return "Unknown (" + _directory.getString(TAG_ISO_1) + ")";
-        return "ISO " + values[1];
-    }
-
-    @Nullable
-    public String getLensDescription()
-    {
-        return getLensSpecificationDescription(TAG_LENS);
-    }
-
-    @Nullable
-    public String getLensFocusDistance()
-    {
-        int[] values = _directory.getDecryptedIntArray(TAG_LENS_DATA);
-
-        if (values == null || values.length < 11)
-            return null;
-
-        return String.format("%.2fm", getDistanceInMeters(values[10]));
-    }
-
-    @Nullable
-    public String getHueAdjustmentDescription()
-    {
-        return getFormattedString(TAG_CAMERA_HUE_ADJUSTMENT, "%s degrees");
-    }
-
-    @Nullable
-    public String getColorModeDescription()
-    {
-        String value = _directory.getString(TAG_CAMERA_COLOR_MODE);
-        return value == null ? null : value.startsWith("MODE1") ? "Mode I (sRGB)" : value;
-    }
-
-    @Nullable
-    public String getFirmwareVersionDescription()
-    {
-        return getVersionBytesDescription(TAG_FIRMWARE_VERSION, 2);
-    }
-
-    private double getDistanceInMeters(int val)
-    {
-        if (val < 0)
-            val += 256;
-        return 0.01 * Math.pow(10, val / 40.0f);
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/NikonType2MakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/NikonType2MakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,990 +1,0 @@
-/*
- * 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
- *
- *        http://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.
- * http://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:
-     * http://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: http://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_UNKNOWN_35 = 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_UNKNOWN_40 = 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_UNKNOWN_11 = 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_UNKNOWN_32 = 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_UNKNOWN_49 = 0x00BB;
-    public static final int TAG_UNKNOWN_50 = 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
-    protected 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_UNKNOWN_11, "Unknown 11");
-        _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_UNKNOWN_35, "Unknown 35");
-        _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_UNKNOWN_40, "Unknown 40");
-        _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_UNKNOWN_32, "Unknown 32");
-        _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_UNKNOWN_49, "Unknown 49");
-        _tagNameMap.put(TAG_UNKNOWN_50, "Unknown 50");
-        _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;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/OlympusCameraSettingsMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/OlympusCameraSettingsMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,1412 +1,0 @@
-/*
- * Copyright 2002-2015 Drew Noakes
- *
- *    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
- *
- *        http://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.Rational;
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import java.text.DecimalFormat;
-import java.util.HashMap;
-
-import static com.drew.metadata.exif.makernotes.OlympusCameraSettingsMakernoteDirectory.*;
-
-/**
- * Provides human-readable String representations of tag values stored in a {@link OlympusCameraSettingsMakernoteDirectory}.
- * <p>
- * Some Description functions and the Extender and Lens types lists converted from Exiftool version 10.10 created by Phil Harvey
- * http://www.sno.phy.queensu.ca/~phil/exiftool/
- * lib\Image\ExifTool\Olympus.pm
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class OlympusCameraSettingsMakernoteDescriptor extends TagDescriptor<OlympusCameraSettingsMakernoteDirectory>
-{
-    public OlympusCameraSettingsMakernoteDescriptor(@NotNull OlympusCameraSettingsMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TagCameraSettingsVersion:
-                return getCameraSettingsVersionDescription();
-            case TagPreviewImageValid:
-                return getPreviewImageValidDescription();
-
-            case TagExposureMode:
-                return getExposureModeDescription();
-            case TagAeLock:
-                return getAeLockDescription();
-            case TagMeteringMode:
-                return getMeteringModeDescription();
-            case TagExposureShift:
-                return getExposureShiftDescription();
-            case TagNdFilter:
-                return getNdFilterDescription();
-
-            case TagMacroMode:
-                return getMacroModeDescription();
-            case TagFocusMode:
-                return getFocusModeDescription();
-            case TagFocusProcess:
-                return getFocusProcessDescription();
-            case TagAfSearch:
-                return getAfSearchDescription();
-            case TagAfAreas:
-                return getAfAreasDescription();
-            case TagAfPointSelected:
-                return getAfPointSelectedDescription();
-            case TagAfFineTune:
-                return getAfFineTuneDescription();
-
-            case TagFlashMode:
-                return getFlashModeDescription();
-            case TagFlashRemoteControl:
-                return getFlashRemoteControlDescription();
-            case TagFlashControlMode:
-                return getFlashControlModeDescription();
-            case TagFlashIntensity:
-                return getFlashIntensityDescription();
-            case TagManualFlashStrength:
-                return getManualFlashStrengthDescription();
-
-            case TagWhiteBalance2:
-                return getWhiteBalance2Description();
-            case TagWhiteBalanceTemperature:
-                return getWhiteBalanceTemperatureDescription();
-            case TagCustomSaturation:
-                return getCustomSaturationDescription();
-            case TagModifiedSaturation:
-                return getModifiedSaturationDescription();
-            case TagContrastSetting:
-                return getContrastSettingDescription();
-            case TagSharpnessSetting:
-                return getSharpnessSettingDescription();
-            case TagColorSpace:
-                return getColorSpaceDescription();
-            case TagSceneMode:
-                return getSceneModeDescription();
-            case TagNoiseReduction:
-                return getNoiseReductionDescription();
-            case TagDistortionCorrection:
-                return getDistortionCorrectionDescription();
-            case TagShadingCompensation:
-                return getShadingCompensationDescription();
-            case TagGradation:
-                return getGradationDescription();
-            case TagPictureMode:
-                return getPictureModeDescription();
-            case TagPictureModeSaturation:
-                return getPictureModeSaturationDescription();
-            case TagPictureModeContrast:
-                return getPictureModeContrastDescription();
-            case TagPictureModeSharpness:
-                return getPictureModeSharpnessDescription();
-            case TagPictureModeBWFilter:
-                return getPictureModeBWFilterDescription();
-            case TagPictureModeTone:
-                return getPictureModeToneDescription();
-            case TagNoiseFilter:
-                return getNoiseFilterDescription();
-            case TagArtFilter:
-                return getArtFilterDescription();
-            case TagMagicFilter:
-                return getMagicFilterDescription();
-            case TagPictureModeEffect:
-                return getPictureModeEffectDescription();
-            case TagToneLevel:
-                return getToneLevelDescription();
-            case TagArtFilterEffect:
-                return getArtFilterEffectDescription();
-            case TagColorCreatorEffect:
-                return getColorCreatorEffectDescription();
-
-            case TagDriveMode:
-                return getDriveModeDescription();
-            case TagPanoramaMode:
-                return getPanoramaModeDescription();
-            case TagImageQuality2:
-                return getImageQuality2Description();
-            case TagImageStabilization:
-                return getImageStabilizationDescription();
-
-            case TagStackedImage:
-                return getStackedImageDescription();
-
-            case TagManometerPressure:
-                return getManometerPressureDescription();
-            case TagManometerReading:
-                return getManometerReadingDescription();
-            case TagExtendedWBDetect:
-                return getExtendedWBDetectDescription();
-            case TagRollAngle:
-                return getRollAngleDescription();
-            case TagPitchAngle:
-                return getPitchAngleDescription();
-            case TagDateTimeUtc:
-                return getDateTimeUTCDescription();
-
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getCameraSettingsVersionDescription()
-    {
-        return getVersionBytesDescription(TagCameraSettingsVersion, 4);
-    }
-
-    @Nullable
-    public String getPreviewImageValidDescription()
-    {
-        return getIndexedDescription(TagPreviewImageValid,
-            "No", "Yes");
-    }
-
-    @Nullable
-    public String getExposureModeDescription()
-    {
-        return getIndexedDescription(TagExposureMode, 1,
-            "Manual", "Program", "Aperture-priority AE", "Shutter speed priority", "Program-shift");
-    }
-
-    @Nullable
-    public String getAeLockDescription()
-    {
-        return getIndexedDescription(TagAeLock,
-            "Off", "On");
-    }
-
-    @Nullable
-    public String getMeteringModeDescription()
-    {
-        Integer value = _directory.getInteger(TagMeteringMode);
-        if (value == null)
-            return null;
-
-        switch (value) {
-            case 2:
-                return "Center-weighted average";
-            case 3:
-                return "Spot";
-            case 5:
-                return "ESP";
-            case 261:
-                return "Pattern+AF";
-            case 515:
-                return "Spot+Highlight control";
-            case 1027:
-                return "Spot+Shadow control";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getExposureShiftDescription()
-    {
-        return getRationalOrDoubleString(TagExposureShift);
-    }
-
-    @Nullable
-    public String getNdFilterDescription()
-    {
-        return getIndexedDescription(TagNdFilter, "Off", "On");
-    }
-
-    @Nullable
-    public String getMacroModeDescription()
-    {
-        return getIndexedDescription(TagMacroMode, "Off", "On", "Super Macro");
-    }
-
-    @Nullable
-    public String getFocusModeDescription()
-    {
-        int[] values = _directory.getIntArray(TagFocusMode);
-        if (values == null) {
-            // check if it's only one value long also
-            Integer value = _directory.getInteger(TagFocusMode);
-            if (value == null)
-                return null;
-
-            values = new int[]{value};
-        }
-
-        if (values.length == 0)
-            return null;
-
-        StringBuilder sb = new StringBuilder();
-        switch (values[0]) {
-            case 0:
-                sb.append("Single AF");
-                break;
-            case 1:
-                sb.append("Sequential shooting AF");
-                break;
-            case 2:
-                sb.append("Continuous AF");
-                break;
-            case 3:
-                sb.append("Multi AF");
-                break;
-            case 4:
-                sb.append("Face detect");
-                break;
-            case 10:
-                sb.append("MF");
-                break;
-            default:
-                sb.append("Unknown (" + values[0] + ")");
-                break;
-        }
-
-        if (values.length > 1) {
-            sb.append("; ");
-            int value1 = values[1];
-
-            if (value1 == 0) {
-                sb.append("(none)");
-            } else {
-                if (( value1       & 1) > 0) sb.append("S-AF, ");
-                if (((value1 >> 2) & 1) > 0) sb.append("C-AF, ");
-                if (((value1 >> 4) & 1) > 0) sb.append("MF, ");
-                if (((value1 >> 5) & 1) > 0) sb.append("Face detect, ");
-                if (((value1 >> 6) & 1) > 0) sb.append("Imager AF, ");
-                if (((value1 >> 7) & 1) > 0) sb.append("Live View Magnification Frame, ");
-                if (((value1 >> 8) & 1) > 0) sb.append("AF sensor, ");
-
-                sb.setLength(sb.length() - 2);
-            }
-        }
-
-        return sb.toString();
-    }
-
-    @Nullable
-    public String getFocusProcessDescription()
-    {
-        int[] values = _directory.getIntArray(TagFocusProcess);
-        if (values == null) {
-            // check if it's only one value long also
-            Integer value = _directory.getInteger(TagFocusProcess);
-            if (value == null)
-                return null;
-
-            values = new int[]{value};
-        }
-
-        if (values.length == 0)
-            return null;
-
-        StringBuilder sb = new StringBuilder();
-
-        switch (values[0]) {
-            case 0:
-                sb.append("AF not used");
-                break;
-            case 1:
-                sb.append("AF used");
-                break;
-            default:
-                sb.append("Unknown (" + values[0] + ")");
-                break;
-        }
-
-        if (values.length > 1)
-            sb.append("; " + values[1]);
-
-        return sb.toString();
-    }
-
-    @Nullable
-    public String getAfSearchDescription()
-    {
-        return getIndexedDescription(TagAfSearch, "Not Ready", "Ready");
-    }
-
-    /// <summary>
-    /// coordinates range from 0 to 255
-    /// </summary>
-    /// <returns></returns>
-    @Nullable
-    public String getAfAreasDescription()
-    {
-        Object obj = _directory.getObject(TagAfAreas);
-        if (obj == null || !(obj instanceof long[]))
-            return null;
-
-        StringBuilder sb = new StringBuilder();
-        for (long point : (long[]) obj) {
-            if (point == 0L)
-                continue;
-            if (sb.length() != 0)
-                sb.append(", ");
-
-            if (point == 0x36794285L)
-                sb.append("Left ");
-            else if (point == 0x79798585L)
-                sb.append("Center ");
-            else if (point == 0xBD79C985L)
-                sb.append("Right ");
-
-            sb.append(String.format("(%d/255,%d/255)-(%d/255,%d/255)",
-                (point >> 24) & 0xFF,
-                (point >> 16) & 0xFF,
-                (point >> 8) & 0xFF,
-                point & 0xFF));
-        }
-
-        return sb.length() == 0 ? null : sb.toString();
-    }
-
-    /// <summary>
-    /// coordinates expressed as a percent
-    /// </summary>
-    /// <returns></returns>
-    @Nullable
-    public String getAfPointSelectedDescription()
-    {
-        Rational[] values = _directory.getRationalArray(TagAfPointSelected);
-        if (values == null)
-            return "n/a";
-
-        if (values.length < 4)
-            return null;
-
-        int index = 0;
-        if (values.length == 5 && values[0].longValue() == 0)
-            index = 1;
-
-        int p1 = (int)(values[index].doubleValue() * 100);
-        int p2 = (int)(values[index + 1].doubleValue() * 100);
-        int p3 = (int)(values[index + 2].doubleValue() * 100);
-        int p4 = (int)(values[index + 3].doubleValue() * 100);
-
-        if(p1 + p2 + p3 + p4 == 0)
-            return "n/a";
-
-        return String.format("(%d%%,%d%%) (%d%%,%d%%)", p1, p2, p3, p4);
-    }
-
-    @Nullable
-    public String getAfFineTuneDescription()
-    {
-        return getIndexedDescription(TagAfFineTune, "Off", "On");
-    }
-
-    @Nullable
-    public String getFlashModeDescription()
-    {
-        Integer value = _directory.getInteger(TagFlashMode);
-        if (value == null)
-            return null;
-
-        if (value == 0)
-            return "Off";
-
-        StringBuilder sb = new StringBuilder();
-        int v = value;
-
-        if (( v       & 1) != 0) sb.append("On, ");
-        if (((v >> 1) & 1) != 0) sb.append("Fill-in, ");
-        if (((v >> 2) & 1) != 0) sb.append("Red-eye, ");
-        if (((v >> 3) & 1) != 0) sb.append("Slow-sync, ");
-        if (((v >> 4) & 1) != 0) sb.append("Forced On, ");
-        if (((v >> 5) & 1) != 0) sb.append("2nd Curtain, ");
-
-        return sb.substring(0, sb.length() - 2);
-    }
-
-    @Nullable
-    public String getFlashRemoteControlDescription()
-    {
-        Integer value = _directory.getInteger(TagFlashRemoteControl);
-        if (value == null)
-            return null;
-
-        switch (value) {
-            case 0:
-                return "Off";
-            case 0x01:
-                return "Channel 1, Low";
-            case 0x02:
-                return "Channel 2, Low";
-            case 0x03:
-                return "Channel 3, Low";
-            case 0x04:
-                return "Channel 4, Low";
-            case 0x09:
-                return "Channel 1, Mid";
-            case 0x0a:
-                return "Channel 2, Mid";
-            case 0x0b:
-                return "Channel 3, Mid";
-            case 0x0c:
-                return "Channel 4, Mid";
-            case 0x11:
-                return "Channel 1, High";
-            case 0x12:
-                return "Channel 2, High";
-            case 0x13:
-                return "Channel 3, High";
-            case 0x14:
-                return "Channel 4, High";
-
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    /// <summary>
-    /// 3 or 4 values
-    /// </summary>
-    /// <returns></returns>
-    @Nullable
-    public String getFlashControlModeDescription()
-    {
-        int[] values = _directory.getIntArray(TagFlashControlMode);
-        if (values == null)
-            return null;
-
-        if (values.length == 0)
-            return null;
-
-        StringBuilder sb = new StringBuilder();
-
-        switch (values[0]) {
-            case 0:
-                sb.append("Off");
-                break;
-            case 3:
-                sb.append("TTL");
-                break;
-            case 4:
-                sb.append("Auto");
-                break;
-            case 5:
-                sb.append("Manual");
-                break;
-            default:
-                sb.append("Unknown (").append(values[0]).append(")");
-                break;
-        }
-
-        for (int i = 1; i < values.length; i++)
-            sb.append("; ").append(values[i]);
-
-        return sb.toString();
-    }
-
-    /// <summary>
-    /// 3 or 4 values
-    /// </summary>
-    /// <returns></returns>
-    @Nullable
-    public String getFlashIntensityDescription()
-    {
-        Rational[] values = _directory.getRationalArray(TagFlashIntensity);
-        if (values == null || values.length == 0)
-            return null;
-
-        if (values.length == 3) {
-            if (values[0].getDenominator() == 0 && values[1].getDenominator() == 0 && values[2].getDenominator() == 0)
-                return "n/a";
-        } else if (values.length == 4) {
-            if (values[0].getDenominator() == 0 && values[1].getDenominator() == 0 && values[2].getDenominator() == 0 && values[3].getDenominator() == 0)
-                return "n/a (x4)";
-        }
-
-        StringBuilder sb = new StringBuilder();
-        for (Rational t : values)
-            sb.append(t).append(", ");
-
-        return sb.substring(0, sb.length() - 2);
-    }
-
-    @Nullable
-    public String getManualFlashStrengthDescription()
-    {
-        Rational[] values = _directory.getRationalArray(TagManualFlashStrength);
-        if (values == null || values.length == 0)
-            return "n/a";
-
-        if (values.length == 3) {
-            if (values[0].getDenominator() == 0 && values[1].getDenominator() == 0 && values[2].getDenominator() == 0)
-                return "n/a";
-        } else if (values.length == 4) {
-            if (values[0].getDenominator() == 0 && values[1].getDenominator() == 0 && values[2].getDenominator() == 0 && values[3].getDenominator() == 0)
-                return "n/a (x4)";
-        }
-
-        StringBuilder sb = new StringBuilder();
-        for (Rational t : values)
-            sb.append(t).append(", ");
-
-        return sb.substring(0, sb.length() - 2);
-    }
-
-    @Nullable
-    public String getWhiteBalance2Description()
-    {
-        Integer value = _directory.getInteger(TagWhiteBalance2);
-        if (value == null)
-            return null;
-
-        switch (value) {
-            case 0:
-                return "Auto";
-            case 1:
-                return "Auto (Keep Warm Color Off)";
-            case 16:
-                return "7500K (Fine Weather with Shade)";
-            case 17:
-                return "6000K (Cloudy)";
-            case 18:
-                return "5300K (Fine Weather)";
-            case 20:
-                return "3000K (Tungsten light)";
-            case 21:
-                return "3600K (Tungsten light-like)";
-            case 22:
-                return "Auto Setup";
-            case 23:
-                return "5500K (Flash)";
-            case 33:
-                return "6600K (Daylight fluorescent)";
-            case 34:
-                return "4500K (Neutral white fluorescent)";
-            case 35:
-                return "4000K (Cool white fluorescent)";
-            case 36:
-                return "White Fluorescent";
-            case 48:
-                return "3600K (Tungsten light-like)";
-            case 67:
-                return "Underwater";
-            case 256:
-                return "One Touch WB 1";
-            case 257:
-                return "One Touch WB 2";
-            case 258:
-                return "One Touch WB 3";
-            case 259:
-                return "One Touch WB 4";
-            case 512:
-                return "Custom WB 1";
-            case 513:
-                return "Custom WB 2";
-            case 514:
-                return "Custom WB 3";
-            case 515:
-                return "Custom WB 4";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getWhiteBalanceTemperatureDescription()
-    {
-        Integer value = _directory.getInteger(TagWhiteBalanceTemperature);
-        if (value == null)
-            return null;
-        if (value == 0)
-            return "Auto";
-        return value.toString();
-    }
-
-    @Nullable
-    public String getCustomSaturationDescription()
-    {
-        // TODO: if model is /^E-1\b/  then
-        // $a-=$b; $c-=$b;
-        // return "CS$a (min CS0, max CS$c)"
-        return getValueMinMaxDescription(TagCustomSaturation);
-    }
-
-    @Nullable
-    public String getModifiedSaturationDescription()
-    {
-        return getIndexedDescription(TagModifiedSaturation,
-            "Off", "CM1 (Red Enhance)", "CM2 (Green Enhance)", "CM3 (Blue Enhance)", "CM4 (Skin Tones)");
-    }
-
-    @Nullable
-    public String getContrastSettingDescription()
-    {
-        return getValueMinMaxDescription(TagContrastSetting);
-    }
-
-    @Nullable
-    public String getSharpnessSettingDescription()
-    {
-        return getValueMinMaxDescription(TagSharpnessSetting);
-    }
-
-    @Nullable
-    public String getColorSpaceDescription()
-    {
-        return getIndexedDescription(TagColorSpace,
-            "sRGB", "Adobe RGB", "Pro Photo RGB");
-    }
-
-    @Nullable
-    public String getSceneModeDescription()
-    {
-        Integer value = _directory.getInteger(TagSceneMode);
-        if (value == null)
-            return null;
-
-        switch (value) {
-            case 0:
-                return "Standard";
-            case 6:
-                return "Auto";
-            case 7:
-                return "Sport";
-            case 8:
-                return "Portrait";
-            case 9:
-                return "Landscape+Portrait";
-            case 10:
-                return "Landscape";
-            case 11:
-                return "Night Scene";
-            case 12:
-                return "Self Portrait";
-            case 13:
-                return "Panorama";
-            case 14:
-                return "2 in 1";
-            case 15:
-                return "Movie";
-            case 16:
-                return "Landscape+Portrait";
-            case 17:
-                return "Night+Portrait";
-            case 18:
-                return "Indoor";
-            case 19:
-                return "Fireworks";
-            case 20:
-                return "Sunset";
-            case 21:
-                return "Beauty Skin";
-            case 22:
-                return "Macro";
-            case 23:
-                return "Super Macro";
-            case 24:
-                return "Food";
-            case 25:
-                return "Documents";
-            case 26:
-                return "Museum";
-            case 27:
-                return "Shoot & Select";
-            case 28:
-                return "Beach & Snow";
-            case 29:
-                return "Self Portrait+Timer";
-            case 30:
-                return "Candle";
-            case 31:
-                return "Available Light";
-            case 32:
-                return "Behind Glass";
-            case 33:
-                return "My Mode";
-            case 34:
-                return "Pet";
-            case 35:
-                return "Underwater Wide1";
-            case 36:
-                return "Underwater Macro";
-            case 37:
-                return "Shoot & Select1";
-            case 38:
-                return "Shoot & Select2";
-            case 39:
-                return "High Key";
-            case 40:
-                return "Digital Image Stabilization";
-            case 41:
-                return "Auction";
-            case 42:
-                return "Beach";
-            case 43:
-                return "Snow";
-            case 44:
-                return "Underwater Wide2";
-            case 45:
-                return "Low Key";
-            case 46:
-                return "Children";
-            case 47:
-                return "Vivid";
-            case 48:
-                return "Nature Macro";
-            case 49:
-                return "Underwater Snapshot";
-            case 50:
-                return "Shooting Guide";
-            case 54:
-                return "Face Portrait";
-            case 57:
-                return "Bulb";
-            case 59:
-                return "Smile Shot";
-            case 60:
-                return "Quick Shutter";
-            case 63:
-                return "Slow Shutter";
-            case 64:
-                return "Bird Watching";
-            case 65:
-                return "Multiple Exposure";
-            case 66:
-                return "e-Portrait";
-            case 67:
-                return "Soft Background Shot";
-            case 142:
-                return "Hand-held Starlight";
-            case 154:
-                return "HDR";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getNoiseReductionDescription()
-    {
-        Integer value = _directory.getInteger(TagNoiseReduction);
-        if (value == null)
-            return null;
-
-        if (value == 0)
-            return "(none)";
-
-        StringBuilder sb = new StringBuilder();
-        int v = value;
-
-        if ((v & 1) != 0) sb.append("Noise Reduction, ");
-        if (((v >> 1) & 1) != 0) sb.append("Noise Filter, ");
-        if (((v >> 2) & 1) != 0) sb.append("Noise Filter (ISO Boost), ");
-        if (((v >> 3) & 1) != 0) sb.append("Auto, ");
-
-        return sb.length() != 0
-            ? sb.substring(0, sb.length() - 2)
-            : "(none)";
-    }
-
-    @Nullable
-    public String getDistortionCorrectionDescription()
-    {
-        return getIndexedDescription(TagDistortionCorrection, "Off", "On");
-    }
-
-    @Nullable
-    public String getShadingCompensationDescription()
-    {
-        return getIndexedDescription(TagShadingCompensation, "Off", "On");
-    }
-
-    /// <summary>
-    /// 3 or 4 values
-    /// </summary>
-    /// <returns></returns>
-    @Nullable
-    public String getGradationDescription()
-    {
-        int[] values = _directory.getIntArray(TagGradation);
-        if (values == null || values.length < 3)
-            return null;
-
-        String join = String.format("%d %d %d", values[0], values[1], values[2]);
-
-        String ret;
-        if (join.equals("0 0 0")) {
-            ret = "n/a";
-        } else if (join.equals("-1 -1 1")) {
-            ret = "Low Key";
-        } else if (join.equals("0 -1 1")) {
-            ret = "Normal";
-        } else if (join.equals("1 -1 1")) {
-            ret = "High Key";
-        } else {
-            ret = "Unknown (" + join + ")";
-        }
-
-        if (values.length > 3) {
-            if (values[3] == 0)
-                ret += "; User-Selected";
-            else if (values[3] == 1)
-                ret += "; Auto-Override";
-        }
-
-        return ret;
-    }
-
-    /// <summary>
-    /// 1 or 2 values
-    /// </summary>
-    /// <returns></returns>
-    @Nullable
-    public String getPictureModeDescription()
-    {
-        int[] values = _directory.getIntArray(TagPictureMode);
-        if (values == null) {
-            // check if it's only one value long also
-            Integer value = _directory.getInteger(TagNoiseReduction);
-            if (value == null)
-                return null;
-
-            values = new int[]{value};
-        }
-
-        if (values.length == 0)
-            return null;
-
-        StringBuilder sb = new StringBuilder();
-        switch (values[0]) {
-            case 1:
-                sb.append("Vivid");
-                break;
-            case 2:
-                sb.append("Natural");
-                break;
-            case 3:
-                sb.append("Muted");
-                break;
-            case 4:
-                sb.append("Portrait");
-                break;
-            case 5:
-                sb.append("i-Enhance");
-                break;
-            case 256:
-                sb.append("Monotone");
-                break;
-            case 512:
-                sb.append("Sepia");
-                break;
-            default:
-                sb.append("Unknown (").append(values[0]).append(")");
-                break;
-        }
-
-        if (values.length > 1)
-            sb.append("; ").append(values[1]);
-
-        return sb.toString();
-    }
-
-    @Nullable
-    public String getPictureModeSaturationDescription()
-    {
-        return getValueMinMaxDescription(TagPictureModeSaturation);
-    }
-
-    @Nullable
-    public String getPictureModeContrastDescription()
-    {
-        return getValueMinMaxDescription(TagPictureModeContrast);
-    }
-
-    @Nullable
-    public String getPictureModeSharpnessDescription()
-    {
-        return getValueMinMaxDescription(TagPictureModeSharpness);
-    }
-
-    @Nullable
-    public String getPictureModeBWFilterDescription()
-    {
-        return getIndexedDescription(TagPictureModeBWFilter,
-            "n/a", "Neutral", "Yellow", "Orange", "Red", "Green");
-    }
-
-    @Nullable
-    public String getPictureModeToneDescription()
-    {
-        return getIndexedDescription(TagPictureModeTone,
-            "n/a", "Neutral", "Sepia", "Blue", "Purple", "Green");
-    }
-
-    @Nullable
-    public String getNoiseFilterDescription()
-    {
-        int[] values = _directory.getIntArray(TagNoiseFilter);
-        if (values == null)
-            return null;
-
-        String join = String.format("%d %d %d", values[0], values[1], values[2]);
-
-        if (join.equals("0 0 0"))
-            return "n/a";
-        if (join.equals("-2 -2 1"))
-            return "Off";
-        if (join.equals("-1 -2 1"))
-            return "Low";
-        if (join.equals("0 -2 1"))
-            return "Standard";
-        if (join.equals("1 -2 1"))
-            return "High";
-        return "Unknown (" + join + ")";
-    }
-
-    @Nullable
-    public String getArtFilterDescription()
-    {
-        return getFiltersDescription(TagArtFilter);
-    }
-
-    @Nullable
-    public String getMagicFilterDescription()
-    {
-        return getFiltersDescription(TagMagicFilter);
-    }
-
-    @Nullable
-    public String getPictureModeEffectDescription()
-    {
-        int[] values = _directory.getIntArray(TagPictureModeEffect);
-        if (values == null)
-            return null;
-
-        String key = String.format("%d %d %d", values[0], values[1], values[2]);
-        if (key.equals("0 0 0"))
-            return "n/a";
-        if (key.equals("-1 -1 1"))
-            return "Low";
-        if (key.equals("0 -1 1"))
-            return "Standard";
-        if (key.equals("1 -1 1"))
-            return "High";
-        return "Unknown (" + key + ")";
-    }
-
-    @Nullable
-    public String getToneLevelDescription()
-    {
-        int[] values = _directory.getIntArray(TagToneLevel);
-        if (values == null || values.length == 0)
-            return null;
-
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < values.length; i++) {
-            if (i == 0 || i == 4 || i == 8 || i == 12 || i == 16 || i == 20 || i == 24)
-                sb.append(_toneLevelType.get(values[i])).append("; ");
-            else
-                sb.append(values[i]).append("; ");
-        }
-
-        return sb.substring(0, sb.length() - 2);
-    }
-
-    @Nullable
-    public String getArtFilterEffectDescription()
-    {
-        int[] values = _directory.getIntArray(TagArtFilterEffect);
-        if (values == null)
-            return null;
-
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < values.length; i++) {
-            if (i == 0) {
-                sb.append((_filters.containsKey(values[i]) ? _filters.get(values[i]) : "[unknown]")).append("; ");
-            } else if (i == 3) {
-                sb.append("Partial Color ").append(values[i]).append("; ");
-            } else if (i == 4) {
-                switch (values[i]) {
-                    case 0x0000:
-                        sb.append("No Effect");
-                        break;
-                    case 0x8010:
-                        sb.append("Star Light");
-                        break;
-                    case 0x8020:
-                        sb.append("Pin Hole");
-                        break;
-                    case 0x8030:
-                        sb.append("Frame");
-                        break;
-                    case 0x8040:
-                        sb.append("Soft Focus");
-                        break;
-                    case 0x8050:
-                        sb.append("White Edge");
-                        break;
-                    case 0x8060:
-                        sb.append("B&W");
-                        break;
-                    default:
-                        sb.append("Unknown (").append(values[i]).append(")");
-                        break;
-                }
-                sb.append("; ");
-            } else if (i == 6) {
-                switch (values[i]) {
-                    case 0:
-                        sb.append("No Color Filter");
-                        break;
-                    case 1:
-                        sb.append("Yellow Color Filter");
-                        break;
-                    case 2:
-                        sb.append("Orange Color Filter");
-                        break;
-                    case 3:
-                        sb.append("Red Color Filter");
-                        break;
-                    case 4:
-                        sb.append("Green Color Filter");
-                        break;
-                    default:
-                        sb.append("Unknown (").append(values[i]).append(")");
-                        break;
-                }
-                sb.append("; ");
-            } else {
-                sb.append(values[i]).append("; ");
-            }
-        }
-
-        return sb.substring(0, sb.length() - 2);
-    }
-
-    @Nullable
-    public String getColorCreatorEffectDescription()
-    {
-        int[] values = _directory.getIntArray(TagColorCreatorEffect);
-        if (values == null)
-            return null;
-
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < values.length; i++) {
-            if (i == 0) {
-                sb.append("Color ").append(values[i]).append("; ");
-            } else if (i == 3) {
-                sb.append("Strength ").append(values[i]).append("; ");
-            } else {
-                sb.append(values[i]).append("; ");
-            }
-        }
-
-        return sb.substring(0, sb.length() - 2);
-    }
-
-    /// <summary>
-    /// 2 or 3 numbers: 1. Mode, 2. Shot number, 3. Mode bits
-    /// </summary>
-    /// <returns></returns>
-    @Nullable
-    public String getDriveModeDescription()
-    {
-        int[] values = _directory.getIntArray(TagDriveMode);
-        if (values == null)
-            return null;
-
-        if (values.length == 0 || values[0] == 0)
-            return "Single Shot";
-
-        StringBuilder a = new StringBuilder();
-
-        if (values[0] == 5 && values.length >= 3) {
-            int c = values[2];
-            if (( c       & 1) > 0) a.append("AE");
-            if (((c >> 1) & 1) > 0) a.append("WB");
-            if (((c >> 2) & 1) > 0) a.append("FL");
-            if (((c >> 3) & 1) > 0) a.append("MF");
-            if (((c >> 6) & 1) > 0) a.append("Focus");
-
-            a.append(" Bracketing");
-        } else {
-            switch (values[0]) {
-                case 1:
-                    a.append("Continuous Shooting");
-                    break;
-                case 2:
-                    a.append("Exposure Bracketing");
-                    break;
-                case 3:
-                    a.append("White Balance Bracketing");
-                    break;
-                case 4:
-                    a.append("Exposure+WB Bracketing");
-                    break;
-                default:
-                    a.append("Unknown (").append(values[0]).append(")");
-                    break;
-            }
-        }
-
-        a.append(", Shot ").append(values[1]);
-
-        return a.toString();
-    }
-
-    /// <summary>
-    /// 2 numbers: 1. Mode, 2. Shot number
-    /// </summary>
-    /// <returns></returns>
-    @Nullable
-    public String getPanoramaModeDescription()
-    {
-        int[] values = _directory.getIntArray(TagPanoramaMode);
-        if (values == null)
-            return null;
-
-        if (values.length == 0 || values[0] == 0)
-            return "Off";
-
-        String a;
-        switch (values[0]) {
-            case 1:
-                a = "Left to Right";
-                break;
-            case 2:
-                a = "Right to Left";
-                break;
-            case 3:
-                a = "Bottom to Top";
-                break;
-            case 4:
-                a = "Top to Bottom";
-                break;
-            default:
-                a = "Unknown (" + values[0] + ")";
-                break;
-        }
-
-        return String.format("%s, Shot %d", a, values[1]);
-    }
-
-    @Nullable
-    public String getImageQuality2Description()
-    {
-        return getIndexedDescription(TagImageQuality2, 1,
-            "SQ", "HQ", "SHQ", "RAW", "SQ (5)");
-    }
-
-    @Nullable
-    public String getImageStabilizationDescription()
-    {
-        return getIndexedDescription(TagImageStabilization,
-            "Off", "On, Mode 1", "On, Mode 2", "On, Mode 3", "On, Mode 4");
-    }
-
-    @Nullable
-    public String getStackedImageDescription()
-    {
-        int[] values = _directory.getIntArray(TagStackedImage);
-        if (values == null || values.length < 2)
-            return null;
-
-        int v1 = values[0];
-        int v2 = values[1];
-
-        if (v1 == 0 && v2 == 0)
-            return "No";
-        if (v1 == 9 && v2 == 8)
-            return "Focus-stacked (8 images)";
-
-        return String.format("Unknown (%d %d)", v1, v2);
-    }
-
-    /// <remarks>
-    /// TODO: need better image examples to test this function
-    /// </remarks>
-    /// <returns></returns>
-    @Nullable
-    public String getManometerPressureDescription()
-    {
-        Integer value = _directory.getInteger(TagManometerPressure);
-        if (value == null)
-            return null;
-
-        return String.format("%s kPa", new DecimalFormat("#.##").format(value / 10.0));
-    }
-
-    /// <remarks>
-    /// TODO: need better image examples to test this function
-    /// </remarks>
-    /// <returns></returns>
-    @Nullable
-    public String getManometerReadingDescription()
-    {
-        int[] values = _directory.getIntArray(TagManometerReading);
-        if (values == null || values.length < 2)
-            return null;
-
-        DecimalFormat format = new DecimalFormat("#.##");
-        return String.format("%s m, %s ft",
-            format.format(values[0] / 10.0),
-            format.format(values[1] / 10.0));
-    }
-
-    @Nullable
-    public String getExtendedWBDetectDescription()
-    {
-        return getIndexedDescription(TagExtendedWBDetect, "Off", "On");
-    }
-
-    /// <summary>
-    /// converted to degrees of clockwise camera rotation
-    /// </summary>
-    /// <remarks>
-    /// TODO: need better image examples to test this function
-    /// </remarks>
-    /// <returns></returns>
-    @Nullable
-    public String getRollAngleDescription()
-    {
-        int[] values = _directory.getIntArray(TagRollAngle);
-        if (values == null || values.length < 2)
-            return null;
-
-        String ret = values[0] != 0
-            ? Double.toString(-values[0] / 10.0)
-            : "n/a";
-
-        return String.format("%s %d", ret, values[1]);
-    }
-
-    /// <summary>
-    /// converted to degrees of upward camera tilt
-    /// </summary>
-    /// <remarks>
-    /// TODO: need better image examples to test this function
-    /// </remarks>
-    /// <returns></returns>
-    @Nullable
-    public String getPitchAngleDescription()
-    {
-        int[] values = _directory.getIntArray(TagPitchAngle);
-        if (values == null || values.length < 2)
-            return null;
-
-        // (second value is 0 if level gauge is off)
-        String ret = values[0] != 0
-            ? Double.toString(values[0] / 10.0)
-            : "n/a";
-
-        return String.format("%s %d", ret, values[1]);
-    }
-
-    @Nullable
-    public String getDateTimeUTCDescription()
-    {
-        Object value = _directory.getObject(TagDateTimeUtc);
-        if (value == null)
-            return null;
-        return value.toString();
-    }
-
-    @Nullable
-    private String getValueMinMaxDescription(int tagId)
-    {
-        int[] values = _directory.getIntArray(tagId);
-        if (values == null || values.length < 3)
-            return null;
-
-        return String.format("%d (min %d, max %d)", values[0], values[1], values[2]);
-    }
-
-    @Nullable
-    private String getFiltersDescription(int tagId)
-    {
-        int[] values = _directory.getIntArray(tagId);
-        if (values == null || values.length == 0)
-            return null;
-
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < values.length; i++) {
-            if (i == 0)
-                sb.append(_filters.containsKey(values[i]) ? _filters.get(values[i]) : "[unknown]");
-            else
-                sb.append(values[i]);
-            sb.append("; ");
-        }
-
-        return sb.substring(0, sb.length() - 2);
-    }
-
-    private static final HashMap<Integer, String> _toneLevelType = new HashMap<Integer, String>();
-    // ArtFilter, ArtFilterEffect and MagicFilter values
-    private static final HashMap<Integer, String> _filters = new HashMap<Integer, String>();
-
-    static {
-        _filters.put(0, "Off");
-        _filters.put(1, "Soft Focus");
-        _filters.put(2, "Pop Art");
-        _filters.put(3, "Pale & Light Color");
-        _filters.put(4, "Light Tone");
-        _filters.put(5, "Pin Hole");
-        _filters.put(6, "Grainy Film");
-        _filters.put(9, "Diorama");
-        _filters.put(10, "Cross Process");
-        _filters.put(12, "Fish Eye");
-        _filters.put(13, "Drawing");
-        _filters.put(14, "Gentle Sepia");
-        _filters.put(15, "Pale & Light Color II");
-        _filters.put(16, "Pop Art II");
-        _filters.put(17, "Pin Hole II");
-        _filters.put(18, "Pin Hole III");
-        _filters.put(19, "Grainy Film II");
-        _filters.put(20, "Dramatic Tone");
-        _filters.put(21, "Punk");
-        _filters.put(22, "Soft Focus 2");
-        _filters.put(23, "Sparkle");
-        _filters.put(24, "Watercolor");
-        _filters.put(25, "Key Line");
-        _filters.put(26, "Key Line II");
-        _filters.put(27, "Miniature");
-        _filters.put(28, "Reflection");
-        _filters.put(29, "Fragmented");
-        _filters.put(31, "Cross Process II");
-        _filters.put(32, "Dramatic Tone II");
-        _filters.put(33, "Watercolor I");
-        _filters.put(34, "Watercolor II");
-        _filters.put(35, "Diorama II");
-        _filters.put(36, "Vintage");
-        _filters.put(37, "Vintage II");
-        _filters.put(38, "Vintage III");
-        _filters.put(39, "Partial Color");
-        _filters.put(40, "Partial Color II");
-        _filters.put(41, "Partial Color III");
-
-        _toneLevelType.put(0, "0");
-        _toneLevelType.put(-31999, "Highlights ");
-        _toneLevelType.put(-31998, "Shadows ");
-        _toneLevelType.put(-31997, "Midtones ");
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/OlympusCameraSettingsMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/OlympusCameraSettingsMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,201 +1,0 @@
-/*
- * Copyright 2002-2015 Drew Noakes
- *
- *    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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * The Olympus camera settings makernote is used by many manufacturers (Epson, Konica, Minolta and Agfa...), and as such contains some tags
- * that appear specific to those manufacturers.
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class OlympusCameraSettingsMakernoteDirectory extends Directory
-{
-    public static final int TagCameraSettingsVersion = 0x0000;
-    public static final int TagPreviewImageValid = 0x0100;
-    public static final int TagPreviewImageStart = 0x0101;
-    public static final int TagPreviewImageLength = 0x0102;
-
-    public static final int TagExposureMode = 0x0200;
-    public static final int TagAeLock = 0x0201;
-    public static final int TagMeteringMode = 0x0202;
-    public static final int TagExposureShift = 0x0203;
-    public static final int TagNdFilter = 0x0204;
-
-    public static final int TagMacroMode = 0x0300;
-    public static final int TagFocusMode = 0x0301;
-    public static final int TagFocusProcess = 0x0302;
-    public static final int TagAfSearch = 0x0303;
-    public static final int TagAfAreas = 0x0304;
-    public static final int TagAfPointSelected = 0x0305;
-    public static final int TagAfFineTune = 0x0306;
-    public static final int TagAfFineTuneAdj = 0x0307;
-
-    public static final int TagFlashMode = 0x400;
-    public static final int TagFlashExposureComp = 0x401;
-    public static final int TagFlashRemoteControl = 0x403;
-    public static final int TagFlashControlMode = 0x404;
-    public static final int TagFlashIntensity = 0x405;
-    public static final int TagManualFlashStrength = 0x406;
-
-    public static final int TagWhiteBalance2 = 0x500;
-    public static final int TagWhiteBalanceTemperature = 0x501;
-    public static final int TagWhiteBalanceBracket = 0x502;
-    public static final int TagCustomSaturation = 0x503;
-    public static final int TagModifiedSaturation = 0x504;
-    public static final int TagContrastSetting = 0x505;
-    public static final int TagSharpnessSetting = 0x506;
-    public static final int TagColorSpace = 0x507;
-    public static final int TagSceneMode = 0x509;
-    public static final int TagNoiseReduction = 0x50a;
-    public static final int TagDistortionCorrection = 0x50b;
-    public static final int TagShadingCompensation = 0x50c;
-    public static final int TagCompressionFactor = 0x50d;
-    public static final int TagGradation = 0x50f;
-    public static final int TagPictureMode = 0x520;
-    public static final int TagPictureModeSaturation = 0x521;
-    public static final int TagPictureModeHue = 0x522;
-    public static final int TagPictureModeContrast = 0x523;
-    public static final int TagPictureModeSharpness = 0x524;
-    public static final int TagPictureModeBWFilter = 0x525;
-    public static final int TagPictureModeTone = 0x526;
-    public static final int TagNoiseFilter = 0x527;
-    public static final int TagArtFilter = 0x529;
-    public static final int TagMagicFilter = 0x52c;
-    public static final int TagPictureModeEffect = 0x52d;
-    public static final int TagToneLevel = 0x52e;
-    public static final int TagArtFilterEffect = 0x52f;
-    public static final int TagColorCreatorEffect = 0x532;
-
-    public static final int TagDriveMode = 0x600;
-    public static final int TagPanoramaMode = 0x601;
-    public static final int TagImageQuality2 = 0x603;
-    public static final int TagImageStabilization = 0x604;
-
-    public static final int TagStackedImage = 0x804;
-
-    public static final int TagManometerPressure = 0x900;
-    public static final int TagManometerReading = 0x901;
-    public static final int TagExtendedWBDetect = 0x902;
-    public static final int TagRollAngle = 0x903;
-    public static final int TagPitchAngle = 0x904;
-    public static final int TagDateTimeUtc = 0x908;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static {
-        _tagNameMap.put(TagCameraSettingsVersion, "Camera Settings Version");
-        _tagNameMap.put(TagPreviewImageValid, "Preview Image Valid");
-        _tagNameMap.put(TagPreviewImageStart, "Preview Image Start");
-        _tagNameMap.put(TagPreviewImageLength, "Preview Image Length");
-
-        _tagNameMap.put(TagExposureMode, "Exposure Mode");
-        _tagNameMap.put(TagAeLock, "AE Lock");
-        _tagNameMap.put(TagMeteringMode, "Metering Mode");
-        _tagNameMap.put(TagExposureShift, "Exposure Shift");
-        _tagNameMap.put(TagNdFilter, "ND Filter");
-
-        _tagNameMap.put(TagMacroMode, "Macro Mode");
-        _tagNameMap.put(TagFocusMode, "Focus Mode");
-        _tagNameMap.put(TagFocusProcess, "Focus Process");
-        _tagNameMap.put(TagAfSearch, "AF Search");
-        _tagNameMap.put(TagAfAreas, "AF Areas");
-        _tagNameMap.put(TagAfPointSelected, "AF Point Selected");
-        _tagNameMap.put(TagAfFineTune, "AF Fine Tune");
-        _tagNameMap.put(TagAfFineTuneAdj, "AF Fine Tune Adj");
-
-        _tagNameMap.put(TagFlashMode, "Flash Mode");
-        _tagNameMap.put(TagFlashExposureComp, "Flash Exposure Comp");
-        _tagNameMap.put(TagFlashRemoteControl, "Flash Remote Control");
-        _tagNameMap.put(TagFlashControlMode, "Flash Control Mode");
-        _tagNameMap.put(TagFlashIntensity, "Flash Intensity");
-        _tagNameMap.put(TagManualFlashStrength, "Manual Flash Strength");
-
-        _tagNameMap.put(TagWhiteBalance2, "White Balance 2");
-        _tagNameMap.put(TagWhiteBalanceTemperature, "White Balance Temperature");
-        _tagNameMap.put(TagWhiteBalanceBracket, "White Balance Bracket");
-        _tagNameMap.put(TagCustomSaturation, "Custom Saturation");
-        _tagNameMap.put(TagModifiedSaturation, "Modified Saturation");
-        _tagNameMap.put(TagContrastSetting, "Contrast Setting");
-        _tagNameMap.put(TagSharpnessSetting, "Sharpness Setting");
-        _tagNameMap.put(TagColorSpace, "Color Space");
-        _tagNameMap.put(TagSceneMode, "Scene Mode");
-        _tagNameMap.put(TagNoiseReduction, "Noise Reduction");
-        _tagNameMap.put(TagDistortionCorrection, "Distortion Correction");
-        _tagNameMap.put(TagShadingCompensation, "Shading Compensation");
-        _tagNameMap.put(TagCompressionFactor, "Compression Factor");
-        _tagNameMap.put(TagGradation, "Gradation");
-        _tagNameMap.put(TagPictureMode, "Picture Mode");
-        _tagNameMap.put(TagPictureModeSaturation, "Picture Mode Saturation");
-        _tagNameMap.put(TagPictureModeHue, "Picture Mode Hue");
-        _tagNameMap.put(TagPictureModeContrast, "Picture Mode Contrast");
-        _tagNameMap.put(TagPictureModeSharpness, "Picture Mode Sharpness");
-        _tagNameMap.put(TagPictureModeBWFilter, "Picture Mode BW Filter");
-        _tagNameMap.put(TagPictureModeTone, "Picture Mode Tone");
-        _tagNameMap.put(TagNoiseFilter, "Noise Filter");
-        _tagNameMap.put(TagArtFilter, "Art Filter");
-        _tagNameMap.put(TagMagicFilter, "Magic Filter");
-        _tagNameMap.put(TagPictureModeEffect, "Picture Mode Effect");
-        _tagNameMap.put(TagToneLevel, "Tone Level");
-        _tagNameMap.put(TagArtFilterEffect, "Art Filter Effect");
-        _tagNameMap.put(TagColorCreatorEffect, "Color Creator Effect");
-
-        _tagNameMap.put(TagDriveMode, "Drive Mode");
-        _tagNameMap.put(TagPanoramaMode, "Panorama Mode");
-        _tagNameMap.put(TagImageQuality2, "Image Quality 2");
-        _tagNameMap.put(TagImageStabilization, "Image Stabilization");
-
-        _tagNameMap.put(TagStackedImage, "Stacked Image");
-
-        _tagNameMap.put(TagManometerPressure, "Manometer Pressure");
-        _tagNameMap.put(TagManometerReading, "Manometer Reading");
-        _tagNameMap.put(TagExtendedWBDetect, "Extended WB Detect");
-        _tagNameMap.put(TagRollAngle, "Roll Angle");
-        _tagNameMap.put(TagPitchAngle, "Pitch Angle");
-        _tagNameMap.put(TagDateTimeUtc, "Date Time UTC");
-    }
-
-    public OlympusCameraSettingsMakernoteDirectory()
-    {
-        this.setDescriptor(new OlympusCameraSettingsMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Olympus Camera Settings";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/OlympusEquipmentMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/OlympusEquipmentMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,386 +1,0 @@
-/*
- * Copyright 2002-2015 Drew Noakes
- *
- *    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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import java.text.DecimalFormat;
-import java.util.HashMap;
-
-import static com.drew.metadata.exif.makernotes.OlympusEquipmentMakernoteDirectory.*;
-
-/**
- * Provides human-readable String representations of tag values stored in a {@link OlympusEquipmentMakernoteDirectory}.
- * <p>
- * Some Description functions and the Extender and Lens types lists converted from Exiftool version 10.10 created by Phil Harvey
- * http://www.sno.phy.queensu.ca/~phil/exiftool/
- * lib\Image\ExifTool\Olympus.pm
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class OlympusEquipmentMakernoteDescriptor extends TagDescriptor<OlympusEquipmentMakernoteDirectory>
-{
-    public OlympusEquipmentMakernoteDescriptor(@NotNull OlympusEquipmentMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_EQUIPMENT_VERSION:
-                return getEquipmentVersionDescription();
-            case TAG_CAMERA_TYPE_2:
-                return getCameraType2Description();
-            case TAG_FOCAL_PLANE_DIAGONAL:
-                return getFocalPlaneDiagonalDescription();
-            case TAG_BODY_FIRMWARE_VERSION:
-                return getBodyFirmwareVersionDescription();
-            case TAG_LENS_TYPE:
-                return getLensTypeDescription();
-            case TAG_LENS_FIRMWARE_VERSION:
-                return getLensFirmwareVersionDescription();
-            case TAG_MAX_APERTURE_AT_MIN_FOCAL:
-                return getMaxApertureAtMinFocalDescription();
-            case TAG_MAX_APERTURE_AT_MAX_FOCAL:
-                return getMaxApertureAtMaxFocalDescription();
-            case TAG_MAX_APERTURE:
-                return getMaxApertureDescription();
-            case TAG_LENS_PROPERTIES:
-                return getLensPropertiesDescription();
-            case TAG_EXTENDER:
-                return getExtenderDescription();
-            case TAG_FLASH_TYPE:
-                return getFlashTypeDescription();
-            case TAG_FLASH_MODEL:
-                return getFlashModelDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getEquipmentVersionDescription()
-    {
-        return getVersionBytesDescription(TAG_EQUIPMENT_VERSION, 4);
-    }
-
-    @Nullable
-    public String getCameraType2Description()
-    {
-        String cameratype = _directory.getString(TAG_CAMERA_TYPE_2);
-        if(cameratype == null)
-            return null;
-
-        if(OlympusMakernoteDirectory.OlympusCameraTypes.containsKey(cameratype))
-            return OlympusMakernoteDirectory.OlympusCameraTypes.get(cameratype);
-
-        return cameratype;
-    }
-
-    @Nullable
-    public String getFocalPlaneDiagonalDescription()
-    {
-        return _directory.getString(TAG_FOCAL_PLANE_DIAGONAL) + " mm";
-    }
-
-    @Nullable
-    public String getBodyFirmwareVersionDescription()
-    {
-        Integer value = _directory.getInteger(TAG_BODY_FIRMWARE_VERSION);
-        if (value == null)
-            return null;
-
-        String hex = String.format("%04X", value);
-        return String.format("%s.%s",
-            hex.substring(0, hex.length() - 3),
-            hex.substring(hex.length() - 3));
-    }
-
-    @Nullable
-    public String getLensTypeDescription()
-    {
-        String str = _directory.getString(TAG_LENS_TYPE);
-
-        if (str == null)
-            return null;
-
-        // The String contains six numbers:
-        //
-        // - Make
-        // - Unknown
-        // - Model
-        // - Sub-model
-        // - Unknown
-        // - Unknown
-        //
-        // Only the Make, Model and Sub-model are used to identify the lens type
-        String[] values = str.split(" ");
-
-        if (values.length < 6)
-            return null;
-
-        try {
-            int num1 = Integer.parseInt(values[0]);
-            int num2 = Integer.parseInt(values[2]);
-            int num3 = Integer.parseInt(values[3]);
-            return _olympusLensTypes.get(String.format("%X %02X %02X", num1, num2, num3));
-        } catch (NumberFormatException e) {
-            return null;
-        }
-    }
-
-    @Nullable
-    public String getLensFirmwareVersionDescription()
-    {
-        Integer value = _directory.getInteger(TAG_LENS_FIRMWARE_VERSION);
-        if (value == null)
-            return null;
-
-        String hex = String.format("%04X", value);
-        return String.format("%s.%s",
-            hex.substring(0, hex.length() - 3),
-            hex.substring(hex.length() - 3));
-    }
-
-    @Nullable
-    public String getMaxApertureAtMinFocalDescription()
-    {
-        Integer value = _directory.getInteger(TAG_MAX_APERTURE_AT_MIN_FOCAL);
-        if (value == null)
-            return null;
-
-        DecimalFormat format = new DecimalFormat("0.#");
-        return format.format(CalcMaxAperture(value));
-    }
-
-    @Nullable
-    public String getMaxApertureAtMaxFocalDescription()
-    {
-        Integer value = _directory.getInteger(TAG_MAX_APERTURE_AT_MAX_FOCAL);
-        if (value == null)
-            return null;
-
-        DecimalFormat format = new DecimalFormat("0.#");
-        return format.format(CalcMaxAperture(value));
-    }
-
-    @Nullable
-    public String getMaxApertureDescription()
-    {
-        Integer value = _directory.getInteger(TAG_MAX_APERTURE);
-        if (value == null)
-            return null;
-
-        DecimalFormat format = new DecimalFormat("0.#");
-        return format.format(CalcMaxAperture(value));
-    }
-
-    private static double CalcMaxAperture(int value)
-    {
-        return Math.pow(Math.sqrt(2.00), value / 256.0);
-    }
-
-    @Nullable
-    public String getLensPropertiesDescription()
-    {
-        Integer value = _directory.getInteger(TAG_LENS_PROPERTIES);
-        if (value == null)
-            return null;
-
-        return String.format("0x%04X", value);
-    }
-
-    @Nullable
-    public String getExtenderDescription()
-    {
-        String str = _directory.getString(TAG_EXTENDER);
-
-        if (str == null)
-            return null;
-
-        // The String contains six numbers:
-        //
-        // - Make
-        // - Unknown
-        // - Model
-        // - Sub-model
-        // - Unknown
-        // - Unknown
-        //
-        // Only the Make and Model are used to identify the extender
-        String[] values = str.split(" ");
-
-        if (values.length < 6)
-            return null;
-
-        try {
-            int num1 = Integer.parseInt(values[0]);
-            int num2 = Integer.parseInt(values[2]);
-            String extenderType = String.format("%X %02X", num1, num2);
-            return _olympusExtenderTypes.get(extenderType);
-        } catch (NumberFormatException e) {
-            return null;
-        }
-    }
-
-    @Nullable
-    public String getFlashTypeDescription()
-    {
-        return getIndexedDescription(TAG_FLASH_TYPE,
-            "None", null, "Simple E-System", "E-System");
-    }
-
-    @Nullable
-    public String getFlashModelDescription()
-    {
-        return getIndexedDescription(TAG_FLASH_MODEL,
-            "None", "FL-20", "FL-50", "RF-11", "TF-22", "FL-36", "FL-50R", "FL-36R");
-    }
-
-    private static final HashMap<String, String> _olympusLensTypes = new HashMap<String, String>();
-    private static final HashMap<String, String> _olympusExtenderTypes = new HashMap<String, String>();
-
-    static {
-        _olympusLensTypes.put("0 00 00", "None");
-        // Olympus lenses (also Kenko Tokina)
-        _olympusLensTypes.put("0 01 00", "Olympus Zuiko Digital ED 50mm F2.0 Macro");
-        _olympusLensTypes.put("0 01 01", "Olympus Zuiko Digital 40-150mm F3.5-4.5"); //8
-        _olympusLensTypes.put("0 01 10", "Olympus M.Zuiko Digital ED 14-42mm F3.5-5.6"); //PH (E-P1 pre-production)
-        _olympusLensTypes.put("0 02 00", "Olympus Zuiko Digital ED 150mm F2.0");
-        _olympusLensTypes.put("0 02 10", "Olympus M.Zuiko Digital 17mm F2.8 Pancake"); //PH (E-P1 pre-production)
-        _olympusLensTypes.put("0 03 00", "Olympus Zuiko Digital ED 300mm F2.8");
-        _olympusLensTypes.put("0 03 10", "Olympus M.Zuiko Digital ED 14-150mm F4.0-5.6 [II]"); //11 (The second version of this lens seems to have the same lens ID number as the first version #20)
-        _olympusLensTypes.put("0 04 10", "Olympus M.Zuiko Digital ED 9-18mm F4.0-5.6"); //11
-        _olympusLensTypes.put("0 05 00", "Olympus Zuiko Digital 14-54mm F2.8-3.5");
-        _olympusLensTypes.put("0 05 01", "Olympus Zuiko Digital Pro ED 90-250mm F2.8"); //9
-        _olympusLensTypes.put("0 05 10", "Olympus M.Zuiko Digital ED 14-42mm F3.5-5.6 L"); //11 (E-PL1)
-        _olympusLensTypes.put("0 06 00", "Olympus Zuiko Digital ED 50-200mm F2.8-3.5");
-        _olympusLensTypes.put("0 06 01", "Olympus Zuiko Digital ED 8mm F3.5 Fisheye"); //9
-        _olympusLensTypes.put("0 06 10", "Olympus M.Zuiko Digital ED 40-150mm F4.0-5.6"); //PH
-        _olympusLensTypes.put("0 07 00", "Olympus Zuiko Digital 11-22mm F2.8-3.5");
-        _olympusLensTypes.put("0 07 01", "Olympus Zuiko Digital 18-180mm F3.5-6.3"); //6
-        _olympusLensTypes.put("0 07 10", "Olympus M.Zuiko Digital ED 12mm F2.0"); //PH
-        _olympusLensTypes.put("0 08 01", "Olympus Zuiko Digital 70-300mm F4.0-5.6"); //7 (seen as release 1 - PH)
-        _olympusLensTypes.put("0 08 10", "Olympus M.Zuiko Digital ED 75-300mm F4.8-6.7"); //PH
-        _olympusLensTypes.put("0 09 10", "Olympus M.Zuiko Digital 14-42mm F3.5-5.6 II"); //PH (E-PL2)
-        _olympusLensTypes.put("0 10 01", "Kenko Tokina Reflex 300mm F6.3 MF Macro"); //20
-        _olympusLensTypes.put("0 10 10", "Olympus M.Zuiko Digital ED 12-50mm F3.5-6.3 EZ"); //PH
-        _olympusLensTypes.put("0 11 10", "Olympus M.Zuiko Digital 45mm F1.8"); //17
-        _olympusLensTypes.put("0 12 10", "Olympus M.Zuiko Digital ED 60mm F2.8 Macro"); //20
-        _olympusLensTypes.put("0 13 10", "Olympus M.Zuiko Digital 14-42mm F3.5-5.6 II R"); //PH/20
-        _olympusLensTypes.put("0 14 10", "Olympus M.Zuiko Digital ED 40-150mm F4.0-5.6 R"); //19
-        // '0 14 10.1", "Olympus M.Zuiko Digital ED 14-150mm F4.0-5.6 II"); //11 (questionable & unconfirmed -- all samples I can find are '0 3 10' - PH)
-        _olympusLensTypes.put("0 15 00", "Olympus Zuiko Digital ED 7-14mm F4.0");
-        _olympusLensTypes.put("0 15 10", "Olympus M.Zuiko Digital ED 75mm F1.8"); //PH
-        _olympusLensTypes.put("0 16 10", "Olympus M.Zuiko Digital 17mm F1.8"); //20
-        _olympusLensTypes.put("0 17 00", "Olympus Zuiko Digital Pro ED 35-100mm F2.0"); //7
-        _olympusLensTypes.put("0 18 00", "Olympus Zuiko Digital 14-45mm F3.5-5.6");
-        _olympusLensTypes.put("0 18 10", "Olympus M.Zuiko Digital ED 75-300mm F4.8-6.7 II"); //20
-        _olympusLensTypes.put("0 19 10", "Olympus M.Zuiko Digital ED 12-40mm F2.8 Pro"); //PH
-        _olympusLensTypes.put("0 20 00", "Olympus Zuiko Digital 35mm F3.5 Macro"); //9
-        _olympusLensTypes.put("0 20 10", "Olympus M.Zuiko Digital ED 40-150mm F2.8 Pro"); //20
-        _olympusLensTypes.put("0 21 10", "Olympus M.Zuiko Digital ED 14-42mm F3.5-5.6 EZ"); //20
-        _olympusLensTypes.put("0 22 00", "Olympus Zuiko Digital 17.5-45mm F3.5-5.6"); //9
-        _olympusLensTypes.put("0 22 10", "Olympus M.Zuiko Digital 25mm F1.8"); //20
-        _olympusLensTypes.put("0 23 00", "Olympus Zuiko Digital ED 14-42mm F3.5-5.6"); //PH
-        _olympusLensTypes.put("0 23 10", "Olympus M.Zuiko Digital ED 7-14mm F2.8 Pro"); //20
-        _olympusLensTypes.put("0 24 00", "Olympus Zuiko Digital ED 40-150mm F4.0-5.6"); //PH
-        _olympusLensTypes.put("0 24 10", "Olympus M.Zuiko Digital ED 300mm F4.0 IS Pro"); //20
-        _olympusLensTypes.put("0 25 10", "Olympus M.Zuiko Digital ED 8mm F1.8 Fisheye Pro"); //20
-        _olympusLensTypes.put("0 30 00", "Olympus Zuiko Digital ED 50-200mm F2.8-3.5 SWD"); //7
-        _olympusLensTypes.put("0 31 00", "Olympus Zuiko Digital ED 12-60mm F2.8-4.0 SWD"); //7
-        _olympusLensTypes.put("0 32 00", "Olympus Zuiko Digital ED 14-35mm F2.0 SWD"); //PH
-        _olympusLensTypes.put("0 33 00", "Olympus Zuiko Digital 25mm F2.8"); //PH
-        _olympusLensTypes.put("0 34 00", "Olympus Zuiko Digital ED 9-18mm F4.0-5.6"); //7
-        _olympusLensTypes.put("0 35 00", "Olympus Zuiko Digital 14-54mm F2.8-3.5 II"); //PH
-        // Sigma lenses
-        _olympusLensTypes.put("1 01 00", "Sigma 18-50mm F3.5-5.6 DC"); //8
-        _olympusLensTypes.put("1 01 10", "Sigma 30mm F2.8 EX DN"); //20
-        _olympusLensTypes.put("1 02 00", "Sigma 55-200mm F4.0-5.6 DC");
-        _olympusLensTypes.put("1 02 10", "Sigma 19mm F2.8 EX DN"); //20
-        _olympusLensTypes.put("1 03 00", "Sigma 18-125mm F3.5-5.6 DC");
-        _olympusLensTypes.put("1 03 10", "Sigma 30mm F2.8 DN | A"); //20
-        _olympusLensTypes.put("1 04 00", "Sigma 18-125mm F3.5-5.6 DC"); //7
-        _olympusLensTypes.put("1 04 10", "Sigma 19mm F2.8 DN | A"); //20
-        _olympusLensTypes.put("1 05 00", "Sigma 30mm F1.4 EX DC HSM"); //10
-        _olympusLensTypes.put("1 05 10", "Sigma 60mm F2.8 DN | A"); //20
-        _olympusLensTypes.put("1 06 00", "Sigma APO 50-500mm F4.0-6.3 EX DG HSM"); //6
-        _olympusLensTypes.put("1 07 00", "Sigma Macro 105mm F2.8 EX DG"); //PH
-        _olympusLensTypes.put("1 08 00", "Sigma APO Macro 150mm F2.8 EX DG HSM"); //PH
-        _olympusLensTypes.put("1 09 00", "Sigma 18-50mm F2.8 EX DC Macro"); //20
-        _olympusLensTypes.put("1 10 00", "Sigma 24mm F1.8 EX DG Aspherical Macro"); //PH
-        _olympusLensTypes.put("1 11 00", "Sigma APO 135-400mm F4.5-5.6 DG"); //11
-        _olympusLensTypes.put("1 12 00", "Sigma APO 300-800mm F5.6 EX DG HSM"); //11
-        _olympusLensTypes.put("1 13 00", "Sigma 30mm F1.4 EX DC HSM"); //11
-        _olympusLensTypes.put("1 14 00", "Sigma APO 50-500mm F4.0-6.3 EX DG HSM"); //11
-        _olympusLensTypes.put("1 15 00", "Sigma 10-20mm F4.0-5.6 EX DC HSM"); //11
-        _olympusLensTypes.put("1 16 00", "Sigma APO 70-200mm F2.8 II EX DG Macro HSM"); //11
-        _olympusLensTypes.put("1 17 00", "Sigma 50mm F1.4 EX DG HSM"); //11
-        // Panasonic/Leica lenses
-        _olympusLensTypes.put("2 01 00", "Leica D Vario Elmarit 14-50mm F2.8-3.5 Asph."); //11
-        _olympusLensTypes.put("2 01 10", "Lumix G Vario 14-45mm F3.5-5.6 Asph. Mega OIS"); //16
-        _olympusLensTypes.put("2 02 00", "Leica D Summilux 25mm F1.4 Asph."); //11
-        _olympusLensTypes.put("2 02 10", "Lumix G Vario 45-200mm F4.0-5.6 Mega OIS"); //16
-        _olympusLensTypes.put("2 03 00", "Leica D Vario Elmar 14-50mm F3.8-5.6 Asph. Mega OIS"); //11
-        _olympusLensTypes.put("2 03 01", "Leica D Vario Elmar 14-50mm F3.8-5.6 Asph."); //14 (L10 kit)
-        _olympusLensTypes.put("2 03 10", "Lumix G Vario HD 14-140mm F4.0-5.8 Asph. Mega OIS"); //16
-        _olympusLensTypes.put("2 04 00", "Leica D Vario Elmar 14-150mm F3.5-5.6"); //13
-        _olympusLensTypes.put("2 04 10", "Lumix G Vario 7-14mm F4.0 Asph."); //PH (E-P1 pre-production)
-        _olympusLensTypes.put("2 05 10", "Lumix G 20mm F1.7 Asph."); //16
-        _olympusLensTypes.put("2 06 10", "Leica DG Macro-Elmarit 45mm F2.8 Asph. Mega OIS"); //PH
-        _olympusLensTypes.put("2 07 10", "Lumix G Vario 14-42mm F3.5-5.6 Asph. Mega OIS"); //20
-        _olympusLensTypes.put("2 08 10", "Lumix G Fisheye 8mm F3.5"); //PH
-        _olympusLensTypes.put("2 09 10", "Lumix G Vario 100-300mm F4.0-5.6 Mega OIS"); //11
-        _olympusLensTypes.put("2 10 10", "Lumix G 14mm F2.5 Asph."); //17
-        _olympusLensTypes.put("2 11 10", "Lumix G 12.5mm F12 3D"); //20 (H-FT012)
-        _olympusLensTypes.put("2 12 10", "Leica DG Summilux 25mm F1.4 Asph."); //20
-        _olympusLensTypes.put("2 13 10", "Lumix G X Vario PZ 45-175mm F4.0-5.6 Asph. Power OIS"); //20
-        _olympusLensTypes.put("2 14 10", "Lumix G X Vario PZ 14-42mm F3.5-5.6 Asph. Power OIS"); //20
-        _olympusLensTypes.put("2 15 10", "Lumix G X Vario 12-35mm F2.8 Asph. Power OIS"); //PH
-        _olympusLensTypes.put("2 16 10", "Lumix G Vario 45-150mm F4.0-5.6 Asph. Mega OIS"); //20
-        _olympusLensTypes.put("2 17 10", "Lumix G X Vario 35-100mm F2.8 Power OIS"); //PH
-        _olympusLensTypes.put("2 18 10", "Lumix G Vario 14-42mm F3.5-5.6 II Asph. Mega OIS"); //20
-        _olympusLensTypes.put("2 19 10", "Lumix G Vario 14-140mm F3.5-5.6 Asph. Power OIS"); //20
-        _olympusLensTypes.put("2 20 10", "Lumix G Vario 12-32mm F3.5-5.6 Asph. Mega OIS"); //20
-        _olympusLensTypes.put("2 21 10", "Leica DG Nocticron 42.5mm F1.2 Asph. Power OIS"); //20
-        _olympusLensTypes.put("2 22 10", "Leica DG Summilux 15mm F1.7 Asph."); //20
-        // '2 23 10", "Lumix G Vario 35-100mm F4.0-5.6 Asph. Mega OIS"); //20 (guess)
-        _olympusLensTypes.put("2 24 10", "Lumix G Macro 30mm F2.8 Asph. Mega OIS"); //20
-        _olympusLensTypes.put("2 25 10", "Lumix G 42.5mm F1.7 Asph. Power OIS"); //20
-        _olympusLensTypes.put("3 01 00", "Leica D Vario Elmarit 14-50mm F2.8-3.5 Asph."); //11
-        _olympusLensTypes.put("3 02 00", "Leica D Summilux 25mm F1.4 Asph."); //11
-        // Tamron lenses
-        _olympusLensTypes.put("5 01 10", "Tamron 14-150mm F3.5-5.8 Di III"); //20 (model C001)
-
-
-        _olympusExtenderTypes.put("0 00", "None");
-        _olympusExtenderTypes.put("0 04", "Olympus Zuiko Digital EC-14 1.4x Teleconverter");
-        _olympusExtenderTypes.put("0 08", "Olympus EX-25 Extension Tube");
-        _olympusExtenderTypes.put("0 10", "Olympus Zuiko Digital EC-20 2.0x Teleconverter");
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/OlympusEquipmentMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/OlympusEquipmentMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,118 +1,0 @@
-/*
- * Copyright 2002-2015 Drew Noakes
- *
- *    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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * The Olympus equipment makernote is used by many manufacturers (Epson, Konica, Minolta and Agfa...), and as such contains some tags
- * that appear specific to those manufacturers.
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class OlympusEquipmentMakernoteDirectory extends Directory
-{
-    public static final int TAG_EQUIPMENT_VERSION = 0x0000;
-    public static final int TAG_CAMERA_TYPE_2 = 0x0100;
-    public static final int TAG_SERIAL_NUMBER = 0x0101;
-
-    public static final int TAG_INTERNAL_SERIAL_NUMBER = 0x0102;
-    public static final int TAG_FOCAL_PLANE_DIAGONAL = 0x0103;
-    public static final int TAG_BODY_FIRMWARE_VERSION = 0x0104;
-
-    public static final int TAG_LENS_TYPE = 0x0201;
-    public static final int TAG_LENS_SERIAL_NUMBER = 0x0202;
-    public static final int TAG_LENS_MODEL = 0x0203;
-    public static final int TAG_LENS_FIRMWARE_VERSION = 0x0204;
-    public static final int TAG_MAX_APERTURE_AT_MIN_FOCAL = 0x0205;
-    public static final int TAG_MAX_APERTURE_AT_MAX_FOCAL = 0x0206;
-    public static final int TAG_MIN_FOCAL_LENGTH = 0x0207;
-    public static final int TAG_MAX_FOCAL_LENGTH = 0x0208;
-    public static final int TAG_MAX_APERTURE = 0x020A;
-    public static final int TAG_LENS_PROPERTIES = 0x020B;
-
-    public static final int TAG_EXTENDER = 0x0301;
-    public static final int TAG_EXTENDER_SERIAL_NUMBER = 0x0302;
-    public static final int TAG_EXTENDER_MODEL = 0x0303;
-    public static final int TAG_EXTENDER_FIRMWARE_VERSION = 0x0304;
-
-    public static final int TAG_CONVERSION_LENS = 0x0403;
-
-    public static final int TAG_FLASH_TYPE = 0x1000;
-    public static final int TAG_FLASH_MODEL = 0x1001;
-    public static final int TAG_FLASH_FIRMWARE_VERSION = 0x1002;
-    public static final int TAG_FLASH_SERIAL_NUMBER = 0x1003;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static {
-        _tagNameMap.put(TAG_EQUIPMENT_VERSION, "Equipment Version");
-        _tagNameMap.put(TAG_CAMERA_TYPE_2, "Camera Type 2");
-        _tagNameMap.put(TAG_SERIAL_NUMBER, "Serial Number");
-        _tagNameMap.put(TAG_INTERNAL_SERIAL_NUMBER, "Internal Serial Number");
-        _tagNameMap.put(TAG_FOCAL_PLANE_DIAGONAL, "Focal Plane Diagonal");
-        _tagNameMap.put(TAG_BODY_FIRMWARE_VERSION, "Body Firmware Version");
-        _tagNameMap.put(TAG_LENS_TYPE, "Lens Type");
-        _tagNameMap.put(TAG_LENS_SERIAL_NUMBER, "Lens Serial Number");
-        _tagNameMap.put(TAG_LENS_MODEL, "Lens Model");
-        _tagNameMap.put(TAG_LENS_FIRMWARE_VERSION, "Lens Firmware Version");
-        _tagNameMap.put(TAG_MAX_APERTURE_AT_MIN_FOCAL, "Max Aperture At Min Focal");
-        _tagNameMap.put(TAG_MAX_APERTURE_AT_MAX_FOCAL, "Max Aperture At Max Focal");
-        _tagNameMap.put(TAG_MIN_FOCAL_LENGTH, "Min Focal Length");
-        _tagNameMap.put(TAG_MAX_FOCAL_LENGTH, "Max Focal Length");
-        _tagNameMap.put(TAG_MAX_APERTURE, "Max Aperture");
-        _tagNameMap.put(TAG_LENS_PROPERTIES, "Lens Properties");
-        _tagNameMap.put(TAG_EXTENDER, "Extender");
-        _tagNameMap.put(TAG_EXTENDER_SERIAL_NUMBER, "Extender Serial Number");
-        _tagNameMap.put(TAG_EXTENDER_MODEL, "Extender Model");
-        _tagNameMap.put(TAG_EXTENDER_FIRMWARE_VERSION, "Extender Firmware Version");
-        _tagNameMap.put(TAG_CONVERSION_LENS, "Conversion Lens");
-        _tagNameMap.put(TAG_FLASH_TYPE, "Flash Type");
-        _tagNameMap.put(TAG_FLASH_MODEL, "Flash Model");
-        _tagNameMap.put(TAG_FLASH_FIRMWARE_VERSION, "Flash Firmware Version");
-        _tagNameMap.put(TAG_FLASH_SERIAL_NUMBER, "Flash Serial Number");
-    }
-
-    public OlympusEquipmentMakernoteDirectory()
-    {
-        this.setDescriptor(new OlympusEquipmentMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Olympus Equipment";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/OlympusFocusInfoMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/OlympusFocusInfoMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,217 +1,0 @@
-/*
- * Copyright 2002-2015 Drew Noakes
- *
- *    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
- *
- *        http://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.Rational;
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.makernotes.OlympusFocusInfoMakernoteDirectory.*;
-
-/**
- * Provides human-readable String representations of tag values stored in a {@link OlympusFocusInfoMakernoteDirectory}.
- * <p>
- * Some Description functions converted from Exiftool version 10.10 created by Phil Harvey
- * http://www.sno.phy.queensu.ca/~phil/exiftool/
- * lib\Image\ExifTool\Olympus.pm
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class OlympusFocusInfoMakernoteDescriptor extends TagDescriptor<OlympusFocusInfoMakernoteDirectory>
-{
-    public OlympusFocusInfoMakernoteDescriptor(@NotNull OlympusFocusInfoMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TagFocusInfoVersion:
-                return getFocusInfoVersionDescription();
-            case TagAutoFocus:
-                return getAutoFocusDescription();
-            case TagFocusDistance:
-                return getFocusDistanceDescription();
-            case TagAfPoint:
-                return getAfPointDescription();
-            case TagExternalFlash:
-                return getExternalFlashDescription();
-            case TagExternalFlashBounce:
-                return getExternalFlashBounceDescription();
-            case TagExternalFlashZoom:
-                return getExternalFlashZoomDescription();
-            case TagManualFlash:
-                return getManualFlashDescription();
-            case TagMacroLed:
-                return getMacroLedDescription();
-            case TagSensorTemperature:
-                return getSensorTemperatureDescription();
-            case TagImageStabilization:
-                return getImageStabilizationDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getFocusInfoVersionDescription()
-    {
-        return getVersionBytesDescription(TagFocusInfoVersion, 4);
-    }
-
-    @Nullable
-    public String getAutoFocusDescription()
-    {
-        return getIndexedDescription(TagAutoFocus,
-            "Off", "On");
-    }
-
-    @Nullable
-    public String getFocusDistanceDescription()
-    {
-        Rational value = _directory.getRational(TagFocusDistance);
-        if (value == null)
-            return "inf";
-        if (value.getNumerator() == 0xFFFFFFFFL || value.getNumerator() == 0x00000000L)
-            return "inf";
-
-        return value.getNumerator() / 1000.0 + " m";
-    }
-
-    @Nullable
-    public String getAfPointDescription()
-    {
-        Integer value = _directory.getInteger(TagAfPoint);
-        if (value == null)
-            return null;
-
-        return value.toString();
-    }
-
-    @Nullable
-    public String getExternalFlashDescription()
-    {
-        int[] values = _directory.getIntArray(TagExternalFlash);
-        if (values == null || values.length < 2)
-            return null;
-
-        String join = String.format("%d %d", (short)values[0], (short)values[1]);
-
-        if(join.equals("0 0"))
-            return "Off";
-        else if(join.equals("1 0"))
-            return "On";
-        else
-            return "Unknown (" + join + ")";
-    }
-
-    @Nullable
-    public String getExternalFlashBounceDescription()
-    {
-        return getIndexedDescription(TagExternalFlashBounce,
-                "Bounce or Off", "Direct");
-    }
-
-    @Nullable
-    public String getExternalFlashZoomDescription()
-    {
-        int[] values = _directory.getIntArray(TagExternalFlashZoom);
-        if (values == null)
-        {
-            // check if it's only one value long also
-            Integer value = _directory.getInteger(TagExternalFlashZoom);
-            if(value == null)
-                return null;
-
-            values = new int[1];
-            values[0] = value;
-        }
-
-        if (values.length == 0)
-            return null;
-
-        String join = String.format("%d", (short)values[0]);
-        if(values.length > 1)
-            join += " " + String.format("%d", (short)values[1]);
-
-        if(join.equals("0"))
-            return "Off";
-        else if(join.equals("1"))
-            return "On";
-        else if(join.equals("0 0"))
-            return "Off";
-        else if(join.equals("1 0"))
-            return "On";
-        else
-            return "Unknown (" + join + ")";
-
-    }
-
-    @Nullable
-    public String getManualFlashDescription()
-    {
-        int[] values = _directory.getIntArray(TagManualFlash);
-        if (values == null)
-            return null;
-
-        if ((short)values[0] == 0)
-            return "Off";
-
-        if ((short)values[1] == 1)
-            return "Full";
-        return "On (1/" + (short)values[1] + " strength)";
-    }
-
-    @Nullable
-    public String getMacroLedDescription()
-    {
-        return getIndexedDescription(TagMacroLed,
-                "Off", "On");
-    }
-
-    /// <remarks>
-    /// <para>TODO: Complete when Camera Model is available.</para>
-    /// <para>There are differences in how to interpret this tag that can only be reconciled by knowing the model.</para>
-    /// </remarks>
-    @Nullable
-    public String getSensorTemperatureDescription()
-    {
-        return _directory.getString(TagSensorTemperature);
-    }
-
-    @Nullable
-    public String getImageStabilizationDescription()
-    {
-        byte[] values = _directory.getByteArray(TagImageStabilization);
-        if (values == null)
-            return null;
-
-        if((values[0] | values[1] | values[2] | values[3]) == 0x0)
-            return "Off";
-        return "On, " + ((values[43] & 1) > 0 ? "Mode 1" : "Mode 2");
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/OlympusFocusInfoMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/OlympusFocusInfoMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,110 +1,0 @@
-/*
- * Copyright 2002-2015 Drew Noakes
- *
- *    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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * The Olympus focus info makernote is used by many manufacturers (Epson, Konica, Minolta and Agfa...), and as such contains some tags
- * that appear specific to those manufacturers.
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class OlympusFocusInfoMakernoteDirectory extends Directory
-{
-    public static final int TagFocusInfoVersion = 0x0000;
-    public static final int TagAutoFocus = 0x0209;
-    public static final int TagSceneDetect = 0x0210;
-    public static final int TagSceneArea = 0x0211;
-    public static final int TagSceneDetectData = 0x0212;
-
-    public static final int TagZoomStepCount = 0x0300;
-    public static final int TagFocusStepCount = 0x0301;
-    public static final int TagFocusStepInfinity = 0x0303;
-    public static final int TagFocusStepNear = 0x0304;
-    public static final int TagFocusDistance = 0x0305;
-    public static final int TagAfPoint = 0x0308;
-    // 0x031a Continuous AF parameters?
-    public static final int TagAfInfo = 0x0328;    // ifd
-
-    public static final int TagExternalFlash = 0x1201;
-    public static final int TagExternalFlashGuideNumber = 0x1203;
-    public static final int TagExternalFlashBounce = 0x1204;
-    public static final int TagExternalFlashZoom = 0x1205;
-    public static final int TagInternalFlash = 0x1208;
-    public static final int TagManualFlash = 0x1209;
-    public static final int TagMacroLed = 0x120A;
-
-    public static final int TagSensorTemperature = 0x1500;
-
-    public static final int TagImageStabilization = 0x1600;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static {
-        _tagNameMap.put(TagFocusInfoVersion, "Focus Info Version");
-        _tagNameMap.put(TagAutoFocus, "Auto Focus");
-        _tagNameMap.put(TagSceneDetect, "Scene Detect");
-        _tagNameMap.put(TagSceneArea, "Scene Area");
-        _tagNameMap.put(TagSceneDetectData, "Scene Detect Data");
-        _tagNameMap.put(TagZoomStepCount, "Zoom Step Count");
-        _tagNameMap.put(TagFocusStepCount, "Focus Step Count");
-        _tagNameMap.put(TagFocusStepInfinity, "Focus Step Infinity");
-        _tagNameMap.put(TagFocusStepNear, "Focus Step Near");
-        _tagNameMap.put(TagFocusDistance, "Focus Distance");
-        _tagNameMap.put(TagAfPoint, "AF Point");
-        _tagNameMap.put(TagAfInfo, "AF Info");
-        _tagNameMap.put(TagExternalFlash, "External Flash");
-        _tagNameMap.put(TagExternalFlashGuideNumber, "External Flash Guide Number");
-        _tagNameMap.put(TagExternalFlashBounce, "External Flash Bounce");
-        _tagNameMap.put(TagExternalFlashZoom, "External Flash Zoom");
-        _tagNameMap.put(TagInternalFlash, "Internal Flash");
-        _tagNameMap.put(TagManualFlash, "Manual Flash");
-        _tagNameMap.put(TagMacroLed, "Macro LED");
-        _tagNameMap.put(TagSensorTemperature, "Sensor Temperature");
-        _tagNameMap.put(TagImageStabilization, "Image Stabilization");
-    }
-
-    public OlympusFocusInfoMakernoteDirectory()
-    {
-        this.setDescriptor(new OlympusFocusInfoMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Olympus Focus Info";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/OlympusImageProcessingMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/OlympusImageProcessingMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,240 +1,0 @@
-/*
- * Copyright 2002-2015 Drew Noakes
- *
- *    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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.makernotes.OlympusImageProcessingMakernoteDirectory.*;
-
-/**
- * Provides human-readable String representations of tag values stored in a {@link OlympusImageProcessingMakernoteDirectory}.
- * <p>
- * Some Description functions converted from Exiftool version 10.33 created by Phil Harvey
- * http://www.sno.phy.queensu.ca/~phil/exiftool/
- * lib\Image\ExifTool\Olympus.pm
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class OlympusImageProcessingMakernoteDescriptor extends TagDescriptor<OlympusImageProcessingMakernoteDirectory>
-{
-    public OlympusImageProcessingMakernoteDescriptor(@NotNull OlympusImageProcessingMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TagImageProcessingVersion:
-                return getImageProcessingVersionDescription();
-            case TagColorMatrix:
-                return getColorMatrixDescription();
-            case TagNoiseReduction2:
-                return getNoiseReduction2Description();
-            case TagDistortionCorrection2:
-                return getDistortionCorrection2Description();
-            case TagShadingCompensation2:
-                return getShadingCompensation2Description();
-            case TagMultipleExposureMode:
-                return getMultipleExposureModeDescription();
-            case TagAspectRatio:
-                return getAspectRatioDescription();
-            case TagKeystoneCompensation:
-                return getKeystoneCompensationDescription();
-            case TagKeystoneDirection:
-                return getKeystoneDirectionDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getImageProcessingVersionDescription()
-    {
-        return getVersionBytesDescription(TagImageProcessingVersion, 4);
-    }
-
-    @Nullable
-    public String getColorMatrixDescription()
-    {
-        int[] obj = _directory.getIntArray(TagColorMatrix);
-        if (obj == null)
-            return null;
-
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < obj.length; i++) {
-            if (i != 0)
-                sb.append(" ");
-            sb.append((short)obj[i]);
-        }
-        return sb.toString();
-    }
-
-    @Nullable
-    public String getNoiseReduction2Description()
-    {
-        Integer value = _directory.getInteger(TagNoiseReduction2);
-        if (value == null)
-            return null;
-
-        if (value == 0)
-            return "(none)";
-
-        StringBuilder sb = new StringBuilder();
-        short v = value.shortValue();
-
-        if (( v       & 1) != 0) sb.append("Noise Reduction, ");
-        if (((v >> 1) & 1) != 0) sb.append("Noise Filter, ");
-        if (((v >> 2) & 1) != 0) sb.append("Noise Filter (ISO Boost), ");
-
-        return sb.substring(0, sb.length() - 2);
-    }
-
-    @Nullable
-    public String getDistortionCorrection2Description()
-    {
-        return getIndexedDescription(TagDistortionCorrection2, "Off", "On");
-    }
-
-    @Nullable
-    public String getShadingCompensation2Description()
-    {
-        return getIndexedDescription(TagShadingCompensation2, "Off", "On");
-    }
-
-    @Nullable
-    public String getMultipleExposureModeDescription()
-    {
-        int[] values = _directory.getIntArray(TagMultipleExposureMode);
-        if (values == null)
-        {
-            // check if it's only one value long also
-            Integer value = _directory.getInteger(TagMultipleExposureMode);
-            if(value == null)
-                return null;
-
-            values = new int[1];
-            values[0] = value;
-        }
-
-        if (values.length == 0)
-            return null;
-
-        StringBuilder sb = new StringBuilder();
-
-        switch ((short)values[0])
-        {
-            case 0:
-                sb.append("Off");
-                break;
-            case 2:
-                sb.append("On (2 frames)");
-                break;
-            case 3:
-                sb.append("On (3 frames)");
-                break;
-            default:
-                sb.append("Unknown (").append((short)values[0]).append(")");
-                break;
-        }
-
-        if (values.length > 1)
-            sb.append("; ").append((short)values[1]);
-
-        return sb.toString();
-    }
-
-    @Nullable
-    public String getAspectRatioDescription()
-    {
-        byte[] values = _directory.getByteArray(TagAspectRatio);
-        if (values == null || values.length < 2)
-            return null;
-
-        String join = String.format("%d %d", values[0], values[1]);
-
-        String ret;
-        if(join.equals("1 1"))
-            ret = "4:3";
-        else if(join.equals("1 4"))
-            ret = "1:1";
-        else if(join.equals("2 1"))
-            ret = "3:2 (RAW)";
-        else if(join.equals("2 2"))
-            ret = "3:2";
-        else if(join.equals("3 1"))
-            ret = "16:9 (RAW)";
-        else if(join.equals("3 3"))
-            ret = "16:9";
-        else if(join.equals("4 1"))
-            ret = "1:1 (RAW)";
-        else if(join.equals("4 4"))
-            ret = "6:6";
-        else if(join.equals("5 5"))
-            ret = "5:4";
-        else if(join.equals("6 6"))
-            ret = "7:6";
-        else if(join.equals("7 7"))
-            ret = "6:5";
-        else if(join.equals("8 8"))
-            ret = "7:5";
-        else if(join.equals("9 1"))
-            ret = "3:4 (RAW)";
-        else if(join.equals("9 9"))
-            ret = "3:4";
-        else
-            ret = "Unknown (" + join + ")";
-
-        return ret;
-    }
-
-    @Nullable
-    public String getKeystoneCompensationDescription()
-    {
-        byte[] values = _directory.getByteArray(TagKeystoneCompensation);
-        if (values == null || values.length < 2)
-            return null;
-
-        String join = String.format("%d %d", values[0], values[1]);
-
-        String ret;
-        if(join.equals("0 0"))
-            ret = "Off";
-        else if(join.equals("0 1"))
-            ret = "On";
-        else
-            ret = "Unknown (" + join + ")";
-
-        return ret;
-    }
-
-    @Nullable
-    public String getKeystoneDirectionDescription()
-    {
-        return getIndexedDescription(TagKeystoneDirection, "Vertical", "Horizontal");
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/OlympusImageProcessingMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/OlympusImageProcessingMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,212 +1,0 @@
-/*
- * Copyright 2002-2015 Drew Noakes
- *
- *    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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * The Olympus image processing makernote is used by many manufacturers (Epson, Konica, Minolta and Agfa...), and as such contains some tags
- * that appear specific to those manufacturers.
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class OlympusImageProcessingMakernoteDirectory extends Directory
-{
-    public static final int TagImageProcessingVersion = 0x0000;
-    public static final int TagWbRbLevels = 0x0100;
-    // 0x0101 - in-camera AutoWB unless it is all 0's or all 256's (ref IB)
-    public static final int TagWbRbLevels3000K = 0x0102;
-    public static final int TagWbRbLevels3300K = 0x0103;
-    public static final int TagWbRbLevels3600K = 0x0104;
-    public static final int TagWbRbLevels3900K = 0x0105;
-    public static final int TagWbRbLevels4000K = 0x0106;
-    public static final int TagWbRbLevels4300K = 0x0107;
-    public static final int TagWbRbLevels4500K = 0x0108;
-    public static final int TagWbRbLevels4800K = 0x0109;
-    public static final int TagWbRbLevels5300K = 0x010a;
-    public static final int TagWbRbLevels6000K = 0x010b;
-    public static final int TagWbRbLevels6600K = 0x010c;
-    public static final int TagWbRbLevels7500K = 0x010d;
-    public static final int TagWbRbLevelsCwB1 = 0x010e;
-    public static final int TagWbRbLevelsCwB2 = 0x010f;
-    public static final int TagWbRbLevelsCwB3 = 0x0110;
-    public static final int TagWbRbLevelsCwB4 = 0x0111;
-    public static final int TagWbGLevel3000K = 0x0113;
-    public static final int TagWbGLevel3300K = 0x0114;
-    public static final int TagWbGLevel3600K = 0x0115;
-    public static final int TagWbGLevel3900K = 0x0116;
-    public static final int TagWbGLevel4000K = 0x0117;
-    public static final int TagWbGLevel4300K = 0x0118;
-    public static final int TagWbGLevel4500K = 0x0119;
-    public static final int TagWbGLevel4800K = 0x011a;
-    public static final int TagWbGLevel5300K = 0x011b;
-    public static final int TagWbGLevel6000K = 0x011c;
-    public static final int TagWbGLevel6600K = 0x011d;
-    public static final int TagWbGLevel7500K = 0x011e;
-    public static final int TagWbGLevel = 0x011f;
-    // 0x0121 = WB preset for flash (about 6000K) (ref IB)
-    // 0x0125 = WB preset for underwater (ref IB)
-
-    public static final int TagColorMatrix = 0x0200;
-    // color matrices (ref 11):
-    // 0x0201-0x020d are sRGB color matrices
-    // 0x020e-0x021a are Adobe RGB color matrices
-    // 0x021b-0x0227 are ProPhoto RGB color matrices
-    // 0x0228 and 0x0229 are ColorMatrix for E-330
-    // 0x0250-0x0252 are sRGB color matrices
-    // 0x0253-0x0255 are Adobe RGB color matrices
-    // 0x0256-0x0258 are ProPhoto RGB color matrices
-
-    public static final int TagEnhancer = 0x0300;
-    public static final int TagEnhancerValues = 0x0301;
-    public static final int TagCoringFilter = 0x0310;
-    public static final int TagCoringValues = 0x0311;
-    public static final int TagBlackLevel2 = 0x0600;
-    public static final int TagGainBase = 0x0610;
-    public static final int TagValidBits = 0x0611;
-    public static final int TagCropLeft = 0x0612;
-    public static final int TagCropTop = 0x0613;
-    public static final int TagCropWidth = 0x0614;
-    public static final int TagCropHeight = 0x0615;
-    public static final int TagUnknownBlock1 = 0x0635;
-    public static final int TagUnknownBlock2 = 0x0636;
-
-    // 0x0800 LensDistortionParams, float[9] (ref 11)
-    // 0x0801 LensShadingParams, int16u[16] (ref 11)
-    public static final int TagSensorCalibration = 0x0805;
-
-    public static final int TagNoiseReduction2 = 0x1010;
-    public static final int TagDistortionCorrection2 = 0x1011;
-    public static final int TagShadingCompensation2 = 0x1012;
-    public static final int TagMultipleExposureMode = 0x101c;
-    public static final int TagUnknownBlock3 = 0x1103;
-    public static final int TagUnknownBlock4 = 0x1104;
-    public static final int TagAspectRatio = 0x1112;
-    public static final int TagAspectFrame = 0x1113;
-    public static final int TagFacesDetected = 0x1200;
-    public static final int TagFaceDetectArea = 0x1201;
-    public static final int TagMaxFaces = 0x1202;
-    public static final int TagFaceDetectFrameSize = 0x1203;
-    public static final int TagFaceDetectFrameCrop = 0x1207;
-    public static final int TagCameraTemperature = 0x1306;
-
-    public static final int TagKeystoneCompensation = 0x1900;
-    public static final int TagKeystoneDirection = 0x1901;
-    // 0x1905 - focal length (PH, E-M1)
-    public static final int TagKeystoneValue = 0x1906;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static {
-        _tagNameMap.put(TagImageProcessingVersion, "Image Processing Version");
-        _tagNameMap.put(TagWbRbLevels, "WB RB Levels");
-        _tagNameMap.put(TagWbRbLevels3000K, "WB RB Levels 3000K");
-        _tagNameMap.put(TagWbRbLevels3300K, "WB RB Levels 3300K");
-        _tagNameMap.put(TagWbRbLevels3600K, "WB RB Levels 3600K");
-        _tagNameMap.put(TagWbRbLevels3900K, "WB RB Levels 3900K");
-        _tagNameMap.put(TagWbRbLevels4000K, "WB RB Levels 4000K");
-        _tagNameMap.put(TagWbRbLevels4300K, "WB RB Levels 4300K");
-        _tagNameMap.put(TagWbRbLevels4500K, "WB RB Levels 4500K");
-        _tagNameMap.put(TagWbRbLevels4800K, "WB RB Levels 4800K");
-        _tagNameMap.put(TagWbRbLevels5300K, "WB RB Levels 5300K");
-        _tagNameMap.put(TagWbRbLevels6000K, "WB RB Levels 6000K");
-        _tagNameMap.put(TagWbRbLevels6600K, "WB RB Levels 6600K");
-        _tagNameMap.put(TagWbRbLevels7500K, "WB RB Levels 7500K");
-        _tagNameMap.put(TagWbRbLevelsCwB1, "WB RB Levels CWB1");
-        _tagNameMap.put(TagWbRbLevelsCwB2, "WB RB Levels CWB2");
-        _tagNameMap.put(TagWbRbLevelsCwB3, "WB RB Levels CWB3");
-        _tagNameMap.put(TagWbRbLevelsCwB4, "WB RB Levels CWB4");
-        _tagNameMap.put(TagWbGLevel3000K, "WB G Level 3000K");
-        _tagNameMap.put(TagWbGLevel3300K, "WB G Level 3300K");
-        _tagNameMap.put(TagWbGLevel3600K, "WB G Level 3600K");
-        _tagNameMap.put(TagWbGLevel3900K, "WB G Level 3900K");
-        _tagNameMap.put(TagWbGLevel4000K, "WB G Level 4000K");
-        _tagNameMap.put(TagWbGLevel4300K, "WB G Level 4300K");
-        _tagNameMap.put(TagWbGLevel4500K, "WB G Level 4500K");
-        _tagNameMap.put(TagWbGLevel4800K, "WB G Level 4800K");
-        _tagNameMap.put(TagWbGLevel5300K, "WB G Level 5300K");
-        _tagNameMap.put(TagWbGLevel6000K, "WB G Level 6000K");
-        _tagNameMap.put(TagWbGLevel6600K, "WB G Level 6600K");
-        _tagNameMap.put(TagWbGLevel7500K, "WB G Level 7500K");
-        _tagNameMap.put(TagWbGLevel, "WB G Level");
-
-        _tagNameMap.put(TagColorMatrix, "Color Matrix");
-
-        _tagNameMap.put(TagEnhancer, "Enhancer");
-        _tagNameMap.put(TagEnhancerValues, "Enhancer Values");
-        _tagNameMap.put(TagCoringFilter, "Coring Filter");
-        _tagNameMap.put(TagCoringValues, "Coring Values");
-        _tagNameMap.put(TagBlackLevel2, "Black Level 2");
-        _tagNameMap.put(TagGainBase, "Gain Base");
-        _tagNameMap.put(TagValidBits, "Valid Bits");
-        _tagNameMap.put(TagCropLeft, "Crop Left");
-        _tagNameMap.put(TagCropTop, "Crop Top");
-        _tagNameMap.put(TagCropWidth, "Crop Width");
-        _tagNameMap.put(TagCropHeight, "Crop Height");
-        _tagNameMap.put(TagUnknownBlock1, "Unknown Block 1");
-        _tagNameMap.put(TagUnknownBlock2, "Unknown Block 2");
-
-        _tagNameMap.put(TagSensorCalibration, "Sensor Calibration");
-
-        _tagNameMap.put(TagNoiseReduction2, "Noise Reduction 2");
-        _tagNameMap.put(TagDistortionCorrection2, "Distortion Correction 2");
-        _tagNameMap.put(TagShadingCompensation2, "Shading Compensation 2");
-        _tagNameMap.put(TagMultipleExposureMode, "Multiple Exposure Mode");
-        _tagNameMap.put(TagUnknownBlock3, "Unknown Block 3");
-        _tagNameMap.put(TagUnknownBlock4, "Unknown Block 4");
-        _tagNameMap.put(TagAspectRatio, "Aspect Ratio");
-        _tagNameMap.put(TagAspectFrame, "Aspect Frame");
-        _tagNameMap.put(TagFacesDetected, "Faces Detected");
-        _tagNameMap.put(TagFaceDetectArea, "Face Detect Area");
-        _tagNameMap.put(TagMaxFaces, "Max Faces");
-        _tagNameMap.put(TagFaceDetectFrameSize, "Face Detect Frame Size");
-        _tagNameMap.put(TagFaceDetectFrameCrop, "Face Detect Frame Crop");
-        _tagNameMap.put(TagCameraTemperature , "Camera Temperature");
-        _tagNameMap.put(TagKeystoneCompensation, "Keystone Compensation");
-        _tagNameMap.put(TagKeystoneDirection, "Keystone Direction");
-        _tagNameMap.put(TagKeystoneValue, "Keystone Value");
-    }
-
-    public OlympusImageProcessingMakernoteDirectory()
-    {
-        this.setDescriptor(new OlympusImageProcessingMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Olympus Image Processing";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/OlympusMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/OlympusMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,992 +1,0 @@
-/*
- * 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
- *
- *        http://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.imaging.PhotographicConversions;
-import com.drew.lang.Rational;
-import com.drew.lang.DateUtil;
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import java.math.RoundingMode;
-import java.text.DecimalFormat;
-
-import static com.drew.metadata.exif.makernotes.OlympusMakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link OlympusMakernoteDirectory}.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class OlympusMakernoteDescriptor extends TagDescriptor<OlympusMakernoteDirectory>
-{
-    // TODO extend support for some offset-encoded byte[] tags: http://www.ozhiker.com/electronics/pjmt/jpeg_info/olympus_mn.html
-
-    public OlympusMakernoteDescriptor(@NotNull OlympusMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_MAKERNOTE_VERSION:
-                return getMakernoteVersionDescription();
-            case TAG_COLOUR_MODE:
-                return getColorModeDescription();
-            case TAG_IMAGE_QUALITY_1:
-                return getImageQuality1Description();
-            case TAG_IMAGE_QUALITY_2:
-                return getImageQuality2Description();
-            case TAG_SPECIAL_MODE:
-                return getSpecialModeDescription();
-            case TAG_JPEG_QUALITY:
-                return getJpegQualityDescription();
-            case TAG_MACRO_MODE:
-                return getMacroModeDescription();
-            case TAG_BW_MODE:
-                return getBWModeDescription();
-            case TAG_DIGITAL_ZOOM:
-                return getDigitalZoomDescription();
-            case TAG_FOCAL_PLANE_DIAGONAL:
-                return getFocalPlaneDiagonalDescription();
-            case TAG_CAMERA_TYPE:
-                return getCameraTypeDescription();
-            case TAG_CAMERA_ID:
-                return getCameraIdDescription();
-            case TAG_ONE_TOUCH_WB:
-                return getOneTouchWbDescription();
-            case TAG_SHUTTER_SPEED_VALUE:
-                return getShutterSpeedDescription();
-            case TAG_ISO_VALUE:
-                return getIsoValueDescription();
-            case TAG_APERTURE_VALUE:
-                return getApertureValueDescription();
-            case TAG_FLASH_MODE:
-                return getFlashModeDescription();
-            case TAG_FOCUS_RANGE:
-                return getFocusRangeDescription();
-            case TAG_FOCUS_MODE:
-                return getFocusModeDescription();
-            case TAG_SHARPNESS:
-                return getSharpnessDescription();
-            case TAG_COLOUR_MATRIX:
-                return getColorMatrixDescription();
-            case TAG_WB_MODE:
-                return getWbModeDescription();
-            case TAG_RED_BALANCE:
-                return getRedBalanceDescription();
-            case TAG_BLUE_BALANCE:
-                return getBlueBalanceDescription();
-            case TAG_CONTRAST:
-                return getContrastDescription();
-            case TAG_PREVIEW_IMAGE_VALID:
-                return getPreviewImageValidDescription();
-
-            case CameraSettings.TAG_EXPOSURE_MODE:
-                return getExposureModeDescription();
-            case CameraSettings.TAG_FLASH_MODE:
-                return getFlashModeCameraSettingDescription();
-            case CameraSettings.TAG_WHITE_BALANCE:
-                return getWhiteBalanceDescription();
-            case CameraSettings.TAG_IMAGE_SIZE:
-                return getImageSizeDescription();
-            case CameraSettings.TAG_IMAGE_QUALITY:
-                return getImageQualityDescription();
-            case CameraSettings.TAG_SHOOTING_MODE:
-                return getShootingModeDescription();
-            case CameraSettings.TAG_METERING_MODE:
-                return getMeteringModeDescription();
-            case CameraSettings.TAG_APEX_FILM_SPEED_VALUE:
-                return getApexFilmSpeedDescription();
-            case CameraSettings.TAG_APEX_SHUTTER_SPEED_TIME_VALUE:
-                return getApexShutterSpeedTimeDescription();
-            case CameraSettings.TAG_APEX_APERTURE_VALUE:
-                return getApexApertureDescription();
-            case CameraSettings.TAG_MACRO_MODE:
-                return getMacroModeCameraSettingDescription();
-            case CameraSettings.TAG_DIGITAL_ZOOM:
-                return getDigitalZoomCameraSettingDescription();
-            case CameraSettings.TAG_EXPOSURE_COMPENSATION:
-                return getExposureCompensationDescription();
-            case CameraSettings.TAG_BRACKET_STEP:
-                return getBracketStepDescription();
-
-            case CameraSettings.TAG_INTERVAL_LENGTH:
-                return getIntervalLengthDescription();
-            case CameraSettings.TAG_INTERVAL_NUMBER:
-                return getIntervalNumberDescription();
-            case CameraSettings.TAG_FOCAL_LENGTH:
-                return getFocalLengthDescription();
-            case CameraSettings.TAG_FOCUS_DISTANCE:
-                return getFocusDistanceDescription();
-            case CameraSettings.TAG_FLASH_FIRED:
-                return getFlashFiredDescription();
-            case CameraSettings.TAG_DATE:
-                return getDateDescription();
-            case CameraSettings.TAG_TIME:
-                return getTimeDescription();
-            case CameraSettings.TAG_MAX_APERTURE_AT_FOCAL_LENGTH:
-                return getMaxApertureAtFocalLengthDescription();
-
-            case CameraSettings.TAG_FILE_NUMBER_MEMORY:
-                return getFileNumberMemoryDescription();
-            case CameraSettings.TAG_LAST_FILE_NUMBER:
-                return getLastFileNumberDescription();
-            case CameraSettings.TAG_WHITE_BALANCE_RED:
-                return getWhiteBalanceRedDescription();
-            case CameraSettings.TAG_WHITE_BALANCE_GREEN:
-                return getWhiteBalanceGreenDescription();
-            case CameraSettings.TAG_WHITE_BALANCE_BLUE:
-                return getWhiteBalanceBlueDescription();
-            case CameraSettings.TAG_SATURATION:
-                return getSaturationDescription();
-            case CameraSettings.TAG_CONTRAST:
-                return getContrastCameraSettingDescription();
-            case CameraSettings.TAG_SHARPNESS:
-                return getSharpnessCameraSettingDescription();
-            case CameraSettings.TAG_SUBJECT_PROGRAM:
-                return getSubjectProgramDescription();
-            case CameraSettings.TAG_FLASH_COMPENSATION:
-                return getFlashCompensationDescription();
-            case CameraSettings.TAG_ISO_SETTING:
-                return getIsoSettingDescription();
-            case CameraSettings.TAG_CAMERA_MODEL:
-                return getCameraModelDescription();
-            case CameraSettings.TAG_INTERVAL_MODE:
-                return getIntervalModeDescription();
-            case CameraSettings.TAG_FOLDER_NAME:
-                return getFolderNameDescription();
-            case CameraSettings.TAG_COLOR_MODE:
-                return getColorModeCameraSettingDescription();
-            case CameraSettings.TAG_COLOR_FILTER:
-                return getColorFilterDescription();
-            case CameraSettings.TAG_BLACK_AND_WHITE_FILTER:
-                return getBlackAndWhiteFilterDescription();
-            case CameraSettings.TAG_INTERNAL_FLASH:
-                return getInternalFlashDescription();
-            case CameraSettings.TAG_APEX_BRIGHTNESS_VALUE:
-                return getApexBrightnessDescription();
-            case CameraSettings.TAG_SPOT_FOCUS_POINT_X_COORDINATE:
-                return getSpotFocusPointXCoordinateDescription();
-            case CameraSettings.TAG_SPOT_FOCUS_POINT_Y_COORDINATE:
-                return getSpotFocusPointYCoordinateDescription();
-            case CameraSettings.TAG_WIDE_FOCUS_ZONE:
-                return getWideFocusZoneDescription();
-            case CameraSettings.TAG_FOCUS_MODE:
-                return getFocusModeCameraSettingDescription();
-            case CameraSettings.TAG_FOCUS_AREA:
-                return getFocusAreaDescription();
-            case CameraSettings.TAG_DEC_SWITCH_POSITION:
-                return getDecSwitchPositionDescription();
-
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getExposureModeDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_EXPOSURE_MODE, "P", "A", "S", "M");
-    }
-
-    @Nullable
-    public String getFlashModeCameraSettingDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_FLASH_MODE,
-            "Normal", "Red-eye reduction", "Rear flash sync", "Wireless");
-    }
-
-    @Nullable
-    public String getWhiteBalanceDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_WHITE_BALANCE,
-            "Auto", // 0
-            "Daylight",
-            "Cloudy",
-            "Tungsten",
-            null,
-            "Custom", // 5
-            null,
-            "Fluorescent",
-            "Fluorescent 2",
-            null,
-            null, // 10
-            "Custom 2",
-            "Custom 3"
-        );
-    }
-
-    @Nullable
-    public String getImageSizeDescription()
-    {
-        // This is a pretty weird way to store this information!
-        return getIndexedDescription(CameraSettings.TAG_IMAGE_SIZE, "2560 x 1920", "1600 x 1200", "1280 x 960", "640 x 480");
-    }
-
-    @Nullable
-    public String getImageQualityDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_IMAGE_QUALITY, "Raw", "Super Fine", "Fine", "Standard", "Economy", "Extra Fine");
-    }
-
-    @Nullable
-    public String getShootingModeDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_SHOOTING_MODE,
-            "Single",
-            "Continuous",
-            "Self Timer",
-            null,
-            "Bracketing",
-            "Interval",
-            "UHS Continuous",
-            "HS Continuous"
-        );
-    }
-
-    @Nullable
-    public String getMeteringModeDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_METERING_MODE, "Multi-Segment", "Centre Weighted", "Spot");
-    }
-
-    @Nullable
-    public String getApexFilmSpeedDescription()
-    {
-        // http://www.ozhiker.com/electronics/pjmt/jpeg_info/minolta_mn.html#Minolta_Camera_Settings
-        // Apex Speed value = value/8-1 ,
-        // ISO = (2^(value/8-1))*3.125
-        Long value = _directory.getLongObject(CameraSettings.TAG_APEX_FILM_SPEED_VALUE);
-
-        if (value == null)
-            return null;
-
-        double iso = Math.pow((value / 8d) - 1, 2) * 3.125;
-        DecimalFormat format = new DecimalFormat("0.##");
-        format.setRoundingMode(RoundingMode.HALF_UP);
-        return format.format(iso);
-    }
-
-    @Nullable
-    public String getApexShutterSpeedTimeDescription()
-    {
-        // http://www.ozhiker.com/electronics/pjmt/jpeg_info/minolta_mn.html#Minolta_Camera_Settings
-        // Apex Time value = value/8-6 ,
-        // ShutterSpeed = 2^( (48-value)/8 ),
-        // Due to rounding error value=8 should be displayed as 30 sec.
-        Long value = _directory.getLongObject(CameraSettings.TAG_APEX_SHUTTER_SPEED_TIME_VALUE);
-
-        if (value == null)
-            return null;
-
-        double shutterSpeed = Math.pow((49-value) / 8d, 2);
-        DecimalFormat format = new DecimalFormat("0.###");
-        format.setRoundingMode(RoundingMode.HALF_UP);
-        return format.format(shutterSpeed) + " sec";
-    }
-
-    @Nullable
-    public String getApexApertureDescription()
-    {
-        // http://www.ozhiker.com/electronics/pjmt/jpeg_info/minolta_mn.html#Minolta_Camera_Settings
-        // Apex Aperture Value = value/8-1 ,
-        // Aperture F-stop = 2^( value/16-0.5 )
-        Long value = _directory.getLongObject(CameraSettings.TAG_APEX_APERTURE_VALUE);
-
-        if (value == null)
-            return null;
-
-        double fStop = Math.pow((value/16d) - 0.5, 2);
-        return getFStopDescription(fStop);
-    }
-
-    @Nullable
-    public String getMacroModeCameraSettingDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_MACRO_MODE, "Off", "On");
-    }
-
-    @Nullable
-    public String getDigitalZoomCameraSettingDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_DIGITAL_ZOOM, "Off", "Electronic magnification", "Digital zoom 2x");
-    }
-
-    @Nullable
-    public String getExposureCompensationDescription()
-    {
-        Long value = _directory.getLongObject(CameraSettings.TAG_EXPOSURE_COMPENSATION);
-        DecimalFormat format = new DecimalFormat("0.##");
-        return value == null ? null : format.format((value / 3d) - 2) + " EV";
-    }
-
-    @Nullable
-    public String getBracketStepDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_BRACKET_STEP, "1/3 EV", "2/3 EV", "1 EV");
-    }
-
-    @Nullable
-    public String getIntervalLengthDescription()
-    {
-        if (!_directory.isIntervalMode())
-            return "N/A";
-
-        Long value = _directory.getLongObject(CameraSettings.TAG_INTERVAL_LENGTH);
-        return value == null ? null : value + " min";
-    }
-
-    @Nullable
-    public String getIntervalNumberDescription()
-    {
-        if (!_directory.isIntervalMode())
-            return "N/A";
-
-        Long value = _directory.getLongObject(CameraSettings.TAG_INTERVAL_NUMBER);
-        return value == null ? null : Long.toString(value);
-    }
-
-    @Nullable
-    public String getFocalLengthDescription()
-    {
-        Long value = _directory.getLongObject(CameraSettings.TAG_FOCAL_LENGTH);
-        return value == null ? null : getFocalLengthDescription(value/256d);
-    }
-
-    @Nullable
-    public String getFocusDistanceDescription()
-    {
-        Long value = _directory.getLongObject(CameraSettings.TAG_FOCUS_DISTANCE);
-        return value == null
-            ? null
-            : value == 0
-                ? "Infinity"
-                : value + " mm";
-    }
-
-    @Nullable
-    public String getFlashFiredDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_FLASH_FIRED, "No", "Yes");
-    }
-
-    @Nullable
-    public String getDateDescription()
-    {
-        // day = value%256,
-        // month = floor( (value - floor( value/65536 )*65536 )/256 )
-        // year = floor( value/65536)
-        Long value = _directory.getLongObject(CameraSettings.TAG_DATE);
-        if (value == null)
-            return null;
-
-        int day = (int) (value & 0xFF);
-        int month = (int) ((value >> 16) & 0xFF);
-        int year = (int) ((value >> 8) & 0xFF) + 1970;
-
-        if (!DateUtil.isValidDate(year, month, day))
-            return "Invalid date";
-
-        return String.format("%04d-%02d-%02d", year, month + 1, day);
-    }
-
-    @Nullable
-    public String getTimeDescription()
-    {
-        // hours = floor( value/65536 ),
-        // minutes = floor( ( value - floor( value/65536 )*65536 )/256 ),
-        // seconds = value%256
-        Long value = _directory.getLongObject(CameraSettings.TAG_TIME);
-        if (value == null)
-            return null;
-
-        int hours = (int) ((value >> 8) & 0xFF);
-        int minutes = (int) ((value >> 16) & 0xFF);
-        int seconds = (int) (value & 0xFF);
-
-        if (!DateUtil.isValidTime(hours, minutes, seconds))
-            return "Invalid time";
-
-        return String.format("%02d:%02d:%02d", hours, minutes, seconds);
-    }
-
-    @Nullable
-    public String getMaxApertureAtFocalLengthDescription()
-    {
-        // Aperture F-Stop = 2^(value/16-0.5)
-        Long value = _directory.getLongObject(CameraSettings.TAG_TIME);
-        if (value == null)
-            return null;
-        double fStop = Math.pow((value/16d) - 0.5, 2);
-        return getFStopDescription(fStop);
-    }
-
-    @Nullable
-    public String getFileNumberMemoryDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_FILE_NUMBER_MEMORY, "Off", "On");
-    }
-
-    @Nullable
-    public String getLastFileNumberDescription()
-    {
-        Long value = _directory.getLongObject(CameraSettings.TAG_LAST_FILE_NUMBER);
-        return value == null
-            ? null
-            : value == 0
-                ? "File Number Memory Off"
-                : Long.toString(value);
-    }
-
-    @Nullable
-    public String getWhiteBalanceRedDescription()
-    {
-        Long value = _directory.getLongObject(CameraSettings.TAG_WHITE_BALANCE_RED);
-        DecimalFormat format = new DecimalFormat("0.##");
-        return value == null ? null : format.format(value/256d);
-    }
-
-    @Nullable
-    public String getWhiteBalanceGreenDescription()
-    {
-        Long value = _directory.getLongObject(CameraSettings.TAG_WHITE_BALANCE_GREEN);
-        DecimalFormat format = new DecimalFormat("0.##");
-        return value == null ? null : format.format(value/256d);
-    }
-
-    @Nullable
-    public String getWhiteBalanceBlueDescription()
-    {
-        Long value = _directory.getLongObject(CameraSettings.TAG_WHITE_BALANCE_BLUE);
-        DecimalFormat format = new DecimalFormat("0.##");
-        return value == null ? null : format.format(value / 256d);
-    }
-
-    @Nullable
-    public String getSaturationDescription()
-    {
-        Long value = _directory.getLongObject(CameraSettings.TAG_SATURATION);
-        return value == null ? null : Long.toString(value-3);
-    }
-
-    @Nullable
-    public String getContrastCameraSettingDescription()
-    {
-        Long value = _directory.getLongObject(CameraSettings.TAG_CONTRAST);
-        return value == null ? null : Long.toString(value-3);
-    }
-
-    @Nullable
-    public String getSharpnessCameraSettingDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_SHARPNESS, "Hard", "Normal", "Soft");
-    }
-
-    @Nullable
-    public String getSubjectProgramDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_SUBJECT_PROGRAM, "None", "Portrait", "Text", "Night Portrait", "Sunset", "Sports Action");
-    }
-
-    @Nullable
-    public String getFlashCompensationDescription()
-    {
-        Long value = _directory.getLongObject(CameraSettings.TAG_FLASH_COMPENSATION);
-        DecimalFormat format = new DecimalFormat("0.##");
-        return value == null ? null : format.format((value-6)/3d) + " EV";
-    }
-
-    @Nullable
-    public String getIsoSettingDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_ISO_SETTING, "100", "200", "400", "800", "Auto", "64");
-    }
-
-    @Nullable
-    public String getCameraModelDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_CAMERA_MODEL,
-            "DiMAGE 7",
-            "DiMAGE 5",
-            "DiMAGE S304",
-            "DiMAGE S404",
-            "DiMAGE 7i",
-            "DiMAGE 7Hi",
-            "DiMAGE A1",
-            "DiMAGE S414");
-    }
-
-    @Nullable
-    public String getIntervalModeDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_INTERVAL_MODE, "Still Image", "Time Lapse Movie");
-    }
-
-    @Nullable
-    public String getFolderNameDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_FOLDER_NAME, "Standard Form", "Data Form");
-    }
-
-    @Nullable
-    public String getColorModeCameraSettingDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_COLOR_MODE, "Natural Color", "Black & White", "Vivid Color", "Solarization", "AdobeRGB");
-    }
-
-    @Nullable
-    public String getColorFilterDescription()
-    {
-        Long value = _directory.getLongObject(CameraSettings.TAG_COLOR_FILTER);
-        return value == null ? null : Long.toString(value-3);
-    }
-
-    @Nullable
-    public String getBlackAndWhiteFilterDescription()
-    {
-        return super.getDescription(CameraSettings.TAG_BLACK_AND_WHITE_FILTER);
-    }
-
-    @Nullable
-    public String getInternalFlashDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_INTERNAL_FLASH, "Did Not Fire", "Fired");
-    }
-
-    @Nullable
-    public String getApexBrightnessDescription()
-    {
-        Long value = _directory.getLongObject(CameraSettings.TAG_APEX_BRIGHTNESS_VALUE);
-        DecimalFormat format = new DecimalFormat("0.##");
-        return value == null ? null : format.format((value/8d)-6);
-    }
-
-    @Nullable
-    public String getSpotFocusPointXCoordinateDescription()
-    {
-        return super.getDescription(CameraSettings.TAG_SPOT_FOCUS_POINT_X_COORDINATE);
-    }
-
-    @Nullable
-    public String getSpotFocusPointYCoordinateDescription()
-    {
-        return super.getDescription(CameraSettings.TAG_SPOT_FOCUS_POINT_Y_COORDINATE);
-    }
-
-    @Nullable
-    public String getWideFocusZoneDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_WIDE_FOCUS_ZONE,
-            "No Zone or AF Failed",
-            "Center Zone (Horizontal Orientation)",
-            "Center Zone (Vertical Orientation)",
-            "Left Zone",
-            "Right Zone"
-        );
-    }
-
-    @Nullable
-    public String getFocusModeCameraSettingDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_FOCUS_MODE, "Auto Focus", "Manual Focus");
-    }
-
-    @Nullable
-    public String getFocusAreaDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_FOCUS_AREA, "Wide Focus (Normal)", "Spot Focus");
-    }
-
-    @Nullable
-    public String getDecSwitchPositionDescription()
-    {
-        return getIndexedDescription(CameraSettings.TAG_DEC_SWITCH_POSITION, "Exposure", "Contrast", "Saturation", "Filter");
-    }
-
-    @Nullable
-    public String getMakernoteVersionDescription()
-    {
-        return getVersionBytesDescription(TAG_MAKERNOTE_VERSION, 2);
-    }
-
-    @Nullable
-    public String getImageQuality2Description()
-    {
-        return getIndexedDescription(TAG_IMAGE_QUALITY_2,
-            "Raw",
-            "Super Fine",
-            "Fine",
-            "Standard",
-            "Extra Fine");
-    }
-
-    @Nullable
-    public String getImageQuality1Description()
-    {
-        return getIndexedDescription(TAG_IMAGE_QUALITY_1,
-            "Raw",
-            "Super Fine",
-            "Fine",
-            "Standard",
-            "Extra Fine");
-    }
-
-    @Nullable
-    public String getColorModeDescription()
-    {
-        return getIndexedDescription(TAG_COLOUR_MODE,
-            "Natural Colour",
-            "Black & White",
-            "Vivid Colour",
-            "Solarization",
-            "AdobeRGB");
-    }
-
-    @Nullable
-    public String getSharpnessDescription()
-    {
-        return getIndexedDescription(TAG_SHARPNESS, "Normal", "Hard", "Soft");
-    }
-
-    @Nullable
-    public String getColorMatrixDescription()
-    {
-        int[] obj = _directory.getIntArray(TAG_COLOUR_MATRIX);
-        if (obj == null)
-            return null;
-
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < obj.length; i++) {
-            sb.append((short)obj[i]);
-            if (i < obj.length - 1)
-                sb.append(" ");
-        }
-        return sb.length() == 0 ? null : sb.toString();
-    }
-
-    @Nullable
-    public String getWbModeDescription()
-    {
-        int[] obj = _directory.getIntArray(TAG_WB_MODE);
-        if (obj == null)
-            return null;
-
-        String val = String.format("%d %d", obj[0], obj[1]);
-
-        if(val.equals("1 0"))
-            return "Auto";
-        else if(val.equals("1 2"))
-            return "Auto (2)";
-        else if(val.equals("1 4"))
-            return "Auto (4)";
-        else if(val.equals("2 2"))
-            return "3000 Kelvin";
-        else if(val.equals("2 3"))
-            return "3700 Kelvin";
-        else if(val.equals("2 4"))
-            return "4000 Kelvin";
-        else if(val.equals("2 5"))
-            return "4500 Kelvin";
-        else if(val.equals("2 6"))
-            return "5500 Kelvin";
-        else if(val.equals("2 7"))
-            return "6500 Kelvin";
-        else if(val.equals("2 8"))
-            return "7500 Kelvin";
-        else if(val.equals("3 0"))
-            return "One-touch";
-        else
-            return "Unknown " + val;
-    }
-
-    @Nullable
-    public String getRedBalanceDescription()
-    {
-        int[] values = _directory.getIntArray(TAG_RED_BALANCE);
-        if (values == null)
-            return null;
-
-        short value = (short)values[0];
-
-        return String.valueOf((double)value/256d);
-    }
-
-    @Nullable
-    public String getBlueBalanceDescription()
-    {
-        int[] values = _directory.getIntArray(TAG_BLUE_BALANCE);
-        if (values == null)
-            return null;
-
-        short value = (short)values[0];
-
-        return String.valueOf((double)value/256d);
-    }
-
-    @Nullable
-    public String getContrastDescription()
-    {
-        return getIndexedDescription(TAG_CONTRAST, "High", "Normal", "Low");
-    }
-
-    @Nullable
-    public String getPreviewImageValidDescription()
-    {
-        return getIndexedDescription(TAG_PREVIEW_IMAGE_VALID, "No", "Yes");
-    }
-
-    @Nullable
-    public String getFocusModeDescription()
-    {
-        return getIndexedDescription(TAG_FOCUS_MODE, "Auto", "Manual");
-    }
-
-    @Nullable
-    public String getFocusRangeDescription()
-    {
-        return getIndexedDescription(TAG_FOCUS_RANGE, "Normal", "Macro");
-    }
-
-    @Nullable
-    public String getFlashModeDescription()
-    {
-        return getIndexedDescription(TAG_FLASH_MODE, null, null, "On", "Off");
-    }
-
-    @Nullable
-    public String getDigitalZoomDescription()
-    {
-        Rational value = _directory.getRational(TAG_DIGITAL_ZOOM);
-        if (value == null)
-            return null;
-        return value.toSimpleString(false);
-    }
-
-    @Nullable
-    public String getFocalPlaneDiagonalDescription()
-    {
-        Rational value = _directory.getRational(TAG_FOCAL_PLANE_DIAGONAL);
-        if (value == null)
-            return null;
-
-        DecimalFormat format = new DecimalFormat("0.###");
-        return format.format(value.doubleValue()) + " mm";
-    }
-
-    @Nullable
-    public String getCameraTypeDescription()
-    {
-        String cameratype = _directory.getString(TAG_CAMERA_TYPE);
-        if(cameratype == null)
-            return null;
-
-        if(OlympusMakernoteDirectory.OlympusCameraTypes.containsKey(cameratype))
-            return OlympusMakernoteDirectory.OlympusCameraTypes.get(cameratype);
-
-        return cameratype;
-    }
-
-    @Nullable
-    public String getCameraIdDescription()
-    {
-        byte[] bytes = _directory.getByteArray(TAG_CAMERA_ID);
-        if (bytes == null)
-            return null;
-        return new String(bytes);
-    }
-
-    @Nullable
-    public String getOneTouchWbDescription()
-    {
-        return getIndexedDescription(TAG_ONE_TOUCH_WB, "Off", "On", "On (Preset)");
-    }
-
-    @Nullable
-    public String getShutterSpeedDescription()
-    {
-        return super.getShutterSpeedDescription(TAG_SHUTTER_SPEED_VALUE);
-    }
-
-    @Nullable
-    public String getIsoValueDescription()
-    {
-        Rational value = _directory.getRational(TAG_ISO_VALUE);
-        if (value == null)
-            return null;
-
-        return String.valueOf(Math.round(Math.pow(2, value.doubleValue() - 5) * 100));
-    }
-
-    @Nullable
-    public String getApertureValueDescription()
-    {
-        Double aperture = _directory.getDoubleObject(TAG_APERTURE_VALUE);
-        if (aperture == null)
-            return null;
-        double fStop = PhotographicConversions.apertureToFStop(aperture);
-        return getFStopDescription(fStop);
-    }
-
-    @Nullable
-    public String getMacroModeDescription()
-    {
-        return getIndexedDescription(TAG_MACRO_MODE, "Normal (no macro)", "Macro");
-    }
-
-    @Nullable
-    public String getBWModeDescription()
-    {
-        return getIndexedDescription(TAG_BW_MODE, "Off", "On");
-    }
-
-    @Nullable
-    public String getJpegQualityDescription()
-    {
-        String cameratype = _directory.getString(TAG_CAMERA_TYPE);
-
-        if(cameratype != null)
-        {
-            Integer value = _directory.getInteger(TAG_JPEG_QUALITY);
-            if(value == null)
-                return null;
-
-            if((cameratype.startsWith("SX") && !cameratype.startsWith("SX151"))
-                || cameratype.startsWith("D4322"))
-            {
-                switch (value)
-                {
-                    case 0:
-                        return "Standard Quality (Low)";
-                    case 1:
-                        return "High Quality (Normal)";
-                    case 2:
-                        return "Super High Quality (Fine)";
-                    case 6:
-                        return "RAW";
-                    default:
-                        return "Unknown (" + value.toString() + ")";
-                }
-            }
-            else
-            {
-                switch (value)
-                {
-                    case 0:
-                        return "Standard Quality (Low)";
-                    case 1:
-                        return "High Quality (Normal)";
-                    case 2:
-                        return "Super High Quality (Fine)";
-                    case 4:
-                        return "RAW";
-                    case 5:
-                        return "Medium-Fine";
-                    case 6:
-                        return "Small-Fine";
-                    case 33:
-                        return "Uncompressed";
-                    default:
-                        return "Unknown (" + value.toString() + ")";
-                }
-            }
-        }
-        else
-            return getIndexedDescription(TAG_JPEG_QUALITY,
-            1,
-            "Standard Quality",
-            "High Quality",
-            "Super High Quality");
-    }
-
-    @Nullable
-    public String getSpecialModeDescription()
-    {
-        long[] values = (long[])_directory.getObject(TAG_SPECIAL_MODE);
-        if (values==null)
-            return null;
-        if (values.length < 1)
-            return "";
-        StringBuilder desc = new StringBuilder();
-
-        switch ((int)values[0]) {
-            case 0:
-                desc.append("Normal picture taking mode");
-                break;
-            case 1:
-                desc.append("Unknown picture taking mode");
-                break;
-            case 2:
-                desc.append("Fast picture taking mode");
-                break;
-            case 3:
-                desc.append("Panorama picture taking mode");
-                break;
-            default:
-                desc.append("Unknown picture taking mode");
-                break;
-        }
-
-        if (values.length >= 2) {
-            switch ((int)values[1]) {
-                case 0:
-                    break;
-                case 1:
-                    desc.append(" / 1st in a sequence");
-                    break;
-                case 2:
-                    desc.append(" / 2nd in a sequence");
-                    break;
-                case 3:
-                    desc.append(" / 3rd in a sequence");
-                    break;
-                default:
-                    desc.append(" / ");
-                    desc.append(values[1]);
-                    desc.append("th in a sequence");
-                    break;
-            }
-        }
-        if (values.length >= 3) {
-            switch ((int)values[2]) {
-                case 1:
-                    desc.append(" / Left to right panorama direction");
-                    break;
-                case 2:
-                    desc.append(" / Right to left panorama direction");
-                    break;
-                case 3:
-                    desc.append(" / Bottom to top panorama direction");
-                    break;
-                case 4:
-                    desc.append(" / Top to bottom panorama direction");
-                    break;
-            }
-        }
-
-        return desc.toString();
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/OlympusMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/OlympusMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,837 +1,0 @@
-/*
- * 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
- *
- *        http://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.SequentialByteArrayReader;
-import com.drew.lang.annotations.NotNull;
-import com.drew.metadata.Directory;
-
-import java.io.IOException;
-import java.util.HashMap;
-
-/**
- * The Olympus makernote is used by many manufacturers (Epson, Konica, Minolta and Agfa...), and as such contains some tags
- * that appear specific to those manufacturers.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class OlympusMakernoteDirectory extends Directory
-{
-    /** Used by Konica / Minolta cameras. */
-    public static final int TAG_MAKERNOTE_VERSION = 0x0000;
-    /** Used by Konica / Minolta cameras. */
-    public static final int TAG_CAMERA_SETTINGS_1 = 0x0001;
-    /** Alternate Camera Settings Tag. Used by Konica / Minolta cameras. */
-    public static final int TAG_CAMERA_SETTINGS_2 = 0x0003;
-    /** Used by Konica / Minolta cameras. */
-    public static final int TAG_COMPRESSED_IMAGE_SIZE = 0x0040;
-    /** Used by Konica / Minolta cameras. */
-    public static final int TAG_MINOLTA_THUMBNAIL_OFFSET_1 = 0x0081;
-    /** Alternate Thumbnail Offset. Used by Konica / Minolta cameras. */
-    public static final int TAG_MINOLTA_THUMBNAIL_OFFSET_2 = 0x0088;
-    /** Length of thumbnail in bytes. Used by Konica / Minolta cameras. */
-    public static final int TAG_MINOLTA_THUMBNAIL_LENGTH = 0x0089;
-
-    public static final int TAG_THUMBNAIL_IMAGE = 0x0100;
-
-    /**
-     * Used by Konica / Minolta cameras
-     * 0 = Natural Colour
-     * 1 = Black &amp; White
-     * 2 = Vivid colour
-     * 3 = Solarization
-     * 4 = AdobeRGB
-     */
-    public static final int TAG_COLOUR_MODE = 0x0101;
-
-    /**
-     * Used by Konica / Minolta cameras.
-     * 0 = Raw
-     * 1 = Super Fine
-     * 2 = Fine
-     * 3 = Standard
-     * 4 = Extra Fine
-     */
-    public static final int TAG_IMAGE_QUALITY_1 = 0x0102;
-
-    /**
-     * Not 100% sure about this tag.
-     * <p>
-     * Used by Konica / Minolta cameras.
-     * 0 = Raw
-     * 1 = Super Fine
-     * 2 = Fine
-     * 3 = Standard
-     * 4 = Extra Fine
-     */
-    public static final int TAG_IMAGE_QUALITY_2 = 0x0103;
-
-    public static final int TAG_BODY_FIRMWARE_VERSION = 0x0104;
-
-    /**
-     * Three values:
-     * Value 1: 0=Normal, 2=Fast, 3=Panorama
-     * Value 2: Sequence Number Value 3:
-     * 1 = Panorama Direction: Left to Right
-     * 2 = Panorama Direction: Right to Left
-     * 3 = Panorama Direction: Bottom to Top
-     * 4 = Panorama Direction: Top to Bottom
-     */
-    public static final int TAG_SPECIAL_MODE = 0x0200;
-
-    /**
-     * 1 = Standard Quality
-     * 2 = High Quality
-     * 3 = Super High Quality
-     */
-    public static final int TAG_JPEG_QUALITY = 0x0201;
-
-    /**
-     * 0 = Normal (Not Macro)
-     * 1 = Macro
-     */
-    public static final int TAG_MACRO_MODE = 0x0202;
-
-    /**
-     * 0 = Off, 1 = On
-     */
-    public static final int TAG_BW_MODE = 0x0203;
-
-    /** Zoom Factor (0 or 1 = normal) */
-    public static final int TAG_DIGITAL_ZOOM = 0x0204;
-    public static final int TAG_FOCAL_PLANE_DIAGONAL = 0x0205;
-    public static final int TAG_LENS_DISTORTION_PARAMETERS = 0x0206;
-    public static final int TAG_CAMERA_TYPE = 0x0207;
-    public static final int TAG_PICT_INFO = 0x0208;
-    public static final int TAG_CAMERA_ID = 0x0209;
-
-    /**
-     * Used by Epson cameras
-     * Units = pixels
-     */
-    public static final int TAG_IMAGE_WIDTH = 0x020B;
-
-    /**
-     * Used by Epson cameras
-     * Units = pixels
-     */
-    public static final int TAG_IMAGE_HEIGHT = 0x020C;
-
-    /** A string. Used by Epson cameras. */
-    public static final int TAG_ORIGINAL_MANUFACTURER_MODEL = 0x020D;
-
-    public static final int TAG_PREVIEW_IMAGE = 0x0280;
-    public static final int TAG_PRE_CAPTURE_FRAMES = 0x0300;
-    public static final int TAG_WHITE_BOARD = 0x0301;
-    public static final int TAG_ONE_TOUCH_WB = 0x0302;
-    public static final int TAG_WHITE_BALANCE_BRACKET = 0x0303;
-    public static final int TAG_WHITE_BALANCE_BIAS = 0x0304;
-    public static final int TAG_SCENE_MODE = 0x0403;
-    public static final int TAG_SERIAL_NUMBER_1 = 0x0404;
-    public static final int TAG_FIRMWARE = 0x0405;
-
-    /**
-     * See the PIM specification here:
-     * http://www.ozhiker.com/electronics/pjmt/jpeg_info/pim.html
-     */
-    public static final int TAG_PRINT_IMAGE_MATCHING_INFO = 0x0E00;
-
-    public static final int TAG_DATA_DUMP_1 = 0x0F00;
-    public static final int TAG_DATA_DUMP_2 = 0x0F01;
-
-    public static final int TAG_SHUTTER_SPEED_VALUE = 0x1000;
-    public static final int TAG_ISO_VALUE = 0x1001;
-    public static final int TAG_APERTURE_VALUE = 0x1002;
-    public static final int TAG_BRIGHTNESS_VALUE = 0x1003;
-    public static final int TAG_FLASH_MODE = 0x1004;
-    public static final int TAG_FLASH_DEVICE = 0x1005;
-    public static final int TAG_BRACKET = 0x1006;
-    public static final int TAG_SENSOR_TEMPERATURE = 0x1007;
-    public static final int TAG_LENS_TEMPERATURE = 0x1008;
-    public static final int TAG_LIGHT_CONDITION = 0x1009;
-    public static final int TAG_FOCUS_RANGE = 0x100A;
-    public static final int TAG_FOCUS_MODE = 0x100B;
-    public static final int TAG_FOCUS_DISTANCE = 0x100C;
-    public static final int TAG_ZOOM = 0x100D;
-    public static final int TAG_MACRO_FOCUS = 0x100E;
-    public static final int TAG_SHARPNESS = 0x100F;
-    public static final int TAG_FLASH_CHARGE_LEVEL = 0x1010;
-    public static final int TAG_COLOUR_MATRIX = 0x1011;
-    public static final int TAG_BLACK_LEVEL = 0x1012;
-    public static final int TAG_COLOR_TEMPERATURE_BG = 0x1013;
-    public static final int TAG_COLOR_TEMPERATURE_RG = 0x1014;
-    public static final int TAG_WB_MODE = 0x1015;
-//    public static final int TAG_ = 0x1016;
-    public static final int TAG_RED_BALANCE = 0x1017;
-    public static final int TAG_BLUE_BALANCE = 0x1018;
-    public static final int TAG_COLOR_MATRIX_NUMBER = 0x1019;
-    public static final int TAG_SERIAL_NUMBER_2 = 0x101A;
-
-    public static final int TAG_EXTERNAL_FLASH_AE1_0 = 0x101B;
-    public static final int TAG_EXTERNAL_FLASH_AE2_0 = 0x101C;
-    public static final int TAG_INTERNAL_FLASH_AE1_0 = 0x101D;
-    public static final int TAG_INTERNAL_FLASH_AE2_0 = 0x101E;
-    public static final int TAG_EXTERNAL_FLASH_AE1 = 0x101F;
-    public static final int TAG_EXTERNAL_FLASH_AE2 = 0x1020;
-    public static final int TAG_INTERNAL_FLASH_AE1 = 0x1021;
-    public static final int TAG_INTERNAL_FLASH_AE2 = 0x1022;
-
-    public static final int TAG_FLASH_BIAS = 0x1023;
-    public static final int TAG_INTERNAL_FLASH_TABLE = 0x1024;
-    public static final int TAG_EXTERNAL_FLASH_G_VALUE = 0x1025;
-    public static final int TAG_EXTERNAL_FLASH_BOUNCE = 0x1026;
-    public static final int TAG_EXTERNAL_FLASH_ZOOM = 0x1027;
-    public static final int TAG_EXTERNAL_FLASH_MODE = 0x1028;
-    public static final int TAG_CONTRAST = 0x1029;
-    public static final int TAG_SHARPNESS_FACTOR = 0x102A;
-    public static final int TAG_COLOUR_CONTROL = 0x102B;
-    public static final int TAG_VALID_BITS = 0x102C;
-    public static final int TAG_CORING_FILTER = 0x102D;
-    public static final int TAG_OLYMPUS_IMAGE_WIDTH = 0x102E;
-    public static final int TAG_OLYMPUS_IMAGE_HEIGHT = 0x102F;
-    public static final int TAG_SCENE_DETECT = 0x1030;
-    public static final int TAG_SCENE_AREA = 0x1031;
-//    public static final int TAG_ = 0x1032;
-    public static final int TAG_SCENE_DETECT_DATA = 0x1033;
-    public static final int TAG_COMPRESSION_RATIO = 0x1034;
-    public static final int TAG_PREVIEW_IMAGE_VALID = 0x1035;
-    public static final int TAG_PREVIEW_IMAGE_START = 0x1036;
-    public static final int TAG_PREVIEW_IMAGE_LENGTH = 0x1037;
-    public static final int TAG_AF_RESULT = 0x1038;
-    public static final int TAG_CCD_SCAN_MODE = 0x1039;
-    public static final int TAG_NOISE_REDUCTION = 0x103A;
-    public static final int TAG_INFINITY_LENS_STEP = 0x103B;
-    public static final int TAG_NEAR_LENS_STEP = 0x103C;
-    public static final int TAG_LIGHT_VALUE_CENTER = 0x103D;
-    public static final int TAG_LIGHT_VALUE_PERIPHERY = 0x103E;
-    public static final int TAG_FIELD_COUNT = 0x103F;
-    public static final int TAG_EQUIPMENT = 0x2010;
-    public static final int TAG_CAMERA_SETTINGS = 0x2020;
-    public static final int TAG_RAW_DEVELOPMENT = 0x2030;
-    public static final int TAG_RAW_DEVELOPMENT_2 = 0x2031;
-    public static final int TAG_IMAGE_PROCESSING = 0x2040;
-    public static final int TAG_FOCUS_INFO = 0x2050;
-    public static final int TAG_RAW_INFO = 0x3000;
-    public static final int TAG_MAIN_INFO = 0x4000;
-
-    public final static class CameraSettings
-    {
-        // These 'sub'-tag values have been created for consistency -- they don't exist within the Makernote IFD
-        private static final int OFFSET = 0xF000;
-
-        public static final int TAG_EXPOSURE_MODE = OFFSET + 2;
-        public static final int TAG_FLASH_MODE = OFFSET + 3;
-        public static final int TAG_WHITE_BALANCE = OFFSET + 4;
-        public static final int TAG_IMAGE_SIZE = OFFSET + 5;
-        public static final int TAG_IMAGE_QUALITY = OFFSET + 6;
-        public static final int TAG_SHOOTING_MODE = OFFSET + 7;
-        public static final int TAG_METERING_MODE = OFFSET + 8;
-        public static final int TAG_APEX_FILM_SPEED_VALUE = OFFSET + 9;
-        public static final int TAG_APEX_SHUTTER_SPEED_TIME_VALUE = OFFSET + 10;
-        public static final int TAG_APEX_APERTURE_VALUE = OFFSET + 11;
-        public static final int TAG_MACRO_MODE = OFFSET + 12;
-        public static final int TAG_DIGITAL_ZOOM = OFFSET + 13;
-        public static final int TAG_EXPOSURE_COMPENSATION = OFFSET + 14;
-        public static final int TAG_BRACKET_STEP = OFFSET + 15;
-        // 16 missing
-        public static final int TAG_INTERVAL_LENGTH = OFFSET + 17;
-        public static final int TAG_INTERVAL_NUMBER = OFFSET + 18;
-        public static final int TAG_FOCAL_LENGTH = OFFSET + 19;
-        public static final int TAG_FOCUS_DISTANCE = OFFSET + 20;
-        public static final int TAG_FLASH_FIRED = OFFSET + 21;
-        public static final int TAG_DATE = OFFSET + 22;
-        public static final int TAG_TIME = OFFSET + 23;
-        public static final int TAG_MAX_APERTURE_AT_FOCAL_LENGTH = OFFSET + 24;
-        // 25, 26 missing
-        public static final int TAG_FILE_NUMBER_MEMORY = OFFSET + 27;
-        public static final int TAG_LAST_FILE_NUMBER = OFFSET + 28;
-        public static final int TAG_WHITE_BALANCE_RED = OFFSET + 29;
-        public static final int TAG_WHITE_BALANCE_GREEN = OFFSET + 30;
-        public static final int TAG_WHITE_BALANCE_BLUE = OFFSET + 31;
-        public static final int TAG_SATURATION = OFFSET + 32;
-        public static final int TAG_CONTRAST = OFFSET + 33;
-        public static final int TAG_SHARPNESS = OFFSET + 34;
-        public static final int TAG_SUBJECT_PROGRAM = OFFSET + 35;
-        public static final int TAG_FLASH_COMPENSATION = OFFSET + 36;
-        public static final int TAG_ISO_SETTING = OFFSET + 37;
-        public static final int TAG_CAMERA_MODEL = OFFSET + 38;
-        public static final int TAG_INTERVAL_MODE = OFFSET + 39;
-        public static final int TAG_FOLDER_NAME = OFFSET + 40;
-        public static final int TAG_COLOR_MODE = OFFSET + 41;
-        public static final int TAG_COLOR_FILTER = OFFSET + 42;
-        public static final int TAG_BLACK_AND_WHITE_FILTER = OFFSET + 43;
-        public static final int TAG_INTERNAL_FLASH = OFFSET + 44;
-        public static final int TAG_APEX_BRIGHTNESS_VALUE = OFFSET + 45;
-        public static final int TAG_SPOT_FOCUS_POINT_X_COORDINATE = OFFSET + 46;
-        public static final int TAG_SPOT_FOCUS_POINT_Y_COORDINATE = OFFSET + 47;
-        public static final int TAG_WIDE_FOCUS_ZONE = OFFSET + 48;
-        public static final int TAG_FOCUS_MODE = OFFSET + 49;
-        public static final int TAG_FOCUS_AREA = OFFSET + 50;
-        public static final int TAG_DEC_SWITCH_POSITION = OFFSET + 51;
-    }
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static {
-        _tagNameMap.put(TAG_MAKERNOTE_VERSION, "Makernote Version");
-        _tagNameMap.put(TAG_CAMERA_SETTINGS_1, "Camera Settings");
-        _tagNameMap.put(TAG_CAMERA_SETTINGS_2, "Camera Settings");
-        _tagNameMap.put(TAG_COMPRESSED_IMAGE_SIZE, "Compressed Image Size");
-        _tagNameMap.put(TAG_MINOLTA_THUMBNAIL_OFFSET_1, "Thumbnail Offset");
-        _tagNameMap.put(TAG_MINOLTA_THUMBNAIL_OFFSET_2, "Thumbnail Offset");
-        _tagNameMap.put(TAG_MINOLTA_THUMBNAIL_LENGTH, "Thumbnail Length");
-        _tagNameMap.put(TAG_THUMBNAIL_IMAGE, "Thumbnail Image");
-        _tagNameMap.put(TAG_COLOUR_MODE, "Colour Mode");
-        _tagNameMap.put(TAG_IMAGE_QUALITY_1, "Image Quality");
-        _tagNameMap.put(TAG_IMAGE_QUALITY_2, "Image Quality");
-        _tagNameMap.put(TAG_BODY_FIRMWARE_VERSION, "Body Firmware Version");
-        _tagNameMap.put(TAG_SPECIAL_MODE, "Special Mode");
-        _tagNameMap.put(TAG_JPEG_QUALITY, "JPEG Quality");
-        _tagNameMap.put(TAG_MACRO_MODE, "Macro");
-        _tagNameMap.put(TAG_BW_MODE, "BW Mode");
-        _tagNameMap.put(TAG_DIGITAL_ZOOM, "Digital Zoom");
-        _tagNameMap.put(TAG_FOCAL_PLANE_DIAGONAL, "Focal Plane Diagonal");
-        _tagNameMap.put(TAG_LENS_DISTORTION_PARAMETERS, "Lens Distortion Parameters");
-        _tagNameMap.put(TAG_CAMERA_TYPE, "Camera Type");
-        _tagNameMap.put(TAG_PICT_INFO, "Pict Info");
-        _tagNameMap.put(TAG_CAMERA_ID, "Camera Id");
-        _tagNameMap.put(TAG_IMAGE_WIDTH, "Image Width");
-        _tagNameMap.put(TAG_IMAGE_HEIGHT, "Image Height");
-        _tagNameMap.put(TAG_ORIGINAL_MANUFACTURER_MODEL, "Original Manufacturer Model");
-        _tagNameMap.put(TAG_PREVIEW_IMAGE, "Preview Image");
-        _tagNameMap.put(TAG_PRE_CAPTURE_FRAMES, "Pre Capture Frames");
-        _tagNameMap.put(TAG_WHITE_BOARD, "White Board");
-        _tagNameMap.put(TAG_ONE_TOUCH_WB, "One Touch WB");
-        _tagNameMap.put(TAG_WHITE_BALANCE_BRACKET, "White Balance Bracket");
-        _tagNameMap.put(TAG_WHITE_BALANCE_BIAS, "White Balance Bias");
-        _tagNameMap.put(TAG_SCENE_MODE, "Scene Mode");
-        _tagNameMap.put(TAG_SERIAL_NUMBER_1, "Serial Number");
-        _tagNameMap.put(TAG_FIRMWARE, "Firmware");
-        _tagNameMap.put(TAG_PRINT_IMAGE_MATCHING_INFO, "Print Image Matching (PIM) Info");
-        _tagNameMap.put(TAG_DATA_DUMP_1, "Data Dump");
-        _tagNameMap.put(TAG_DATA_DUMP_2, "Data Dump 2");
-        _tagNameMap.put(TAG_SHUTTER_SPEED_VALUE, "Shutter Speed Value");
-        _tagNameMap.put(TAG_ISO_VALUE, "ISO Value");
-        _tagNameMap.put(TAG_APERTURE_VALUE, "Aperture Value");
-        _tagNameMap.put(TAG_BRIGHTNESS_VALUE, "Brightness Value");
-        _tagNameMap.put(TAG_FLASH_MODE, "Flash Mode");
-        _tagNameMap.put(TAG_FLASH_DEVICE, "Flash Device");
-        _tagNameMap.put(TAG_BRACKET, "Bracket");
-        _tagNameMap.put(TAG_SENSOR_TEMPERATURE, "Sensor Temperature");
-        _tagNameMap.put(TAG_LENS_TEMPERATURE, "Lens Temperature");
-        _tagNameMap.put(TAG_LIGHT_CONDITION, "Light Condition");
-        _tagNameMap.put(TAG_FOCUS_RANGE, "Focus Range");
-        _tagNameMap.put(TAG_FOCUS_MODE, "Focus Mode");
-        _tagNameMap.put(TAG_FOCUS_DISTANCE, "Focus Distance");
-        _tagNameMap.put(TAG_ZOOM, "Zoom");
-        _tagNameMap.put(TAG_MACRO_FOCUS, "Macro Focus");
-        _tagNameMap.put(TAG_SHARPNESS, "Sharpness");
-        _tagNameMap.put(TAG_FLASH_CHARGE_LEVEL, "Flash Charge Level");
-        _tagNameMap.put(TAG_COLOUR_MATRIX, "Colour Matrix");
-        _tagNameMap.put(TAG_BLACK_LEVEL, "Black Level");
-        _tagNameMap.put(TAG_COLOR_TEMPERATURE_BG, "Color Temperature BG");
-        _tagNameMap.put(TAG_COLOR_TEMPERATURE_RG, "Color Temperature RG");
-        _tagNameMap.put(TAG_WB_MODE, "White Balance Mode");
-        _tagNameMap.put(TAG_RED_BALANCE, "Red Balance");
-        _tagNameMap.put(TAG_BLUE_BALANCE, "Blue Balance");
-        _tagNameMap.put(TAG_COLOR_MATRIX_NUMBER, "Color Matrix Number");
-        _tagNameMap.put(TAG_SERIAL_NUMBER_2, "Serial Number");
-        _tagNameMap.put(TAG_EXTERNAL_FLASH_AE1_0, "External Flash AE1 0");
-        _tagNameMap.put(TAG_EXTERNAL_FLASH_AE2_0, "External Flash AE2 0");
-        _tagNameMap.put(TAG_INTERNAL_FLASH_AE1_0, "Internal Flash AE1 0");
-        _tagNameMap.put(TAG_INTERNAL_FLASH_AE2_0, "Internal Flash AE2 0");
-        _tagNameMap.put(TAG_EXTERNAL_FLASH_AE1, "External Flash AE1");
-        _tagNameMap.put(TAG_EXTERNAL_FLASH_AE2, "External Flash AE2");
-        _tagNameMap.put(TAG_INTERNAL_FLASH_AE1, "Internal Flash AE1");
-        _tagNameMap.put(TAG_INTERNAL_FLASH_AE2, "Internal Flash AE2");
-        _tagNameMap.put(TAG_FLASH_BIAS, "Flash Bias");
-        _tagNameMap.put(TAG_INTERNAL_FLASH_TABLE, "Internal Flash Table");
-        _tagNameMap.put(TAG_EXTERNAL_FLASH_G_VALUE, "External Flash G Value");
-        _tagNameMap.put(TAG_EXTERNAL_FLASH_BOUNCE, "External Flash Bounce");
-        _tagNameMap.put(TAG_EXTERNAL_FLASH_ZOOM, "External Flash Zoom");
-        _tagNameMap.put(TAG_EXTERNAL_FLASH_MODE, "External Flash Mode");
-        _tagNameMap.put(TAG_CONTRAST, "Contrast");
-        _tagNameMap.put(TAG_SHARPNESS_FACTOR, "Sharpness Factor");
-        _tagNameMap.put(TAG_COLOUR_CONTROL, "Colour Control");
-        _tagNameMap.put(TAG_VALID_BITS, "Valid Bits");
-        _tagNameMap.put(TAG_CORING_FILTER, "Coring Filter");
-        _tagNameMap.put(TAG_OLYMPUS_IMAGE_WIDTH, "Olympus Image Width");
-        _tagNameMap.put(TAG_OLYMPUS_IMAGE_HEIGHT, "Olympus Image Height");
-        _tagNameMap.put(TAG_SCENE_DETECT, "Scene Detect");
-        _tagNameMap.put(TAG_SCENE_AREA, "Scene Area");
-        _tagNameMap.put(TAG_SCENE_DETECT_DATA, "Scene Detect Data");
-        _tagNameMap.put(TAG_COMPRESSION_RATIO, "Compression Ratio");
-        _tagNameMap.put(TAG_PREVIEW_IMAGE_VALID, "Preview Image Valid");
-        _tagNameMap.put(TAG_PREVIEW_IMAGE_START, "Preview Image Start");
-        _tagNameMap.put(TAG_PREVIEW_IMAGE_LENGTH, "Preview Image Length");
-        _tagNameMap.put(TAG_AF_RESULT, "AF Result");
-        _tagNameMap.put(TAG_CCD_SCAN_MODE, "CCD Scan Mode");
-        _tagNameMap.put(TAG_NOISE_REDUCTION, "Noise Reduction");
-        _tagNameMap.put(TAG_INFINITY_LENS_STEP, "Infinity Lens Step");
-        _tagNameMap.put(TAG_NEAR_LENS_STEP, "Near Lens Step");
-        _tagNameMap.put(TAG_LIGHT_VALUE_CENTER, "Light Value Center");
-        _tagNameMap.put(TAG_LIGHT_VALUE_PERIPHERY, "Light Value Periphery");
-        _tagNameMap.put(TAG_FIELD_COUNT, "Field Count");
-        _tagNameMap.put(TAG_EQUIPMENT, "Equipment");
-        _tagNameMap.put(TAG_CAMERA_SETTINGS, "Camera Settings");
-        _tagNameMap.put(TAG_RAW_DEVELOPMENT, "Raw Development");
-        _tagNameMap.put(TAG_RAW_DEVELOPMENT_2, "Raw Development 2");
-        _tagNameMap.put(TAG_IMAGE_PROCESSING, "Image Processing");
-        _tagNameMap.put(TAG_FOCUS_INFO, "Focus Info");
-        _tagNameMap.put(TAG_RAW_INFO, "Raw Info");
-        _tagNameMap.put(TAG_MAIN_INFO, "Main Info");
-
-        _tagNameMap.put(CameraSettings.TAG_EXPOSURE_MODE, "Exposure Mode");
-        _tagNameMap.put(CameraSettings.TAG_FLASH_MODE, "Flash Mode");
-        _tagNameMap.put(CameraSettings.TAG_WHITE_BALANCE, "White Balance");
-        _tagNameMap.put(CameraSettings.TAG_IMAGE_SIZE, "Image Size");
-        _tagNameMap.put(CameraSettings.TAG_IMAGE_QUALITY, "Image Quality");
-        _tagNameMap.put(CameraSettings.TAG_SHOOTING_MODE, "Shooting Mode");
-        _tagNameMap.put(CameraSettings.TAG_METERING_MODE, "Metering Mode");
-        _tagNameMap.put(CameraSettings.TAG_APEX_FILM_SPEED_VALUE, "Apex Film Speed Value");
-        _tagNameMap.put(CameraSettings.TAG_APEX_SHUTTER_SPEED_TIME_VALUE, "Apex Shutter Speed Time Value");
-        _tagNameMap.put(CameraSettings.TAG_APEX_APERTURE_VALUE, "Apex Aperture Value");
-        _tagNameMap.put(CameraSettings.TAG_MACRO_MODE, "Macro Mode");
-        _tagNameMap.put(CameraSettings.TAG_DIGITAL_ZOOM, "Digital Zoom");
-        _tagNameMap.put(CameraSettings.TAG_EXPOSURE_COMPENSATION, "Exposure Compensation");
-        _tagNameMap.put(CameraSettings.TAG_BRACKET_STEP, "Bracket Step");
-
-        _tagNameMap.put(CameraSettings.TAG_INTERVAL_LENGTH, "Interval Length");
-        _tagNameMap.put(CameraSettings.TAG_INTERVAL_NUMBER, "Interval Number");
-        _tagNameMap.put(CameraSettings.TAG_FOCAL_LENGTH, "Focal Length");
-        _tagNameMap.put(CameraSettings.TAG_FOCUS_DISTANCE, "Focus Distance");
-        _tagNameMap.put(CameraSettings.TAG_FLASH_FIRED, "Flash Fired");
-        _tagNameMap.put(CameraSettings.TAG_DATE, "Date");
-        _tagNameMap.put(CameraSettings.TAG_TIME, "Time");
-        _tagNameMap.put(CameraSettings.TAG_MAX_APERTURE_AT_FOCAL_LENGTH, "Max Aperture at Focal Length");
-
-        _tagNameMap.put(CameraSettings.TAG_FILE_NUMBER_MEMORY, "File Number Memory");
-        _tagNameMap.put(CameraSettings.TAG_LAST_FILE_NUMBER, "Last File Number");
-        _tagNameMap.put(CameraSettings.TAG_WHITE_BALANCE_RED, "White Balance Red");
-        _tagNameMap.put(CameraSettings.TAG_WHITE_BALANCE_GREEN, "White Balance Green");
-        _tagNameMap.put(CameraSettings.TAG_WHITE_BALANCE_BLUE, "White Balance Blue");
-        _tagNameMap.put(CameraSettings.TAG_SATURATION, "Saturation");
-        _tagNameMap.put(CameraSettings.TAG_CONTRAST, "Contrast");
-        _tagNameMap.put(CameraSettings.TAG_SHARPNESS, "Sharpness");
-        _tagNameMap.put(CameraSettings.TAG_SUBJECT_PROGRAM, "Subject Program");
-        _tagNameMap.put(CameraSettings.TAG_FLASH_COMPENSATION, "Flash Compensation");
-        _tagNameMap.put(CameraSettings.TAG_ISO_SETTING, "ISO Setting");
-        _tagNameMap.put(CameraSettings.TAG_CAMERA_MODEL, "Camera Model");
-        _tagNameMap.put(CameraSettings.TAG_INTERVAL_MODE, "Interval Mode");
-        _tagNameMap.put(CameraSettings.TAG_FOLDER_NAME, "Folder Name");
-        _tagNameMap.put(CameraSettings.TAG_COLOR_MODE, "Color Mode");
-        _tagNameMap.put(CameraSettings.TAG_COLOR_FILTER, "Color Filter");
-        _tagNameMap.put(CameraSettings.TAG_BLACK_AND_WHITE_FILTER, "Black and White Filter");
-        _tagNameMap.put(CameraSettings.TAG_INTERNAL_FLASH, "Internal Flash");
-        _tagNameMap.put(CameraSettings.TAG_APEX_BRIGHTNESS_VALUE, "Apex Brightness Value");
-        _tagNameMap.put(CameraSettings.TAG_SPOT_FOCUS_POINT_X_COORDINATE, "Spot Focus Point X Coordinate");
-        _tagNameMap.put(CameraSettings.TAG_SPOT_FOCUS_POINT_Y_COORDINATE, "Spot Focus Point Y Coordinate");
-        _tagNameMap.put(CameraSettings.TAG_WIDE_FOCUS_ZONE, "Wide Focus Zone");
-        _tagNameMap.put(CameraSettings.TAG_FOCUS_MODE, "Focus Mode");
-        _tagNameMap.put(CameraSettings.TAG_FOCUS_AREA, "Focus Area");
-        _tagNameMap.put(CameraSettings.TAG_DEC_SWITCH_POSITION, "DEC Switch Position");
-    }
-
-    public OlympusMakernoteDirectory()
-    {
-        this.setDescriptor(new OlympusMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Olympus Makernote";
-    }
-
-    @Override
-    public void setByteArray(int tagType, @NotNull byte[] bytes)
-    {
-        if (tagType == TAG_CAMERA_SETTINGS_1 || tagType == TAG_CAMERA_SETTINGS_2) {
-            processCameraSettings(bytes);
-        } else {
-            super.setByteArray(tagType, bytes);
-        }
-    }
-
-    private void processCameraSettings(byte[] bytes)
-    {
-        SequentialByteArrayReader reader = new SequentialByteArrayReader(bytes);
-        reader.setMotorolaByteOrder(true);
-
-        int count = bytes.length / 4;
-
-        try {
-            for (int i = 0; i < count; i++) {
-                int value = reader.getInt32();
-                setInt(CameraSettings.OFFSET + i, value);
-            }
-        } catch (IOException e) {
-            // Should never happen, given that we check the length of the bytes beforehand.
-            e.printStackTrace();
-        }
-    }
-
-    public boolean isIntervalMode()
-    {
-        Long value = getLongObject(CameraSettings.TAG_SHOOTING_MODE);
-        return value != null && value == 5;
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-
-    // <summary>
-    // These values are currently decoded only for Olympus models.  Models with
-    // Olympus-style maker notes from other brands such as Acer, BenQ, Hitachi, HP,
-    // Premier, Konica-Minolta, Maginon, Ricoh, Rollei, SeaLife, Sony, Supra,
-    // Vivitar are not listed.
-    // </summary>
-    // <remarks>
-    // Converted from Exiftool version 10.33 created by Phil Harvey
-    // http://www.sno.phy.queensu.ca/~phil/exiftool/
-    // lib\Image\ExifTool\Olympus.pm
-    // </remarks>
-    public static final HashMap<String, String> OlympusCameraTypes = new HashMap<String, String>();
-
-    static {
-        OlympusCameraTypes.put("D4028", "X-2,C-50Z");
-        OlympusCameraTypes.put("D4029", "E-20,E-20N,E-20P");
-        OlympusCameraTypes.put("D4034", "C720UZ");
-        OlympusCameraTypes.put("D4040", "E-1");
-        OlympusCameraTypes.put("D4041", "E-300");
-        OlympusCameraTypes.put("D4083", "C2Z,D520Z,C220Z");
-        OlympusCameraTypes.put("D4106", "u20D,S400D,u400D");
-        OlympusCameraTypes.put("D4120", "X-1");
-        OlympusCameraTypes.put("D4122", "u10D,S300D,u300D");
-        OlympusCameraTypes.put("D4125", "AZ-1");
-        OlympusCameraTypes.put("D4141", "C150,D390");
-        OlympusCameraTypes.put("D4193", "C-5000Z");
-        OlympusCameraTypes.put("D4194", "X-3,C-60Z");
-        OlympusCameraTypes.put("D4199", "u30D,S410D,u410D");
-        OlympusCameraTypes.put("D4205", "X450,D535Z,C370Z");
-        OlympusCameraTypes.put("D4210", "C160,D395");
-        OlympusCameraTypes.put("D4211", "C725UZ");
-        OlympusCameraTypes.put("D4213", "FerrariMODEL2003");
-        OlympusCameraTypes.put("D4216", "u15D");
-        OlympusCameraTypes.put("D4217", "u25D");
-        OlympusCameraTypes.put("D4220", "u-miniD,Stylus V");
-        OlympusCameraTypes.put("D4221", "u40D,S500,uD500");
-        OlympusCameraTypes.put("D4231", "FerrariMODEL2004");
-        OlympusCameraTypes.put("D4240", "X500,D590Z,C470Z");
-        OlympusCameraTypes.put("D4244", "uD800,S800");
-        OlympusCameraTypes.put("D4256", "u720SW,S720SW");
-        OlympusCameraTypes.put("D4261", "X600,D630,FE5500");
-        OlympusCameraTypes.put("D4262", "uD600,S600");
-        OlympusCameraTypes.put("D4301", "u810/S810"); // (yes, "/".  Olympus is not consistent in the notation)
-        OlympusCameraTypes.put("D4302", "u710,S710");
-        OlympusCameraTypes.put("D4303", "u700,S700");
-        OlympusCameraTypes.put("D4304", "FE100,X710");
-        OlympusCameraTypes.put("D4305", "FE110,X705");
-        OlympusCameraTypes.put("D4310", "FE-130,X-720");
-        OlympusCameraTypes.put("D4311", "FE-140,X-725");
-        OlympusCameraTypes.put("D4312", "FE150,X730");
-        OlympusCameraTypes.put("D4313", "FE160,X735");
-        OlympusCameraTypes.put("D4314", "u740,S740");
-        OlympusCameraTypes.put("D4315", "u750,S750");
-        OlympusCameraTypes.put("D4316", "u730/S730");
-        OlympusCameraTypes.put("D4317", "FE115,X715");
-        OlympusCameraTypes.put("D4321", "SP550UZ");
-        OlympusCameraTypes.put("D4322", "SP510UZ");
-        OlympusCameraTypes.put("D4324", "FE170,X760");
-        OlympusCameraTypes.put("D4326", "FE200");
-        OlympusCameraTypes.put("D4327", "FE190/X750"); // (also SX876)
-        OlympusCameraTypes.put("D4328", "u760,S760");
-        OlympusCameraTypes.put("D4330", "FE180/X745"); // (also SX875)
-        OlympusCameraTypes.put("D4331", "u1000/S1000");
-        OlympusCameraTypes.put("D4332", "u770SW,S770SW");
-        OlympusCameraTypes.put("D4333", "FE240/X795");
-        OlympusCameraTypes.put("D4334", "FE210,X775");
-        OlympusCameraTypes.put("D4336", "FE230/X790");
-        OlympusCameraTypes.put("D4337", "FE220,X785");
-        OlympusCameraTypes.put("D4338", "u725SW,S725SW");
-        OlympusCameraTypes.put("D4339", "FE250/X800");
-        OlympusCameraTypes.put("D4341", "u780,S780");
-        OlympusCameraTypes.put("D4343", "u790SW,S790SW");
-        OlympusCameraTypes.put("D4344", "u1020,S1020");
-        OlympusCameraTypes.put("D4346", "FE15,X10");
-        OlympusCameraTypes.put("D4348", "FE280,X820,C520");
-        OlympusCameraTypes.put("D4349", "FE300,X830");
-        OlympusCameraTypes.put("D4350", "u820,S820");
-        OlympusCameraTypes.put("D4351", "u1200,S1200");
-        OlympusCameraTypes.put("D4352", "FE270,X815,C510");
-        OlympusCameraTypes.put("D4353", "u795SW,S795SW");
-        OlympusCameraTypes.put("D4354", "u1030SW,S1030SW");
-        OlympusCameraTypes.put("D4355", "SP560UZ");
-        OlympusCameraTypes.put("D4356", "u1010,S1010");
-        OlympusCameraTypes.put("D4357", "u830,S830");
-        OlympusCameraTypes.put("D4359", "u840,S840");
-        OlympusCameraTypes.put("D4360", "FE350WIDE,X865");
-        OlympusCameraTypes.put("D4361", "u850SW,S850SW");
-        OlympusCameraTypes.put("D4362", "FE340,X855,C560");
-        OlympusCameraTypes.put("D4363", "FE320,X835,C540");
-        OlympusCameraTypes.put("D4364", "SP570UZ");
-        OlympusCameraTypes.put("D4366", "FE330,X845,C550");
-        OlympusCameraTypes.put("D4368", "FE310,X840,C530");
-        OlympusCameraTypes.put("D4370", "u1050SW,S1050SW");
-        OlympusCameraTypes.put("D4371", "u1060,S1060");
-        OlympusCameraTypes.put("D4372", "FE370,X880,C575");
-        OlympusCameraTypes.put("D4374", "SP565UZ");
-        OlympusCameraTypes.put("D4377", "u1040,S1040");
-        OlympusCameraTypes.put("D4378", "FE360,X875,C570");
-        OlympusCameraTypes.put("D4379", "FE20,X15,C25");
-        OlympusCameraTypes.put("D4380", "uT6000,ST6000");
-        OlympusCameraTypes.put("D4381", "uT8000,ST8000");
-        OlympusCameraTypes.put("D4382", "u9000,S9000");
-        OlympusCameraTypes.put("D4384", "SP590UZ");
-        OlympusCameraTypes.put("D4385", "FE3010,X895");
-        OlympusCameraTypes.put("D4386", "FE3000,X890");
-        OlympusCameraTypes.put("D4387", "FE35,X30");
-        OlympusCameraTypes.put("D4388", "u550WP,S550WP");
-        OlympusCameraTypes.put("D4390", "FE5000,X905");
-        OlympusCameraTypes.put("D4391", "u5000");
-        OlympusCameraTypes.put("D4392", "u7000,S7000");
-        OlympusCameraTypes.put("D4396", "FE5010,X915");
-        OlympusCameraTypes.put("D4397", "FE25,X20");
-        OlympusCameraTypes.put("D4398", "FE45,X40");
-        OlympusCameraTypes.put("D4401", "XZ-1");
-        OlympusCameraTypes.put("D4402", "uT6010,ST6010");
-        OlympusCameraTypes.put("D4406", "u7010,S7010 / u7020,S7020");
-        OlympusCameraTypes.put("D4407", "FE4010,X930");
-        OlympusCameraTypes.put("D4408", "X560WP");
-        OlympusCameraTypes.put("D4409", "FE26,X21");
-        OlympusCameraTypes.put("D4410", "FE4000,X920,X925");
-        OlympusCameraTypes.put("D4411", "FE46,X41,X42");
-        OlympusCameraTypes.put("D4412", "FE5020,X935");
-        OlympusCameraTypes.put("D4413", "uTough-3000");
-        OlympusCameraTypes.put("D4414", "StylusTough-6020");
-        OlympusCameraTypes.put("D4415", "StylusTough-8010");
-        OlympusCameraTypes.put("D4417", "u5010,S5010");
-        OlympusCameraTypes.put("D4418", "u7040,S7040");
-        OlympusCameraTypes.put("D4419", "u9010,S9010");
-        OlympusCameraTypes.put("D4423", "FE4040");
-        OlympusCameraTypes.put("D4424", "FE47,X43");
-        OlympusCameraTypes.put("D4426", "FE4030,X950");
-        OlympusCameraTypes.put("D4428", "FE5030,X965,X960");
-        OlympusCameraTypes.put("D4430", "u7030,S7030");
-        OlympusCameraTypes.put("D4432", "SP600UZ");
-        OlympusCameraTypes.put("D4434", "SP800UZ");
-        OlympusCameraTypes.put("D4439", "FE4020,X940");
-        OlympusCameraTypes.put("D4442", "FE5035");
-        OlympusCameraTypes.put("D4448", "FE4050,X970");
-        OlympusCameraTypes.put("D4450", "FE5050,X985");
-        OlympusCameraTypes.put("D4454", "u-7050");
-        OlympusCameraTypes.put("D4464", "T10,X27");
-        OlympusCameraTypes.put("D4470", "FE5040,X980");
-        OlympusCameraTypes.put("D4472", "TG-310");
-        OlympusCameraTypes.put("D4474", "TG-610");
-        OlympusCameraTypes.put("D4476", "TG-810");
-        OlympusCameraTypes.put("D4478", "VG145,VG140,D715");
-        OlympusCameraTypes.put("D4479", "VG130,D710");
-        OlympusCameraTypes.put("D4480", "VG120,D705");
-        OlympusCameraTypes.put("D4482", "VR310,D720");
-        OlympusCameraTypes.put("D4484", "VR320,D725");
-        OlympusCameraTypes.put("D4486", "VR330,D730");
-        OlympusCameraTypes.put("D4488", "VG110,D700");
-        OlympusCameraTypes.put("D4490", "SP-610UZ");
-        OlympusCameraTypes.put("D4492", "SZ-10");
-        OlympusCameraTypes.put("D4494", "SZ-20");
-        OlympusCameraTypes.put("D4496", "SZ-30MR");
-        OlympusCameraTypes.put("D4498", "SP-810UZ");
-        OlympusCameraTypes.put("D4500", "SZ-11");
-        OlympusCameraTypes.put("D4504", "TG-615");
-        OlympusCameraTypes.put("D4508", "TG-620");
-        OlympusCameraTypes.put("D4510", "TG-820");
-        OlympusCameraTypes.put("D4512", "TG-1");
-        OlympusCameraTypes.put("D4516", "SH-21");
-        OlympusCameraTypes.put("D4519", "SZ-14");
-        OlympusCameraTypes.put("D4520", "SZ-31MR");
-        OlympusCameraTypes.put("D4521", "SH-25MR");
-        OlympusCameraTypes.put("D4523", "SP-720UZ");
-        OlympusCameraTypes.put("D4529", "VG170");
-        OlympusCameraTypes.put("D4531", "XZ-2");
-        OlympusCameraTypes.put("D4535", "SP-620UZ");
-        OlympusCameraTypes.put("D4536", "TG-320");
-        OlympusCameraTypes.put("D4537", "VR340,D750");
-        OlympusCameraTypes.put("D4538", "VG160,X990,D745");
-        OlympusCameraTypes.put("D4541", "SZ-12");
-        OlympusCameraTypes.put("D4545", "VH410");
-        OlympusCameraTypes.put("D4546", "XZ-10"); //IB
-        OlympusCameraTypes.put("D4547", "TG-2");
-        OlympusCameraTypes.put("D4548", "TG-830");
-        OlympusCameraTypes.put("D4549", "TG-630");
-        OlympusCameraTypes.put("D4550", "SH-50");
-        OlympusCameraTypes.put("D4553", "SZ-16,DZ-105");
-        OlympusCameraTypes.put("D4562", "SP-820UZ");
-        OlympusCameraTypes.put("D4566", "SZ-15");
-        OlympusCameraTypes.put("D4572", "STYLUS1");
-        OlympusCameraTypes.put("D4574", "TG-3");
-        OlympusCameraTypes.put("D4575", "TG-850");
-        OlympusCameraTypes.put("D4579", "SP-100EE");
-        OlympusCameraTypes.put("D4580", "SH-60");
-        OlympusCameraTypes.put("D4581", "SH-1");
-        OlympusCameraTypes.put("D4582", "TG-835");
-        OlympusCameraTypes.put("D4585", "SH-2 / SH-3");
-        OlympusCameraTypes.put("D4586", "TG-4");
-        OlympusCameraTypes.put("D4587", "TG-860");
-        OlympusCameraTypes.put("D4591", "TG-870");
-        OlympusCameraTypes.put("D4809", "C2500L");
-        OlympusCameraTypes.put("D4842", "E-10");
-        OlympusCameraTypes.put("D4856", "C-1");
-        OlympusCameraTypes.put("D4857", "C-1Z,D-150Z");
-        OlympusCameraTypes.put("DCHC", "D500L");
-        OlympusCameraTypes.put("DCHT", "D600L / D620L");
-        OlympusCameraTypes.put("K0055", "AIR-A01");
-        OlympusCameraTypes.put("S0003", "E-330");
-        OlympusCameraTypes.put("S0004", "E-500");
-        OlympusCameraTypes.put("S0009", "E-400");
-        OlympusCameraTypes.put("S0010", "E-510");
-        OlympusCameraTypes.put("S0011", "E-3");
-        OlympusCameraTypes.put("S0013", "E-410");
-        OlympusCameraTypes.put("S0016", "E-420");
-        OlympusCameraTypes.put("S0017", "E-30");
-        OlympusCameraTypes.put("S0018", "E-520");
-        OlympusCameraTypes.put("S0019", "E-P1");
-        OlympusCameraTypes.put("S0023", "E-620");
-        OlympusCameraTypes.put("S0026", "E-P2");
-        OlympusCameraTypes.put("S0027", "E-PL1");
-        OlympusCameraTypes.put("S0029", "E-450");
-        OlympusCameraTypes.put("S0030", "E-600");
-        OlympusCameraTypes.put("S0032", "E-P3");
-        OlympusCameraTypes.put("S0033", "E-5");
-        OlympusCameraTypes.put("S0034", "E-PL2");
-        OlympusCameraTypes.put("S0036", "E-M5");
-        OlympusCameraTypes.put("S0038", "E-PL3");
-        OlympusCameraTypes.put("S0039", "E-PM1");
-        OlympusCameraTypes.put("S0040", "E-PL1s");
-        OlympusCameraTypes.put("S0042", "E-PL5");
-        OlympusCameraTypes.put("S0043", "E-PM2");
-        OlympusCameraTypes.put("S0044", "E-P5");
-        OlympusCameraTypes.put("S0045", "E-PL6");
-        OlympusCameraTypes.put("S0046", "E-PL7"); //IB
-        OlympusCameraTypes.put("S0047", "E-M1");
-        OlympusCameraTypes.put("S0051", "E-M10");
-        OlympusCameraTypes.put("S0052", "E-M5MarkII"); //IB
-        OlympusCameraTypes.put("S0059", "E-M10MarkII");
-        OlympusCameraTypes.put("S0061", "PEN-F"); //forum7005
-        OlympusCameraTypes.put("S0065", "E-PL8");
-        OlympusCameraTypes.put("S0067", "E-M1MarkII");
-        OlympusCameraTypes.put("SR45", "D220");
-        OlympusCameraTypes.put("SR55", "D320L");
-        OlympusCameraTypes.put("SR83", "D340L");
-        OlympusCameraTypes.put("SR85", "C830L,D340R");
-        OlympusCameraTypes.put("SR852", "C860L,D360L");
-        OlympusCameraTypes.put("SR872", "C900Z,D400Z");
-        OlympusCameraTypes.put("SR874", "C960Z,D460Z");
-        OlympusCameraTypes.put("SR951", "C2000Z");
-        OlympusCameraTypes.put("SR952", "C21");
-        OlympusCameraTypes.put("SR953", "C21T.commu");
-        OlympusCameraTypes.put("SR954", "C2020Z");
-        OlympusCameraTypes.put("SR955", "C990Z,D490Z");
-        OlympusCameraTypes.put("SR956", "C211Z");
-        OlympusCameraTypes.put("SR959", "C990ZS,D490Z");
-        OlympusCameraTypes.put("SR95A", "C2100UZ");
-        OlympusCameraTypes.put("SR971", "C100,D370");
-        OlympusCameraTypes.put("SR973", "C2,D230");
-        OlympusCameraTypes.put("SX151", "E100RS");
-        OlympusCameraTypes.put("SX351", "C3000Z / C3030Z");
-        OlympusCameraTypes.put("SX354", "C3040Z");
-        OlympusCameraTypes.put("SX355", "C2040Z");
-        OlympusCameraTypes.put("SX357", "C700UZ");
-        OlympusCameraTypes.put("SX358", "C200Z,D510Z");
-        OlympusCameraTypes.put("SX374", "C3100Z,C3020Z");
-        OlympusCameraTypes.put("SX552", "C4040Z");
-        OlympusCameraTypes.put("SX553", "C40Z,D40Z");
-        OlympusCameraTypes.put("SX556", "C730UZ");
-        OlympusCameraTypes.put("SX558", "C5050Z");
-        OlympusCameraTypes.put("SX571", "C120,D380");
-        OlympusCameraTypes.put("SX574", "C300Z,D550Z");
-        OlympusCameraTypes.put("SX575", "C4100Z,C4000Z");
-        OlympusCameraTypes.put("SX751", "X200,D560Z,C350Z");
-        OlympusCameraTypes.put("SX752", "X300,D565Z,C450Z");
-        OlympusCameraTypes.put("SX753", "C750UZ");
-        OlympusCameraTypes.put("SX754", "C740UZ");
-        OlympusCameraTypes.put("SX755", "C755UZ");
-        OlympusCameraTypes.put("SX756", "C5060WZ");
-        OlympusCameraTypes.put("SX757", "C8080WZ");
-        OlympusCameraTypes.put("SX758", "X350,D575Z,C360Z");
-        OlympusCameraTypes.put("SX759", "X400,D580Z,C460Z");
-        OlympusCameraTypes.put("SX75A", "AZ-2ZOOM");
-        OlympusCameraTypes.put("SX75B", "D595Z,C500Z");
-        OlympusCameraTypes.put("SX75C", "X550,D545Z,C480Z");
-        OlympusCameraTypes.put("SX75D", "IR-300");
-        OlympusCameraTypes.put("SX75F", "C55Z,C5500Z");
-        OlympusCameraTypes.put("SX75G", "C170,D425");
-        OlympusCameraTypes.put("SX75J", "C180,D435");
-        OlympusCameraTypes.put("SX771", "C760UZ");
-        OlympusCameraTypes.put("SX772", "C770UZ");
-        OlympusCameraTypes.put("SX773", "C745UZ");
-        OlympusCameraTypes.put("SX774", "X250,D560Z,C350Z");
-        OlympusCameraTypes.put("SX775", "X100,D540Z,C310Z");
-        OlympusCameraTypes.put("SX776", "C460ZdelSol");
-        OlympusCameraTypes.put("SX777", "C765UZ");
-        OlympusCameraTypes.put("SX77A", "D555Z,C315Z");
-        OlympusCameraTypes.put("SX851", "C7070WZ");
-        OlympusCameraTypes.put("SX852", "C70Z,C7000Z");
-        OlympusCameraTypes.put("SX853", "SP500UZ");
-        OlympusCameraTypes.put("SX854", "SP310");
-        OlympusCameraTypes.put("SX855", "SP350");
-        OlympusCameraTypes.put("SX873", "SP320");
-        OlympusCameraTypes.put("SX875", "FE180/X745"); // (also D4330)
-        OlympusCameraTypes.put("SX876", "FE190/X750"); // (also D4327)
-
-        //   other brands
-        //    4MP9Q3", "Camera 4MP-9Q3'
-        //    4MP9T2", "BenQ DC C420 / Camera 4MP-9T2'
-        //    5MP9Q3", "Camera 5MP-9Q3" },
-        //    5MP9X9", "Camera 5MP-9X9" },
-        //   '5MP-9T'=> 'Camera 5MP-9T3" },
-        //   '5MP-9Y'=> 'Camera 5MP-9Y2" },
-        //   '6MP-9U'=> 'Camera 6MP-9U9" },
-        //    7MP9Q3", "Camera 7MP-9Q3" },
-        //   '8MP-9U'=> 'Camera 8MP-9U4" },
-        //    CE5330", "Acer CE-5330" },
-        //   'CP-853'=> 'Acer CP-8531" },
-        //    CS5531", "Acer CS5531" },
-        //    DC500 ", "SeaLife DC500" },
-        //    DC7370", "Camera 7MP-9GA" },
-        //    DC7371", "Camera 7MP-9GM" },
-        //    DC7371", "Hitachi HDC-751E" },
-        //    DC7375", "Hitachi HDC-763E / Rollei RCP-7330X / Ricoh Caplio RR770 / Vivitar ViviCam 7330" },
-        //   'DC E63'=> 'BenQ DC E63+" },
-        //   'DC P86'=> 'BenQ DC P860" },
-        //    DS5340", "Maginon Performic S5 / Premier 5MP-9M7" },
-        //    DS5341", "BenQ E53+ / Supra TCM X50 / Maginon X50 / Premier 5MP-9P8" },
-        //    DS5346", "Premier 5MP-9Q2" },
-        //    E500  ", "Konica Minolta DiMAGE E500" },
-        //    MAGINO", "Maginon X60" },
-        //    Mz60  ", "HP Photosmart Mz60" },
-        //    Q3DIGI", "Camera 5MP-9Q3" },
-        //    SLIMLI", "Supra Slimline X6" },
-        //    V8300s", "Vivitar V8300s" },
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/OlympusRawDevelopment2MakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/OlympusRawDevelopment2MakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,234 +1,0 @@
-/*
- * Copyright 2002-2015 Drew Noakes
- *
- *    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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import java.util.HashMap;
-
-import static com.drew.metadata.exif.makernotes.OlympusRawDevelopment2MakernoteDirectory.*;
-
-/**
- * Provides human-readable String representations of tag values stored in a {@link OlympusRawDevelopment2MakernoteDirectory}.
- * <p>
- * Some Description functions converted from Exiftool version 10.10 created by Phil Harvey
- * http://www.sno.phy.queensu.ca/~phil/exiftool/
- * lib\Image\ExifTool\Olympus.pm
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class OlympusRawDevelopment2MakernoteDescriptor extends TagDescriptor<OlympusRawDevelopment2MakernoteDirectory>
-{
-    public OlympusRawDevelopment2MakernoteDescriptor(@NotNull OlympusRawDevelopment2MakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TagRawDevVersion:
-                return getRawDevVersionDescription();
-            case TagRawDevExposureBiasValue:
-                return getRawDevExposureBiasValueDescription();
-            case TagRawDevColorSpace:
-                return getRawDevColorSpaceDescription();
-            case TagRawDevNoiseReduction:
-                return getRawDevNoiseReductionDescription();
-            case TagRawDevEngine:
-                return getRawDevEngineDescription();
-            case TagRawDevPictureMode:
-                return getRawDevPictureModeDescription();
-            case TagRawDevPmBwFilter:
-                return getRawDevPmBwFilterDescription();
-            case TagRawDevPmPictureTone:
-                return getRawDevPmPictureToneDescription();
-            case TagRawDevArtFilter:
-                return getRawDevArtFilterDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getRawDevVersionDescription()
-    {
-        return getVersionBytesDescription(TagRawDevVersion, 4);
-    }
-
-    @Nullable
-    public String getRawDevExposureBiasValueDescription()
-    {
-        return getIndexedDescription(TagRawDevExposureBiasValue,
-                1, "Color Temperature", "Gray Point");
-    }
-
-    @Nullable
-    public String getRawDevColorSpaceDescription()
-    {
-        return getIndexedDescription(TagRawDevColorSpace,
-            "sRGB", "Adobe RGB", "Pro Photo RGB");
-    }
-
-    @Nullable
-    public String getRawDevNoiseReductionDescription()
-    {
-        Integer value = _directory.getInteger(TagRawDevNoiseReduction);
-        if (value == null)
-            return null;
-
-        if (value == 0)
-            return "(none)";
-
-        StringBuilder sb = new StringBuilder();
-        int v = value;
-
-        if ((v        & 1) != 0) sb.append("Noise Reduction, ");
-        if (((v >> 1) & 1) != 0) sb.append("Noise Filter, ");
-        if (((v >> 2) & 1) != 0) sb.append("Noise Filter (ISO Boost), ");
-        if (((v >> 3) & 1) != 0) sb.append("Noise Filter (Auto), ");
-        
-        if (sb.length() > 2) {
-            sb.delete(sb.length() - 2, sb.length());
-        }
-        return sb.toString();
-    }
-
-    @Nullable
-    public String getRawDevEngineDescription()
-    {
-        return getIndexedDescription(TagRawDevEngine,
-            "High Speed", "High Function", "Advanced High Speed", "Advanced High Function");
-    }
-
-    @Nullable
-    public String getRawDevPictureModeDescription()
-    {
-        Integer value = _directory.getInteger(TagRawDevPictureMode);
-        if (value == null)
-            return null;
-
-        switch (value)
-        {
-            case 1:
-                return "Vivid";
-            case 2:
-                return "Natural";
-            case 3:
-                return "Muted";
-            case 256:
-                return "Monotone";
-            case 512:
-                return "Sepia";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getRawDevPmBwFilterDescription()
-    {
-        return getIndexedDescription(TagRawDevPmBwFilter,
-            "Neutral", "Yellow", "Orange", "Red", "Green");
-    }
-
-    @Nullable
-    public String getRawDevPmPictureToneDescription()
-    {
-        return getIndexedDescription(TagRawDevPmPictureTone,
-            "Neutral", "Sepia", "Blue", "Purple", "Green");
-    }
-
-    @Nullable
-    public String getRawDevArtFilterDescription()
-    {
-        return getFilterDescription(TagRawDevArtFilter);
-    }
-
-    @Nullable
-    public String getFilterDescription(int tag)
-    {
-        int[] values = _directory.getIntArray(tag);
-        if (values == null || values.length == 0)
-            return null;
-
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < values.length; i++) {
-            if (i == 0)
-                sb.append(_filters.containsKey(values[i]) ? _filters.get(values[i]) : "[unknown]");
-            else
-                sb.append(values[i]).append("; ");
-            sb.append("; ");
-        }
-
-        return sb.substring(0, sb.length() - 2);
-    }
-
-    // RawDevArtFilter values
-    private static final HashMap<Integer, String> _filters = new HashMap<Integer, String>();
-
-    static {
-        _filters.put(0, "Off");
-        _filters.put(1, "Soft Focus");
-        _filters.put(2, "Pop Art");
-        _filters.put(3, "Pale & Light Color");
-        _filters.put(4, "Light Tone");
-        _filters.put(5, "Pin Hole");
-        _filters.put(6, "Grainy Film");
-        _filters.put(9, "Diorama");
-        _filters.put(10, "Cross Process");
-        _filters.put(12, "Fish Eye");
-        _filters.put(13, "Drawing");
-        _filters.put(14, "Gentle Sepia");
-        _filters.put(15, "Pale & Light Color II");
-        _filters.put(16, "Pop Art II");
-        _filters.put(17, "Pin Hole II");
-        _filters.put(18, "Pin Hole III");
-        _filters.put(19, "Grainy Film II");
-        _filters.put(20, "Dramatic Tone");
-        _filters.put(21, "Punk");
-        _filters.put(22, "Soft Focus 2");
-        _filters.put(23, "Sparkle");
-        _filters.put(24, "Watercolor");
-        _filters.put(25, "Key Line");
-        _filters.put(26, "Key Line II");
-        _filters.put(27, "Miniature");
-        _filters.put(28, "Reflection");
-        _filters.put(29, "Fragmented");
-        _filters.put(31, "Cross Process II");
-        _filters.put(32, "Dramatic Tone II");
-        _filters.put(33, "Watercolor I");
-        _filters.put(34, "Watercolor II");
-        _filters.put(35, "Diorama II");
-        _filters.put(36, "Vintage");
-        _filters.put(37, "Vintage II");
-        _filters.put(38, "Vintage III");
-        _filters.put(39, "Partial Color");
-        _filters.put(40, "Partial Color II");
-        _filters.put(41, "Partial Color III");
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/OlympusRawDevelopment2MakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/OlympusRawDevelopment2MakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,111 +1,0 @@
-/*
- * Copyright 2002-2015 Drew Noakes
- *
- *    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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * The Olympus raw development 2 makernote is used by many manufacturers (Epson, Konica, Minolta and Agfa...), and as such contains some tags
- * that appear specific to those manufacturers.
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class OlympusRawDevelopment2MakernoteDirectory extends Directory
-{    
-    public static final int TagRawDevVersion = 0x0000;
-    public static final int TagRawDevExposureBiasValue = 0x0100;
-    public static final int TagRawDevWhiteBalance = 0x0101;
-    public static final int TagRawDevWhiteBalanceValue = 0x0102;
-    public static final int TagRawDevWbFineAdjustment = 0x0103;
-    public static final int TagRawDevGrayPoint = 0x0104;
-    public static final int TagRawDevContrastValue = 0x0105;
-    public static final int TagRawDevSharpnessValue = 0x0106;
-    public static final int TagRawDevSaturationEmphasis = 0x0107;
-    public static final int TagRawDevMemoryColorEmphasis = 0x0108;
-    public static final int TagRawDevColorSpace = 0x0109;
-    public static final int TagRawDevNoiseReduction = 0x010a;
-    public static final int TagRawDevEngine = 0x010b;
-    public static final int TagRawDevPictureMode = 0x010c;
-    public static final int TagRawDevPmSaturation = 0x010d;
-    public static final int TagRawDevPmContrast = 0x010e;
-    public static final int TagRawDevPmSharpness = 0x010f;
-    public static final int TagRawDevPmBwFilter = 0x0110;
-    public static final int TagRawDevPmPictureTone = 0x0111;
-    public static final int TagRawDevGradation = 0x0112;
-    public static final int TagRawDevSaturation3 = 0x0113;
-    public static final int TagRawDevAutoGradation = 0x0119;
-    public static final int TagRawDevPmNoiseFilter = 0x0120;
-    public static final int TagRawDevArtFilter = 0x0121;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static {        
-        _tagNameMap.put(TagRawDevVersion, "Raw Dev Version");
-        _tagNameMap.put(TagRawDevExposureBiasValue, "Raw Dev Exposure Bias Value");
-        _tagNameMap.put(TagRawDevWhiteBalance, "Raw Dev White Balance");
-        _tagNameMap.put(TagRawDevWhiteBalanceValue, "Raw Dev White Balance Value");
-        _tagNameMap.put(TagRawDevWbFineAdjustment, "Raw Dev WB Fine Adjustment");
-        _tagNameMap.put(TagRawDevGrayPoint, "Raw Dev Gray Point");
-        _tagNameMap.put(TagRawDevContrastValue, "Raw Dev Contrast Value");
-        _tagNameMap.put(TagRawDevSharpnessValue, "Raw Dev Sharpness Value");
-        _tagNameMap.put(TagRawDevSaturationEmphasis, "Raw Dev Saturation Emphasis");
-        _tagNameMap.put(TagRawDevMemoryColorEmphasis, "Raw Dev Memory Color Emphasis");
-        _tagNameMap.put(TagRawDevColorSpace, "Raw Dev Color Space");
-        _tagNameMap.put(TagRawDevNoiseReduction, "Raw Dev Noise Reduction");
-        _tagNameMap.put(TagRawDevEngine, "Raw Dev Engine");
-        _tagNameMap.put(TagRawDevPictureMode, "Raw Dev Picture Mode");
-        _tagNameMap.put(TagRawDevPmSaturation, "Raw Dev PM Saturation");
-        _tagNameMap.put(TagRawDevPmContrast, "Raw Dev PM Contrast");
-        _tagNameMap.put(TagRawDevPmSharpness, "Raw Dev PM Sharpness");
-        _tagNameMap.put(TagRawDevPmBwFilter, "Raw Dev PM BW Filter");
-        _tagNameMap.put(TagRawDevPmPictureTone, "Raw Dev PM Picture Tone");
-        _tagNameMap.put(TagRawDevGradation, "Raw Dev Gradation");
-        _tagNameMap.put(TagRawDevSaturation3, "Raw Dev Saturation 3");
-        _tagNameMap.put(TagRawDevAutoGradation, "Raw Dev Auto Gradation");
-        _tagNameMap.put(TagRawDevPmNoiseFilter, "Raw Dev PM Noise Filter");
-        _tagNameMap.put(TagRawDevArtFilter, "Raw Dev Art Filter");
-    }
-
-    public OlympusRawDevelopment2MakernoteDirectory()
-    {
-        this.setDescriptor(new OlympusRawDevelopment2MakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Olympus Raw Development 2";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/OlympusRawDevelopmentMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/OlympusRawDevelopmentMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,155 +1,0 @@
-/*
- * Copyright 2002-2015 Drew Noakes
- *
- *    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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.makernotes.OlympusRawDevelopmentMakernoteDirectory.*;
-
-/**
- * Provides human-readable String representations of tag values stored in a {@link OlympusRawDevelopmentMakernoteDirectory}.
- * <p>
- * Some Description functions converted from Exiftool version 10.10 created by Phil Harvey
- * http://www.sno.phy.queensu.ca/~phil/exiftool/
- * lib\Image\ExifTool\Olympus.pm
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class OlympusRawDevelopmentMakernoteDescriptor extends TagDescriptor<OlympusRawDevelopmentMakernoteDirectory>
-{
-    public OlympusRawDevelopmentMakernoteDescriptor(@NotNull OlympusRawDevelopmentMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TagRawDevVersion:
-                return getRawDevVersionDescription();
-            case TagRawDevColorSpace:
-                return getRawDevColorSpaceDescription();
-            case TagRawDevEngine:
-                return getRawDevEngineDescription();
-            case TagRawDevNoiseReduction:
-                return getRawDevNoiseReductionDescription();
-            case TagRawDevEditStatus:
-                return getRawDevEditStatusDescription();
-            case TagRawDevSettings:
-                return getRawDevSettingsDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getRawDevVersionDescription()
-    {
-        return getVersionBytesDescription(TagRawDevVersion, 4);
-    }
-
-    @Nullable
-    public String getRawDevColorSpaceDescription()
-    {
-        return getIndexedDescription(TagRawDevColorSpace,
-            "sRGB", "Adobe RGB", "Pro Photo RGB");
-    }
-
-    @Nullable
-    public String getRawDevEngineDescription()
-    {
-        return getIndexedDescription(TagRawDevEngine,
-            "High Speed", "High Function", "Advanced High Speed", "Advanced High Function");
-    }
-
-    @Nullable
-    public String getRawDevNoiseReductionDescription()
-    {
-        Integer value = _directory.getInteger(TagRawDevNoiseReduction);
-        if (value == null)
-            return null;
-
-        if (value == 0)
-            return "(none)";
-
-        StringBuilder sb = new StringBuilder();
-        int v = value;
-
-        if ((v        & 1) != 0) sb.append("Noise Reduction, ");
-        if (((v >> 1) & 1) != 0) sb.append("Noise Filter, ");
-        if (((v >> 2) & 1) != 0) sb.append("Noise Filter (ISO Boost), ");
-
-        return sb.substring(0, sb.length() - 2);
-    }
-
-    @Nullable
-    public String getRawDevEditStatusDescription()
-    {
-        Integer value = _directory.getInteger(TagRawDevEditStatus);
-        if (value == null)
-            return null;
-
-        switch (value)
-        {
-            case 0:
-                return "Original";
-            case 1:
-                return "Edited (Landscape)";
-            case 6:
-            case 8:
-                return "Edited (Portrait)";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getRawDevSettingsDescription()
-    {
-        Integer value = _directory.getInteger(TagRawDevSettings);
-        if (value == null)
-            return null;
-
-        if (value == 0)
-            return "(none)";
-
-        StringBuilder sb = new StringBuilder();
-        int v = value;
-
-        if ((v        & 1) != 0) sb.append("WB Color Temp, ");
-        if (((v >> 1) & 1) != 0) sb.append("WB Gray Point, ");
-        if (((v >> 2) & 1) != 0) sb.append("Saturation, ");
-        if (((v >> 3) & 1) != 0) sb.append("Contrast, ");
-        if (((v >> 4) & 1) != 0) sb.append("Sharpness, ");
-        if (((v >> 5) & 1) != 0) sb.append("Color Space, ");
-        if (((v >> 6) & 1) != 0) sb.append("High Function, ");
-        if (((v >> 7) & 1) != 0) sb.append("Noise Reduction, ");
-
-        return sb.substring(0, sb.length() - 2);
-    }
-
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/OlympusRawDevelopmentMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/OlympusRawDevelopmentMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,91 +1,0 @@
-/*
- * Copyright 2002-2015 Drew Noakes
- *
- *    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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * The Olympus raw development makernote is used by many manufacturers (Epson, Konica, Minolta and Agfa...), and as such contains some tags
- * that appear specific to those manufacturers.
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class OlympusRawDevelopmentMakernoteDirectory extends Directory
-{
-    public static final int TagRawDevVersion = 0x0000;
-    public static final int TagRawDevExposureBiasValue = 0x0100;
-    public static final int TagRawDevWhiteBalanceValue = 0x0101;
-    public static final int TagRawDevWbFineAdjustment = 0x0102;
-    public static final int TagRawDevGrayPoint = 0x0103;
-    public static final int TagRawDevSaturationEmphasis = 0x0104;
-    public static final int TagRawDevMemoryColorEmphasis = 0x0105;
-    public static final int TagRawDevContrastValue = 0x0106;
-    public static final int TagRawDevSharpnessValue = 0x0107;
-    public static final int TagRawDevColorSpace = 0x0108;
-    public static final int TagRawDevEngine = 0x0109;
-    public static final int TagRawDevNoiseReduction = 0x010a;
-    public static final int TagRawDevEditStatus = 0x010b;
-    public static final int TagRawDevSettings = 0x010c;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static {
-        _tagNameMap.put(TagRawDevVersion, "Raw Dev Version");
-        _tagNameMap.put(TagRawDevExposureBiasValue, "Raw Dev Exposure Bias Value");
-        _tagNameMap.put(TagRawDevWhiteBalanceValue, "Raw Dev White Balance Value");
-        _tagNameMap.put(TagRawDevWbFineAdjustment, "Raw Dev WB Fine Adjustment");
-        _tagNameMap.put(TagRawDevGrayPoint, "Raw Dev Gray Point");
-        _tagNameMap.put(TagRawDevSaturationEmphasis, "Raw Dev Saturation Emphasis");
-        _tagNameMap.put(TagRawDevMemoryColorEmphasis, "Raw Dev Memory Color Emphasis");
-        _tagNameMap.put(TagRawDevContrastValue, "Raw Dev Contrast Value");
-        _tagNameMap.put(TagRawDevSharpnessValue, "Raw Dev Sharpness Value");
-        _tagNameMap.put(TagRawDevColorSpace, "Raw Dev Color Space");
-        _tagNameMap.put(TagRawDevEngine, "Raw Dev Engine");
-        _tagNameMap.put(TagRawDevNoiseReduction, "Raw Dev Noise Reduction");
-        _tagNameMap.put(TagRawDevEditStatus, "Raw Dev Edit Status");
-        _tagNameMap.put(TagRawDevSettings, "Raw Dev Settings");
-    }
-
-    public OlympusRawDevelopmentMakernoteDirectory()
-    {
-        this.setDescriptor(new OlympusRawDevelopmentMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Olympus Raw Development";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/OlympusRawInfoMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/OlympusRawInfoMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,141 +1,0 @@
-/*
- * Copyright 2002-2015 Drew Noakes
- *
- *    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
- *
- *        http://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.Rational;
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.makernotes.OlympusRawInfoMakernoteDirectory.*;
-
-/**
- * Provides human-readable String representations of tag values stored in a {@link OlympusRawInfoMakernoteDirectory}.
- * <p>
- * Some Description functions converted from Exiftool version 10.33 created by Phil Harvey
- * http://www.sno.phy.queensu.ca/~phil/exiftool/
- * lib\Image\ExifTool\Olympus.pm
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class OlympusRawInfoMakernoteDescriptor extends TagDescriptor<OlympusRawInfoMakernoteDirectory>
-{
-    public OlympusRawInfoMakernoteDescriptor(@NotNull OlympusRawInfoMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TagRawInfoVersion:
-                return getVersionBytesDescription(TagRawInfoVersion, 4);
-            case TagColorMatrix2:
-                return getColorMatrix2Description();
-            case TagYCbCrCoefficients:
-                return getYCbCrCoefficientsDescription();
-            case TagLightSource:
-                return getOlympusLightSourceDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getColorMatrix2Description()
-    {
-        int[] values = _directory.getIntArray(TagColorMatrix2);
-        if (values == null)
-            return null;
-
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < values.length; i++) {
-            sb.append((short)values[i]);
-            if (i < values.length - 1)
-                sb.append(" ");
-        }
-        return sb.length() == 0 ? null : sb.toString();
-    }
-
-    @Nullable
-    public String getYCbCrCoefficientsDescription()
-    {
-        int[] values = _directory.getIntArray(TagYCbCrCoefficients);
-        if (values == null)
-            return null;
-
-        Rational[] ret = new Rational[values.length / 2];
-        for(int i = 0; i < values.length / 2; i++)
-        {
-            ret[i] = new Rational((short)values[2*i], (short)values[2*i + 1]);
-        }
-
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < ret.length; i++) {
-            sb.append(ret[i].doubleValue());
-            if (i < ret.length - 1)
-                sb.append(" ");
-        }
-        return sb.length() == 0 ? null : sb.toString();
-    }
-    
-    @Nullable
-    public String getOlympusLightSourceDescription()
-    {
-        Integer value = _directory.getInteger(TagLightSource);
-        if (value == null)
-            return null;
-
-        switch (value.shortValue())
-        {
-            case 0:
-                return "Unknown";
-            case 16:
-                return "Shade";
-            case 17:
-                return "Cloudy";
-            case 18:
-                return "Fine Weather";
-            case 20:
-                return "Tungsten (Incandescent)";
-            case 22:
-                return "Evening Sunlight";
-            case 33:
-                return "Daylight Fluorescent";
-            case 34:
-                return "Day White Fluorescent";
-            case 35:
-                return "Cool White Fluorescent";
-            case 36:
-                return "White Fluorescent";
-            case 256:
-                return "One Touch White Balance";
-            case 512:
-                return "Custom 1-4";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/OlympusRawInfoMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/OlympusRawInfoMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,142 +1,0 @@
-/*
- * Copyright 2002-2015 Drew Noakes
- *
- *    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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * These tags are found only in ORF images of some models (eg. C8080WZ)
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class OlympusRawInfoMakernoteDirectory extends Directory
-{
-    public static final int TagRawInfoVersion = 0x0000;
-    public static final int TagWbRbLevelsUsed = 0x0100;
-    public static final int TagWbRbLevelsAuto = 0x0110;
-    public static final int TagWbRbLevelsShade = 0x0120;
-    public static final int TagWbRbLevelsCloudy = 0x0121;
-    public static final int TagWbRbLevelsFineWeather = 0x0122;
-    public static final int TagWbRbLevelsTungsten = 0x0123;
-    public static final int TagWbRbLevelsEveningSunlight = 0x0124;
-    public static final int TagWbRbLevelsDaylightFluor = 0x0130;
-    public static final int TagWbRbLevelsDayWhiteFluor = 0x0131;
-    public static final int TagWbRbLevelsCoolWhiteFluor = 0x0132;
-    public static final int TagWbRbLevelsWhiteFluorescent = 0x0133;
-
-    public static final int TagColorMatrix2 = 0x0200;
-    public static final int TagCoringFilter = 0x0310;
-    public static final int TagCoringValues = 0x0311;
-    public static final int TagBlackLevel2 = 0x0600;
-    public static final int TagYCbCrCoefficients = 0x0601;
-    public static final int TagValidPixelDepth = 0x0611;
-    public static final int TagCropLeft = 0x0612;
-    public static final int TagCropTop = 0x0613;
-    public static final int TagCropWidth = 0x0614;
-    public static final int TagCropHeight = 0x0615;
-
-    public static final int TagLightSource = 0x1000;
-
-    //the following 5 tags all have 3 values: val, min, max
-    public static final int TagWhiteBalanceComp = 0x1001;
-    public static final int TagSaturationSetting = 0x1010;
-    public static final int TagHueSetting = 0x1011;
-    public static final int TagContrastSetting = 0x1012;
-    public static final int TagSharpnessSetting = 0x1013;
-
-    // settings written by Camedia Master 4.x
-    public static final int TagCmExposureCompensation = 0x2000;
-    public static final int TagCmWhiteBalance = 0x2001;
-    public static final int TagCmWhiteBalanceComp = 0x2002;
-    public static final int TagCmWhiteBalanceGrayPoint = 0x2010;
-    public static final int TagCmSaturation = 0x2020;
-    public static final int TagCmHue = 0x2021;
-    public static final int TagCmContrast = 0x2022;
-    public static final int TagCmSharpness = 0x2023;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static {
-        _tagNameMap.put(TagRawInfoVersion, "Raw Info Version");
-        _tagNameMap.put(TagWbRbLevelsUsed, "WB RB Levels Used");
-        _tagNameMap.put(TagWbRbLevelsAuto, "WB RB Levels Auto");
-        _tagNameMap.put(TagWbRbLevelsShade, "WB RB Levels Shade");
-        _tagNameMap.put(TagWbRbLevelsCloudy, "WB RB Levels Cloudy");
-        _tagNameMap.put(TagWbRbLevelsFineWeather, "WB RB Levels Fine Weather");
-        _tagNameMap.put(TagWbRbLevelsTungsten, "WB RB Levels Tungsten");
-        _tagNameMap.put(TagWbRbLevelsEveningSunlight, "WB RB Levels Evening Sunlight");
-        _tagNameMap.put(TagWbRbLevelsDaylightFluor, "WB RB Levels Daylight Fluor");
-        _tagNameMap.put(TagWbRbLevelsDayWhiteFluor, "WB RB Levels Day White Fluor");
-        _tagNameMap.put(TagWbRbLevelsCoolWhiteFluor, "WB RB Levels Cool White Fluor");
-        _tagNameMap.put(TagWbRbLevelsWhiteFluorescent, "WB RB Levels White Fluorescent");
-        _tagNameMap.put(TagColorMatrix2, "Color Matrix 2");
-        _tagNameMap.put(TagCoringFilter, "Coring Filter");
-        _tagNameMap.put(TagCoringValues, "Coring Values");
-        _tagNameMap.put(TagBlackLevel2, "Black Level 2");
-        _tagNameMap.put(TagYCbCrCoefficients, "YCbCrCoefficients");
-        _tagNameMap.put(TagValidPixelDepth, "Valid Pixel Depth");
-        _tagNameMap.put(TagCropLeft, "Crop Left");
-        _tagNameMap.put(TagCropTop, "Crop Top");
-        _tagNameMap.put(TagCropWidth, "Crop Width");
-        _tagNameMap.put(TagCropHeight, "Crop Height");
-        _tagNameMap.put(TagLightSource, "Light Source");
-
-        _tagNameMap.put(TagWhiteBalanceComp, "White Balance Comp");
-        _tagNameMap.put(TagSaturationSetting, "Saturation Setting");
-        _tagNameMap.put(TagHueSetting, "Hue Setting");
-        _tagNameMap.put(TagContrastSetting, "Contrast Setting");
-        _tagNameMap.put(TagSharpnessSetting, "Sharpness Setting");
-
-        _tagNameMap.put(TagCmExposureCompensation, "CM Exposure Compensation");
-        _tagNameMap.put(TagCmWhiteBalance, "CM White Balance");
-        _tagNameMap.put(TagCmWhiteBalanceComp, "CM White Balance Comp");
-        _tagNameMap.put(TagCmWhiteBalanceGrayPoint, "CM White Balance Gray Point");
-        _tagNameMap.put(TagCmSaturation, "CM Saturation");
-        _tagNameMap.put(TagCmHue, "CM Hue");
-        _tagNameMap.put(TagCmContrast, "CM Contrast");
-        _tagNameMap.put(TagCmSharpness, "CM Sharpness");
-    }
-
-    public OlympusRawInfoMakernoteDirectory()
-    {
-        this.setDescriptor(new OlympusRawInfoMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Olympus Raw Info";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/PanasonicMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/PanasonicMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,921 +1,0 @@
-/*
- * 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
- *
- *        http://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.ByteArrayReader;
-import com.drew.lang.Charsets;
-import com.drew.lang.RandomAccessReader;
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.Age;
-import com.drew.metadata.Face;
-import com.drew.metadata.TagDescriptor;
-
-import java.text.DecimalFormat;
-import java.io.IOException;
-
-import static com.drew.metadata.exif.makernotes.PanasonicMakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link PanasonicMakernoteDirectory}.
- * <p>
- * Some information about this makernote taken from here:
- * <ul>
- * <li><a href="http://www.ozhiker.com/electronics/pjmt/jpeg_info/panasonic_mn.html">http://www.ozhiker.com/electronics/pjmt/jpeg_info/panasonic_mn.html</a></li>
- * <li><a href="http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Panasonic.html">http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Panasonic.html</a></li>
- * </ul>
- *
- * @author Drew Noakes https://drewnoakes.com
- * @author Philipp Sandhaus
- */
-@SuppressWarnings("WeakerAccess")
-public class PanasonicMakernoteDescriptor extends TagDescriptor<PanasonicMakernoteDirectory>
-{
-    public PanasonicMakernoteDescriptor(@NotNull PanasonicMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_QUALITY_MODE:
-                return getQualityModeDescription();
-            case TAG_FIRMWARE_VERSION:
-                return getVersionDescription();
-            case TAG_WHITE_BALANCE:
-                return getWhiteBalanceDescription();
-            case TAG_FOCUS_MODE:
-                return getFocusModeDescription();
-            case TAG_AF_AREA_MODE:
-                return getAfAreaModeDescription();
-            case TAG_IMAGE_STABILIZATION:
-                return getImageStabilizationDescription();
-            case TAG_MACRO_MODE:
-                return getMacroModeDescription();
-            case TAG_RECORD_MODE:
-                return getRecordModeDescription();
-            case TAG_AUDIO:
-                return getAudioDescription();
-            case TAG_UNKNOWN_DATA_DUMP:
-                return getUnknownDataDumpDescription();
-            case TAG_COLOR_EFFECT:
-                return getColorEffectDescription();
-            case TAG_UPTIME:
-                return getUptimeDescription();
-            case TAG_BURST_MODE:
-                return getBurstModeDescription();
-            case TAG_CONTRAST_MODE:
-                return getContrastModeDescription();
-            case TAG_NOISE_REDUCTION:
-                return getNoiseReductionDescription();
-            case TAG_SELF_TIMER:
-                return getSelfTimerDescription();
-            case TAG_ROTATION:
-                return getRotationDescription();
-            case TAG_AF_ASSIST_LAMP:
-                return getAfAssistLampDescription();
-            case TAG_COLOR_MODE:
-                return getColorModeDescription();
-            case TAG_OPTICAL_ZOOM_MODE:
-                return getOpticalZoomModeDescription();
-            case TAG_CONVERSION_LENS:
-                return getConversionLensDescription();
-            case TAG_CONTRAST:
-                return getContrastDescription();
-            case TAG_WORLD_TIME_LOCATION:
-                return getWorldTimeLocationDescription();
-            case TAG_ADVANCED_SCENE_MODE:
-                return getAdvancedSceneModeDescription();
-            case TAG_FACE_DETECTION_INFO:
-                return getDetectedFacesDescription();
-            case TAG_TRANSFORM:
-                return getTransformDescription();
-            case TAG_TRANSFORM_1:
-                return getTransform1Description();
-            case TAG_INTELLIGENT_EXPOSURE:
-                return getIntelligentExposureDescription();
-            case TAG_FLASH_WARNING:
-                return getFlashWarningDescription();
-            case TAG_COUNTRY:
-                return getCountryDescription();
-            case TAG_STATE:
-                return getStateDescription();
-            case TAG_CITY:
-                return getCityDescription();
-            case TAG_LANDMARK:
-                return getLandmarkDescription();
-            case TAG_INTELLIGENT_RESOLUTION:
-                return getIntelligentResolutionDescription();
-            case TAG_FACE_RECOGNITION_INFO:
-                return getRecognizedFacesDescription();
-            case TAG_SCENE_MODE:
-                return getSceneModeDescription();
-            case TAG_FLASH_FIRED:
-                return getFlashFiredDescription();
-            case TAG_TEXT_STAMP:
-                return getTextStampDescription();
-            case TAG_TEXT_STAMP_1:
-                return getTextStamp1Description();
-            case TAG_TEXT_STAMP_2:
-                return getTextStamp2Description();
-            case TAG_TEXT_STAMP_3:
-                return getTextStamp3Description();
-            case TAG_MAKERNOTE_VERSION:
-                return getMakernoteVersionDescription();
-            case TAG_EXIF_VERSION:
-                return getExifVersionDescription();
-            case TAG_INTERNAL_SERIAL_NUMBER:
-                return getInternalSerialNumberDescription();
-            case TAG_TITLE:
-                return getTitleDescription();
-            case TAG_BRACKET_SETTINGS:
-                return getBracketSettingsDescription();
-            case TAG_FLASH_CURTAIN:
-                return getFlashCurtainDescription();
-            case TAG_LONG_EXPOSURE_NOISE_REDUCTION:
-                return getLongExposureNoiseReductionDescription();
-            case TAG_BABY_NAME:
-                return getBabyNameDescription();
-            case TAG_LOCATION:
-                return getLocationDescription();
-
-            case TAG_LENS_FIRMWARE_VERSION:
-                return getLensFirmwareVersionDescription();
-            case TAG_INTELLIGENT_D_RANGE:
-                return getIntelligentDRangeDescription();
-            case TAG_CLEAR_RETOUCH:
-                return getClearRetouchDescription();
-            case TAG_PHOTO_STYLE:
-                return getPhotoStyleDescription();
-            case TAG_SHADING_COMPENSATION:
-                return getShadingCompensationDescription();
-
-            case TAG_ACCELEROMETER_Z:
-                return getAccelerometerZDescription();
-            case TAG_ACCELEROMETER_X:
-                return getAccelerometerXDescription();
-            case TAG_ACCELEROMETER_Y:
-                return getAccelerometerYDescription();
-            case TAG_CAMERA_ORIENTATION:
-                return getCameraOrientationDescription();
-            case TAG_ROLL_ANGLE:
-                return getRollAngleDescription();
-            case TAG_PITCH_ANGLE:
-                return getPitchAngleDescription();
-            case TAG_SWEEP_PANORAMA_DIRECTION:
-                return getSweepPanoramaDirectionDescription();
-            case TAG_TIMER_RECORDING:
-                return getTimerRecordingDescription();
-            case TAG_HDR:
-                return getHDRDescription();
-            case TAG_SHUTTER_TYPE:
-                return getShutterTypeDescription();
-            case TAG_TOUCH_AE:
-                return getTouchAeDescription();
-
-            case TAG_BABY_AGE:
-                return getBabyAgeDescription();
-            case TAG_BABY_AGE_1:
-                return getBabyAge1Description();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getTextStampDescription()
-    {
-        return getIndexedDescription(TAG_TEXT_STAMP, 1, "Off", "On");
-    }
-
-	@Nullable
-    public String getTextStamp1Description()
-    {
-        return getIndexedDescription(TAG_TEXT_STAMP_1, 1, "Off", "On");
-    }
-
-	@Nullable
-    public String getTextStamp2Description()
-    {
-        return getIndexedDescription(TAG_TEXT_STAMP_2, 1, "Off", "On");
-    }
-
-	@Nullable
-    public String getTextStamp3Description()
-    {
-        return getIndexedDescription(TAG_TEXT_STAMP_3, 1, "Off", "On");
-    }
-
-	@Nullable
-    public String getMacroModeDescription()
-    {
-        return getIndexedDescription(TAG_MACRO_MODE, 1, "Off", "On");
-    }
-
-    @Nullable
-    public String getFlashFiredDescription()
-    {
-        return getIndexedDescription(TAG_FLASH_FIRED, 1, "Off", "On");
-    }
-
-    @Nullable
-    public String getImageStabilizationDescription()
-    {
-        return getIndexedDescription(TAG_IMAGE_STABILIZATION,
-            2,
-            "On, Mode 1",
-            "Off",
-            "On, Mode 2"
-        );
-    }
-
-    @Nullable
-    public String getAudioDescription()
-    {
-        return getIndexedDescription(TAG_AUDIO, 1, "Off", "On");
-    }
-
-    @Nullable
-    public String getTransformDescription()
-    {
-        return getTransformDescription(TAG_TRANSFORM);
-    }
-
-    @Nullable
-    public String getTransform1Description()
-    {
-        return getTransformDescription(TAG_TRANSFORM_1);
-    }
-
-    @Nullable
-    private String getTransformDescription(int tag)
-    {
-        byte[] values = _directory.getByteArray(tag);
-        if (values == null)
-            return null;
-
-        RandomAccessReader reader = new ByteArrayReader(values);
-
-        try
-        {
-            int val1 = reader.getUInt16(0);
-            int val2 = reader.getUInt16(2);
-
-            if (val1 == -1 && val2 == 1)
-                return "Slim Low";
-            if (val1 == -3 && val2 == 2)
-                return "Slim High";
-            if (val1 == 0 && val2 == 0)
-                return "Off";
-            if (val1 == 1 && val2 == 1)
-                return "Stretch Low";
-            if (val1 == 3 && val2 == 2)
-                return "Stretch High";
-
-            return "Unknown (" + val1 + " " + val2 + ")";
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    @Nullable
-    public String getIntelligentExposureDescription()
-    {
-        return getIndexedDescription(TAG_INTELLIGENT_EXPOSURE,
-            "Off", "Low", "Standard", "High");
-    }
-
-    @Nullable
-    public String getFlashWarningDescription()
-    {
-        return getIndexedDescription(TAG_FLASH_WARNING,
-            "No", "Yes (Flash required but disabled)");
-    }
-
-    @Nullable
-    private static String trim(@Nullable String s)
-    {
-        return s == null ? null : s.trim();
-    }
-
-    @Nullable
-    public String getCountryDescription()
-    {
-        return trim(getStringFromBytes(TAG_COUNTRY, Charsets.UTF_8));
-    }
-
-    @Nullable
-    public String getStateDescription()
-    {
-        return trim(getStringFromBytes(TAG_STATE, Charsets.UTF_8));
-    }
-
-    @Nullable
-    public String getCityDescription()
-    {
-        return trim(getStringFromBytes(TAG_CITY, Charsets.UTF_8));
-    }
-
-    @Nullable
-    public String getLandmarkDescription()
-    {
-        return trim(getStringFromBytes(TAG_LANDMARK, Charsets.UTF_8));
-    }
-
-    @Nullable
-    public String getTitleDescription()
-    {
-        return trim(getStringFromBytes(TAG_TITLE, Charsets.UTF_8));
-    }
-
-    @Nullable
-    public String getBracketSettingsDescription()
-    {
-        return getIndexedDescription(TAG_BRACKET_SETTINGS,
-            "No Bracket", "3 Images, Sequence 0/-/+", "3 Images, Sequence -/0/+", "5 Images, Sequence 0/-/+",
-            "5 Images, Sequence -/0/+", "7 Images, Sequence 0/-/+", "7 Images, Sequence -/0/+");
-    }
-
-    @Nullable
-    public String getFlashCurtainDescription()
-    {
-        return getIndexedDescription(TAG_FLASH_CURTAIN,
-            "n/a", "1st", "2nd");
-    }
-
-    @Nullable
-    public String getLongExposureNoiseReductionDescription()
-    {
-        return getIndexedDescription(TAG_LONG_EXPOSURE_NOISE_REDUCTION, 1,
-            "Off", "On");
-    }
-
-    @Nullable
-    public String getLensFirmwareVersionDescription()
-    {
-        // lens version has 4 parts separated by periods
-        byte[] bytes = _directory.getByteArray(TAG_LENS_FIRMWARE_VERSION);
-        if (bytes == null)
-            return null;
-
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < bytes.length; i++) {
-            sb.append(bytes[i]);
-            if (i < bytes.length - 1)
-                sb.append(".");
-        }
-        return sb.toString();
-        //return string.Join(".", bytes.Select(b => b.ToString()).ToArray());
-    }
-
-    @Nullable
-    public String getIntelligentDRangeDescription()
-    {
-        return getIndexedDescription(TAG_INTELLIGENT_D_RANGE,
-            "Off", "Low", "Standard", "High");
-    }
-
-    @Nullable
-    public String getClearRetouchDescription()
-    {
-        return getIndexedDescription(TAG_CLEAR_RETOUCH,
-                "Off", "On");
-
-    }
-
-    @Nullable
-    public String getPhotoStyleDescription()
-    {
-        return getIndexedDescription(TAG_PHOTO_STYLE,
-            "Auto", "Standard or Custom", "Vivid", "Natural", "Monochrome", "Scenery", "Portrait");
-    }
-
-    @Nullable
-    public String getShadingCompensationDescription()
-    {
-        return getIndexedDescription(TAG_SHADING_COMPENSATION,
-            "Off", "On");
-    }
-
-    @Nullable
-    public String getAccelerometerZDescription()
-    {
-        Integer value = _directory.getInteger(TAG_ACCELEROMETER_Z);
-        if (value == null)
-            return null;
-
-        // positive is acceleration upwards
-        return String.valueOf(value.shortValue());
-    }
-
-    @Nullable
-    public String getAccelerometerXDescription()
-    {
-        Integer value = _directory.getInteger(TAG_ACCELEROMETER_X);
-        if (value == null)
-            return null;
-
-        // positive is acceleration to the left
-        return String.valueOf(value.shortValue());
-    }
-
-    @Nullable
-    public String getAccelerometerYDescription()
-    {
-        Integer value = _directory.getInteger(TAG_ACCELEROMETER_Y);
-        if (value == null)
-            return null;
-
-        // positive is acceleration backwards
-        return String.valueOf(value.shortValue());
-    }
-
-    @Nullable
-    public String getCameraOrientationDescription()
-    {
-        return getIndexedDescription(TAG_CAMERA_ORIENTATION,
-                "Normal", "Rotate CW", "Rotate 180", "Rotate CCW", "Tilt Upwards", "Tile Downwards");
-    }
-
-    @Nullable
-    public String getRollAngleDescription()
-    {
-        Integer value = _directory.getInteger(TAG_ROLL_ANGLE);
-        if (value == null)
-            return null;
-
-        DecimalFormat format = new DecimalFormat("0.#");
-        // converted to degrees of clockwise camera rotation
-        return format.format(value.shortValue() / 10.0);
-    }
-
-    @Nullable
-    public String getPitchAngleDescription()
-    {
-        Integer value = _directory.getInteger(TAG_PITCH_ANGLE);
-        if (value == null)
-            return null;
-
-        DecimalFormat format = new DecimalFormat("0.#");
-        // converted to degrees of upward camera tilt
-        return format.format(-value.shortValue() / 10.0);
-    }
-
-    @Nullable
-    public String getSweepPanoramaDirectionDescription()
-    {
-        return getIndexedDescription(TAG_SWEEP_PANORAMA_DIRECTION,
-                "Off", "Left to Right", "Right to Left", "Top to Bottom", "Bottom to Top");
-    }
-
-    @Nullable
-    public String getTimerRecordingDescription()
-    {
-        return getIndexedDescription(TAG_TIMER_RECORDING,
-                "Off", "Time Lapse", "Stop-motion Animation");
-    }
-
-    @Nullable
-    public String getHDRDescription()
-    {
-        Integer value = _directory.getInteger(TAG_HDR);
-        if (value == null)
-            return null;
-
-        switch (value)
-        {
-            case 0:
-                return "Off";
-            case 100:
-                return "1 EV";
-            case 200:
-                return "2 EV";
-            case 300:
-                return "3 EV";
-            case 32868:
-                return "1 EV (Auto)";
-            case 32968:
-                return "2 EV (Auto)";
-            case 33068:
-                return "3 EV (Auto)";
-            default:
-                return String.format("Unknown (%d)", value);
-        }
-    }
-
-    @Nullable
-    public String getShutterTypeDescription()
-    {
-        return getIndexedDescription(TAG_SHUTTER_TYPE,
-                "Mechanical", "Electronic", "Hybrid");
-    }
-
-    @Nullable
-    public String getTouchAeDescription()
-    {
-        return getIndexedDescription(TAG_TOUCH_AE,
-                "Off", "On");
-    }
-
-    @Nullable
-    public String getBabyNameDescription()
-    {
-        return trim(getStringFromBytes(TAG_BABY_NAME, Charsets.UTF_8));
-    }
-
-	@Nullable
-    public String getLocationDescription()
-    {
-        return trim(getStringFromBytes(TAG_LOCATION, Charsets.UTF_8));
-    }
-
-    @Nullable
-    public String getIntelligentResolutionDescription()
-    {
-        return getIndexedDescription(TAG_INTELLIGENT_RESOLUTION,
-            "Off", null, "Auto", "On");
-    }
-
-    @Nullable
-    public String getContrastDescription()
-    {
-        return getIndexedDescription(TAG_CONTRAST, "Normal");
-    }
-
-    @Nullable
-    public String getWorldTimeLocationDescription()
-    {
-        return getIndexedDescription(TAG_WORLD_TIME_LOCATION,
-            1, "Home", "Destination");
-    }
-
-    @Nullable
-    public String getAdvancedSceneModeDescription()
-    {
-        return getIndexedDescription(TAG_ADVANCED_SCENE_MODE,
-            1,
-            "Normal",
-            "Outdoor/Illuminations/Flower/HDR Art",
-            "Indoor/Architecture/Objects/HDR B&W",
-            "Creative",
-            "Auto",
-            null,
-            "Expressive",
-            "Retro",
-            "Pure",
-            "Elegant",
-            null,
-            "Monochrome",
-            "Dynamic Art",
-            "Silhouette"
-        );
-    }
-
-    @Nullable
-    public String getUnknownDataDumpDescription()
-    {
-        return getByteLengthDescription(TAG_UNKNOWN_DATA_DUMP);
-    }
-
-    @Nullable
-    public String getColorEffectDescription()
-    {
-        return getIndexedDescription(TAG_COLOR_EFFECT,
-            1, "Off", "Warm", "Cool", "Black & White", "Sepia"
-        );
-    }
-
-    @Nullable
-    public String getUptimeDescription()
-    {
-        Integer value = _directory.getInteger(TAG_UPTIME);
-        if (value == null)
-            return null;
-        return value / 100f + " s";
-    }
-
-    @Nullable
-    public String getBurstModeDescription()
-    {
-        return getIndexedDescription(TAG_BURST_MODE,
-            "Off", null, "On", "Indefinite", "Unlimited"
-        );
-    }
-
-    @Nullable
-    public String getContrastModeDescription()
-    {
-        Integer value = _directory.getInteger(TAG_CONTRAST_MODE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0x0: return "Normal";
-            case 0x1: return "Low";
-            case 0x2: return "High";
-            case 0x6: return "Medium Low";
-            case 0x7: return "Medium High";
-            case 0x100: return "Low";
-            case 0x110: return "Normal";
-            case 0x120: return "High";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getNoiseReductionDescription()
-    {
-        return getIndexedDescription(TAG_NOISE_REDUCTION,
-            "Standard (0)", "Low (-1)", "High (+1)", "Lowest (-2)", "Highest (+2)"
-        );
-    }
-
-    @Nullable
-    public String getSelfTimerDescription()
-    {
-        return getIndexedDescription(TAG_SELF_TIMER,
-            1, "Off", "10 s", "2 s"
-        );
-    }
-
-    @Nullable
-    public String getRotationDescription()
-    {
-        Integer value = _directory.getInteger(TAG_ROTATION);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 1: return "Horizontal";
-            case 3: return "Rotate 180";
-            case 6: return "Rotate 90 CW";
-            case 8: return "Rotate 270 CW";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getAfAssistLampDescription()
-    {
-        return getIndexedDescription(TAG_AF_ASSIST_LAMP,
-            1, "Fired", "Enabled but not used", "Disabled but required", "Disabled and not required"
-        );
-    }
-
-    @Nullable
-    public String getColorModeDescription()
-    {
-        return getIndexedDescription(TAG_COLOR_MODE,
-            "Normal", "Natural", "Vivid"
-        );
-    }
-
-    @Nullable
-    public String getOpticalZoomModeDescription()
-    {
-        return getIndexedDescription(TAG_OPTICAL_ZOOM_MODE,
-            1, "Standard", "Extended"
-        );
-    }
-
-    @Nullable
-    public String getConversionLensDescription()
-    {
-        return getIndexedDescription(TAG_CONVERSION_LENS,
-            1, "Off", "Wide", "Telephoto", "Macro"
-        );
-    }
-
-    @Nullable
-    public String getDetectedFacesDescription()
-    {
-        return buildFacesDescription(_directory.getDetectedFaces());
-    }
-
-    @Nullable
-    public String getRecognizedFacesDescription()
-    {
-        return buildFacesDescription(_directory.getRecognizedFaces());
-    }
-
-    @Nullable
-    private String buildFacesDescription(@Nullable Face[] faces)
-    {
-        if (faces == null)
-            return null;
-
-        StringBuilder result = new StringBuilder();
-
-        for (int i = 0; i < faces.length; i++)
-            result.append("Face ").append(i + 1).append(": ").append(faces[i].toString()).append("\n");
-
-        return result.length() > 0 ? result.substring(0, result.length() - 1) : null;
-
-    }
-
-    private static final String[] _sceneModes = new String[] {
-        "Normal", // 1
-        "Portrait",
-        "Scenery",
-        "Sports",
-        "Night Portrait",
-        "Program",
-        "Aperture Priority",
-        "Shutter Priority",
-        "Macro",
-        "Spot", // 10
-        "Manual",
-        "Movie Preview",
-        "Panning",
-        "Simple",
-        "Color Effects",
-        "Self Portrait",
-        "Economy",
-        "Fireworks",
-        "Party",
-        "Snow", // 20
-        "Night Scenery",
-        "Food",
-        "Baby",
-        "Soft Skin",
-        "Candlelight",
-        "Starry Night",
-        "High Sensitivity",
-        "Panorama Assist",
-        "Underwater",
-        "Beach", // 30
-        "Aerial Photo",
-        "Sunset",
-        "Pet",
-        "Intelligent ISO",
-        "Clipboard",
-        "High Speed Continuous Shooting",
-        "Intelligent Auto",
-        null,
-        "Multi-aspect",
-        null, // 40
-        "Transform",
-        "Flash Burst",
-        "Pin Hole",
-        "Film Grain",
-        "My Color",
-        "Photo Frame",
-        null,
-        null,
-        null,
-        null, // 50
-        "HDR"
-    };
-
-    @Nullable
-    public String getRecordModeDescription()
-    {
-        return getIndexedDescription(TAG_RECORD_MODE, 1, _sceneModes);
-    }
-
-    @Nullable
-    public String getSceneModeDescription()
-    {
-        return getIndexedDescription(TAG_SCENE_MODE, 1, _sceneModes);
-    }
-
-    @Nullable
-    public String getFocusModeDescription()
-    {
-        return getIndexedDescription(TAG_FOCUS_MODE, 1,
-            "Auto", "Manual", null, "Auto, Focus Button", "Auto, Continuous");
-    }
-
-    @Nullable
-    public String getAfAreaModeDescription()
-    {
-        int[] value = _directory.getIntArray(TAG_AF_AREA_MODE);
-        if (value == null || value.length < 2)
-            return null;
-        switch (value[0]) {
-            case 0:
-                switch (value[1]) {
-                    case 1: return "Spot Mode On";
-                    case 16: return "Spot Mode Off";
-                    default: return "Unknown (" + value[0] + " " + value[1] + ")";
-                }
-            case 1:
-                switch (value[1]) {
-                    case 0: return "Spot Focusing";
-                    case 1: return "5-area";
-                    default: return "Unknown (" + value[0] + " " + value[1] + ")";
-                }
-            case 16:
-                switch (value[1]) {
-                    case 0: return "1-area";
-                    case 16: return "1-area (high speed)";
-                    default: return "Unknown (" + value[0] + " " + value[1] + ")";
-                }
-            case 32:
-                switch (value[1]) {
-                    case 0: return "Auto or Face Detect";
-                    case 1: return "3-area (left)";
-                    case 2: return "3-area (center)";
-                    case 3: return "3-area (right)";
-                    default: return "Unknown (" + value[0] + " " + value[1] + ")";
-                }
-            case 64: return "Face Detect";
-            default: return "Unknown (" + value[0] + " " + value[1] + ")";
-        }
-    }
-
-    @Nullable
-    public String getQualityModeDescription()
-    {
-        return getIndexedDescription(TAG_QUALITY_MODE,
-            2,
-            "High", // 2
-            "Normal",
-            null,
-            null,
-            "Very High",
-            "Raw",
-            null,
-            "Motion Picture" // 9
-        );
-    }
-
-    @Nullable
-    public String getVersionDescription()
-    {
-        return getVersionBytesDescription(TAG_FIRMWARE_VERSION, 2);
-    }
-
-    @Nullable
-    public String getMakernoteVersionDescription()
-    {
-        return getVersionBytesDescription(TAG_MAKERNOTE_VERSION, 2);
-    }
-
-    @Nullable
-    public String getExifVersionDescription()
-    {
-        return getVersionBytesDescription(TAG_EXIF_VERSION, 2);
-    }
-
-    @Nullable
-    public String getInternalSerialNumberDescription()
-    {
-        return get7BitStringFromBytes(TAG_INTERNAL_SERIAL_NUMBER);
-    }
-
-    @Nullable
-    public String getWhiteBalanceDescription()
-    {
-        return getIndexedDescription(TAG_WHITE_BALANCE,
-            1,
-            "Auto", // 1
-            "Daylight",
-            "Cloudy",
-            "Incandescent",
-            "Manual",
-            null,
-            null,
-            "Flash",
-            null,
-            "Black & White", // 10
-            "Manual",
-            "Shade" // 12
-        );
-    }
-
-	@Nullable
-	public String getBabyAgeDescription()
-    {
-        final Age age = _directory.getAge(TAG_BABY_AGE);
-        return age == null ? null : age.toFriendlyString();
-    }
-
-	@Nullable
-	public String getBabyAge1Description()
-    {
-        final Age age = _directory.getAge(TAG_BABY_AGE_1);
-        return age == null ? null : age.toFriendlyString();
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/PanasonicMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/PanasonicMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,711 +1,0 @@
-/*
- * 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
- *
- *        http://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.ByteArrayReader;
-import com.drew.lang.RandomAccessReader;
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.Age;
-import com.drew.metadata.Directory;
-import com.drew.metadata.Face;
-
-import java.io.IOException;
-import java.util.HashMap;
-
-/**
- * Describes tags specific to Panasonic and Leica cameras.
- *
- * @author Drew Noakes https://drewnoakes.com
- * @author Philipp Sandhaus
- */
-@SuppressWarnings("WeakerAccess")
-public class PanasonicMakernoteDirectory extends Directory
-{
-
-    /**
-     * <br>
-     * 2 = High            <br>
-     * 3 = Normal          <br>
-     * 6 = Very High       <br>
-     * 7 = Raw             <br>
-     * 9 = Motion Picture  <br>
-     */
-    public static final int TAG_QUALITY_MODE = 0x0001;
-    public static final int TAG_FIRMWARE_VERSION = 0x0002;
-
-    /**
-     * <br>
-     * 1 = Auto            <br>
-     * 2 = Daylight        <br>
-     * 3 = Cloudy          <br>
-     * 4 = Incandescent    <br>
-     * 5 = Manual          <br>
-     * 8 = Flash           <br>
-     * 10 = Black &amp; White  <br>
-     * 11 = Manual         <br>
-     * 12 = Shade          <br>
-     */
-    public static final int TAG_WHITE_BALANCE = 0x0003;
-
-
-    /**
-     * <br>
-     * 1 = Auto                <br>
-     * 2 = Manual              <br>
-     * 4 =  Auto, Focus Button <br>
-     * 5 = Auto, Continuous    <br>
-     */
-    public static final int TAG_FOCUS_MODE = 0x0007;
-
-    /**
-     * <br>
-     * 2 bytes                         <br>
-     * (DMC-FZ10)                      <br>
-     * '0 1' = Spot Mode On            <br>
-     * '0 16' = Spot Mode Off          <br>
-     * '(other models)                 <br>
-     * 16 = Normal?                    <br>
-     * '0 1' = 9-area                  <br>
-     * '0 16' = 3-area (high speed)    <br>
-     * '1 0' = Spot Focusing           <br>
-     * '1 1' = 5-area                  <br>
-     * '16 0' = 1-area                 <br>
-     * '16 16' = 1-area (high speed)   <br>
-     * '32 0' = Auto or Face Detect    <br>
-     * '32 1' = 3-area (left)?         <br>
-     * '32 2' = 3-area (center)?       <br>
-     * '32 3' = 3-area (right)?        <br>
-     * '64 0' = Face Detect            <br>
-     */
-    public static final int TAG_AF_AREA_MODE = 0x000f;
-
-    /**
-     * <br>
-     * 2 = On, Mode 1   <br>
-     * 3 = Off          <br>
-     * 4 = On, Mode 2   <br>
-     */
-    public static final int TAG_IMAGE_STABILIZATION = 0x001a;
-
-    /**
-     * <br>
-     * 1 = On    <br>
-     * 2 = Off   <br>
-     */
-    public static final int TAG_MACRO_MODE = 0x001C;
-
-    /**
-     * <br>
-     * 1 = Normal                            <br>
-     * 2 = Portrait                          <br>
-     * 3 = Scenery                           <br>
-     * 4 = Sports                            <br>
-     * 5 = Night Portrait                    <br>
-     * 6 = Program                           <br>
-     * 7 = Aperture Priority                 <br>
-     * 8 = Shutter Priority                  <br>
-     * 9 = Macro                             <br>
-     * 10= Spot                              <br>
-     * 11= Manual                            <br>
-     * 12= Movie Preview                     <br>
-     * 13= Panning                           <br>
-     * 14= Simple                            <br>
-     * 15= Color Effects                     <br>
-     * 16= Self Portrait                     <br>
-     * 17= Economy                           <br>
-     * 18= Fireworks                         <br>
-     * 19= Party                             <br>
-     * 20= Snow                              <br>
-     * 21= Night Scenery                     <br>
-     * 22= Food                              <br>
-     * 23= Baby                              <br>
-     * 24= Soft Skin                         <br>
-     * 25= Candlelight                       <br>
-     * 26= Starry Night                      <br>
-     * 27= High Sensitivity                  <br>
-     * 28= Panorama Assist                   <br>
-     * 29= Underwater                        <br>
-     * 30= Beach                             <br>
-     * 31= Aerial Photo                      <br>
-     * 32= Sunset                            <br>
-     * 33= Pet                               <br>
-     * 34= Intelligent ISO                   <br>
-     * 35= Clipboard                         <br>
-     * 36= High Speed Continuous Shooting    <br>
-     * 37= Intelligent Auto                  <br>
-     * 39= Multi-aspect                      <br>
-     * 41= Transform                         <br>
-     * 42= Flash Burst                       <br>
-     * 43= Pin Hole                          <br>
-     * 44= Film Grain                        <br>
-     * 45= My Color                          <br>
-     * 46= Photo Frame                       <br>
-     * 51= HDR                               <br>
-     */
-    public static final int TAG_RECORD_MODE = 0x001F;
-
-    /**
-     * 1 = Yes <br>
-     * 2 = No  <br>
-     */
-    public static final int TAG_AUDIO = 0x0020;
-
-    /**
-     * No idea, what this is
-     */
-    public static final int TAG_UNKNOWN_DATA_DUMP = 0x0021;
-
-    public static final int TAG_EASY_MODE = 0x0022;
-    public static final int TAG_WHITE_BALANCE_BIAS = 0x0023;
-    public static final int TAG_FLASH_BIAS = 0x0024;
-
-    /**
-     * this number is unique, and contains the date of manufacture,
-     * but is not the same as the number printed on the camera body
-     */
-    public static final int TAG_INTERNAL_SERIAL_NUMBER = 0x0025;
-
-    /**
-     * Panasonic Exif Version
-     */
-    public static final int TAG_EXIF_VERSION = 0x0026;
-
-
-    /**
-     * 1 = Off           <br>
-     * 2 = Warm          <br>
-     * 3 = Cool          <br>
-     * 4 = Black &amp; White <br>
-     * 5 = Sepia         <br>
-     */
-    public static final int TAG_COLOR_EFFECT = 0x0028;
-
-    /**
-     * 4 Bytes <br>
-     * Time in 1/100 s from when the camera was powered on to when the
-     * image is written to memory card
-     */
-    public static final int TAG_UPTIME = 0x0029;
-
-
-    /**
-     * 0 = Off        <br>
-     * 1 = On         <br>
-     * 2 = Infinite   <br>
-     * 4 = Unlimited  <br>
-     */
-    public static final int TAG_BURST_MODE = 0x002a;
-
-    public static final int TAG_SEQUENCE_NUMBER = 0x002b;
-
-    /**
-     * (this decoding seems to work for some models such as the LC1, LX2, FZ7, FZ8, FZ18 and FZ50, but may not be correct for other models such as the FX10, G1, L1, L10 and LC80) <br>
-     * 0x0 = Normal                                            <br>
-     * 0x1 = Low                                               <br>
-     * 0x2 = High                                              <br>
-     * 0x6 = Medium Low                                        <br>
-     * 0x7 = Medium High                                       <br>
-     * 0x100 = Low                                             <br>
-     * 0x110 = Normal                                          <br>
-     * 0x120 = High                                            <br>
-     * (these values are used by the GF1)                      <br>
-     * 0 = -2                                                  <br>
-     * 1 = -1                                                  <br>
-     * 2 = Normal                                              <br>
-     * 3 = +1                                                  <br>
-     * 4 = +2                                                  <br>
-     * 7 = Nature (Color Film)                                 <br>
-     * 12 = Smooth (Color Film) or Pure (My Color)             <br>
-     * 17 = Dynamic (B&amp;W Film)                                 <br>
-     * 22 = Smooth (B&amp;W Film)                                  <br>
-     * 27 = Dynamic (Color Film)                               <br>
-     * 32 = Vibrant (Color Film) or Expressive (My Color)      <br>
-     * 33 = Elegant (My Color)                                 <br>
-     * 37 = Nostalgic (Color Film)                             <br>
-     * 41 = Dynamic Art (My Color)                             <br>
-     * 42 = Retro (My Color)                                   <br>
-     */
-    public static final int TAG_CONTRAST_MODE = 0x002c;
-
-
-    /**
-     * 0 = Standard      <br>
-     * 1 = Low (-1)      <br>
-     * 2 = High (+1)     <br>
-     * 3 = Lowest (-2)   <br>
-     * 4 = Highest (+2)  <br>
-     */
-    public static final int TAG_NOISE_REDUCTION = 0x002d;
-
-    /**
-     * 1 = Off   <br>
-     * 2 = 10 s  <br>
-     * 3 = 2 s   <br>
-     */
-    public static final int TAG_SELF_TIMER = 0x002e;
-
-    /**
-     * 1 = 0 DG    <br>
-     * 3 = 180 DG  <br>
-     * 6 =  90 DG  <br>
-     * 8 = 270 DG  <br>
-     */
-    public static final int TAG_ROTATION = 0x0030;
-
-    /**
-     * 1 = Fired <br>
-     * 2 = Enabled nut not used <br>
-     * 3 = Disabled but required <br>
-     * 4 = Disabled and not required
-     */
-    public static final int TAG_AF_ASSIST_LAMP = 0x0031;
-
-    /**
-     * 0 = Normal <br>
-     * 1 = Natural<br>
-     * 2 = Vivid
-     *
-     */
-    public static final int TAG_COLOR_MODE = 0x0032;
-
-    public static final int TAG_BABY_AGE = 0x0033;
-
-    /**
-     *  1 = Standard <br>
-     *  2 = Extended
-     */
-    public static final int TAG_OPTICAL_ZOOM_MODE = 0x0034;
-
-    /**
-     * 1 = Off <br>
-     * 2 = Wide <br>
-     * 3 = Telephoto <br>
-     * 4 = Macro
-     */
-    public static final int TAG_CONVERSION_LENS = 0x0035;
-
-    public static final int TAG_TRAVEL_DAY = 0x0036;
-
-    /**
-     * 0 = Normal
-     */
-    public static final int TAG_CONTRAST = 0x0039;
-
-    /**
-     * <br>
-     * 1 = Home <br>
-     * 2 = Destination
-     */
-    public static final int TAG_WORLD_TIME_LOCATION = 0x003a;
-
-    /**
-     * 1 = Off   <br>
-     * 2 = On
-     */
-    public static final int TAG_TEXT_STAMP = 0x003b;
-
-	public static final int TAG_PROGRAM_ISO = 0x003c;
-
-    /**
-     * <br>
-     * 1 = Normal                               <br>
-     * 2 = Outdoor/Illuminations/Flower/HDR Art <br>
-     * 3 = Indoor/Architecture/Objects/HDR B&amp;W  <br>
-     * 4 = Creative                             <br>
-     * 5 = Auto                                 <br>
-     * 7 = Expressive                           <br>
-     * 8 = Retro                                <br>
-     * 9 = Pure                                 <br>
-     * 10 = Elegant                             <br>
-     * 12 = Monochrome                          <br>
-     * 13 = Dynamic Art                         <br>
-     * 14 = Silhouette                          <br>
-     */
-    public static final int TAG_ADVANCED_SCENE_MODE = 0x003d;
-
-    /**
-     * 1 = Off   <br>
-     * 2 = On
-     */
-    public static final int TAG_TEXT_STAMP_1 = 0x003e;
-
-    public static final int TAG_FACES_DETECTED = 0x003f;
-
-    public static final int TAG_SATURATION = 0x0040;
-    public static final int TAG_SHARPNESS = 0x0041;
-    public static final int TAG_FILM_MODE = 0x0042;
-
-    public static final int TAG_COLOR_TEMP_KELVIN = 0x0044;
-    public static final int TAG_BRACKET_SETTINGS = 0x0045;
-
-    /**
-    * WB adjust AB. Positive is a shift toward blue.
-    */
-    public static final int TAG_WB_ADJUST_AB = 0x0046;
-    /**
-    * WB adjust GM. Positive is a shift toward green.
-    */
-    public static final int TAG_WB_ADJUST_GM = 0x0047;
-
-    public static final int TAG_FLASH_CURTAIN = 0x0048;
-    public static final int TAG_LONG_EXPOSURE_NOISE_REDUCTION = 0x0049;
-
-    public static final int TAG_PANASONIC_IMAGE_WIDTH = 0x004b;
-    public static final int TAG_PANASONIC_IMAGE_HEIGHT = 0x004c;
-    public static final int TAG_AF_POINT_POSITION = 0x004d;
-
-
-    /**
-     * <br>
-     * Integer (16Bit) Indexes:                                             <br>
-     * 0  Number Face Positions (maybe less than Faces Detected)            <br>
-     * 1-4 Face Position 1                                                  <br>
-     * 5-8 Face Position 2                                                  <br>
-     * and so on                                                            <br>
-     *                                                                      <br>
-     * The four Integers are interpreted as follows:                        <br>
-     * (XYWH)  X,Y Center of Face,  (W,H) Width and Height                  <br>
-     * All values are in respect to double the size of the thumbnail image  <br>
-     *
-     */
-    public static final int TAG_FACE_DETECTION_INFO = 0x004e;
-    public static final int TAG_LENS_TYPE = 0x0051;
-    public static final int TAG_LENS_SERIAL_NUMBER = 0x0052;
-    public static final int TAG_ACCESSORY_TYPE = 0x0053;
-    public static final int TAG_ACCESSORY_SERIAL_NUMBER = 0x0054;
-
-    /**
-     * (decoded as two 16-bit signed integers)
-     * '-1 1' = Slim Low
-     * '-3 2' = Slim High
-     * '0 0' = Off
-     * '1 1' = Stretch Low
-     * '3 2' = Stretch High
-     */
-    public static final int TAG_TRANSFORM = 0x0059;
-
-    /**
-    * 0 = Off <br>
-    * 1 = Low <br>
-    * 2 = Standard <br>
-    * 3 = High
-    */
-    public static final int TAG_INTELLIGENT_EXPOSURE = 0x005d;
-
-    public static final int TAG_LENS_FIRMWARE_VERSION = 0x0060;
-    public static final int TAG_BURST_SPEED = 0x0077;
-    public static final int TAG_INTELLIGENT_D_RANGE = 0x0079;
-    public static final int TAG_CLEAR_RETOUCH = 0x007c;
-    public static final int TAG_CITY2 = 0x0080;
-    public static final int TAG_PHOTO_STYLE = 0x0089;
-    public static final int TAG_SHADING_COMPENSATION = 0x008a;
-
-    public static final int TAG_ACCELEROMETER_Z = 0x008c;
-    public static final int TAG_ACCELEROMETER_X = 0x008d;
-    public static final int TAG_ACCELEROMETER_Y = 0x008e;
-    public static final int TAG_CAMERA_ORIENTATION = 0x008f;
-    public static final int TAG_ROLL_ANGLE = 0x0090;
-    public static final int TAG_PITCH_ANGLE = 0x0091;
-    public static final int TAG_SWEEP_PANORAMA_DIRECTION = 0x0093;
-    public static final int TAG_SWEEP_PANORAMA_FIELD_OF_VIEW = 0x0094;
-    public static final int TAG_TIMER_RECORDING = 0x0096;
-
-    public static final int TAG_INTERNAL_ND_FILTER = 0x009d;
-    public static final int TAG_HDR = 0x009e;
-    public static final int TAG_SHUTTER_TYPE = 0x009f;
-
-    public static final int TAG_CLEAR_RETOUCH_VALUE = 0x00a3;
-    public static final int TAG_TOUCH_AE = 0x00ab;
-
-    /**
-    * Info at http://www.ozhiker.com/electronics/pjmt/jpeg_info/pim.html
-    */
-    public static final int TAG_PRINT_IMAGE_MATCHING_INFO = 0x0E00;
-
-    /**
-     * Byte Indexes:                                                                       <br>
-     *  0    Int (2  Byte) Number of Recognized Faces                                      <br>
-     *  4    String(20 Byte)    Recognized Face 1 Name                                     <br>
-     * 24    4 Int (8 Byte)     Recognized Face 1 Position  (Same Format as Face Detection)  <br>
-     * 32    String(20 Byte)    Recognized Face 1 Age                                      <br>
-     * 52    String(20 Byte)    Recognized Face 2 Name                                     <br>
-     * 72    4 Int (8 Byte)     Recognized Face 2 Position  (Same Format as Face Detection)  <br>
-     * 80    String(20 Byte)    Recognized Face 2 Age                                      <br>
-     *                                                                                     <br>
-     * And so on                                                                           <br>
-     *                                                                                     <br>
-     * The four Integers are interpreted as follows:                                       <br>
-     * (XYWH)  X,Y Center of Face,  (W,H) Width and Height                                 <br>
-     * All values are in respect to double the size of the thumbnail image                 <br>
-     *
-     */
-    public static final int TAG_FACE_RECOGNITION_INFO = 0x0061;
-
-    /**
-    * 0 = No <br>
-    * 1 = Yes
-    */
-    public static final int TAG_FLASH_WARNING = 0x0062;
-    public static final int TAG_RECOGNIZED_FACE_FLAGS = 0x0063;
-    public static final int TAG_TITLE = 0x0065;
-    public static final int TAG_BABY_NAME = 0x0066;
-    public static final int TAG_LOCATION = 0x0067;
-    public static final int TAG_COUNTRY = 0x0069;
-    public static final int TAG_STATE = 0x006b;
-    public static final int TAG_CITY = 0x006d;
-    public static final int TAG_LANDMARK = 0x006f;
-
-    /**
-     * 0 = Off <br>
-     * 2 = Auto <br>
-     * 3 = On
-     */
-    public static final int TAG_INTELLIGENT_RESOLUTION = 0x0070;
-
-    public static final int TAG_MAKERNOTE_VERSION = 0x8000;
-    public static final int TAG_SCENE_MODE = 0x8001;
-    public static final int TAG_WB_RED_LEVEL = 0x8004;
-    public static final int TAG_WB_GREEN_LEVEL = 0x8005;
-    public static final int TAG_WB_BLUE_LEVEL = 0x8006;
-    public static final int TAG_FLASH_FIRED = 0x8007;
-    public static final int TAG_TEXT_STAMP_2 = 0x8008;
-    public static final int TAG_TEXT_STAMP_3 = 0x8009;
-    public static final int TAG_BABY_AGE_1 = 0x8010;
-
-	/**
-     * (decoded as two 16-bit signed integers)
-     * '-1 1' = Slim Low
-     * '-3 2' = Slim High
-     * '0 0' = Off
-     * '1 1' = Stretch Low
-     * '3 2' = Stretch High
-     */
-    public static final int TAG_TRANSFORM_1 = 0x8012;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TAG_QUALITY_MODE, "Quality Mode");
-        _tagNameMap.put(TAG_FIRMWARE_VERSION, "Version");
-        _tagNameMap.put(TAG_WHITE_BALANCE, "White Balance");
-        _tagNameMap.put(TAG_FOCUS_MODE, "Focus Mode");
-        _tagNameMap.put(TAG_AF_AREA_MODE, "AF Area Mode");
-        _tagNameMap.put(TAG_IMAGE_STABILIZATION, "Image Stabilization");
-        _tagNameMap.put(TAG_MACRO_MODE, "Macro Mode");
-        _tagNameMap.put(TAG_RECORD_MODE, "Record Mode");
-        _tagNameMap.put(TAG_AUDIO, "Audio");
-        _tagNameMap.put(TAG_INTERNAL_SERIAL_NUMBER, "Internal Serial Number");
-        _tagNameMap.put(TAG_UNKNOWN_DATA_DUMP, "Unknown Data Dump");
-        _tagNameMap.put(TAG_EASY_MODE, "Easy Mode");
-        _tagNameMap.put(TAG_WHITE_BALANCE_BIAS, "White Balance Bias");
-        _tagNameMap.put(TAG_FLASH_BIAS, "Flash Bias");
-        _tagNameMap.put(TAG_EXIF_VERSION, "Exif Version");
-        _tagNameMap.put(TAG_COLOR_EFFECT, "Color Effect");
-        _tagNameMap.put(TAG_UPTIME, "Camera Uptime");
-        _tagNameMap.put(TAG_BURST_MODE, "Burst Mode");
-        _tagNameMap.put(TAG_SEQUENCE_NUMBER, "Sequence Number");
-        _tagNameMap.put(TAG_CONTRAST_MODE, "Contrast Mode");
-        _tagNameMap.put(TAG_NOISE_REDUCTION, "Noise Reduction");
-        _tagNameMap.put(TAG_SELF_TIMER, "Self Timer");
-        _tagNameMap.put(TAG_ROTATION, "Rotation");
-        _tagNameMap.put(TAG_AF_ASSIST_LAMP, "AF Assist Lamp");
-        _tagNameMap.put(TAG_COLOR_MODE, "Color Mode");
-        _tagNameMap.put(TAG_BABY_AGE, "Baby Age");
-        _tagNameMap.put(TAG_OPTICAL_ZOOM_MODE, "Optical Zoom Mode");
-        _tagNameMap.put(TAG_CONVERSION_LENS, "Conversion Lens");
-        _tagNameMap.put(TAG_TRAVEL_DAY, "Travel Day");
-        _tagNameMap.put(TAG_CONTRAST, "Contrast");
-        _tagNameMap.put(TAG_WORLD_TIME_LOCATION, "World Time Location");
-        _tagNameMap.put(TAG_TEXT_STAMP, "Text Stamp");
-        _tagNameMap.put(TAG_PROGRAM_ISO, "Program ISO");
-	_tagNameMap.put(TAG_ADVANCED_SCENE_MODE, "Advanced Scene Mode");
-        _tagNameMap.put(TAG_PRINT_IMAGE_MATCHING_INFO, "Print Image Matching (PIM) Info");
-        _tagNameMap.put(TAG_FACES_DETECTED, "Number of Detected Faces");
-        _tagNameMap.put(TAG_SATURATION, "Saturation");
-        _tagNameMap.put(TAG_SHARPNESS, "Sharpness");
-        _tagNameMap.put(TAG_FILM_MODE, "Film Mode");
-        _tagNameMap.put(TAG_COLOR_TEMP_KELVIN, "Color Temp Kelvin");
-        _tagNameMap.put(TAG_BRACKET_SETTINGS, "Bracket Settings");
-        _tagNameMap.put(TAG_WB_ADJUST_AB, "White Balance Adjust (AB)");
-	_tagNameMap.put(TAG_WB_ADJUST_GM, "White Balance Adjust (GM)");
-
-        _tagNameMap.put(TAG_FLASH_CURTAIN, "Flash Curtain");
-        _tagNameMap.put(TAG_LONG_EXPOSURE_NOISE_REDUCTION, "Long Exposure Noise Reduction");
-        _tagNameMap.put(TAG_PANASONIC_IMAGE_WIDTH, "Panasonic Image Width");
-        _tagNameMap.put(TAG_PANASONIC_IMAGE_HEIGHT, "Panasonic Image Height");
-
-        _tagNameMap.put(TAG_AF_POINT_POSITION, "Af Point Position");
-        _tagNameMap.put(TAG_FACE_DETECTION_INFO, "Face Detection Info");
-        _tagNameMap.put(TAG_LENS_TYPE, "Lens Type");
-        _tagNameMap.put(TAG_LENS_SERIAL_NUMBER, "Lens Serial Number");
-        _tagNameMap.put(TAG_ACCESSORY_TYPE, "Accessory Type");
-        _tagNameMap.put(TAG_ACCESSORY_SERIAL_NUMBER, "Accessory Serial Number");
-        _tagNameMap.put(TAG_TRANSFORM, "Transform");
-        _tagNameMap.put(TAG_INTELLIGENT_EXPOSURE, "Intelligent Exposure");
-        _tagNameMap.put(TAG_LENS_FIRMWARE_VERSION, "Lens Firmware Version");
-        _tagNameMap.put(TAG_FACE_RECOGNITION_INFO, "Face Recognition Info");
-        _tagNameMap.put(TAG_FLASH_WARNING, "Flash Warning");
-        _tagNameMap.put(TAG_RECOGNIZED_FACE_FLAGS, "Recognized Face Flags");
-        _tagNameMap.put(TAG_TITLE, "Title");
-        _tagNameMap.put(TAG_BABY_NAME, "Baby Name");
-        _tagNameMap.put(TAG_LOCATION, "Location");
-        _tagNameMap.put(TAG_COUNTRY, "Country");
-        _tagNameMap.put(TAG_STATE, "State");
-        _tagNameMap.put(TAG_CITY, "City");
-        _tagNameMap.put(TAG_LANDMARK, "Landmark");
-        _tagNameMap.put(TAG_INTELLIGENT_RESOLUTION, "Intelligent Resolution");
-        _tagNameMap.put(TAG_BURST_SPEED, "Burst Speed");
-        _tagNameMap.put(TAG_INTELLIGENT_D_RANGE, "Intelligent D-Range");
-        _tagNameMap.put(TAG_CLEAR_RETOUCH, "Clear Retouch");
-        _tagNameMap.put(TAG_CITY2, "City 2");
-        _tagNameMap.put(TAG_PHOTO_STYLE, "Photo Style");
-        _tagNameMap.put(TAG_SHADING_COMPENSATION, "Shading Compensation");
-
-        _tagNameMap.put(TAG_ACCELEROMETER_Z, "Accelerometer Z");
-        _tagNameMap.put(TAG_ACCELEROMETER_X, "Accelerometer X");
-        _tagNameMap.put(TAG_ACCELEROMETER_Y, "Accelerometer Y");
-        _tagNameMap.put(TAG_CAMERA_ORIENTATION, "Camera Orientation");
-        _tagNameMap.put(TAG_ROLL_ANGLE, "Roll Angle");
-        _tagNameMap.put(TAG_PITCH_ANGLE, "Pitch Angle");
-        _tagNameMap.put(TAG_SWEEP_PANORAMA_DIRECTION, "Sweep Panorama Direction");
-        _tagNameMap.put(TAG_SWEEP_PANORAMA_FIELD_OF_VIEW, "Sweep Panorama Field Of View");
-        _tagNameMap.put(TAG_TIMER_RECORDING, "Timer Recording");
-
-        _tagNameMap.put(TAG_INTERNAL_ND_FILTER, "Internal ND Filter");
-        _tagNameMap.put(TAG_HDR, "HDR");
-        _tagNameMap.put(TAG_SHUTTER_TYPE, "Shutter Type");
-        _tagNameMap.put(TAG_CLEAR_RETOUCH_VALUE, "Clear Retouch Value");
-        _tagNameMap.put(TAG_TOUCH_AE, "Touch AE");
-
-        _tagNameMap.put(TAG_MAKERNOTE_VERSION, "Makernote Version");
-        _tagNameMap.put(TAG_SCENE_MODE, "Scene Mode");
-        _tagNameMap.put(TAG_WB_RED_LEVEL, "White Balance (Red)");
-        _tagNameMap.put(TAG_WB_GREEN_LEVEL, "White Balance (Green)");
-        _tagNameMap.put(TAG_WB_BLUE_LEVEL, "White Balance (Blue)");
-        _tagNameMap.put(TAG_FLASH_FIRED, "Flash Fired");
-        _tagNameMap.put(TAG_TEXT_STAMP_1, "Text Stamp 1");
-        _tagNameMap.put(TAG_TEXT_STAMP_2, "Text Stamp 2");
-        _tagNameMap.put(TAG_TEXT_STAMP_3, "Text Stamp 3");
-        _tagNameMap.put(TAG_BABY_AGE_1, "Baby Age 1");
-        _tagNameMap.put(TAG_TRANSFORM_1, "Transform 1");
-    }
-
-    public PanasonicMakernoteDirectory()
-    {
-        this.setDescriptor(new PanasonicMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Panasonic Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-
-    @Nullable
-    public Face[] getDetectedFaces()
-    {
-        byte[] bytes = getByteArray(TAG_FACE_DETECTION_INFO);
-        if (bytes==null)
-            return null;
-
-        RandomAccessReader reader = new ByteArrayReader(bytes);
-        reader.setMotorolaByteOrder(false);
-
-        try {
-            int faceCount = reader.getUInt16(0);
-            if (faceCount==0)
-                return null;
-            Face[] faces = new Face[faceCount];
-
-            for (int i = 0; i < faceCount; i++) {
-                int offset = 2 + i * 8;
-                faces[i] = new Face(
-                        reader.getUInt16(offset),
-                        reader.getUInt16(offset + 2),
-                        reader.getUInt16(offset + 4),
-                        reader.getUInt16(offset + 6)
-                        , null, null);
-            }
-            return faces;
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    @Nullable
-    public Face[] getRecognizedFaces()
-    {
-        byte[] bytes = getByteArray(TAG_FACE_RECOGNITION_INFO);
-        if (bytes == null)
-            return null;
-
-        RandomAccessReader reader = new ByteArrayReader(bytes);
-        reader.setMotorolaByteOrder(false);
-
-        try {
-            int faceCount = reader.getUInt16(0);
-            if (faceCount==0)
-                return null;
-            Face[] faces = new Face[faceCount];
-
-            for (int i = 0; i < faceCount; i++) {
-                int offset = 4 + i * 44;
-                String name = reader.getString(offset, 20, "ASCII").trim();
-                String age = reader.getString(offset + 28, 20, "ASCII").trim();
-                faces[i] = new Face(
-                        reader.getUInt16(offset + 20),
-                        reader.getUInt16(offset + 22),
-                        reader.getUInt16(offset + 24),
-                        reader.getUInt16(offset + 26),
-                        name,
-                        Age.fromPanasonicString(age));
-            }
-            return faces;
-        } catch (IOException e) {
-            return null;
-        }
-    }
-
-    /**
-     * Attempts to convert the underlying string value (as stored in the directory) into an Age object.
-     * @param tag The tag identifier.
-     * @return The parsed Age object, or null if the tag was empty of the value unable to be parsed.
-     */
-	@Nullable
-	public Age getAge(int tag)
-    {
-        final String ageString = getString(tag);
-        if (ageString==null)
-            return null;
-        return Age.fromPanasonicString(ageString);
-	}
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/PentaxMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/PentaxMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,160 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.makernotes.PentaxMakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link PentaxMakernoteDirectory}.
- * <p>
- * Some information about this makernote taken from here:
- * http://www.ozhiker.com/electronics/pjmt/jpeg_info/pentax_mn.html
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class PentaxMakernoteDescriptor extends TagDescriptor<PentaxMakernoteDirectory>
-{
-    public PentaxMakernoteDescriptor(@NotNull PentaxMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_CAPTURE_MODE:
-                return getCaptureModeDescription();
-            case TAG_QUALITY_LEVEL:
-                return getQualityLevelDescription();
-            case TAG_FOCUS_MODE:
-                return getFocusModeDescription();
-            case TAG_FLASH_MODE:
-                return getFlashModeDescription();
-            case TAG_WHITE_BALANCE:
-                return getWhiteBalanceDescription();
-            case TAG_DIGITAL_ZOOM:
-                return getDigitalZoomDescription();
-            case TAG_SHARPNESS:
-                return getSharpnessDescription();
-            case TAG_CONTRAST:
-                return getContrastDescription();
-            case TAG_SATURATION:
-                return getSaturationDescription();
-            case TAG_ISO_SPEED:
-                return getIsoSpeedDescription();
-            case TAG_COLOUR:
-                return getColourDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getColourDescription()
-    {
-        return getIndexedDescription(TAG_COLOUR, 1, "Normal", "Black & White", "Sepia");
-    }
-
-    @Nullable
-    public String getIsoSpeedDescription()
-    {
-        Integer value = _directory.getInteger(TAG_ISO_SPEED);
-        if (value == null)
-            return null;
-        switch (value) {
-            // TODO there must be other values which aren't catered for here
-            case 10: return "ISO 100";
-            case 16: return "ISO 200";
-            case 100: return "ISO 100";
-            case 200: return "ISO 200";
-            default: return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getSaturationDescription()
-    {
-        return getIndexedDescription(TAG_SATURATION, "Normal", "Low", "High");
-    }
-
-    @Nullable
-    public String getContrastDescription()
-    {
-        return getIndexedDescription(TAG_CONTRAST, "Normal", "Low", "High");
-    }
-
-    @Nullable
-    public String getSharpnessDescription()
-    {
-        return getIndexedDescription(TAG_SHARPNESS, "Normal", "Soft", "Hard");
-    }
-
-    @Nullable
-    public String getDigitalZoomDescription()
-    {
-        Float value = _directory.getFloatObject(TAG_DIGITAL_ZOOM);
-        if (value == null)
-            return null;
-        if (value == 0)
-            return "Off";
-        return Float.toString(value);
-    }
-
-    @Nullable
-    public String getWhiteBalanceDescription()
-    {
-        return getIndexedDescription(TAG_WHITE_BALANCE,
-            "Auto", "Daylight", "Shade", "Tungsten", "Fluorescent", "Manual");
-    }
-
-    @Nullable
-    public String getFlashModeDescription()
-    {
-        return getIndexedDescription(TAG_FLASH_MODE,
-            1, "Auto", "Flash On", null, "Flash Off", null, "Red-eye Reduction");
-    }
-
-    @Nullable
-    public String getFocusModeDescription()
-    {
-        return getIndexedDescription(TAG_FOCUS_MODE, 2, "Custom", "Auto");
-    }
-
-    @Nullable
-    public String getQualityLevelDescription()
-    {
-        return getIndexedDescription(TAG_QUALITY_LEVEL, "Good", "Better", "Best");
-    }
-
-    @Nullable
-    public String getCaptureModeDescription()
-    {
-        return getIndexedDescription(TAG_CAPTURE_MODE,
-            "Auto", "Night-scene", "Manual", null, "Multiple");
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/PentaxMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/PentaxMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,171 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific to Pentax and Asahi cameras.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class PentaxMakernoteDirectory extends Directory
-{
-    /**
-     * 0 = Auto
-     * 1 = Night-scene
-     * 2 = Manual
-     * 4 = Multiple
-     */
-    public static final int TAG_CAPTURE_MODE = 0x0001;
-
-    /**
-     * 0 = Good
-     * 1 = Better
-     * 2 = Best
-     */
-    public static final int TAG_QUALITY_LEVEL = 0x0002;
-
-    /**
-     * 2 = Custom
-     * 3 = Auto
-     */
-    public static final int TAG_FOCUS_MODE = 0x0003;
-
-    /**
-     * 1 = Auto
-     * 2 = Flash on
-     * 4 = Flash off
-     * 6 = Red-eye Reduction
-     */
-    public static final int TAG_FLASH_MODE = 0x0004;
-
-    /**
-     * 0 = Auto
-     * 1 = Daylight
-     * 2 = Shade
-     * 3 = Tungsten
-     * 4 = Fluorescent
-     * 5 = Manual
-     */
-    public static final int TAG_WHITE_BALANCE = 0x0007;
-
-    /**
-     * (0 = Off)
-     */
-    public static final int TAG_DIGITAL_ZOOM = 0x000A;
-
-    /**
-     * 0 = Normal
-     * 1 = Soft
-     * 2 = Hard
-     */
-    public static final int TAG_SHARPNESS = 0x000B;
-
-    /**
-     * 0 = Normal
-     * 1 = Low
-     * 2 = High
-     */
-    public static final int TAG_CONTRAST = 0x000C;
-
-    /**
-     * 0 = Normal
-     * 1 = Low
-     * 2 = High
-     */
-    public static final int TAG_SATURATION = 0x000D;
-
-    /**
-     * 10 = ISO 100
-     * 16 = ISO 200
-     * 100 = ISO 100
-     * 200 = ISO 200
-     */
-    public static final int TAG_ISO_SPEED = 0x0014;
-
-    /**
-     * 1 = Normal
-     * 2 = Black &amp; White
-     * 3 = Sepia
-     */
-    public static final int TAG_COLOUR = 0x0017;
-
-    /**
-     * See Print Image Matching for specification.
-     * http://www.ozhiker.com/electronics/pjmt/jpeg_info/pim.html
-     */
-    public static final int TAG_PRINT_IMAGE_MATCHING_INFO = 0x0E00;
-
-    /**
-     * (String).
-     */
-    public static final int TAG_TIME_ZONE = 0x1000;
-
-    /**
-     * (String).
-     */
-    public static final int TAG_DAYLIGHT_SAVINGS = 0x1001;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TAG_CAPTURE_MODE, "Capture Mode");
-        _tagNameMap.put(TAG_QUALITY_LEVEL, "Quality Level");
-        _tagNameMap.put(TAG_FOCUS_MODE, "Focus Mode");
-        _tagNameMap.put(TAG_FLASH_MODE, "Flash Mode");
-        _tagNameMap.put(TAG_WHITE_BALANCE, "White Balance");
-        _tagNameMap.put(TAG_DIGITAL_ZOOM, "Digital Zoom");
-        _tagNameMap.put(TAG_SHARPNESS, "Sharpness");
-        _tagNameMap.put(TAG_CONTRAST, "Contrast");
-        _tagNameMap.put(TAG_SATURATION, "Saturation");
-        _tagNameMap.put(TAG_ISO_SPEED, "ISO Speed");
-        _tagNameMap.put(TAG_COLOUR, "Colour");
-        _tagNameMap.put(TAG_PRINT_IMAGE_MATCHING_INFO, "Print Image Matching (PIM) Info");
-        _tagNameMap.put(TAG_TIME_ZONE, "Time Zone");
-        _tagNameMap.put(TAG_DAYLIGHT_SAVINGS, "Daylight Savings");
-    }
-
-    public PentaxMakernoteDirectory()
-    {
-        this.setDescriptor(new PentaxMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Pentax Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/ReconyxHyperFireMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/ReconyxHyperFireMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,105 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.StringValue;
-import com.drew.metadata.TagDescriptor;
-
-import java.text.DateFormat;
-import java.text.DecimalFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-
-import static com.drew.metadata.exif.makernotes.ReconyxHyperFireMakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link ReconyxHyperFireMakernoteDirectory}.
- *
- * @author Todd West http://cascadescarnivoreproject.blogspot.com
- */
-@SuppressWarnings("WeakerAccess")
-public class ReconyxHyperFireMakernoteDescriptor extends TagDescriptor<ReconyxHyperFireMakernoteDirectory>
-{
-    public ReconyxHyperFireMakernoteDescriptor(@NotNull ReconyxHyperFireMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_MAKERNOTE_VERSION:
-                return String.format("%d", _directory.getInteger(tagType));
-            case TAG_FIRMWARE_VERSION:
-                return _directory.getString(tagType);
-            case TAG_TRIGGER_MODE:
-                return _directory.getString(tagType);
-            case TAG_SEQUENCE:
-                int[] sequence = _directory.getIntArray(tagType);
-                if (sequence == null)
-                    return null;
-                return String.format("%d/%d", sequence[0], sequence[1]);
-            case TAG_EVENT_NUMBER:
-                return String.format("%d", _directory.getInteger(tagType));
-            case TAG_MOTION_SENSITIVITY:
-                return String.format("%d", _directory.getInteger(tagType));
-            case TAG_BATTERY_VOLTAGE:
-                Double value = _directory.getDoubleObject(tagType);
-                DecimalFormat formatter = new DecimalFormat("0.000");
-                return value == null ? null : formatter.format(value);
-            case TAG_DATE_TIME_ORIGINAL:
-                String date = _directory.getString(tagType);
-                try {
-                    DateFormat parser = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
-                    return parser.format(parser.parse(date));
-                } catch (ParseException e) {
-                    return null;
-                }
-            case TAG_MOON_PHASE:
-                return getIndexedDescription(tagType, "New", "Waxing Crescent", "First Quarter", "Waxing Gibbous", "Full", "Waning Gibbous", "Last Quarter", "Waning Crescent");
-            case TAG_AMBIENT_TEMPERATURE_FAHRENHEIT:
-            case TAG_AMBIENT_TEMPERATURE:
-                return String.format("%d", _directory.getInteger(tagType));
-            case TAG_SERIAL_NUMBER:
-                // default is UTF_16LE
-                StringValue svalue = _directory.getStringValue(tagType);
-                if(svalue == null)
-                    return null;
-                return svalue.toString();
-            case TAG_CONTRAST:
-            case TAG_BRIGHTNESS:
-            case TAG_SHARPNESS:
-            case TAG_SATURATION:
-                return String.format("%d", _directory.getInteger(tagType));
-            case TAG_INFRARED_ILLUMINATOR:
-                return getIndexedDescription(tagType, "Off", "On");
-            case TAG_USER_LABEL:
-                return _directory.getString(tagType);
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/ReconyxHyperFireMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/ReconyxHyperFireMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,105 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific to Reconyx HyperFire cameras.
- *
- * Reconyx uses a fixed makernote block.  Tag values are the byte index of the tag within the makernote.
- * @author Todd West http://cascadescarnivoreproject.blogspot.com
- */
-@SuppressWarnings("WeakerAccess")
-public class ReconyxHyperFireMakernoteDirectory extends Directory
-{
-    /**
-     * Version number used for identifying makernotes from Reconyx HyperFire cameras.
-     */
-    public static final int MAKERNOTE_VERSION = 61697;
-
-    public static final int TAG_MAKERNOTE_VERSION = 0;
-    public static final int TAG_FIRMWARE_VERSION = 2;
-    public static final int TAG_TRIGGER_MODE = 12;
-    public static final int TAG_SEQUENCE = 14;
-    public static final int TAG_EVENT_NUMBER = 18;
-    public static final int TAG_DATE_TIME_ORIGINAL = 22;
-    public static final int TAG_MOON_PHASE = 36;
-    public static final int TAG_AMBIENT_TEMPERATURE_FAHRENHEIT = 38;
-    public static final int TAG_AMBIENT_TEMPERATURE = 40;
-    public static final int TAG_SERIAL_NUMBER = 42;
-    public static final int TAG_CONTRAST = 72;
-    public static final int TAG_BRIGHTNESS = 74;
-    public static final int TAG_SHARPNESS = 76;
-    public static final int TAG_SATURATION = 78;
-    public static final int TAG_INFRARED_ILLUMINATOR = 80;
-    public static final int TAG_MOTION_SENSITIVITY = 82;
-    public static final int TAG_BATTERY_VOLTAGE = 84;
-    public static final int TAG_USER_LABEL = 86;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TAG_MAKERNOTE_VERSION, "Makernote Version");
-        _tagNameMap.put(TAG_FIRMWARE_VERSION, "Firmware Version");
-        _tagNameMap.put(TAG_TRIGGER_MODE, "Trigger Mode");
-        _tagNameMap.put(TAG_SEQUENCE, "Sequence");
-        _tagNameMap.put(TAG_EVENT_NUMBER, "Event Number");
-        _tagNameMap.put(TAG_DATE_TIME_ORIGINAL, "Date/Time Original");
-        _tagNameMap.put(TAG_MOON_PHASE, "Moon Phase");
-        _tagNameMap.put(TAG_AMBIENT_TEMPERATURE_FAHRENHEIT, "Ambient Temperature Fahrenheit");
-        _tagNameMap.put(TAG_AMBIENT_TEMPERATURE, "Ambient Temperature");
-        _tagNameMap.put(TAG_SERIAL_NUMBER, "Serial Number");
-        _tagNameMap.put(TAG_CONTRAST, "Contrast");
-        _tagNameMap.put(TAG_BRIGHTNESS, "Brightness");
-        _tagNameMap.put(TAG_SHARPNESS, "Sharpness");
-        _tagNameMap.put(TAG_SATURATION, "Saturation");
-        _tagNameMap.put(TAG_INFRARED_ILLUMINATOR, "Infrared Illuminator");
-        _tagNameMap.put(TAG_MOTION_SENSITIVITY, "Motion Sensitivity");
-        _tagNameMap.put(TAG_BATTERY_VOLTAGE, "Battery Voltage");
-        _tagNameMap.put(TAG_USER_LABEL, "User Label");
-    }
-
-    public ReconyxHyperFireMakernoteDirectory()
-    {
-        this.setDescriptor(new ReconyxHyperFireMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Reconyx HyperFire Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/ReconyxUltraFireMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/ReconyxUltraFireMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,110 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.StringValue;
-import com.drew.metadata.TagDescriptor;
-
-import java.text.DateFormat;
-import java.text.DecimalFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-
-import static com.drew.metadata.exif.makernotes.ReconyxUltraFireMakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link ReconyxUltraFireMakernoteDirectory}.
- *
- * @author Todd West http://cascadescarnivoreproject.blogspot.com
- */
-@SuppressWarnings("WeakerAccess")
-public class ReconyxUltraFireMakernoteDescriptor extends TagDescriptor<ReconyxUltraFireMakernoteDirectory>
-{
-    public ReconyxUltraFireMakernoteDescriptor(@NotNull ReconyxUltraFireMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_LABEL:
-                return _directory.getString(tagType);
-            case TAG_MAKERNOTE_ID:
-                return String.format("0x%08X", _directory.getInteger(tagType));
-            case TAG_MAKERNOTE_SIZE:
-                return String.format("%d", _directory.getInteger(tagType));
-            case TAG_MAKERNOTE_PUBLIC_ID:
-                return String.format("0x%08X", _directory.getInteger(tagType));
-            case TAG_MAKERNOTE_PUBLIC_SIZE:
-                return String.format("%d", _directory.getInteger(tagType));
-            case TAG_CAMERA_VERSION:
-            case TAG_UIB_VERSION:
-            case TAG_BTL_VERSION:
-            case TAG_PEX_VERSION:
-            case TAG_EVENT_TYPE:
-                return _directory.getString(tagType);
-            case TAG_SEQUENCE:
-                int[] sequence = _directory.getIntArray(tagType);
-                if (sequence == null)
-                    return null;
-                return String.format("%d/%d", sequence[0], sequence[1]);
-            case TAG_EVENT_NUMBER:
-                return String.format("%d", _directory.getInteger(tagType));
-            case TAG_DATE_TIME_ORIGINAL:
-                String date = _directory.getString(tagType);
-                try {
-                    DateFormat parser = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss");
-                    return parser.format(parser.parse(date));
-                } catch (ParseException e) {
-                    return null;
-                }
-            /*case TAG_DAY_OF_WEEK:
-                return getIndexedDescription(tagType, CultureInfo.CurrentCulture.DateTimeFormat.DayNames);*/
-            case TAG_MOON_PHASE:
-                return getIndexedDescription(tagType, "New", "Waxing Crescent", "First Quarter", "Waxing Gibbous", "Full", "Waning Gibbous", "Last Quarter", "Waning Crescent");
-            case TAG_AMBIENT_TEMPERATURE_FAHRENHEIT:
-            case TAG_AMBIENT_TEMPERATURE:
-                return String.format("%d", _directory.getInteger(tagType));
-            case TAG_FLASH:
-                return getIndexedDescription(tagType, "Off", "On");
-            case TAG_BATTERY_VOLTAGE:
-                Double value = _directory.getDoubleObject(tagType);
-                DecimalFormat formatter = new DecimalFormat("0.000");
-                return value == null ? null : formatter.format(value);
-            case TAG_SERIAL_NUMBER:
-                // default is UTF_8
-                StringValue svalue = _directory.getStringValue(tagType);
-                if(svalue == null)
-                    return null;
-                return svalue.toString();
-            case TAG_USER_LABEL:
-                return _directory.getString(tagType);
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/ReconyxUltraFireMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/ReconyxUltraFireMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,116 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific to Reconyx UltraFire cameras.
- *
- * Reconyx uses a fixed makernote block.  Tag values are the byte index of the tag within the makernote.
- * @author Todd West http://cascadescarnivoreproject.blogspot.com
- */
-@SuppressWarnings("WeakerAccess")
-public class ReconyxUltraFireMakernoteDirectory extends Directory
-{
-    /**
-     * Version number used for identifying makernotes from Reconyx UltraFire cameras.
-     */
-    public static final int MAKERNOTE_ID = 0x00010000;
-
-    /**
-     * Version number used for identifying the public portion of makernotes from Reconyx UltraFire cameras.
-     */
-    public static final int MAKERNOTE_PUBLIC_ID = 0x07f10001;
-
-    public static final int TAG_LABEL = 0;
-    public static final int TAG_MAKERNOTE_ID = 10;
-    public static final int TAG_MAKERNOTE_SIZE = 14;
-    public static final int TAG_MAKERNOTE_PUBLIC_ID = 18;
-    public static final int TAG_MAKERNOTE_PUBLIC_SIZE = 22;
-    public static final int TAG_CAMERA_VERSION = 24;
-    public static final int TAG_UIB_VERSION = 31;
-    public static final int TAG_BTL_VERSION = 38;
-    public static final int TAG_PEX_VERSION = 45;
-    public static final int TAG_EVENT_TYPE = 52;
-    public static final int TAG_SEQUENCE = 53;
-    public static final int TAG_EVENT_NUMBER = 55;
-    public static final int TAG_DATE_TIME_ORIGINAL = 59;
-    public static final int TAG_DAY_OF_WEEK = 66;
-    public static final int TAG_MOON_PHASE = 67;
-    public static final int TAG_AMBIENT_TEMPERATURE_FAHRENHEIT = 68;
-    public static final int TAG_AMBIENT_TEMPERATURE = 70;
-    public static final int TAG_FLASH = 72;
-    public static final int TAG_BATTERY_VOLTAGE = 73;
-    public static final int TAG_SERIAL_NUMBER = 75;
-    public static final int TAG_USER_LABEL = 80;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TAG_LABEL, "Makernote Label");
-        _tagNameMap.put(TAG_MAKERNOTE_ID, "Makernote ID");
-        _tagNameMap.put(TAG_MAKERNOTE_SIZE, "Makernote Size");
-        _tagNameMap.put(TAG_MAKERNOTE_PUBLIC_ID, "Makernote Public ID");
-        _tagNameMap.put(TAG_MAKERNOTE_PUBLIC_SIZE, "Makernote Public Size");
-        _tagNameMap.put(TAG_CAMERA_VERSION, "Camera Version");
-        _tagNameMap.put(TAG_UIB_VERSION, "Uib Version");
-        _tagNameMap.put(TAG_BTL_VERSION, "Btl Version");
-        _tagNameMap.put(TAG_PEX_VERSION, "Pex Version");
-        _tagNameMap.put(TAG_EVENT_TYPE, "Event Type");
-        _tagNameMap.put(TAG_SEQUENCE, "Sequence");
-        _tagNameMap.put(TAG_EVENT_NUMBER, "Event Number");
-        _tagNameMap.put(TAG_DATE_TIME_ORIGINAL, "Date/Time Original");
-        _tagNameMap.put(TAG_DAY_OF_WEEK, "Day of Week");
-        _tagNameMap.put(TAG_MOON_PHASE, "Moon Phase");
-        _tagNameMap.put(TAG_AMBIENT_TEMPERATURE_FAHRENHEIT, "Ambient Temperature Fahrenheit");
-        _tagNameMap.put(TAG_AMBIENT_TEMPERATURE, "Ambient Temperature");
-        _tagNameMap.put(TAG_FLASH, "Flash");
-        _tagNameMap.put(TAG_BATTERY_VOLTAGE, "Battery Voltage");
-        _tagNameMap.put(TAG_SERIAL_NUMBER, "Serial Number");
-        _tagNameMap.put(TAG_USER_LABEL, "User Label");
-    }
-
-    public ReconyxUltraFireMakernoteDirectory()
-    {
-        this.setDescriptor(new ReconyxUltraFireMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Reconyx UltraFire Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/RicohMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/RicohMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,60 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link RicohMakernoteDirectory}.
- * <p>
- * Some information about this makernote taken from here:
- * http://www.ozhiker.com/electronics/pjmt/jpeg_info/ricoh_mn.html
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class RicohMakernoteDescriptor extends TagDescriptor<RicohMakernoteDirectory>
-{
-    public RicohMakernoteDescriptor(@NotNull RicohMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-//            case TAG_PROPRIETARY_THUMBNAIL:
-//                return getProprietaryThumbnailDataDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-//
-//    @Nullable
-//    public String getProprietaryThumbnailDataDescription()
-//    {
-//        return getByteLengthDescription(TAG_PROPRIETARY_THUMBNAIL);
-//    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/RicohMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/RicohMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,70 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific to Ricoh cameras.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class RicohMakernoteDirectory extends Directory
-{
-    public static final int TAG_MAKERNOTE_DATA_TYPE = 0x0001;
-    public static final int TAG_VERSION = 0x0002;
-    public static final int TAG_PRINT_IMAGE_MATCHING_INFO = 0x0E00;
-    public static final int TAG_RICOH_CAMERA_INFO_MAKERNOTE_SUB_IFD_POINTER = 0x2001;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TAG_MAKERNOTE_DATA_TYPE, "Makernote Data Type");
-        _tagNameMap.put(TAG_VERSION, "Version");
-        _tagNameMap.put(TAG_PRINT_IMAGE_MATCHING_INFO, "Print Image Matching (PIM) Info");
-        _tagNameMap.put(TAG_RICOH_CAMERA_INFO_MAKERNOTE_SUB_IFD_POINTER, "Ricoh Camera Info Makernote Sub-IFD");
-    }
-
-    public RicohMakernoteDirectory()
-    {
-        this.setDescriptor(new RicohMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Ricoh Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/SamsungType2MakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/SamsungType2MakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,213 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.makernotes.SamsungType2MakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link SamsungType2MakernoteDirectory}.
- * <p>
- * Tag reference from: http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Samsung.html
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class SamsungType2MakernoteDescriptor extends TagDescriptor<SamsungType2MakernoteDirectory>
-{
-    public SamsungType2MakernoteDescriptor(@NotNull SamsungType2MakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TagMakerNoteVersion:
-                return getMakernoteVersionDescription();
-            case TagDeviceType:
-                return getDeviceTypeDescription();
-            case TagSamsungModelId:
-                return getSamsungModelIdDescription();
-
-            case TagCameraTemperature:
-                return getCameraTemperatureDescription();
-
-            case TagFaceDetect:
-                return getFaceDetectDescription();
-            case TagFaceRecognition:
-                return getFaceRecognitionDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getMakernoteVersionDescription()
-    {
-        return getVersionBytesDescription(TagMakerNoteVersion, 2);
-    }
-
-    @Nullable
-    public String getDeviceTypeDescription()
-    {
-        Integer value = _directory.getInteger(TagDeviceType);
-        if (value == null)
-            return null;
-
-        switch (value)
-        {
-            case 0x1000:
-                return "Compact Digital Camera";
-            case 0x2000:
-                return "High-end NX Camera";
-            case 0x3000:
-                return "HXM Video Camera";
-            case 0x12000:
-                return "Cell Phone";
-            case 0x300000:
-                return "SMX Video Camera";
-            default:
-                return String.format("Unknown (%d)", value);
-        }
-    }
-
-    @Nullable
-    public String getSamsungModelIdDescription()
-    {
-        Integer value = _directory.getInteger(TagSamsungModelId);
-        if (value == null)
-            return null;
-
-        switch (value)
-        {
-            case 0x100101c:
-                return "NX10";
-            /*case 0x1001226:
-                    return "HMX-S10BP";*/
-            case 0x1001226:
-                    return "HMX-S15BP";
-            case 0x1001233:
-                    return "HMX-Q10";
-            /*case 0x1001234:
-                    return "HMX-H300";*/
-            case 0x1001234:
-                    return "HMX-H304";
-            case 0x100130c:
-                    return "NX100";
-            case 0x1001327:
-                    return "NX11";
-            case 0x170104e:
-                    return "ES70, ES71 / VLUU ES70, ES71 / SL600";
-            case 0x1701052:
-                    return "ES73 / VLUU ES73 / SL605";
-            case 0x1701300:
-                    return "ES28 / VLUU ES28";
-            case 0x1701303:
-                    return "ES74,ES75,ES78 / VLUU ES75,ES78";
-            case 0x2001046:
-                    return "PL150 / VLUU PL150 / TL210 / PL151";
-            case 0x2001311:
-                    return "PL120,PL121 / VLUU PL120,PL121";
-            case 0x2001315:
-                    return "PL170,PL171 / VLUUPL170,PL171";
-            case 0x200131e:
-                    return "PL210, PL211 / VLUU PL210, PL211";
-            case 0x2701317:
-                    return "PL20,PL21 / VLUU PL20,PL21";
-            case 0x2a0001b:
-                    return "WP10 / VLUU WP10 / AQ100";
-            case 0x3000000:
-                    return "Various Models (0x3000000)";
-            case 0x3a00018:
-                    return "Various Models (0x3a00018)";
-            case 0x400101f:
-                    return "ST1000 / ST1100 / VLUU ST1000 / CL65";
-            case 0x4001022:
-                    return "ST550 / VLUU ST550 / TL225";
-            case 0x4001025:
-                    return "Various Models (0x4001025)";
-            case 0x400103e:
-                    return "VLUU ST5500, ST5500, CL80";
-            case 0x4001041:
-                    return "VLUU ST5000, ST5000, TL240";
-            case 0x4001043:
-                    return "ST70 / VLUU ST70 / ST71";
-            case 0x400130a:
-                    return "Various Models (0x400130a)";
-            case 0x400130e:
-                    return "ST90,ST91 / VLUU ST90,ST91";
-            case 0x4001313:
-                    return "VLUU ST95, ST95";
-            case 0x4a00015:
-                    return "VLUU ST60";
-            case 0x4a0135b:
-                    return "ST30, ST65 / VLUU ST65 / ST67";
-            case 0x5000000:
-                    return "Various Models (0x5000000)";
-            case 0x5001038:
-                    return "Various Models (0x5001038)";
-            case 0x500103a:
-                    return "WB650 / VLUU WB650 / WB660";
-            case 0x500103c:
-                    return "WB600 / VLUU WB600 / WB610";
-            case 0x500133e:
-                    return "WB150 / WB150F / WB152 / WB152F / WB151";
-            case 0x5a0000f:
-                    return "WB5000 / HZ25W";
-            case 0x6001036:
-                    return "EX1";
-            case 0x700131c:
-                    return "VLUU SH100, SH100";
-            case 0x27127002:
-                    return "SMX - C20N";
-            default:
-                return String.format("Unknown (%d)", value);
-        }
-    }
-
-    @Nullable
-    private String getCameraTemperatureDescription()
-    {
-        return getFormattedInt(TagCameraTemperature, "%d C");
-    }
-
-    @Nullable
-    public String getFaceDetectDescription()
-    {
-        return getIndexedDescription(TagFaceDetect,
-            "Off", "On");
-    }
-
-    @Nullable
-    public String getFaceRecognitionDescription()
-    {
-        return getIndexedDescription(TagFaceRecognition,
-            "Off", "On");
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/SamsungType2MakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/SamsungType2MakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,89 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific certain 'newer' Samsung cameras.
- * <p>
- * Tag reference from: http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Samsung.html
- *
- * @author Kevin Mott https://github.com/kwhopper
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class SamsungType2MakernoteDirectory extends Directory
-{
-    // This list is incomplete
-    public static final int TagMakerNoteVersion = 0x001;
-    public static final int TagDeviceType = 0x0002;
-    public static final int TagSamsungModelId = 0x0003;
-
-    public static final int TagCameraTemperature = 0x0043;
-
-    public static final int TagFaceDetect = 0x0100;
-    public static final int TagFaceRecognition = 0x0120;
-    public static final int TagFaceName = 0x0123;
-
-    // following tags found only in SRW images
-    public static final int TagFirmwareName = 0xa001;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TagMakerNoteVersion, "Maker Note Version");
-        _tagNameMap.put(TagDeviceType, "Device Type");
-        _tagNameMap.put(TagSamsungModelId, "Model Id");
-
-        _tagNameMap.put(TagCameraTemperature, "Camera Temperature");
-
-        _tagNameMap.put(TagFaceDetect, "Face Detect");
-        _tagNameMap.put(TagFaceRecognition, "Face Recognition");
-        _tagNameMap.put(TagFaceName, "Face Name");
-        _tagNameMap.put(TagFirmwareName, "Firmware Name");
-    }
-
-    public SamsungType2MakernoteDirectory()
-    {
-        this.setDescriptor(new SamsungType2MakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Samsung Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/SanyoMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/SanyoMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,229 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.makernotes.SanyoMakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link com.drew.metadata.exif.makernotes.SonyType6MakernoteDirectory}.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class SanyoMakernoteDescriptor extends TagDescriptor<SanyoMakernoteDirectory>
-{
-    public SanyoMakernoteDescriptor(@NotNull SanyoMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_SANYO_QUALITY:
-                return getSanyoQualityDescription();
-            case TAG_MACRO:
-                return getMacroDescription();
-            case TAG_DIGITAL_ZOOM:
-                return getDigitalZoomDescription();
-            case TAG_SEQUENTIAL_SHOT:
-                return getSequentialShotDescription();
-            case TAG_WIDE_RANGE:
-                return getWideRangeDescription();
-            case TAG_COLOR_ADJUSTMENT_MODE:
-                return getColorAdjustmentModeDescription();
-            case TAG_QUICK_SHOT:
-                return getQuickShotDescription();
-            case TAG_SELF_TIMER:
-                return getSelfTimerDescription();
-            case TAG_VOICE_MEMO:
-                return getVoiceMemoDescription();
-            case TAG_RECORD_SHUTTER_RELEASE:
-                return getRecordShutterDescription();
-            case TAG_FLICKER_REDUCE:
-                return getFlickerReduceDescription();
-            case TAG_OPTICAL_ZOOM_ON:
-                return getOptimalZoomOnDescription();
-            case TAG_DIGITAL_ZOOM_ON:
-                return getDigitalZoomOnDescription();
-            case TAG_LIGHT_SOURCE_SPECIAL:
-                return getLightSourceSpecialDescription();
-            case TAG_RESAVED:
-                return getResavedDescription();
-            case TAG_SCENE_SELECT:
-                return getSceneSelectDescription();
-            case TAG_SEQUENCE_SHOT_INTERVAL:
-                return getSequenceShotIntervalDescription();
-            case TAG_FLASH_MODE:
-                return getFlashModeDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getSanyoQualityDescription()
-    {
-        Integer value = _directory.getInteger(TAG_SANYO_QUALITY);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0x0: return "Normal/Very Low";
-            case 0x1: return "Normal/Low";
-            case 0x2: return "Normal/Medium Low";
-            case 0x3: return "Normal/Medium";
-            case 0x4: return "Normal/Medium High";
-            case 0x5: return "Normal/High";
-            case 0x6: return "Normal/Very High";
-            case 0x7: return "Normal/Super High";
-            case 0x100: return "Fine/Very Low";
-            case 0x101: return "Fine/Low";
-            case 0x102: return "Fine/Medium Low";
-            case 0x103: return "Fine/Medium";
-            case 0x104: return "Fine/Medium High";
-            case 0x105: return "Fine/High";
-            case 0x106: return "Fine/Very High";
-            case 0x107: return "Fine/Super High";
-            case 0x200: return "Super Fine/Very Low";
-            case 0x201: return "Super Fine/Low";
-            case 0x202: return "Super Fine/Medium Low";
-            case 0x203: return "Super Fine/Medium";
-            case 0x204: return "Super Fine/Medium High";
-            case 0x205: return "Super Fine/High";
-            case 0x206: return "Super Fine/Very High";
-            case 0x207: return "Super Fine/Super High";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    private String getMacroDescription()
-    {
-        return getIndexedDescription(TAG_MACRO, "Normal", "Macro", "View", "Manual");
-    }
-
-    @Nullable
-    private String getDigitalZoomDescription()
-    {
-        return getDecimalRational(TAG_DIGITAL_ZOOM, 3);
-    }
-
-    @Nullable
-    private String getSequentialShotDescription()
-    {
-        return getIndexedDescription(TAG_SEQUENTIAL_SHOT, "None", "Standard", "Best", "Adjust Exposure");
-    }
-
-    @Nullable
-    private String getWideRangeDescription()
-    {
-        return getIndexedDescription(TAG_WIDE_RANGE, "Off", "On");
-    }
-
-    @Nullable
-    private String getColorAdjustmentModeDescription()
-    {
-        return getIndexedDescription(TAG_COLOR_ADJUSTMENT_MODE, "Off", "On");
-    }
-
-    @Nullable
-    private String getQuickShotDescription()
-    {
-        return getIndexedDescription(TAG_QUICK_SHOT, "Off", "On");
-    }
-
-    @Nullable
-    private String getSelfTimerDescription()
-    {
-        return getIndexedDescription(TAG_SELF_TIMER, "Off", "On");
-    }
-
-    @Nullable
-    private String getVoiceMemoDescription()
-    {
-        return getIndexedDescription(TAG_VOICE_MEMO, "Off", "On");
-    }
-
-    @Nullable
-    private String getRecordShutterDescription()
-    {
-        return getIndexedDescription(TAG_RECORD_SHUTTER_RELEASE, "Record while down", "Press start, press stop");
-    }
-
-    @Nullable
-    private String getFlickerReduceDescription()
-    {
-        return getIndexedDescription(TAG_FLICKER_REDUCE, "Off", "On");
-    }
-
-    @Nullable
-    private String getOptimalZoomOnDescription()
-    {
-        return getIndexedDescription(TAG_OPTICAL_ZOOM_ON, "Off", "On");
-    }
-
-    @Nullable
-    private String getDigitalZoomOnDescription()
-    {
-        return getIndexedDescription(TAG_DIGITAL_ZOOM_ON, "Off", "On");
-    }
-
-    @Nullable
-    private String getLightSourceSpecialDescription()
-    {
-        return getIndexedDescription(TAG_LIGHT_SOURCE_SPECIAL, "Off", "On");
-    }
-
-    @Nullable
-    private String getResavedDescription()
-    {
-        return getIndexedDescription(TAG_RESAVED, "No", "Yes");
-    }
-
-    @Nullable
-    private String getSceneSelectDescription()
-    {
-        return getIndexedDescription(TAG_SCENE_SELECT,
-            "Off", "Sport", "TV", "Night", "User 1", "User 2", "Lamp");
-    }
-
-    @Nullable
-    private String getSequenceShotIntervalDescription()
-    {
-        return getIndexedDescription(TAG_SEQUENCE_SHOT_INTERVAL,
-            "5 frames/sec", "10 frames/sec", "15 frames/sec", "20 frames/sec");
-    }
-
-    @Nullable
-    private String getFlashModeDescription()
-    {
-        return getIndexedDescription(TAG_FLASH_MODE,
-            "Auto", "Force", "Disabled", "Red eye");
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/SanyoMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/SanyoMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,125 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific to Sanyo cameras.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class SanyoMakernoteDirectory extends Directory
-{
-    public static final int TAG_MAKERNOTE_OFFSET = 0x00ff;
-
-    public static final int TAG_SANYO_THUMBNAIL = 0x0100;
-
-    public static final int TAG_SPECIAL_MODE = 0x0200;
-    public static final int TAG_SANYO_QUALITY = 0x0201;
-    public static final int TAG_MACRO = 0x0202;
-    public static final int TAG_DIGITAL_ZOOM = 0x0204;
-    public static final int TAG_SOFTWARE_VERSION = 0x0207;
-    public static final int TAG_PICT_INFO = 0x0208;
-    public static final int TAG_CAMERA_ID = 0x0209;
-    public static final int TAG_SEQUENTIAL_SHOT = 0x020e;
-    public static final int TAG_WIDE_RANGE = 0x020f;
-    public static final int TAG_COLOR_ADJUSTMENT_MODE = 0x0210;
-    public static final int TAG_QUICK_SHOT = 0x0213;
-    public static final int TAG_SELF_TIMER = 0x0214;
-    public static final int TAG_VOICE_MEMO = 0x0216;
-    public static final int TAG_RECORD_SHUTTER_RELEASE = 0x0217;
-    public static final int TAG_FLICKER_REDUCE = 0x0218;
-    public static final int TAG_OPTICAL_ZOOM_ON = 0x0219;
-    public static final int TAG_DIGITAL_ZOOM_ON = 0x021b;
-    public static final int TAG_LIGHT_SOURCE_SPECIAL = 0x021d;
-    public static final int TAG_RESAVED = 0x021e;
-    public static final int TAG_SCENE_SELECT = 0x021f;
-    public static final int TAG_MANUAL_FOCUS_DISTANCE_OR_FACE_INFO = 0x0223;
-    public static final int TAG_SEQUENCE_SHOT_INTERVAL = 0x0224;
-    public static final int TAG_FLASH_MODE = 0x0225;
-
-    public static final int TAG_PRINT_IMAGE_MATCHING_INFO = 0x0E00;
-
-    public static final int TAG_DATA_DUMP = 0x0f00;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TAG_MAKERNOTE_OFFSET, "Makernote Offset");
-
-        _tagNameMap.put(TAG_SANYO_THUMBNAIL, "Sanyo Thumbnail");
-
-        _tagNameMap.put(TAG_SPECIAL_MODE, "Special Mode");
-        _tagNameMap.put(TAG_SANYO_QUALITY, "Sanyo Quality");
-        _tagNameMap.put(TAG_MACRO, "Macro");
-        _tagNameMap.put(TAG_DIGITAL_ZOOM, "Digital Zoom");
-        _tagNameMap.put(TAG_SOFTWARE_VERSION, "Software Version");
-        _tagNameMap.put(TAG_PICT_INFO, "Pict Info");
-        _tagNameMap.put(TAG_CAMERA_ID, "Camera ID");
-        _tagNameMap.put(TAG_SEQUENTIAL_SHOT, "Sequential Shot");
-        _tagNameMap.put(TAG_WIDE_RANGE, "Wide Range");
-        _tagNameMap.put(TAG_COLOR_ADJUSTMENT_MODE, "Color Adjustment Node");
-        _tagNameMap.put(TAG_QUICK_SHOT, "Quick Shot");
-        _tagNameMap.put(TAG_SELF_TIMER, "Self Timer");
-        _tagNameMap.put(TAG_VOICE_MEMO, "Voice Memo");
-        _tagNameMap.put(TAG_RECORD_SHUTTER_RELEASE, "Record Shutter Release");
-        _tagNameMap.put(TAG_FLICKER_REDUCE, "Flicker Reduce");
-        _tagNameMap.put(TAG_OPTICAL_ZOOM_ON, "Optical Zoom On");
-        _tagNameMap.put(TAG_DIGITAL_ZOOM_ON, "Digital Zoom On");
-        _tagNameMap.put(TAG_LIGHT_SOURCE_SPECIAL, "Light Source Special");
-        _tagNameMap.put(TAG_RESAVED, "Resaved");
-        _tagNameMap.put(TAG_SCENE_SELECT, "Scene Select");
-        _tagNameMap.put(TAG_MANUAL_FOCUS_DISTANCE_OR_FACE_INFO, "Manual Focus Distance or Face Info");
-        _tagNameMap.put(TAG_SEQUENCE_SHOT_INTERVAL, "Sequence Shot Interval");
-        _tagNameMap.put(TAG_FLASH_MODE, "Flash Mode");
-
-        _tagNameMap.put(TAG_PRINT_IMAGE_MATCHING_INFO, "Print IM");
-
-        _tagNameMap.put(TAG_DATA_DUMP, "Data Dump");
-    }
-
-    public SanyoMakernoteDirectory()
-    {
-        this.setDescriptor(new SanyoMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Sanyo Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/SigmaMakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/SigmaMakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,85 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.makernotes.SigmaMakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link SigmaMakernoteDirectory}.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class SigmaMakernoteDescriptor extends TagDescriptor<SigmaMakernoteDirectory>
-{
-    public SigmaMakernoteDescriptor(@NotNull SigmaMakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_EXPOSURE_MODE:
-                return getExposureModeDescription();
-            case TAG_METERING_MODE:
-                return getMeteringModeDescription();
-        }
-        return super.getDescription(tagType);
-    }
-
-    @Nullable
-    private String getMeteringModeDescription()
-    {
-        String value = _directory.getString(TAG_METERING_MODE);
-        if (value == null || value.length() == 0)
-            return null;
-        switch (value.charAt(0)) {
-            case '8': return "Multi Segment";
-            case 'A': return "Average";
-            case 'C': return "Center Weighted Average";
-            default:
-                return value;
-        }
-    }
-
-    @Nullable
-    private String getExposureModeDescription()
-    {
-        String value = _directory.getString(TAG_EXPOSURE_MODE);
-        if (value == null || value.length() == 0)
-            return null;
-        switch (value.charAt(0)) {
-            case 'A': return "Aperture Priority AE";
-            case 'M': return "Manual";
-            case 'P': return "Program AE";
-            case 'S': return "Shutter Speed Priority AE";
-            default:
-                return value;
-        }
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/SigmaMakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/SigmaMakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,110 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific to Sigma / Foveon cameras.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class SigmaMakernoteDirectory extends Directory
-{
-    public static final int TAG_SERIAL_NUMBER = 0x2;
-    public static final int TAG_DRIVE_MODE = 0x3;
-    public static final int TAG_RESOLUTION_MODE = 0x4;
-    public static final int TAG_AUTO_FOCUS_MODE = 0x5;
-    public static final int TAG_FOCUS_SETTING = 0x6;
-    public static final int TAG_WHITE_BALANCE = 0x7;
-    public static final int TAG_EXPOSURE_MODE = 0x8;
-    public static final int TAG_METERING_MODE = 0x9;
-    public static final int TAG_LENS_RANGE = 0xa;
-    public static final int TAG_COLOR_SPACE = 0xb;
-    public static final int TAG_EXPOSURE = 0xc;
-    public static final int TAG_CONTRAST = 0xd;
-    public static final int TAG_SHADOW = 0xe;
-    public static final int TAG_HIGHLIGHT = 0xf;
-    public static final int TAG_SATURATION = 0x10;
-    public static final int TAG_SHARPNESS = 0x11;
-    public static final int TAG_FILL_LIGHT = 0x12;
-    public static final int TAG_COLOR_ADJUSTMENT = 0x14;
-    public static final int TAG_ADJUSTMENT_MODE = 0x15;
-    public static final int TAG_QUALITY = 0x16;
-    public static final int TAG_FIRMWARE = 0x17;
-    public static final int TAG_SOFTWARE = 0x18;
-    public static final int TAG_AUTO_BRACKET = 0x19;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TAG_SERIAL_NUMBER, "Serial Number");
-        _tagNameMap.put(TAG_DRIVE_MODE, "Drive Mode");
-        _tagNameMap.put(TAG_RESOLUTION_MODE, "Resolution Mode");
-        _tagNameMap.put(TAG_AUTO_FOCUS_MODE, "Auto Focus Mode");
-        _tagNameMap.put(TAG_FOCUS_SETTING, "Focus Setting");
-        _tagNameMap.put(TAG_WHITE_BALANCE, "White Balance");
-        _tagNameMap.put(TAG_EXPOSURE_MODE, "Exposure Mode");
-        _tagNameMap.put(TAG_METERING_MODE, "Metering Mode");
-        _tagNameMap.put(TAG_LENS_RANGE, "Lens Range");
-        _tagNameMap.put(TAG_COLOR_SPACE, "Color Space");
-        _tagNameMap.put(TAG_EXPOSURE, "Exposure");
-        _tagNameMap.put(TAG_CONTRAST, "Contrast");
-        _tagNameMap.put(TAG_SHADOW, "Shadow");
-        _tagNameMap.put(TAG_HIGHLIGHT, "Highlight");
-        _tagNameMap.put(TAG_SATURATION, "Saturation");
-        _tagNameMap.put(TAG_SHARPNESS, "Sharpness");
-        _tagNameMap.put(TAG_FILL_LIGHT, "Fill Light");
-        _tagNameMap.put(TAG_COLOR_ADJUSTMENT, "Color Adjustment");
-        _tagNameMap.put(TAG_ADJUSTMENT_MODE, "Adjustment Mode");
-        _tagNameMap.put(TAG_QUALITY, "Quality");
-        _tagNameMap.put(TAG_FIRMWARE, "Firmware");
-        _tagNameMap.put(TAG_SOFTWARE, "Software");
-        _tagNameMap.put(TAG_AUTO_BRACKET, "Auto Bracket");
-    }
-
-
-    public SigmaMakernoteDirectory()
-    {
-        this.setDescriptor(new SigmaMakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Sigma Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/SonyType1MakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/SonyType1MakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,702 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.makernotes.SonyType1MakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link SonyType1MakernoteDirectory}.
- * Thanks to David Carson for the initial version of this class.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class SonyType1MakernoteDescriptor extends TagDescriptor<SonyType1MakernoteDirectory>
-{
-    public SonyType1MakernoteDescriptor(@NotNull SonyType1MakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_IMAGE_QUALITY:
-                return getImageQualityDescription();
-            case TAG_FLASH_EXPOSURE_COMP:
-                return getFlashExposureCompensationDescription();
-            case TAG_TELECONVERTER:
-                return getTeleconverterDescription();
-            case TAG_WHITE_BALANCE:
-                return getWhiteBalanceDescription();
-            case TAG_COLOR_TEMPERATURE:
-                return getColorTemperatureDescription();
-            case TAG_SCENE_MODE:
-                return getSceneModeDescription();
-            case TAG_ZONE_MATCHING:
-                return getZoneMatchingDescription();
-            case TAG_DYNAMIC_RANGE_OPTIMISER:
-                return getDynamicRangeOptimizerDescription();
-            case TAG_IMAGE_STABILISATION:
-                return getImageStabilizationDescription();
-            // Unfortunately it seems that there is no definite mapping between a lens ID and a lens model
-            // http://gvsoft.homedns.org/exif/makernote-sony-type1.html#0xb027
-//            case TAG_LENS_ID:
-//                return getLensIDDescription();
-            case TAG_COLOR_MODE:
-                return getColorModeDescription();
-            case TAG_MACRO:
-                return getMacroDescription();
-            case TAG_EXPOSURE_MODE:
-                return getExposureModeDescription();
-            case TAG_JPEG_QUALITY:
-                return getJpegQualityDescription();
-            case TAG_ANTI_BLUR:
-                return getAntiBlurDescription();
-            case TAG_LONG_EXPOSURE_NOISE_REDUCTION_OR_FOCUS_MODE:
-                return getLongExposureNoiseReductionDescription();
-            case TAG_HIGH_ISO_NOISE_REDUCTION:
-                return getHighIsoNoiseReductionDescription();
-            case TAG_PICTURE_EFFECT:
-                return getPictureEffectDescription();
-            case TAG_SOFT_SKIN_EFFECT:
-                return getSoftSkinEffectDescription();
-            case TAG_VIGNETTING_CORRECTION:
-                return getVignettingCorrectionDescription();
-            case TAG_LATERAL_CHROMATIC_ABERRATION:
-                return getLateralChromaticAberrationDescription();
-            case TAG_DISTORTION_CORRECTION:
-                return getDistortionCorrectionDescription();
-            case TAG_AUTO_PORTRAIT_FRAMED:
-                return getAutoPortraitFramedDescription();
-            case TAG_FOCUS_MODE:
-                return getFocusModeDescription();
-            case TAG_AF_POINT_SELECTED:
-                return getAFPointSelectedDescription();
-            case TAG_SONY_MODEL_ID:
-                return getSonyModelIdDescription();
-            case TAG_AF_MODE:
-                return getAFModeDescription();
-            case TAG_AF_ILLUMINATOR:
-                return getAFIlluminatorDescription();
-            case TAG_FLASH_LEVEL:
-                return getFlashLevelDescription();
-            case TAG_RELEASE_MODE:
-                return getReleaseModeDescription();
-            case TAG_SEQUENCE_NUMBER:
-                return getSequenceNumberDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getImageQualityDescription()
-    {
-        return getIndexedDescription(TAG_IMAGE_QUALITY,
-            "RAW",
-            "Super Fine",
-            "Fine",
-            "Standard",
-            "Economy",
-            "Extra Fine",
-            "RAW + JPEG",
-            "Compressed RAW",
-            "Compressed RAW + JPEG");
-    }
-
-    @Nullable
-    public String getFlashExposureCompensationDescription()
-    {
-        return getFormattedInt(TAG_FLASH_EXPOSURE_COMP, "%d EV");
-    }
-
-    @Nullable
-    public String getTeleconverterDescription()
-    {
-        Integer value = _directory.getInteger(TAG_TELECONVERTER);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0x00: return "None";
-            case 0x48: return "Minolta/Sony AF 2x APO (D)";
-            case 0x50: return "Minolta AF 2x APO II";
-            case 0x60: return "Minolta AF 2x APO";
-            case 0x88: return "Minolta/Sony AF 1.4x APO (D)";
-            case 0x90: return "Minolta AF 1.4x APO II";
-            case 0xa0: return "Minolta AF 1.4x APO";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getWhiteBalanceDescription()
-    {
-        Integer value = _directory.getInteger(TAG_WHITE_BALANCE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0x00: return "Auto";
-            case 0x01: return "Color Temperature/Color Filter";
-            case 0x10: return "Daylight";
-            case 0x20: return "Cloudy";
-            case 0x30: return "Shade";
-            case 0x40: return "Tungsten";
-            case 0x50: return "Flash";
-            case 0x60: return "Fluorescent";
-            case 0x70: return "Custom";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getColorTemperatureDescription()
-    {
-        Integer value = _directory.getInteger(TAG_COLOR_TEMPERATURE);
-        if (value == null)
-            return null;
-        if (value == 0)
-            return "Auto";
-        int kelvin = ((value & 0x00FF0000) >> 8) | ((value & 0xFF000000) >> 24);
-        return String.format("%d K", kelvin);
-    }
-
-    @Nullable
-    public String getZoneMatchingDescription()
-    {
-        return getIndexedDescription(TAG_ZONE_MATCHING,
-            "ISO Setting Used", "High Key", "Low Key");
-    }
-
-    @Nullable
-    public String getDynamicRangeOptimizerDescription()
-    {
-        Integer value = _directory.getInteger(TAG_DYNAMIC_RANGE_OPTIMISER);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "Off";
-            case 1: return "Standard";
-            case 2: return "Advanced Auto";
-            case 3: return "Auto";
-            case 8: return "Advanced LV1";
-            case 9: return "Advanced LV2";
-            case 10: return "Advanced LV3";
-            case 11: return "Advanced LV4";
-            case 12: return "Advanced LV5";
-            case 16: return "LV1";
-            case 17: return "LV2";
-            case 18: return "LV3";
-            case 19: return "LV4";
-            case 20: return "LV5";
-            default: return String.format("Unknown (%d)", value);
-        }
-    }
-
-    @Nullable
-    public String getImageStabilizationDescription()
-    {
-        Integer value = _directory.getInteger(TAG_IMAGE_STABILISATION);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "Off";
-            case 1: return "On";
-            default: return "N/A";
-        }
-    }
-
-    @Nullable
-    public String getColorModeDescription()
-    {
-        Integer value = _directory.getInteger(TAG_COLOR_MODE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "Standard";
-            case 1: return "Vivid";
-            case 2: return "Portrait";
-            case 3: return "Landscape";
-            case 4: return "Sunset";
-            case 5: return "Night Portrait";
-            case 6: return "Black & White";
-            case 7: return "Adobe RGB";
-            case 12: case 100: return "Neutral";
-            case 13: case 101: return "Clear";
-            case 14: case 102: return "Deep";
-            case 15: case 103: return "Light";
-            case 16: return "Autumn";
-            case 17: return "Sepia";
-            case 104: return "Night View";
-            case 105: return "Autumn Leaves";
-            default: return String.format("Unknown (%d)", value);
-        }
-    }
-
-    @Nullable
-    public String getMacroDescription()
-    {
-        Integer value = _directory.getInteger(TAG_MACRO);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "Off";
-            case 1: return "On";
-            case 2: return "Magnifying Glass/Super Macro";
-            case 0xFFFF: return "N/A";
-            default: return String.format("Unknown (%d)", value);
-        }
-    }
-
-    @Nullable
-    public String getExposureModeDescription()
-    {
-        Integer value = _directory.getInteger(TAG_EXPOSURE_MODE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "Program";
-            case 1: return "Portrait";
-            case 2: return "Beach";
-            case 3: return "Sports";
-            case 4: return "Snow";
-            case 5: return "Landscape";
-            case 6: return "Auto";
-            case 7: return "Aperture Priority";
-            case 8: return "Shutter Priority";
-            case 9: return "Night Scene / Twilight";
-            case 10: return "Hi-Speed Shutter";
-            case 11: return "Twilight Portrait";
-            case 12: return "Soft Snap/Portrait";
-            case 13: return "Fireworks";
-            case 14: return "Smile Shutter";
-            case 15: return "Manual";
-            case 18: return "High Sensitivity";
-            case 19: return "Macro";
-            case 20: return "Advanced Sports Shooting";
-            case 29: return "Underwater";
-            case 33: return "Food";
-            case 34: return "Panorama";
-            case 35: return "Handheld Night Shot";
-            case 36: return "Anti Motion Blur";
-            case 37: return "Pet";
-            case 38: return "Backlight Correction HDR";
-            case 39: return "Superior Auto";
-            case 40: return "Background Defocus";
-            case 41: return "Soft Skin";
-            case 42: return "3D Image";
-            case 0xFFFF: return "N/A";
-            default: return String.format("Unknown (%d)", value);
-        }
-    }
-
-    @Nullable
-    public String getJpegQualityDescription()
-    {
-        Integer value = _directory.getInteger(TAG_JPEG_QUALITY);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "Normal";
-            case 1: return "Fine";
-            case 2: return "Extra Fine";
-            case 0xFFFF: return "N/A";
-            default: return String.format("Unknown (%d)", value);
-        }
-    }
-
-    @Nullable
-    public String getAntiBlurDescription()
-    {
-        Integer value = _directory.getInteger(TAG_ANTI_BLUR);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "Off";
-            case 1: return "On (Continuous)";
-            case 2: return "On (Shooting)";
-            case 0xFFFF: return "N/A";
-            default: return String.format("Unknown (%d)", value);
-        }
-    }
-
-    @Nullable
-    public String getLongExposureNoiseReductionDescription()
-    {
-        Integer value = _directory.getInteger(TAG_LONG_EXPOSURE_NOISE_REDUCTION_OR_FOCUS_MODE);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "Off";
-            case 1: return "On";
-            case 0xFFFF: return "N/A";
-            default: return String.format("Unknown (%d)", value);
-        }
-    }
-
-    @Nullable
-    public String getHighIsoNoiseReductionDescription()
-    {
-        Integer value = _directory.getInteger(TAG_HIGH_ISO_NOISE_REDUCTION);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "Off";
-            case 1: return "On";
-            case 2: return "Normal";
-            case 3: return "High";
-            case 0x100: return "Auto";
-            case 0xffff: return "N/A";
-            default: return String.format("Unknown (%d)", value);
-        }
-    }
-
-    @Nullable
-    public String getPictureEffectDescription()
-    {
-        Integer value = _directory.getInteger(TAG_PICTURE_EFFECT);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "Off";
-            case 1: return "Toy Camera";
-            case 2: return "Pop Color";
-            case 3: return "Posterization";
-            case 4: return "Posterization B/W";
-            case 5: return "Retro Photo";
-            case 6: return "Soft High Key";
-            case 7: return "Partial Color (red)";
-            case 8: return "Partial Color (green)";
-            case 9: return "Partial Color (blue)";
-            case 10: return "Partial Color (yellow)";
-            case 13: return "High Contrast Monochrome";
-            case 16: return "Toy Camera (normal)";
-            case 17: return "Toy Camera (cool)";
-            case 18: return "Toy Camera (warm)";
-            case 19: return "Toy Camera (green)";
-            case 20: return "Toy Camera (magenta)";
-            case 32: return "Soft Focus (low)";
-            case 33: return "Soft Focus";
-            case 34: return "Soft Focus (high)";
-            case 48: return "Miniature (auto)";
-            case 49: return "Miniature (top)";
-            case 50: return "Miniature (middle horizontal)";
-            case 51: return "Miniature (bottom)";
-            case 52: return "Miniature (left)";
-            case 53: return "Miniature (middle vertical)";
-            case 54: return "Miniature (right)";
-            case 64: return "HDR Painting (low)";
-            case 65: return "HDR Painting";
-            case 66: return "HDR Painting (high)";
-            case 80: return "Rich-tone Monochrome";
-            case 97: return "Water Color";
-            case 98: return "Water Color 2";
-            case 112: return "Illustration (low)";
-            case 113: return "Illustration";
-            case 114: return "Illustration (high)";
-            default: return String.format("Unknown (%d)", value);
-        }
-    }
-
-    @Nullable
-    public String getSoftSkinEffectDescription()
-    {
-        return getIndexedDescription(TAG_SOFT_SKIN_EFFECT, "Off", "Low", "Mid", "High");
-    }
-
-    @Nullable
-    public String getVignettingCorrectionDescription()
-    {
-        Integer value = _directory.getInteger(TAG_VIGNETTING_CORRECTION);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "Off";
-            case 2: return "Auto";
-            case 0xffffffff: return "N/A";
-            default: return String.format("Unknown (%d)", value);
-        }
-    }
-
-    @Nullable
-    public String getLateralChromaticAberrationDescription()
-    {
-        Integer value = _directory.getInteger(TAG_LATERAL_CHROMATIC_ABERRATION);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "Off";
-            case 2: return "Auto";
-            case 0xffffffff: return "N/A";
-            default: return String.format("Unknown (%d)", value);
-        }
-    }
-
-    @Nullable
-    public String getDistortionCorrectionDescription()
-    {
-        Integer value = _directory.getInteger(TAG_DISTORTION_CORRECTION);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "Off";
-            case 2: return "Auto";
-            case 0xffffffff: return "N/A";
-            default: return String.format("Unknown (%d)", value);
-        }
-    }
-
-    @Nullable
-    public String getAutoPortraitFramedDescription()
-    {
-        return getIndexedDescription(TAG_AUTO_PORTRAIT_FRAMED, "No", "Yes");
-    }
-
-    @Nullable
-    public String getFocusModeDescription()
-    {
-        return getIndexedDescription(TAG_FOCUS_MODE,
-            "Manual", null, "AF-A", "AF-C", "AF-S", null, "DMF", "AF-D");
-    }
-
-    @Nullable
-    public String getAFPointSelectedDescription()
-    {
-        return getIndexedDescription(TAG_AF_POINT_SELECTED,
-            "Auto", // 0
-            "Center", // 1
-            "Top", // 2
-            "Upper-right", // 3
-            "Right", // 4
-            "Lower-right", // 5
-            "Bottom", // 6
-            "Lower-left", // 7
-            "Left", // 8
-            "Upper-left	  	", // 9
-            "Far Right", // 10
-            "Far Left", // 11
-            "Upper-middle", // 12
-            "Near Right", // 13
-            "Lower-middle", // 14
-            "Near Left", // 15
-            "Upper Far Right", // 16
-            "Lower Far Right", // 17
-            "Lower Far Left", // 18
-            "Upper Far Left" // 19
-        );
-    }
-
-    @Nullable
-    public String getSonyModelIdDescription()
-    {
-        Integer value = _directory.getInteger(TAG_SONY_MODEL_ID);
-
-        if (value == null)
-            return null;
-
-        switch (value) {
-            case 2: return "DSC-R1";
-            case 256: return "DSLR-A100";
-            case 257: return "DSLR-A900";
-            case 258: return "DSLR-A700";
-            case 259: return "DSLR-A200";
-            case 260: return "DSLR-A350";
-            case 261: return "DSLR-A300";
-            case 262: return "DSLR-A900 (APS-C mode)";
-            case 263: return "DSLR-A380/A390";
-            case 264: return "DSLR-A330";
-            case 265: return "DSLR-A230";
-            case 266: return "DSLR-A290";
-            case 269: return "DSLR-A850";
-            case 270: return "DSLR-A850 (APS-C mode)";
-            case 273: return "DSLR-A550";
-            case 274: return "DSLR-A500";
-            case 275: return "DSLR-A450";
-            case 278: return "NEX-5";
-            case 279: return "NEX-3";
-            case 280: return "SLT-A33";
-            case 281: return "SLT-A55V";
-            case 282: return "DSLR-A560";
-            case 283: return "DSLR-A580";
-            case 284: return "NEX-C3";
-            case 285: return "SLT-A35";
-            case 286: return "SLT-A65V";
-            case 287: return "SLT-A77V";
-            case 288: return "NEX-5N";
-            case 289: return "NEX-7";
-            case 290: return "NEX-VG20E";
-            case 291: return "SLT-A37";
-            case 292: return "SLT-A57";
-            case 293: return "NEX-F3";
-            case 294: return "SLT-A99V";
-            case 295: return "NEX-6";
-            case 296: return "NEX-5R";
-            case 297: return "DSC-RX100";
-            case 298: return "DSC-RX1";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getSceneModeDescription()
-    {
-        Integer value = _directory.getInteger(TAG_SCENE_MODE);
-
-        if (value == null)
-            return null;
-
-        switch (value) {
-            case 0: return "Standard";
-            case 1: return "Portrait";
-            case 2: return "Text";
-            case 3: return "Night Scene";
-            case 4: return "Sunset";
-            case 5: return "Sports";
-            case 6: return "Landscape";
-            case 7: return "Night Portrait";
-            case 8: return "Macro";
-            case 9: return "Super Macro";
-            case 16: return "Auto";
-            case 17: return "Night View/Portrait";
-            case 18: return "Sweep Panorama";
-            case 19: return "Handheld Night Shot";
-            case 20: return "Anti Motion Blur";
-            case 21: return "Cont. Priority AE";
-            case 22: return "Auto+";
-            case 23: return "3D Sweep Panorama";
-            case 24: return "Superior Auto";
-            case 25: return "High Sensitivity";
-            case 26: return "Fireworks";
-            case 27: return "Food";
-            case 28: return "Pet";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getAFModeDescription()
-    {
-        Integer value = _directory.getInteger(TAG_AF_MODE);
-
-        if (value == null)
-            return null;
-
-        switch (value) {
-            case 0: return "Default";
-            case 1: return "Multi";
-            case 2: return "Center";
-            case 3: return "Spot";
-            case 4: return "Flexible Spot";
-            case 6: return "Touch";
-            case 14: return "Manual Focus";
-            case 15: return "Face Detected";
-            case 0xffff: return "n/a";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getAFIlluminatorDescription()
-    {
-        Integer value = _directory.getInteger(TAG_AF_ILLUMINATOR);
-
-        if (value == null)
-            return null;
-
-        switch (value) {
-            case 0: return "Off";
-            case 1: return "Auto";
-            case 0xffff: return "n/a";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getFlashLevelDescription()
-    {
-        Integer value = _directory.getInteger(TAG_FLASH_LEVEL);
-
-        if (value == null)
-            return null;
-
-        switch (value) {
-            case -32768: return "Low";
-            case -3: return "-3/3";
-            case -2: return "-2/3";
-            case -1: return "-1/3";
-            case 0: return "Normal";
-            case 1: return "+1/3";
-            case 2: return "+2/3";
-            case 3: return "+3/3";
-            case 128: return "n/a";
-            case 32767: return "High";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getReleaseModeDescription()
-    {
-        Integer value = _directory.getInteger(TAG_RELEASE_MODE);
-
-        if (value == null)
-            return null;
-
-        switch (value) {
-            case 0: return "Normal";
-            case 2: return "Continuous";
-            case 5: return "Exposure Bracketing";
-            case 6: return "White Balance Bracketing";
-            case 65535: return "n/a";
-            default:
-                return "Unknown (" + value + ")";
-        }
-    }
-
-    @Nullable
-    public String getSequenceNumberDescription()
-    {
-        Integer value = _directory.getInteger(TAG_RELEASE_MODE);
-
-        if (value == null)
-            return null;
-
-        switch (value) {
-            case 0: return "Single";
-            case 65535: return "n/a";
-            default:
-                return value.toString();
-        }
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/SonyType1MakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/SonyType1MakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,229 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific to Sony cameras that use the Sony Type 1 makernote tags.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class SonyType1MakernoteDirectory extends Directory
-{
-    public static final int TAG_CAMERA_INFO = 0x0010;
-    public static final int TAG_FOCUS_INFO = 0x0020;
-
-    public static final int TAG_IMAGE_QUALITY = 0x0102;
-    public static final int TAG_FLASH_EXPOSURE_COMP = 0x0104;
-    public static final int TAG_TELECONVERTER = 0x0105;
-
-    public static final int TAG_WHITE_BALANCE_FINE_TUNE = 0x0112;
-    public static final int TAG_CAMERA_SETTINGS = 0x0114;
-    public static final int TAG_WHITE_BALANCE = 0x0115;
-    public static final int TAG_EXTRA_INFO = 0x0116;
-
-    public static final int TAG_PRINT_IMAGE_MATCHING_INFO = 0x0E00;
-
-    public static final int TAG_MULTI_BURST_MODE = 0x1000;
-    public static final int TAG_MULTI_BURST_IMAGE_WIDTH = 0x1001;
-    public static final int TAG_MULTI_BURST_IMAGE_HEIGHT = 0x1002;
-    public static final int TAG_PANORAMA = 0x1003;
-
-    public static final int TAG_PREVIEW_IMAGE = 0x2001;
-    public static final int TAG_RATING = 0x2002;
-    public static final int TAG_CONTRAST = 0x2004;
-    public static final int TAG_SATURATION = 0x2005;
-    public static final int TAG_SHARPNESS = 0x2006;
-    public static final int TAG_BRIGHTNESS = 0x2007;
-    public static final int TAG_LONG_EXPOSURE_NOISE_REDUCTION = 0x2008;
-    public static final int TAG_HIGH_ISO_NOISE_REDUCTION = 0x2009;
-    public static final int TAG_HDR = 0x200a;
-    public static final int TAG_MULTI_FRAME_NOISE_REDUCTION = 0x200b;
-    public static final int TAG_PICTURE_EFFECT = 0x200e;
-    public static final int TAG_SOFT_SKIN_EFFECT = 0x200f;
-
-    public static final int TAG_VIGNETTING_CORRECTION = 0x2011;
-    public static final int TAG_LATERAL_CHROMATIC_ABERRATION = 0x2012;
-    public static final int TAG_DISTORTION_CORRECTION = 0x2013;
-    public static final int TAG_WB_SHIFT_AMBER_MAGENTA = 0x2014;
-    public static final int TAG_AUTO_PORTRAIT_FRAMED = 0x2016;
-    public static final int TAG_FOCUS_MODE = 0x201b;
-    public static final int TAG_AF_POINT_SELECTED = 0x201e;
-
-    public static final int TAG_SHOT_INFO = 0x3000;
-
-    public static final int TAG_FILE_FORMAT = 0xb000;
-    public static final int TAG_SONY_MODEL_ID = 0xb001;
-
-    public static final int TAG_COLOR_MODE_SETTING = 0xb020;
-    public static final int TAG_COLOR_TEMPERATURE = 0xb021;
-    public static final int TAG_COLOR_COMPENSATION_FILTER = 0xb022;
-    public static final int TAG_SCENE_MODE = 0xb023;
-    public static final int TAG_ZONE_MATCHING = 0xb024;
-    public static final int TAG_DYNAMIC_RANGE_OPTIMISER = 0xb025;
-    public static final int TAG_IMAGE_STABILISATION = 0xb026;
-    public static final int TAG_LENS_ID = 0xb027;
-    public static final int TAG_MINOLTA_MAKERNOTE = 0xb028;
-    public static final int TAG_COLOR_MODE = 0xb029;
-    public static final int TAG_LENS_SPEC = 0xb02a;
-    public static final int TAG_FULL_IMAGE_SIZE = 0xb02b;
-    public static final int TAG_PREVIEW_IMAGE_SIZE = 0xb02c;
-
-    public static final int TAG_MACRO = 0xb040;
-    public static final int TAG_EXPOSURE_MODE = 0xb041;
-    public static final int TAG_FOCUS_MODE_2 = 0xb042;
-    public static final int TAG_AF_MODE = 0xb043;
-    public static final int TAG_AF_ILLUMINATOR = 0xb044;
-    public static final int TAG_JPEG_QUALITY = 0xb047;
-    public static final int TAG_FLASH_LEVEL = 0xb048;
-    public static final int TAG_RELEASE_MODE = 0xb049;
-    public static final int TAG_SEQUENCE_NUMBER = 0xb04a;
-    public static final int TAG_ANTI_BLUR = 0xb04b;
-    /**
-     * (FocusMode for RX100)
-     * 0 = Manual
-     * 2 = AF-S
-     * 3 = AF-C
-     * 5 = Semi-manual
-     * 6 = Direct Manual Focus
-     * (LongExposureNoiseReduction for other models)
-     * 0 = Off
-     * 1 = On
-     * 2 = On 2
-     * 65535 = n/a
-     */
-    public static final int TAG_LONG_EXPOSURE_NOISE_REDUCTION_OR_FOCUS_MODE = 0xb04e;
-    public static final int TAG_DYNAMIC_RANGE_OPTIMIZER = 0xb04f;
-
-    public static final int TAG_HIGH_ISO_NOISE_REDUCTION_2 = 0xb050;
-    public static final int TAG_INTELLIGENT_AUTO = 0xb052;
-    public static final int TAG_WHITE_BALANCE_2 = 0xb054;
-
-    public static final int TAG_NO_PRINT = 0xFFFF;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TAG_CAMERA_INFO, "Camera Info");
-        _tagNameMap.put(TAG_FOCUS_INFO, "Focus Info");
-
-        _tagNameMap.put(TAG_IMAGE_QUALITY, "Image Quality");
-        _tagNameMap.put(TAG_FLASH_EXPOSURE_COMP, "Flash Exposure Compensation");
-        _tagNameMap.put(TAG_TELECONVERTER, "Teleconverter Model");
-
-        _tagNameMap.put(TAG_WHITE_BALANCE_FINE_TUNE, "White Balance Fine Tune Value");
-        _tagNameMap.put(TAG_CAMERA_SETTINGS, "Camera Settings");
-        _tagNameMap.put(TAG_WHITE_BALANCE, "White Balance");
-        _tagNameMap.put(TAG_EXTRA_INFO, "Extra Info");
-
-        _tagNameMap.put(TAG_PRINT_IMAGE_MATCHING_INFO, "Print Image Matching (PIM) Info");
-
-        _tagNameMap.put(TAG_MULTI_BURST_MODE, "Multi Burst Mode");
-        _tagNameMap.put(TAG_MULTI_BURST_IMAGE_WIDTH, "Multi Burst Image Width");
-        _tagNameMap.put(TAG_MULTI_BURST_IMAGE_HEIGHT, "Multi Burst Image Height");
-        _tagNameMap.put(TAG_PANORAMA, "Panorama");
-
-        _tagNameMap.put(TAG_PREVIEW_IMAGE, "Preview Image");
-        _tagNameMap.put(TAG_RATING, "Rating");
-        _tagNameMap.put(TAG_CONTRAST, "Contrast");
-        _tagNameMap.put(TAG_SATURATION, "Saturation");
-        _tagNameMap.put(TAG_SHARPNESS, "Sharpness");
-        _tagNameMap.put(TAG_BRIGHTNESS, "Brightness");
-        _tagNameMap.put(TAG_LONG_EXPOSURE_NOISE_REDUCTION, "Long Exposure Noise Reduction");
-        _tagNameMap.put(TAG_HIGH_ISO_NOISE_REDUCTION, "High ISO Noise Reduction");
-        _tagNameMap.put(TAG_HDR, "HDR");
-        _tagNameMap.put(TAG_MULTI_FRAME_NOISE_REDUCTION, "Multi Frame Noise Reduction");
-        _tagNameMap.put(TAG_PICTURE_EFFECT, "Picture Effect");
-        _tagNameMap.put(TAG_SOFT_SKIN_EFFECT, "Soft Skin Effect");
-
-        _tagNameMap.put(TAG_VIGNETTING_CORRECTION, "Vignetting Correction");
-        _tagNameMap.put(TAG_LATERAL_CHROMATIC_ABERRATION, "Lateral Chromatic Aberration");
-        _tagNameMap.put(TAG_DISTORTION_CORRECTION, "Distortion Correction");
-        _tagNameMap.put(TAG_WB_SHIFT_AMBER_MAGENTA, "WB Shift Amber/Magenta");
-        _tagNameMap.put(TAG_AUTO_PORTRAIT_FRAMED, "Auto Portrait Framing");
-        _tagNameMap.put(TAG_FOCUS_MODE, "Focus Mode");
-        _tagNameMap.put(TAG_AF_POINT_SELECTED, "AF Point Selected");
-
-        _tagNameMap.put(TAG_SHOT_INFO, "Shot Info");
-
-        _tagNameMap.put(TAG_FILE_FORMAT, "File Format");
-        _tagNameMap.put(TAG_SONY_MODEL_ID, "Sony Model ID");
-
-        _tagNameMap.put(TAG_COLOR_MODE_SETTING, "Color Mode Setting");
-        _tagNameMap.put(TAG_COLOR_TEMPERATURE, "Color Temperature");
-        _tagNameMap.put(TAG_COLOR_COMPENSATION_FILTER, "Color Compensation Filter");
-        _tagNameMap.put(TAG_SCENE_MODE, "Scene Mode");
-        _tagNameMap.put(TAG_ZONE_MATCHING, "Zone Matching");
-        _tagNameMap.put(TAG_DYNAMIC_RANGE_OPTIMISER, "Dynamic Range Optimizer");
-        _tagNameMap.put(TAG_IMAGE_STABILISATION, "Image Stabilisation");
-        _tagNameMap.put(TAG_LENS_ID, "Lens ID");
-        _tagNameMap.put(TAG_MINOLTA_MAKERNOTE, "Minolta Makernote");
-        _tagNameMap.put(TAG_COLOR_MODE, "Color Mode");
-        _tagNameMap.put(TAG_LENS_SPEC, "Lens Spec");
-        _tagNameMap.put(TAG_FULL_IMAGE_SIZE, "Full Image Size");
-        _tagNameMap.put(TAG_PREVIEW_IMAGE_SIZE, "Preview Image Size");
-
-        _tagNameMap.put(TAG_MACRO, "Macro");
-        _tagNameMap.put(TAG_EXPOSURE_MODE, "Exposure Mode");
-        _tagNameMap.put(TAG_FOCUS_MODE_2, "Focus Mode");
-        _tagNameMap.put(TAG_AF_MODE, "AF Mode");
-        _tagNameMap.put(TAG_AF_ILLUMINATOR, "AF Illuminator");
-        _tagNameMap.put(TAG_JPEG_QUALITY, "Quality");
-        _tagNameMap.put(TAG_FLASH_LEVEL, "Flash Level");
-        _tagNameMap.put(TAG_RELEASE_MODE, "Release Mode");
-        _tagNameMap.put(TAG_SEQUENCE_NUMBER, "Sequence Number");
-        _tagNameMap.put(TAG_ANTI_BLUR, "Anti Blur");
-        _tagNameMap.put(TAG_LONG_EXPOSURE_NOISE_REDUCTION_OR_FOCUS_MODE, "Long Exposure Noise Reduction");
-        _tagNameMap.put(TAG_DYNAMIC_RANGE_OPTIMIZER, "Dynamic Range Optimizer");
-
-        _tagNameMap.put(TAG_HIGH_ISO_NOISE_REDUCTION_2, "High ISO Noise Reduction");
-        _tagNameMap.put(TAG_INTELLIGENT_AUTO, "Intelligent Auto");
-        _tagNameMap.put(TAG_WHITE_BALANCE_2, "White Balance 2");
-
-        _tagNameMap.put(TAG_NO_PRINT, "No Print");
-    }
-
-    public SonyType1MakernoteDirectory()
-    {
-        this.setDescriptor(new SonyType1MakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Sony Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/SonyType6MakernoteDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/SonyType6MakernoteDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,60 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.exif.makernotes.SonyType6MakernoteDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link SonyType6MakernoteDirectory}.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class SonyType6MakernoteDescriptor extends TagDescriptor<SonyType6MakernoteDirectory>
-{
-    public SonyType6MakernoteDescriptor(@NotNull SonyType6MakernoteDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_MAKERNOTE_THUMB_VERSION:
-                return getMakernoteThumbVersionDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getMakernoteThumbVersionDescription()
-    {
-        return getVersionBytesDescription(TAG_MAKERNOTE_THUMB_VERSION, 2);
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/SonyType6MakernoteDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/SonyType6MakernoteDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,71 +1,0 @@
-/*
- * 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
- *
- *        http://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.NotNull;
-import com.drew.metadata.Directory;
-
-import java.util.HashMap;
-
-/**
- * Describes tags specific to Sony cameras that use the Sony Type 6 makernote tags.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class SonyType6MakernoteDirectory extends Directory
-{
-    public static final int TAG_MAKERNOTE_THUMB_OFFSET = 0x0513;
-    public static final int TAG_MAKERNOTE_THUMB_LENGTH = 0x0514;
-//    public static final int TAG_UNKNOWN_1 = 0x0515;
-    public static final int TAG_MAKERNOTE_THUMB_VERSION = 0x2000;
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TAG_MAKERNOTE_THUMB_OFFSET, "Makernote Thumb Offset");
-        _tagNameMap.put(TAG_MAKERNOTE_THUMB_LENGTH, "Makernote Thumb Length");
-//        _tagNameMap.put(TAG_UNKNOWN_1, "Sony-6-0x0203");
-        _tagNameMap.put(TAG_MAKERNOTE_THUMB_VERSION, "Makernote Thumb Version");
-    }
-
-    public SonyType6MakernoteDirectory()
-    {
-        this.setDescriptor(new SonyType6MakernoteDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "Sony Makernote";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-}
Index: trunk/src/com/drew/metadata/exif/makernotes/package-info.java
===================================================================
--- trunk/src/com/drew/metadata/exif/makernotes/package-info.java	(revision 15217)
+++ 	(revision )
@@ -1,5 +1,0 @@
-/**
- * Contains {@link com.drew.metadata.Directory} and {@link com.drew.metadata.TagDescriptor} classes related to the
- * modelling of manufacturer-specific makernotes.
- */
-package com.drew.metadata.exif.makernotes;
Index: trunk/src/com/drew/metadata/exif/package-info.java
===================================================================
--- trunk/src/com/drew/metadata/exif/package-info.java	(revision 15217)
+++ 	(revision )
@@ -1,4 +1,0 @@
-/**
- * Contains classes for the extraction and modelling of Exif metadata and camera manufacturer-specific makernotes.
- */
-package com.drew.metadata.exif;
