diff --git a/twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDEXIF1Data.java b/twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDEXIF1Data.java
index 47a30e94..877bc34d 100644
--- a/twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDEXIF1Data.java
+++ b/twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDEXIF1Data.java
@@ -1,15 +1,10 @@
package com.twelvemonkeys.imageio.plugins.psd;
+import com.twelvemonkeys.imageio.metadata.Directory;
import com.twelvemonkeys.imageio.metadata.exif.EXIFReader;
-import com.twelvemonkeys.lang.StringUtil;
-import javax.imageio.IIOException;
import javax.imageio.stream.ImageInputStream;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.List;
/**
* EXIF metadata.
@@ -23,9 +18,7 @@ import java.util.List;
* @see Adobe TIFF developer resources
*/
final class PSDEXIF1Data extends PSDImageResource {
-// protected byte[] mData;
-// protected Directory mDirectory;
- protected com.twelvemonkeys.imageio.metadata.Directory mDirectory;
+ protected Directory mDirectory;
PSDEXIF1Data(final short pId, final ImageInputStream pInput) throws IOException {
super(pId, pInput);
@@ -34,320 +27,16 @@ final class PSDEXIF1Data extends PSDImageResource {
@Override
protected void readData(final ImageInputStream pInput) throws IOException {
// This is in essence an embedded TIFF file.
- // TODO: Extract TIFF parsing to more general purpose package
// TODO: Instead, read the byte data, store for later parsing (or better yet, store offset, and read on request)
mDirectory = new EXIFReader().read(pInput);
-// byte[] bom = new byte[2];
-// stream.readFully(bom);
-// if (bom[0] == 'I' && bom[1] == 'I') {
-// stream.setByteOrder(ByteOrder.LITTLE_ENDIAN);
-// }
-// else if (!(bom[0] == 'M' && bom[1] == 'M')) {
-// throw new IIOException(String.format("Invalid byte order marker '%s'", StringUtil.decode(bom, 0, bom.length, "ASCII")));
-// }
-//
-// if (stream.readUnsignedShort() != 42) {
-// throw new IIOException("Wrong TIFF magic in EXIF data.");
-// }
-//
-// long directoryOffset = stream.readUnsignedInt();
-//
-// // Read TIFF directory
-// mDirectory = Directory.read(stream, directoryOffset);
}
@Override
public String toString() {
StringBuilder builder = toStringBuilder();
-
builder.append(", ").append(mDirectory);
-
builder.append("]");
return builder.toString();
}
-
- // TIFF Image file directory (IFD)
- static class Directory implements Iterable {
- private List mEntries = new ArrayList();
-
- private Directory() {}
-
- public static Directory read(final ImageInputStream pInput, final long pOffset) throws IOException {
- Directory directory = new Directory();
-
- pInput.seek(pOffset);
- int entryCount = pInput.readUnsignedShort();
-
- for (int i = 0; i < entryCount; i++) {
- directory.mEntries.add(Entry.read(pInput));
- }
-
- long nextOffset = pInput.readUnsignedInt();
-
- if (nextOffset != 0) {
- Directory next = Directory.read(pInput, nextOffset);
- directory.mEntries.addAll(next.mEntries);
- }
-
- return directory;
- }
-
- public Entry get(int pTagId) {
- for (Entry entry : mEntries) {
- if (entry.mTagId == pTagId) {
- return entry;
- }
- }
-
- return null;
- }
-
- public Iterator iterator() {
- return mEntries.iterator();
- }
-
- @Override
- public String toString() {
- return String.format("Directory%s", mEntries);
- }
- }
-
- // TIFF IFD Entry
- static class Entry {
- private static final int EXIF_IFD = 0x8769;
-
- private final static String[] TYPE_NAMES = {
- "BYTE", "ASCII", "SHORT", "LONG", "RATIONAL",
-
- "SBYTE", "UNDEFINED", "SSHORT", "SLONG", "SRATIONAL", "FLOAT", "DOUBLE",
- };
-
- private final static int[] TYPE_LENGTHS = {
- 1, 1, 2, 4, 8,
-
- 1, 1, 2, 4, 8, 4, 8,
- };
-
- final int mTagId;
- /*
- 1 = BYTE 8-bit unsigned integer.
- 2 = ASCII 8-bit byte that contains a 7-bit ASCII code; the last byte
- must be NUL (binary zero).
- 3 = SHORT 16-bit (2-byte) unsigned integer.
- 4 = LONG 32-bit (4-byte) unsigned integer.
- 5 = RATIONAL Two LONGs: the first represents the numerator of a
- fraction; the second, the denominator.
-
- TIFF 6.0 and above:
- 6 = SBYTE An 8-bit signed (twos-complement) integer.
- 7 = UNDEFINED An 8-bit byte that may contain anything, depending on
- the definition of the field.
- 8 = SSHORT A 16-bit (2-byte) signed (twos-complement) integer.
- 9 = SLONG A 32-bit (4-byte) signed (twos-complement) integer.
- 10 = SRATIONAL Two SLONGs: the first represents the numerator of a
- fraction, the second the denominator.
- 11 = FLOAT Single precision (4-byte) IEEE format.
- 12 = DOUBLE Double precision (8-byte) IEEE format.
- */
- private short mType;
- private int mCount;
- private long mValueOffset;
- private Object mValue;
-
- private Entry(int pTagId) {
- mTagId = pTagId;
- }
-
- public static Entry read(final ImageInputStream pInput) throws IOException {
- Entry entry = new Entry(pInput.readUnsignedShort());
-
- entry.mType = pInput.readShort();
- entry.mCount = pInput.readInt(); // Number of values
-
- // TODO: Handle other sub-IFDs
- // GPS IFD: 0x8825, Interoperability IFD: 0xA005
- if (entry.mTagId == EXIF_IFD) {
- long offset = pInput.readUnsignedInt();
- pInput.mark();
-
- try {
- entry.mValue = Directory.read(pInput, offset);
- }
- finally {
- pInput.reset();
- }
- }
- else {
- int valueLength = entry.getValueLength();
-
- if (valueLength > 0 && valueLength <= 4) {
- entry.readValueInLine(pInput);
- pInput.skipBytes(4 - valueLength);
- }
- else {
- entry.mValueOffset = pInput.readUnsignedInt(); // This is the *value* iff the value size is <= 4 bytes
- entry.readValue(pInput);
- }
- }
-
- return entry;
- }
-
- private void readValue(final ImageInputStream pInput) throws IOException {
- long pos = pInput.getStreamPosition();
- try {
- pInput.seek(mValueOffset);
- readValueInLine(pInput);
- }
- finally {
- pInput.seek(pos);
- }
- }
-
- private void readValueInLine(ImageInputStream pInput) throws IOException {
- mValue = readValueDirect(pInput, mType, mCount);
- }
-
- private static Object readValueDirect(final ImageInputStream pInput, final short pType, final int pCount) throws IOException {
- switch (pType) {
- case 2:
- // TODO: This might be UTF-8 or ISO-8859-1, even though against the spec
- byte[] ascii = new byte[pCount];
- pInput.readFully(ascii);
- return StringUtil.decode(ascii, 0, ascii.length, "ASCII");
- case 1:
- if (pCount == 1) {
- return pInput.readUnsignedByte();
- }
- case 6:
- if (pCount == 1) {
- return pInput.readByte();
- }
- case 7:
- byte[] bytes = new byte[pCount];
- pInput.readFully(bytes);
- return bytes;
- case 3:
- if (pCount == 1) {
- return pInput.readUnsignedShort();
- }
- case 8:
- if (pCount == 1) {
- return pInput.readShort();
- }
-
- short[] shorts = new short[pCount];
- pInput.readFully(shorts, 0, shorts.length);
- return shorts;
- case 4:
- if (pCount == 1) {
- return pInput.readUnsignedInt();
- }
- case 9:
- if (pCount == 1) {
- return pInput.readInt();
- }
-
- int[] ints = new int[pCount];
- pInput.readFully(ints, 0, ints.length);
- return ints;
- case 11:
- if (pCount == 1) {
- return pInput.readFloat();
- }
-
- float[] floats = new float[pCount];
- pInput.readFully(floats, 0, floats.length);
- return floats;
- case 12:
- if (pCount == 1) {
- return pInput.readDouble();
- }
-
- double[] doubles = new double[pCount];
- pInput.readFully(doubles, 0, doubles.length);
- return doubles;
-
- // TODO: Consider using a Rational class
- case 5:
- if (pCount == 1) {
- return pInput.readUnsignedInt() / (double) pInput.readUnsignedInt();
- }
-
- double[] rationals = new double[pCount];
- for (int i = 0; i < rationals.length; i++) {
- rationals[i] = pInput.readUnsignedInt() / (double) pInput.readUnsignedInt();
- }
-
- return rationals;
- case 10:
- if (pCount == 1) {
- return pInput.readInt() / (double) pInput.readInt();
- }
-
- double[] srationals = new double[pCount];
- for (int i = 0; i < srationals.length; i++) {
- srationals[i] = pInput.readInt() / (double) pInput.readInt();
- }
-
- return srationals;
-
- default:
- throw new IIOException(String.format("Unknown EXIF type '%s'", pType));
- }
- }
-
- private int getValueLength() {
- if (mType > 0 && mType <= TYPE_LENGTHS.length) {
- return TYPE_LENGTHS[mType - 1] * mCount;
- }
- return -1;
- }
-
- public final String getTypeName() {
- if (mType > 0 && mType <= TYPE_NAMES.length) {
- return TYPE_NAMES[mType - 1];
- }
-
- return "Unknown type";
- }
-
- public final Object getValue() {
- return mValue;
- }
-
- public final String getValueAsString() {
- if (mValue instanceof String) {
- return String.format("%s", mValue);
- }
-
- if (mValue != null && mValue.getClass().isArray()) {
- Class> type = mValue.getClass().getComponentType();
- if (byte.class == type) {
- return Arrays.toString((byte[]) mValue);
- }
- if (short.class == type) {
- return Arrays.toString((short[]) mValue);
- }
- if (int.class == type) {
- return Arrays.toString((int[]) mValue);
- }
- if (float.class == type) {
- return Arrays.toString((float[]) mValue);
- }
- if (double.class == type) {
- return Arrays.toString((double[]) mValue);
- }
- }
-
- return String.valueOf(mValue);
- }
-
- // TODO: Tag names!
- @Override
- public String toString() {
- return String.format("0x%04x: %s (%s, %d)", mTagId, mType == 2 ? String.format("\"%s\"", mValue) : getValueAsString(), getTypeName(), mCount);
- }
- }
}
diff --git a/twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDIPTCData.java b/twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDIPTCData.java
index 04846e07..59a076e9 100644
--- a/twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDIPTCData.java
+++ b/twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDIPTCData.java
@@ -1,20 +1,10 @@
package com.twelvemonkeys.imageio.plugins.psd;
+import com.twelvemonkeys.imageio.metadata.Directory;
import com.twelvemonkeys.imageio.metadata.iptc.IPTCReader;
-import com.twelvemonkeys.lang.StringUtil;
-import javax.imageio.IIOException;
import javax.imageio.stream.ImageInputStream;
import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.CharBuffer;
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetDecoder;
-import java.nio.charset.CodingErrorAction;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
/**
* PSDIPTCData
@@ -24,9 +14,7 @@ import java.util.List;
* @version $Id: PSDIPTCData.java,v 1.0 Nov 7, 2009 9:52:14 PM haraldk Exp$
*/
final class PSDIPTCData extends PSDImageResource {
- // TODO: Refactor to be more like PSDEXIF1Data...
- // TODO: Extract IPTC/EXIF/XMP metadata extraction/parsing to separate module(s)
- com.twelvemonkeys.imageio.metadata.Directory mDirectory;
+ Directory mDirectory;
PSDIPTCData(final short pId, final ImageInputStream pInput) throws IOException {
super(pId, pInput);
@@ -43,379 +31,7 @@ final class PSDIPTCData extends PSDImageResource {
StringBuilder builder = toStringBuilder();
builder.append(", ").append(mDirectory);
builder.append("]");
+
return builder.toString();
}
-
- static class Entry {
- final int mTagId;
- private Object mValue;
-
- public Entry(final int pTagId, final Object pValue) {
- mTagId = pTagId;
- mValue = pValue;
- }
-
- @Override
- public String toString() {
- return String.format("%d:%d: %s", mTagId >> 8, mTagId & 0xff, mValue);
- }
-
- public final String getTypeName() {
- // TODO: Should this really look like EXIF?
- if (mTagId == IPTC.TAG_RECORD_VERSION) {
- return "SHORT";
- }
- else if (mValue instanceof String) {
- return "ASCII";
- }
-
- return "Unknown type";
- }
-
- public final String getValueAsString() {
- return String.valueOf(mValue);
- }
-
- public final Object getValue() {
- return mValue;
- }
- }
-
- static class Directory implements Iterable {
- private static final int ENCODING_UNKNOWN = -1;
- private static final int ENCODING_UNSPECIFIED = 0;
- private static final int ENCODING_UTF_8 = 0x1b2547;
-
- private int mEncoding = ENCODING_UNSPECIFIED;
-
- final List mEntries = new ArrayList();
-
- private Directory() {}
-
- @Override
- public String toString() {
- return "Directory" + mEntries.toString();
- }
-
- public Entry get(int pTagId) {
- for (Entry entry : mEntries) {
- if (entry.mTagId == pTagId) {
- return entry;
- }
- }
-
- return null;
- }
-
- public Iterator iterator() {
- return mEntries.iterator();
- }
-
- public static Directory read(final ImageInputStream pInput, final long pSize) throws IOException {
- Directory directory = new Directory();
-
- final long streamEnd = pInput.getStreamPosition() + pSize;
-
- // For each tag
- while (pInput.getStreamPosition() < streamEnd) {
- // Identifies start of a tag
- byte marker = pInput.readByte();
-
- if (marker != 0x1c) {
- throw new IIOException(String.format("Corrupt IPTC stream segment, found 0x%02x (expected 0x1c)", marker));
- }
-
- int tagId = pInput.readShort();
- int tagByteCount = pInput.readUnsignedShort();
-
- directory.readEntry(pInput, tagId, tagByteCount);
- }
-
- return directory;
- }
-
- private void readEntry(final ImageInputStream pInput, final int pTagId, final int pLength) throws IOException {
- Object value = null;
-
- switch (pTagId) {
- case IPTC.TAG_CODED_CHARACTER_SET:
- // TODO: Mapping from ISO 646 to Java supported character sets?
- // TODO: Move somewhere else?
- mEncoding = parseEncoding(pInput, pLength);
- return;
- case IPTC.TAG_RECORD_VERSION:
- // A single unsigned short value
- value = pInput.readUnsignedShort();
- break;
-// case IPTC.TAG_RELEASE_DATE:
-// case IPTC.TAG_EXPIRATION_DATE:
-// case IPTC.TAG_REFERENCE_DATE:
-// case IPTC.TAG_DATE_CREATED:
-// case IPTC.TAG_DIGITAL_CREATION_DATE:
-// // Date object
-// Date date = parseISO8601DatePart(pInput, tagByteCount);
-// if (date != null) {
-// directory.setDate(tagIdentifier, date);
-// return;
-// }
-// case IPTC.TAG_RELEASE_TIME:
-// case IPTC.TAG_EXPIRATION_TIME:
-// case IPTC.TAG_TIME_CREATED:
-// case IPTC.TAG_DIGITAL_CREATION_TIME:
-// // NOTE: Spec says fields should be sent in order, so this is okay
-// date = getDateForTime(directory, tagIdentifier);
-//
-// Date time = parseISO8601TimePart(pInput, tagByteCount, date);
-// if (time != null) {
-// directory.setDate(tagIdentifier, time);
-// return;
-// }
-//
- default:
- // Skip non-Application fields, as they are typically not human readable
- if ((pTagId & 0xff00) != IPTC.APPLICATION_RECORD) {
- pInput.skipBytes(pLength);
- return;
- }
-
- // fall through
- }
-
- // If we don't have a value, treat it as a string
- if (value == null) {
- if (pLength < 1) {
- value = "(No value)";
- }
- else {
- value = parseString(pInput, pLength);
- }
- }
-
- mEntries.add(new Entry(pTagId, value));
- }
-
-// private Date getDateForTime(final Directory directory, final int tagIdentifier) {
-// int dateTag;
-//
-// switch (tagIdentifier) {
-// case IPTC.TAG_RELEASE_TIME:
-// dateTag = IPTC.TAG_RELEASE_DATE;
-// break;
-// case IPTC.TAG_EXPIRATION_TIME:
-// dateTag = IPTC.TAG_EXPIRATION_DATE;
-// break;
-// case IPTC.TAG_TIME_CREATED:
-// dateTag = IPTC.TAG_DATE_CREATED;
-// break;
-// case IPTC.TAG_DIGITAL_CREATION_TIME:
-// dateTag = IPTC.TAG_DIGITAL_CREATION_DATE;
-// break;
-// default:
-// return new Date(0l);
-// }
-//
-// return directory.containsTag(dateTag) ? directory.getDate(dateTag) : new Date(0l);
-// }
-
-
- private int parseEncoding(final ImageInputStream pInput, int tagByteCount) throws IOException {
- return tagByteCount == 3
- && (pInput.readUnsignedByte() << 16 | pInput.readUnsignedByte() << 8 | pInput.readUnsignedByte()) == ENCODING_UTF_8
- ? ENCODING_UTF_8 : ENCODING_UNKNOWN;
- }
-
-// private Date parseISO8601TimePart(final ImageInputStream pInputStream, int tagByteCount, final Date date) throws IOException {
-// // ISO 8601: HHMMSS±HHMM
-// if (tagByteCount >= 11) {
-// String timeStr = parseString(pInputStream, tagByteCount);
-// try {
-// int hour = Integer.parseInt(timeStr.substring(0, 2));
-// int minute = Integer.parseInt(timeStr.substring(2, 4));
-// int second = Integer.parseInt(timeStr.substring(4, 6));
-// String tzOffset = timeStr.substring(6, 11);
-//
-// TimeZone zone = new SimpleTimeZone(Integer.parseInt(tzOffset.charAt(0) == '+' ? tzOffset.substring(1) : tzOffset), tzOffset);
-//
-// GregorianCalendar calendar = new GregorianCalendar(zone);
-// calendar.setTime(date);
-//
-// calendar.add(Calendar.HOUR_OF_DAY, hour);
-// calendar.add(Calendar.MINUTE, minute);
-// calendar.add(Calendar.SECOND, second);
-//
-// return calendar.getTime();
-// }
-// catch (NumberFormatException e) {
-// // fall through and we'll store whatever was there as a String
-// }
-// }
-// return null;
-// }
-//
-// private Date parseISO8601DatePart(final ImageInputStream pInputStream, int tagByteCount) throws IOException {
-// // ISO 8601: CCYYMMDD
-// if (tagByteCount >= 8) {
-// String dateStr = parseString(pInputStream, tagByteCount);
-// try {
-// int year = Integer.parseInt(dateStr.substring(0, 4));
-// int month = Integer.parseInt(dateStr.substring(4, 6)) - 1;
-// int day = Integer.parseInt(dateStr.substring(6, 8));
-// GregorianCalendar calendar = new GregorianCalendar(year, month, day);
-// return calendar.getTime();
-// }
-// catch (NumberFormatException e) {
-// // fall through and we'll store whatever was there as a String
-// }
-// }
-// return null;
-// }
-
- // TODO: Pass encoding as parameter? Use if specified
- private String parseString(final ImageInputStream pInput, final int pLength) throws IOException {
- byte[] data = new byte[pLength];
- pInput.readFully(data);
-
- // NOTE: The IPTC specification says character data should use ISO 646 or ISO 2022 encoding.
- // UTF-8 contains all 646 characters, but not 2022.
- // This is however close to what libiptcdata does, see: http://libiptcdata.sourceforge.net/docs/iptc-i18n.html
- Charset charset = Charset.forName("UTF-8");
- CharsetDecoder decoder = charset.newDecoder();
-
- try {
- // First try to decode using UTF-8 (which seems to be the de-facto standard)
- // Will fail fast on illegal UTF-8-sequences
- CharBuffer chars = decoder.onMalformedInput(CodingErrorAction.REPORT)
- .onUnmappableCharacter(CodingErrorAction.REPORT)
- .decode(ByteBuffer.wrap(data));
- return chars.toString();
- }
- catch (CharacterCodingException notUTF8) {
- if (mEncoding == ENCODING_UTF_8) {
- throw new IIOException("Wrong encoding of IPTC data, explicitly set to UTF-8 in DataSet 1:90", notUTF8);
- }
-
- // Fall back to use ISO-8859-1
- // This will not fail, but may may create wrong fallback-characters
- return StringUtil.decode(data, 0, data.length, "ISO8859_1");
- }
- }
- }
-
- static interface IPTC {
- static final int ENVELOPE_RECORD = 1 << 8;
- static final int APPLICATION_RECORD = 2 << 8;
-
- static final int TAG_CODED_CHARACTER_SET = ENVELOPE_RECORD | 90;
-
- /** 2:00 Record Version (mandatory) */
- public static final int TAG_RECORD_VERSION = APPLICATION_RECORD; // 0x0200
-// /** 2:03 Object Type Reference */
-// public static final int TAG_OBJECT_TYPE_REFERENCE = APPLICATION_RECORD | 3;
-// /** 2:04 Object Attribute Reference (repeatable) */
-// public static final int TAG_OBJECT_ATTRIBUTE_REFERENCE = APPLICATION_RECORD | 4;
-// /** 2:05 Object Name */
-// public static final int TAG_OBJECT_NAME = APPLICATION_RECORD | 5; // 0x0205
-// /** 2:07 Edit Status */
-// public static final int TAG_EDIT_STATUS = APPLICATION_RECORD | 7;
-// /** 2:08 Editorial Update */
-// public static final int TAG_EDITORIAL_UPDATE = APPLICATION_RECORD | 8;
-// /** 2:10 Urgency */
-// public static final int TAG_URGENCY = APPLICATION_RECORD | 10;
-// /** 2:12 Subect Reference (repeatable) */
-// public static final int TAG_SUBJECT_REFERENCE = APPLICATION_RECORD | 12;
-// /** 2:15 Category */
-// public static final int TAG_CATEGORY = APPLICATION_RECORD | 15; // 0x020f
-// /** 2:20 Supplemental Category (repeatable) */
-// public static final int TAG_SUPPLEMENTAL_CATEGORIES = APPLICATION_RECORD | 20;
-// /** 2:22 Fixture Identifier */
-// public static final int TAG_FIXTURE_IDENTIFIER = APPLICATION_RECORD | 22;
-// /** 2:25 Keywords (repeatable) */
-// public static final int TAG_KEYWORDS = APPLICATION_RECORD | 25;
-// /** 2:26 Content Locataion Code (repeatable) */
-// public static final int TAG_CONTENT_LOCATION_CODE = APPLICATION_RECORD | 26;
-// /** 2:27 Content Locataion Name (repeatable) */
-// public static final int TAG_CONTENT_LOCATION_NAME = APPLICATION_RECORD | 27;
-// /** 2:30 Release Date */
-// public static final int TAG_RELEASE_DATE = APPLICATION_RECORD | 30;
-// /** 2:35 Release Time */
-// public static final int TAG_RELEASE_TIME = APPLICATION_RECORD | 35;
-// /** 2:37 Expiration Date */
-// public static final int TAG_EXPIRATION_DATE = APPLICATION_RECORD | 37;
-// /** 2:38 Expiration Time */
-// public static final int TAG_EXPIRATION_TIME = APPLICATION_RECORD | 38;
-// /** 2:40 Special Instructions */
-// public static final int TAG_SPECIAL_INSTRUCTIONS = APPLICATION_RECORD | 40; // 0x0228
-// /** 2:42 Action Advised (1: Kill, 2: Replace, 3: Append, 4: Reference) */
-// public static final int TAG_ACTION_ADVICED = APPLICATION_RECORD | 42;
-// /** 2:45 Reference Service (repeatable in triplets with 2:47 and 2:50) */
-// public static final int TAG_REFERENCE_SERVICE = APPLICATION_RECORD | 45;
-// /** 2:47 Reference Date (mandatory if 2:45 present) */
-// public static final int TAG_REFERENCE_DATE = APPLICATION_RECORD | 47;
-// /** 2:50 Reference Number (mandatory if 2:45 present) */
-// public static final int TAG_REFERENCE_NUMBER = APPLICATION_RECORD | 50;
-// /** 2:55 Date Created */
-// public static final int TAG_DATE_CREATED = APPLICATION_RECORD | 55; // 0x0237
-// /** 2:60 Time Created */
-// public static final int TAG_TIME_CREATED = APPLICATION_RECORD | 60;
-// /** 2:62 Digital Creation Date */
-// public static final int TAG_DIGITAL_CREATION_DATE = APPLICATION_RECORD | 62;
-// /** 2:63 Digital Creation Date */
-// public static final int TAG_DIGITAL_CREATION_TIME = APPLICATION_RECORD | 63;
-// /** 2:65 Originating Program */
-// public static final int TAG_ORIGINATING_PROGRAM = APPLICATION_RECORD | 65;
-// /** 2:70 Program Version (only valid if 2:65 present) */
-// public static final int TAG_PROGRAM_VERSION = APPLICATION_RECORD | 70;
-// /** 2:75 Object Cycle (a: morning, p: evening, b: both) */
-// public static final int TAG_OBJECT_CYCLE = APPLICATION_RECORD | 75;
-// /** 2:80 By-line (repeatable) */
-// public static final int TAG_BY_LINE = APPLICATION_RECORD | 80; // 0x0250
-// /** 2:85 By-line Title (repeatable) */
-// public static final int TAG_BY_LINE_TITLE = APPLICATION_RECORD | 85; // 0x0255
-// /** 2:90 City */
-// public static final int TAG_CITY = APPLICATION_RECORD | 90; // 0x025a
-// /** 2:92 Sub-location */
-// public static final int TAG_SUB_LOCATION = APPLICATION_RECORD | 92;
-// /** 2:95 Province/State */
-// public static final int TAG_PROVINCE_OR_STATE = APPLICATION_RECORD | 95; // 0x025f
-// /** 2:100 Country/Primary Location Code */
-// public static final int TAG_COUNTRY_OR_PRIMARY_LOCATION_CODE = APPLICATION_RECORD | 100;
-// /** 2:101 Country/Primary Location Name */
-// public static final int TAG_COUNTRY_OR_PRIMARY_LOCATION = APPLICATION_RECORD | 101; // 0x0265
-// /** 2:103 Original Transmission Reference */
-// public static final int TAG_ORIGINAL_TRANSMISSION_REFERENCE = APPLICATION_RECORD | 103; // 0x0267
-// /** 2:105 Headline */
-// public static final int TAG_HEADLINE = APPLICATION_RECORD | 105; // 0x0269
-// /** 2:110 Credit */
-// public static final int TAG_CREDIT = APPLICATION_RECORD | 110; // 0x026e
-// /** 2:115 Source */
-// public static final int TAG_SOURCE = APPLICATION_RECORD | 115; // 0x0273
-// /** 2:116 Copyright Notice */
-// public static final int TAG_COPYRIGHT_NOTICE = APPLICATION_RECORD | 116; // 0x0274
-// /** 2:118 Contact */
-// public static final int TAG_CONTACT = APPLICATION_RECORD | 118;
-// /** 2:120 Catption/Abstract */
-// public static final int TAG_CAPTION = APPLICATION_RECORD | 120; // 0x0278
-// /** 2:122 Writer/Editor (repeatable) */
-// public static final int TAG_WRITER = APPLICATION_RECORD | 122; // 0x027a
-// /** 2:125 Rasterized Caption (binary data) */
-// public static final int TAG_RASTERIZED_CATPTION = APPLICATION_RECORD | 125;
-// /** 2:130 Image Type */
-// public static final int TAG_IMAGE_TYPE = APPLICATION_RECORD | 130;
-// /** 2:131 Image Orientation */
-// public static final int TAG_IMAGE_ORIENTATION = APPLICATION_RECORD | 131;
-// /** 2:135 Language Identifier */
-// public static final int TAG_LANGUAGE_IDENTIFIER = APPLICATION_RECORD | 135;
-//
-// // TODO: Should we expose this field?
-// /**
-// * 2:199 JobMinder Assignment Data (Custom IPTC field).
-// * A common custom IPTC field used by a now discontinued application called JobMinder.
-// *
-// * @see JobMinder Homepage
-// */
-// static final int CUSTOM_TAG_JOBMINDER_ASSIGMENT_DATA = APPLICATION_RECORD | 199;
-//
-// // TODO: 2:150-2:154 Audio and 2:200-2:202 Object Preview Data
-
- }
}
diff --git a/twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDXMPData.java b/twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDXMPData.java
index c83dc49b..7ba689e1 100644
--- a/twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDXMPData.java
+++ b/twelvemonkeys-imageio/psd/src/main/java/com/twelvemonkeys/imageio/plugins/psd/PSDXMPData.java
@@ -47,7 +47,7 @@ final class PSDXMPData extends PSDImageResource {
builder.append("\"]");
return builder.toString();
- }
+ }
/**
* Returns a character stream containing the XMP metadata (XML).