Index: trunk/src/com/drew/metadata/iptc/IptcDescriptor.java
===================================================================
--- trunk/src/com/drew/metadata/iptc/IptcDescriptor.java	(revision 15217)
+++ 	(revision )
@@ -1,332 +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.iptc;
-
-import com.drew.lang.StringUtil;
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.TagDescriptor;
-
-import static com.drew.metadata.iptc.IptcDirectory.*;
-
-/**
- * Provides human-readable string representations of tag values stored in a {@link IptcDirectory}.
- * <p>
- * As the IPTC directory already stores values as strings, this class simply returns the tag's value.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class IptcDescriptor extends TagDescriptor<IptcDirectory>
-{
-    public IptcDescriptor(@NotNull IptcDirectory directory)
-    {
-        super(directory);
-    }
-
-    @Override
-    @Nullable
-    public String getDescription(int tagType)
-    {
-        switch (tagType) {
-            case TAG_DATE_CREATED:
-                return getDateCreatedDescription();
-            case TAG_DIGITAL_DATE_CREATED:
-                return getDigitalDateCreatedDescription();
-            case TAG_DATE_SENT:
-                return getDateSentDescription();
-            case TAG_EXPIRATION_DATE:
-                return getExpirationDateDescription();
-            case TAG_EXPIRATION_TIME:
-                return getExpirationTimeDescription();
-            case TAG_FILE_FORMAT:
-                return getFileFormatDescription();
-            case TAG_KEYWORDS:
-                return getKeywordsDescription();
-            case TAG_REFERENCE_DATE:
-                return getReferenceDateDescription();
-            case TAG_RELEASE_DATE:
-                return getReleaseDateDescription();
-            case TAG_RELEASE_TIME:
-                return getReleaseTimeDescription();
-            case TAG_TIME_CREATED:
-                return getTimeCreatedDescription();
-            case TAG_DIGITAL_TIME_CREATED:
-                return getDigitalTimeCreatedDescription();
-            case TAG_TIME_SENT:
-                return getTimeSentDescription();
-            default:
-                return super.getDescription(tagType);
-        }
-    }
-
-    @Nullable
-    public String getDateDescription(int tagType)
-    {
-        String s = _directory.getString(tagType);
-        if (s == null)
-            return null;
-        if (s.length() == 8)
-            return s.substring(0, 4) + ':' + s.substring(4, 6) + ':' + s.substring(6);
-        return s;
-    }
-
-    @Nullable
-    public String getTimeDescription(int tagType)
-    {
-        String s = _directory.getString(tagType);
-        if (s == null)
-            return null;
-        if (s.length() == 6 || s.length() == 11)
-            return s.substring(0, 2) + ':' + s.substring(2, 4) + ':' + s.substring(4);
-        return s;
-    }
-
-    @Nullable
-    public String getFileFormatDescription()
-    {
-        Integer value = _directory.getInteger(TAG_FILE_FORMAT);
-        if (value == null)
-            return null;
-        switch (value) {
-            case 0: return "No ObjectData";
-            case 1: return "IPTC-NAA Digital Newsphoto Parameter Record";
-            case 2: return "IPTC7901 Recommended Message Format";
-            case 3: return "Tagged Image File Format (Adobe/Aldus Image data)";
-            case 4: return "Illustrator (Adobe Graphics data)";
-            case 5: return "AppleSingle (Apple Computer Inc)";
-            case 6: return "NAA 89-3 (ANPA 1312)";
-            case 7: return "MacBinary II";
-            case 8: return "IPTC Unstructured Character Oriented File Format (UCOFF)";
-            case 9: return "United Press International ANPA 1312 variant";
-            case 10: return "United Press International Down-Load Message";
-            case 11: return "JPEG File Interchange (JFIF)";
-            case 12: return "Photo-CD Image-Pac (Eastman Kodak)";
-            case 13: return "Bit Mapped Graphics File [.BMP] (Microsoft)";
-            case 14: return "Digital Audio File [.WAV] (Microsoft & Creative Labs)";
-            case 15: return "Audio plus Moving Video [.AVI] (Microsoft)";
-            case 16: return "PC DOS/Windows Executable Files [.COM][.EXE]";
-            case 17: return "Compressed Binary File [.ZIP] (PKWare Inc)";
-            case 18: return "Audio Interchange File Format AIFF (Apple Computer Inc)";
-            case 19: return "RIFF Wave (Microsoft Corporation)";
-            case 20: return "Freehand (Macromedia/Aldus)";
-            case 21: return "Hypertext Markup Language [.HTML] (The Internet Society)";
-            case 22: return "MPEG 2 Audio Layer 2 (Musicom), ISO/IEC";
-            case 23: return "MPEG 2 Audio Layer 3, ISO/IEC";
-            case 24: return "Portable Document File [.PDF] Adobe";
-            case 25: return "News Industry Text Format (NITF)";
-            case 26: return "Tape Archive [.TAR]";
-            case 27: return "Tidningarnas Telegrambyra NITF version (TTNITF DTD)";
-            case 28: return "Ritzaus Bureau NITF version (RBNITF DTD)";
-            case 29: return "Corel Draw [.CDR]";
-        }
-        return String.format("Unknown (%d)", value);
-    }
-
-    @Nullable
-    public String getByLineDescription()
-    {
-        return _directory.getString(TAG_BY_LINE);
-    }
-
-    @Nullable
-    public String getByLineTitleDescription()
-    {
-        return _directory.getString(TAG_BY_LINE_TITLE);
-    }
-
-    @Nullable
-    public String getCaptionDescription()
-    {
-        return _directory.getString(TAG_CAPTION);
-    }
-
-    @Nullable
-    public String getCategoryDescription()
-    {
-        return _directory.getString(TAG_CATEGORY);
-    }
-
-    @Nullable
-    public String getCityDescription()
-    {
-        return _directory.getString(TAG_CITY);
-    }
-
-    @Nullable
-    public String getCopyrightNoticeDescription()
-    {
-        return _directory.getString(TAG_COPYRIGHT_NOTICE);
-    }
-
-    @Nullable
-    public String getCountryOrPrimaryLocationDescription()
-    {
-        return _directory.getString(TAG_COUNTRY_OR_PRIMARY_LOCATION_NAME);
-    }
-
-    @Nullable
-    public String getCreditDescription()
-    {
-        return _directory.getString(TAG_CREDIT);
-    }
-
-    @Nullable
-    public String getDateCreatedDescription()
-    {
-        return getDateDescription(TAG_DATE_CREATED);
-    }
-
-    @Nullable
-    public String getDigitalDateCreatedDescription()
-    {
-        return getDateDescription(TAG_DIGITAL_DATE_CREATED);
-    }
-
-    @Nullable
-    public String getDateSentDescription()
-    {
-        return getDateDescription(TAG_DATE_SENT);
-    }
-
-    @Nullable
-    public String getExpirationDateDescription()
-    {
-        return getDateDescription(TAG_EXPIRATION_DATE);
-    }
-
-    @Nullable
-    public String getExpirationTimeDescription()
-    {
-        return getTimeDescription(TAG_EXPIRATION_TIME);
-    }
-
-    @Nullable
-    public String getHeadlineDescription()
-    {
-        return _directory.getString(TAG_HEADLINE);
-    }
-
-    @Nullable
-    public String getKeywordsDescription()
-    {
-        final String[] keywords = _directory.getStringArray(TAG_KEYWORDS);
-        if (keywords==null)
-            return null;
-        return StringUtil.join(keywords, ";");
-    }
-
-    @Nullable
-    public String getObjectNameDescription()
-    {
-        return _directory.getString(TAG_OBJECT_NAME);
-    }
-
-    @Nullable
-    public String getOriginalTransmissionReferenceDescription()
-    {
-        return _directory.getString(TAG_ORIGINAL_TRANSMISSION_REFERENCE);
-    }
-
-    @Nullable
-    public String getOriginatingProgramDescription()
-    {
-        return _directory.getString(TAG_ORIGINATING_PROGRAM);
-    }
-
-    @Nullable
-    public String getProvinceOrStateDescription()
-    {
-        return _directory.getString(TAG_PROVINCE_OR_STATE);
-    }
-
-    @Nullable
-    public String getRecordVersionDescription()
-    {
-        return _directory.getString(TAG_APPLICATION_RECORD_VERSION);
-    }
-
-    @Nullable
-    public String getReferenceDateDescription()
-    {
-        return getDateDescription(TAG_REFERENCE_DATE);
-    }
-
-    @Nullable
-    public String getReleaseDateDescription()
-    {
-        return getDateDescription(TAG_RELEASE_DATE);
-    }
-
-    @Nullable
-    public String getReleaseTimeDescription()
-    {
-        return getTimeDescription(TAG_RELEASE_TIME);
-    }
-
-    @Nullable
-    public String getSourceDescription()
-    {
-        return _directory.getString(TAG_SOURCE);
-    }
-
-    @Nullable
-    public String getSpecialInstructionsDescription()
-    {
-        return _directory.getString(TAG_SPECIAL_INSTRUCTIONS);
-    }
-
-    @Nullable
-    public String getSupplementalCategoriesDescription()
-    {
-        return _directory.getString(TAG_SUPPLEMENTAL_CATEGORIES);
-    }
-
-    @Nullable
-    public String getTimeCreatedDescription()
-    {
-        return getTimeDescription(TAG_TIME_CREATED);
-    }
-
-    @Nullable
-    public String getDigitalTimeCreatedDescription()
-    {
-        return getTimeDescription(TAG_DIGITAL_TIME_CREATED);
-    }
-
-    @Nullable
-    public String getTimeSentDescription()
-    {
-        return getTimeDescription(TAG_TIME_SENT);
-    }
-
-    @Nullable
-    public String getUrgencyDescription()
-    {
-        return _directory.getString(TAG_URGENCY);
-    }
-
-    @Nullable
-    public String getWriterDescription()
-    {
-        return _directory.getString(TAG_CAPTION_WRITER);
-    }
-}
Index: trunk/src/com/drew/metadata/iptc/IptcDirectory.java
===================================================================
--- trunk/src/com/drew/metadata/iptc/IptcDirectory.java	(revision 15217)
+++ 	(revision )
@@ -1,318 +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.iptc;
-
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-import com.drew.metadata.Directory;
-
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-
-/**
- * Describes tags used by the International Press Telecommunications Council (IPTC) metadata format.
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-@SuppressWarnings("WeakerAccess")
-public class IptcDirectory extends Directory
-{
-    // IPTC EnvelopeRecord Tags
-    public static final int TAG_ENVELOPE_RECORD_VERSION          = 0x0100; // 0 + 0x0100
-    public static final int TAG_DESTINATION                      = 0x0105; // 5
-    public static final int TAG_FILE_FORMAT                      = 0x0114; // 20
-    public static final int TAG_FILE_VERSION                     = 0x0116; // 22
-    public static final int TAG_SERVICE_ID                       = 0x011E; // 30
-    public static final int TAG_ENVELOPE_NUMBER                  = 0x0128; // 40
-    public static final int TAG_PRODUCT_ID                       = 0x0132; // 50
-    public static final int TAG_ENVELOPE_PRIORITY                = 0x013C; // 60
-    public static final int TAG_DATE_SENT                        = 0x0146; // 70
-    public static final int TAG_TIME_SENT                        = 0x0150; // 80
-    public static final int TAG_CODED_CHARACTER_SET              = 0x015A; // 90
-    public static final int TAG_UNIQUE_OBJECT_NAME               = 0x0164; // 100
-    public static final int TAG_ARM_IDENTIFIER                   = 0x0178; // 120
-    public static final int TAG_ARM_VERSION                      = 0x017a; // 122
-
-    // IPTC ApplicationRecord Tags
-    public static final int TAG_APPLICATION_RECORD_VERSION       = 0x0200; // 0 + 0x0200
-    public static final int TAG_OBJECT_TYPE_REFERENCE            = 0x0203; // 3
-    public static final int TAG_OBJECT_ATTRIBUTE_REFERENCE       = 0x0204; // 4
-    public static final int TAG_OBJECT_NAME                      = 0x0205; // 5
-    public static final int TAG_EDIT_STATUS                      = 0x0207; // 7
-    public static final int TAG_EDITORIAL_UPDATE                 = 0x0208; // 8
-    public static final int TAG_URGENCY                          = 0X020A; // 10
-    public static final int TAG_SUBJECT_REFERENCE                = 0X020C; // 12
-    public static final int TAG_CATEGORY                         = 0x020F; // 15
-    public static final int TAG_SUPPLEMENTAL_CATEGORIES          = 0x0214; // 20
-    public static final int TAG_FIXTURE_ID                       = 0x0216; // 22
-    public static final int TAG_KEYWORDS                         = 0x0219; // 25
-    public static final int TAG_CONTENT_LOCATION_CODE            = 0x021A; // 26
-    public static final int TAG_CONTENT_LOCATION_NAME            = 0x021B; // 27
-    public static final int TAG_RELEASE_DATE                     = 0X021E; // 30
-    public static final int TAG_RELEASE_TIME                     = 0x0223; // 35
-    public static final int TAG_EXPIRATION_DATE                  = 0x0225; // 37
-    public static final int TAG_EXPIRATION_TIME                  = 0x0226; // 38
-    public static final int TAG_SPECIAL_INSTRUCTIONS             = 0x0228; // 40
-    public static final int TAG_ACTION_ADVISED                   = 0x022A; // 42
-    public static final int TAG_REFERENCE_SERVICE                = 0x022D; // 45
-    public static final int TAG_REFERENCE_DATE                   = 0x022F; // 47
-    public static final int TAG_REFERENCE_NUMBER                 = 0x0232; // 50
-    public static final int TAG_DATE_CREATED                     = 0x0237; // 55
-    public static final int TAG_TIME_CREATED                     = 0X023C; // 60
-    public static final int TAG_DIGITAL_DATE_CREATED             = 0x023E; // 62
-    public static final int TAG_DIGITAL_TIME_CREATED             = 0x023F; // 63
-    public static final int TAG_ORIGINATING_PROGRAM              = 0x0241; // 65
-    public static final int TAG_PROGRAM_VERSION                  = 0x0246; // 70
-    public static final int TAG_OBJECT_CYCLE                     = 0x024B; // 75
-    public static final int TAG_BY_LINE                          = 0x0250; // 80
-    public static final int TAG_BY_LINE_TITLE                    = 0x0255; // 85
-    public static final int TAG_CITY                             = 0x025A; // 90
-    public static final int TAG_SUB_LOCATION                     = 0x025C; // 92
-    public static final int TAG_PROVINCE_OR_STATE                = 0x025F; // 95
-    public static final int TAG_COUNTRY_OR_PRIMARY_LOCATION_CODE = 0x0264; // 100
-    public static final int TAG_COUNTRY_OR_PRIMARY_LOCATION_NAME = 0x0265; // 101
-    public static final int TAG_ORIGINAL_TRANSMISSION_REFERENCE  = 0x0267; // 103
-    public static final int TAG_HEADLINE                         = 0x0269; // 105
-    public static final int TAG_CREDIT                           = 0x026E; // 110
-    public static final int TAG_SOURCE                           = 0x0273; // 115
-    public static final int TAG_COPYRIGHT_NOTICE                 = 0x0274; // 116
-    public static final int TAG_CONTACT                          = 0x0276; // 118
-    public static final int TAG_CAPTION                          = 0x0278; // 120
-    public static final int TAG_LOCAL_CAPTION                    = 0x0279; // 121
-    public static final int TAG_CAPTION_WRITER                   = 0x027A; // 122
-    public static final int TAG_RASTERIZED_CAPTION               = 0x027D; // 125
-    public static final int TAG_IMAGE_TYPE                       = 0x0282; // 130
-    public static final int TAG_IMAGE_ORIENTATION                = 0x0283; // 131
-    public static final int TAG_LANGUAGE_IDENTIFIER              = 0x0287; // 135
-    public static final int TAG_AUDIO_TYPE                       = 0x0296; // 150
-    public static final int TAG_AUDIO_SAMPLING_RATE              = 0x0297; // 151
-    public static final int TAG_AUDIO_SAMPLING_RESOLUTION        = 0x0298; // 152
-    public static final int TAG_AUDIO_DURATION                   = 0x0299; // 153
-    public static final int TAG_AUDIO_OUTCUE                     = 0x029A; // 154
-
-    public static final int TAG_JOB_ID                           = 0x02B8; // 184
-    public static final int TAG_MASTER_DOCUMENT_ID               = 0x02B9; // 185
-    public static final int TAG_SHORT_DOCUMENT_ID                = 0x02BA; // 186
-    public static final int TAG_UNIQUE_DOCUMENT_ID               = 0x02BB; // 187
-    public static final int TAG_OWNER_ID                         = 0x02BC; // 188
-
-    public static final int TAG_OBJECT_PREVIEW_FILE_FORMAT       = 0x02C8; // 200
-    public static final int TAG_OBJECT_PREVIEW_FILE_FORMAT_VERSION  = 0x02C9; // 201
-    public static final int TAG_OBJECT_PREVIEW_DATA              = 0x02CA; // 202
-
-    @NotNull
-    protected static final HashMap<Integer, String> _tagNameMap = new HashMap<Integer, String>();
-
-    static
-    {
-        _tagNameMap.put(TAG_ENVELOPE_RECORD_VERSION, "Enveloped Record Version");
-        _tagNameMap.put(TAG_DESTINATION, "Destination");
-        _tagNameMap.put(TAG_FILE_FORMAT, "File Format");
-        _tagNameMap.put(TAG_FILE_VERSION, "File Version");
-        _tagNameMap.put(TAG_SERVICE_ID, "Service Identifier");
-        _tagNameMap.put(TAG_ENVELOPE_NUMBER, "Envelope Number");
-        _tagNameMap.put(TAG_PRODUCT_ID, "Product Identifier");
-        _tagNameMap.put(TAG_ENVELOPE_PRIORITY, "Envelope Priority");
-        _tagNameMap.put(TAG_DATE_SENT, "Date Sent");
-        _tagNameMap.put(TAG_TIME_SENT, "Time Sent");
-        _tagNameMap.put(TAG_CODED_CHARACTER_SET, "Coded Character Set");
-        _tagNameMap.put(TAG_UNIQUE_OBJECT_NAME, "Unique Object Name");
-        _tagNameMap.put(TAG_ARM_IDENTIFIER, "ARM Identifier");
-        _tagNameMap.put(TAG_ARM_VERSION, "ARM Version");
-
-        _tagNameMap.put(TAG_APPLICATION_RECORD_VERSION, "Application Record Version");
-        _tagNameMap.put(TAG_OBJECT_TYPE_REFERENCE, "Object Type Reference");
-        _tagNameMap.put(TAG_OBJECT_ATTRIBUTE_REFERENCE, "Object Attribute Reference");
-        _tagNameMap.put(TAG_OBJECT_NAME, "Object Name");
-        _tagNameMap.put(TAG_EDIT_STATUS, "Edit Status");
-        _tagNameMap.put(TAG_EDITORIAL_UPDATE, "Editorial Update");
-        _tagNameMap.put(TAG_URGENCY, "Urgency");
-        _tagNameMap.put(TAG_SUBJECT_REFERENCE, "Subject Reference");
-        _tagNameMap.put(TAG_CATEGORY, "Category");
-        _tagNameMap.put(TAG_SUPPLEMENTAL_CATEGORIES, "Supplemental Category(s)");
-        _tagNameMap.put(TAG_FIXTURE_ID, "Fixture Identifier");
-        _tagNameMap.put(TAG_KEYWORDS, "Keywords");
-        _tagNameMap.put(TAG_CONTENT_LOCATION_CODE, "Content Location Code");
-        _tagNameMap.put(TAG_CONTENT_LOCATION_NAME, "Content Location Name");
-        _tagNameMap.put(TAG_RELEASE_DATE, "Release Date");
-        _tagNameMap.put(TAG_RELEASE_TIME, "Release Time");
-        _tagNameMap.put(TAG_EXPIRATION_DATE, "Expiration Date");
-        _tagNameMap.put(TAG_EXPIRATION_TIME, "Expiration Time");
-        _tagNameMap.put(TAG_SPECIAL_INSTRUCTIONS, "Special Instructions");
-        _tagNameMap.put(TAG_ACTION_ADVISED, "Action Advised");
-        _tagNameMap.put(TAG_REFERENCE_SERVICE, "Reference Service");
-        _tagNameMap.put(TAG_REFERENCE_DATE, "Reference Date");
-        _tagNameMap.put(TAG_REFERENCE_NUMBER, "Reference Number");
-        _tagNameMap.put(TAG_DATE_CREATED, "Date Created");
-        _tagNameMap.put(TAG_TIME_CREATED, "Time Created");
-        _tagNameMap.put(TAG_DIGITAL_DATE_CREATED, "Digital Date Created");
-        _tagNameMap.put(TAG_DIGITAL_TIME_CREATED, "Digital Time Created");
-        _tagNameMap.put(TAG_ORIGINATING_PROGRAM, "Originating Program");
-        _tagNameMap.put(TAG_PROGRAM_VERSION, "Program Version");
-        _tagNameMap.put(TAG_OBJECT_CYCLE, "Object Cycle");
-        _tagNameMap.put(TAG_BY_LINE, "By-line");
-        _tagNameMap.put(TAG_BY_LINE_TITLE, "By-line Title");
-        _tagNameMap.put(TAG_CITY, "City");
-        _tagNameMap.put(TAG_SUB_LOCATION, "Sub-location");
-        _tagNameMap.put(TAG_PROVINCE_OR_STATE, "Province/State");
-        _tagNameMap.put(TAG_COUNTRY_OR_PRIMARY_LOCATION_CODE, "Country/Primary Location Code");
-        _tagNameMap.put(TAG_COUNTRY_OR_PRIMARY_LOCATION_NAME, "Country/Primary Location Name");
-        _tagNameMap.put(TAG_ORIGINAL_TRANSMISSION_REFERENCE, "Original Transmission Reference");
-        _tagNameMap.put(TAG_HEADLINE, "Headline");
-        _tagNameMap.put(TAG_CREDIT, "Credit");
-        _tagNameMap.put(TAG_SOURCE, "Source");
-        _tagNameMap.put(TAG_COPYRIGHT_NOTICE, "Copyright Notice");
-        _tagNameMap.put(TAG_CONTACT, "Contact");
-        _tagNameMap.put(TAG_CAPTION, "Caption/Abstract");
-        _tagNameMap.put(TAG_LOCAL_CAPTION, "Local Caption");
-        _tagNameMap.put(TAG_CAPTION_WRITER, "Caption Writer/Editor");
-        _tagNameMap.put(TAG_RASTERIZED_CAPTION, "Rasterized Caption");
-        _tagNameMap.put(TAG_IMAGE_TYPE, "Image Type");
-        _tagNameMap.put(TAG_IMAGE_ORIENTATION, "Image Orientation");
-        _tagNameMap.put(TAG_LANGUAGE_IDENTIFIER, "Language Identifier");
-        _tagNameMap.put(TAG_AUDIO_TYPE, "Audio Type");
-        _tagNameMap.put(TAG_AUDIO_SAMPLING_RATE, "Audio Sampling Rate");
-        _tagNameMap.put(TAG_AUDIO_SAMPLING_RESOLUTION, "Audio Sampling Resolution");
-        _tagNameMap.put(TAG_AUDIO_DURATION, "Audio Duration");
-        _tagNameMap.put(TAG_AUDIO_OUTCUE, "Audio Outcue");
-
-        _tagNameMap.put(TAG_JOB_ID, "Job Identifier");
-        _tagNameMap.put(TAG_MASTER_DOCUMENT_ID, "Master Document Identifier");
-        _tagNameMap.put(TAG_SHORT_DOCUMENT_ID, "Short Document Identifier");
-        _tagNameMap.put(TAG_UNIQUE_DOCUMENT_ID, "Unique Document Identifier");
-        _tagNameMap.put(TAG_OWNER_ID, "Owner Identifier");
-
-        _tagNameMap.put(TAG_OBJECT_PREVIEW_FILE_FORMAT, "Object Data Preview File Format");
-        _tagNameMap.put(TAG_OBJECT_PREVIEW_FILE_FORMAT_VERSION, "Object Data Preview File Format Version");
-        _tagNameMap.put(TAG_OBJECT_PREVIEW_DATA, "Object Data Preview Data");
-    }
-
-    public IptcDirectory()
-    {
-        this.setDescriptor(new IptcDescriptor(this));
-    }
-
-    @Override
-    @NotNull
-    public String getName()
-    {
-        return "IPTC";
-    }
-
-    @Override
-    @NotNull
-    protected HashMap<Integer, String> getTagNameMap()
-    {
-        return _tagNameMap;
-    }
-
-    /**
-     * Returns any keywords contained in the IPTC data.  This value may be <code>null</code>.
-     */
-    @Nullable
-    public List<String> getKeywords()
-    {
-        final String[] array = getStringArray(TAG_KEYWORDS);
-        if (array==null)
-            return null;
-        return Arrays.asList(array);
-    }
-
-    /**
-     * Parses the Date Sent tag and the Time Sent tag to obtain a single Date object representing the
-     * date and time when the service sent this image.
-     * @return A Date object representing when the service sent this image, if possible, otherwise null
-     */
-    @Nullable
-    public Date getDateSent()
-    {
-        return getDate(TAG_DATE_SENT, TAG_TIME_SENT);
-    }
-
-    /**
-     * Parses the Release Date tag and the Release Time tag to obtain a single Date object representing the
-     * date and time when this image was released.
-     * @return A Date object representing when this image was released, if possible, otherwise null
-     */
-    @Nullable
-    public Date getReleaseDate()
-    {
-        return getDate(TAG_RELEASE_DATE, TAG_RELEASE_TIME);
-    }
-
-    /**
-     * Parses the Expiration Date tag and the Expiration Time tag to obtain a single Date object representing
-     * that this image should not used after this date and time.
-     * @return A Date object representing when this image was released, if possible, otherwise null
-     */
-    @Nullable
-    public Date getExpirationDate()
-    {
-        return getDate(TAG_EXPIRATION_DATE, TAG_EXPIRATION_TIME);
-    }
-
-    /**
-     * Parses the Date Created tag and the Time Created 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 getDateCreated()
-    {
-        return getDate(TAG_DATE_CREATED, TAG_TIME_CREATED);
-    }
-
-    /**
-     * Parses the Digital Date Created tag and the Digital Time Created tag to obtain a single Date object
-     * representing the date and time when the digital representation of this image was created.
-     * @return A Date object representing when the digital representation of this image was created,
-     * if possible, otherwise null
-     */
-    @Nullable
-    public Date getDigitalDateCreated()
-    {
-        return getDate(TAG_DIGITAL_DATE_CREATED, TAG_DIGITAL_TIME_CREATED);
-    }
-
-    @Nullable
-    private Date getDate(int dateTagType, int timeTagType)
-    {
-        String date = getString(dateTagType);
-        String time = getString(timeTagType);
-
-        if (date == null)
-            return null;
-        if (time == null)
-            return null;
-
-        try {
-            DateFormat parser = new SimpleDateFormat("yyyyMMddHHmmssZ");
-            return parser.parse(date + time);
-        } catch (ParseException e) {
-            return null;
-        }
-    }
-}
Index: trunk/src/com/drew/metadata/iptc/IptcReader.java
===================================================================
--- trunk/src/com/drew/metadata/iptc/IptcReader.java	(revision 15217)
+++ 	(revision )
@@ -1,241 +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.iptc;
-
-import com.drew.imaging.jpeg.JpegSegmentMetadataReader;
-import com.drew.imaging.jpeg.JpegSegmentType;
-import com.drew.lang.SequentialByteArrayReader;
-import com.drew.lang.SequentialReader;
-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 java.io.IOException;
-import java.nio.charset.Charset;
-import java.util.Collections;
-
-/**
- * Decodes IPTC binary data, populating a {@link Metadata} object with tag values in an {@link IptcDirectory}.
- * <p>
- * http://www.iptc.org/std/IIM/4.1/specification/IIMV4.1.pdf
- *
- * @author Drew Noakes https://drewnoakes.com
- */
-public class IptcReader implements JpegSegmentMetadataReader
-{
-    // TODO consider breaking the IPTC section up into multiple directories and providing segregation of each IPTC directory
-/*
-    public static final int DIRECTORY_IPTC = 2;
-
-    public static final int ENVELOPE_RECORD = 1;
-    public static final int APPLICATION_RECORD_2 = 2;
-    public static final int APPLICATION_RECORD_3 = 3;
-    public static final int APPLICATION_RECORD_4 = 4;
-    public static final int APPLICATION_RECORD_5 = 5;
-    public static final int APPLICATION_RECORD_6 = 6;
-    public static final int PRE_DATA_RECORD = 7;
-    public static final int DATA_RECORD = 8;
-    public static final int POST_DATA_RECORD = 9;
-*/
-    private static final byte IptcMarkerByte = 0x1c;
-
-    @NotNull
-    public Iterable<JpegSegmentType> getSegmentTypes()
-    {
-        return Collections.singletonList(JpegSegmentType.APPD);
-    }
-
-    public void readJpegSegments(@NotNull Iterable<byte[]> segments, @NotNull Metadata metadata, @NotNull JpegSegmentType segmentType)
-    {
-        for (byte[] segmentBytes : segments) {
-            // Ensure data starts with the IPTC marker byte
-            if (segmentBytes.length != 0 && segmentBytes[0] == IptcMarkerByte) {
-                extract(new SequentialByteArrayReader(segmentBytes), metadata, segmentBytes.length);
-            }
-        }
-    }
-
-    /**
-     * Performs the IPTC data extraction, adding found values to the specified instance of {@link Metadata}.
-     */
-    public void extract(@NotNull final SequentialReader reader, @NotNull final Metadata metadata, long length)
-    {
-        extract(reader, metadata, length, null);
-    }
-
-    /**
-     * Performs the IPTC data extraction, adding found values to the specified instance of {@link Metadata}.
-     */
-    public void extract(@NotNull final SequentialReader reader, @NotNull final Metadata metadata, long length, @Nullable Directory parentDirectory)
-    {
-        IptcDirectory directory = new IptcDirectory();
-        metadata.addDirectory(directory);
-
-        if (parentDirectory != null)
-            directory.setParent(parentDirectory);
-
-        int offset = 0;
-
-        // for each tag
-        while (offset < length) {
-
-            // identifies start of a tag
-            short startByte;
-            try {
-                startByte = reader.getUInt8();
-                offset++;
-            } catch (IOException e) {
-                directory.addError("Unable to read starting byte of IPTC tag");
-                return;
-            }
-
-            if (startByte != IptcMarkerByte) {
-                // NOTE have seen images where there was one extra byte at the end, giving
-                // offset==length at this point, which is not worth logging as an error.
-                if (offset != length)
-                    directory.addError("Invalid IPTC tag marker at offset " + (offset - 1) + ". Expected '0x" + Integer.toHexString(IptcMarkerByte) + "' but got '0x" + Integer.toHexString(startByte) + "'.");
-                return;
-            }
-
-            // we need at least four bytes left to read a tag
-            if (offset + 4 > length) {
-                directory.addError("Too few bytes remain for a valid IPTC tag");
-                return;
-            }
-
-            int directoryType;
-            int tagType;
-            int tagByteCount;
-            try {
-                directoryType = reader.getUInt8();
-                tagType = reader.getUInt8();
-                tagByteCount = reader.getUInt16();
-                if (tagByteCount > 32767) {
-                    // Extended DataSet Tag (see 1.5(c), p14, IPTC-IIMV4.2.pdf)
-                    tagByteCount = ((tagByteCount & 0x7FFF) << 16) | reader.getUInt16();
-                    offset += 2;
-                }
-                offset += 4;
-            } catch (IOException e) {
-                directory.addError("IPTC data segment ended mid-way through tag descriptor");
-                return;
-            }
-
-            if (offset + tagByteCount > length) {
-                directory.addError("Data for tag extends beyond end of IPTC segment");
-                return;
-            }
-
-            try {
-                processTag(reader, directory, directoryType, tagType, tagByteCount);
-            } catch (IOException e) {
-                directory.addError("Error processing IPTC tag");
-                return;
-            }
-
-            offset += tagByteCount;
-        }
-    }
-
-    private void processTag(@NotNull SequentialReader reader, @NotNull Directory directory, int directoryType, int tagType, int tagByteCount) throws IOException
-    {
-        int tagIdentifier = tagType | (directoryType << 8);
-
-        // Some images have been seen that specify a zero byte tag, which cannot be of much use.
-        // We elect here to completely ignore the tag. The IPTC specification doesn't mention
-        // anything about the interpretation of this situation.
-        // https://raw.githubusercontent.com/wiki/drewnoakes/metadata-extractor/docs/IPTC-IIMV4.2.pdf
-        if (tagByteCount == 0) {
-            directory.setString(tagIdentifier, "");
-            return;
-        }
-
-        switch (tagIdentifier) {
-            case IptcDirectory.TAG_CODED_CHARACTER_SET:
-                byte[] bytes = reader.getBytes(tagByteCount);
-                String charsetName = Iso2022Converter.convertISO2022CharsetToJavaCharset(bytes);
-                if (charsetName == null) {
-                    // Unable to determine the charset, so fall through and treat tag as a regular string
-                    charsetName = new String(bytes);
-                }
-                directory.setString(tagIdentifier, charsetName);
-                return;
-            case IptcDirectory.TAG_ENVELOPE_RECORD_VERSION:
-            case IptcDirectory.TAG_APPLICATION_RECORD_VERSION:
-            case IptcDirectory.TAG_FILE_VERSION:
-            case IptcDirectory.TAG_ARM_VERSION:
-            case IptcDirectory.TAG_PROGRAM_VERSION:
-                // short
-                if (tagByteCount >= 2) {
-                    int shortValue = reader.getUInt16();
-                    reader.skip(tagByteCount - 2);
-                    directory.setInt(tagIdentifier, shortValue);
-                    return;
-                }
-                break;
-            case IptcDirectory.TAG_URGENCY:
-                // byte
-                directory.setInt(tagIdentifier, reader.getUInt8());
-                reader.skip(tagByteCount - 1);
-                return;
-            default:
-                // fall through
-        }
-
-        // If we haven't returned yet, treat it as a string
-        // NOTE that there's a chance we've already loaded the value as a string above, but failed to parse the value
-        String charSetName = directory.getString(IptcDirectory.TAG_CODED_CHARACTER_SET);
-        Charset charset = null;
-        try {
-            if (charSetName != null)
-                charset = Charset.forName(charSetName);
-        } catch (Throwable ignored) {
-        }
-
-        StringValue string;
-        if (charSetName != null) {
-            string = reader.getStringValue(tagByteCount, charset);
-        } else {
-            byte[] bytes = reader.getBytes(tagByteCount);
-            Charset charSet = Iso2022Converter.guessCharSet(bytes);
-            string = charSet != null ? new StringValue(bytes, charSet) : new StringValue(bytes, null);
-        }
-
-        if (directory.containsTag(tagIdentifier)) {
-            // this fancy StringValue[] business avoids using an ArrayList for performance reasons
-            StringValue[] oldStrings = directory.getStringValueArray(tagIdentifier);
-            StringValue[] newStrings;
-            if (oldStrings == null) {
-                // TODO hitting this block means any prior value(s) are discarded
-                newStrings = new StringValue[1];
-            } else {
-                newStrings = new StringValue[oldStrings.length + 1];
-                System.arraycopy(oldStrings, 0, newStrings, 0, oldStrings.length);
-            }
-            newStrings[newStrings.length - 1] = string;
-            directory.setStringValueArray(tagIdentifier, newStrings);
-        } else {
-            directory.setStringValue(tagIdentifier, string);
-        }
-    }
-}
Index: trunk/src/com/drew/metadata/iptc/Iso2022Converter.java
===================================================================
--- trunk/src/com/drew/metadata/iptc/Iso2022Converter.java	(revision 15217)
+++ 	(revision )
@@ -1,104 +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.iptc;
-
-import com.drew.lang.annotations.NotNull;
-import com.drew.lang.annotations.Nullable;
-
-import java.nio.ByteBuffer;
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-
-public final class Iso2022Converter
-{
-    private static final String ISO_8859_1 = "ISO-8859-1";
-    private static final String UTF_8 = "UTF-8";
-
-    private static final byte LATIN_CAPITAL_A = 0x41;
-    private static final int DOT = 0xe280a2;
-    private static final byte LATIN_CAPITAL_G = 0x47;
-    private static final byte PERCENT_SIGN = 0x25;
-    private static final byte ESC = 0x1B;
-
-    /**
-     * Converts the given ISO2022 char set to a Java charset name.
-     *
-     * @param bytes string data encoded using ISO2022
-     * @return the Java charset name as a string, or <code>null</code> if the conversion was not possible
-     */
-    @Nullable
-    public static String convertISO2022CharsetToJavaCharset(@NotNull final byte[] bytes)
-    {
-        if (bytes.length > 2 && bytes[0] == ESC && bytes[1] == PERCENT_SIGN && bytes[2] == LATIN_CAPITAL_G)
-            return UTF_8;
-
-        if (bytes.length > 3 && bytes[0] == ESC && (bytes[3] & 0xFF | ((bytes[2] & 0xFF) << 8) | ((bytes[1] & 0xFF) << 16)) == DOT && bytes[4] == LATIN_CAPITAL_A)
-            return ISO_8859_1;
-
-        return null;
-    }
-
-    /**
-     * Attempts to guess the {@link Charset} of a string provided as a byte array.
-     * <p>
-     * Charsets trialled are, in order:
-     * <ul>
-     *     <li>UTF-8</li>
-     *     <li><code>System.getProperty("file.encoding")</code></li>
-     *     <li>ISO-8859-1</li>
-     * </ul>
-     * <p>
-     * Its only purpose is to guess the Charset if and only if IPTC tag coded character set is not set. If the
-     * encoding is not UTF-8, the tag should be set. Otherwise it is bad practice. This method tries to
-     * workaround this issue since some metadata manipulating tools do not prevent such bad practice.
-     * <p>
-     * About the reliability of this method: The check if some bytes are UTF-8 or not has a very high reliability.
-     * The two other checks are less reliable.
-     *
-     * @param bytes some text as bytes
-     * @return the name of the encoding or null if none could be guessed
-     */
-    @Nullable
-    static Charset guessCharSet(@NotNull final byte[] bytes)
-    {
-        String[] encodings = { UTF_8, System.getProperty("file.encoding"), ISO_8859_1 };
-
-        for (String encoding : encodings)
-        {
-            Charset charset = Charset.forName(encoding);
-            CharsetDecoder cs = charset.newDecoder();
-
-            try {
-                cs.decode(ByteBuffer.wrap(bytes));
-                return charset;
-            } catch (CharacterCodingException e) {
-                // fall through...
-            }
-        }
-
-        // No encodings succeeded. Return null.
-        return null;
-    }
-
-    private Iso2022Converter()
-    {}
-}
Index: trunk/src/com/drew/metadata/iptc/package-info.java
===================================================================
--- trunk/src/com/drew/metadata/iptc/package-info.java	(revision 15217)
+++ 	(revision )
@@ -1,4 +1,0 @@
-/**
- * Contains classes for the extraction and modelling of IPTC metadata.
- */
-package com.drew.metadata.iptc;
