TMI-METADATA: Minor clean-up, preparing for read/write of metadata.

Now uses proper constants for TIFF types.
This commit is contained in:
Harald Kuhr 2013-09-08 14:33:40 +02:00
parent 5531c863cf
commit cdc832623a
5 changed files with 42 additions and 20 deletions

View File

@ -44,7 +44,7 @@ import java.util.Arrays;
public abstract class AbstractEntry implements Entry {
private final Object identifier;
private final Object value; // TODO: Might need to be mutable..
private final Object value; // Entries are immutable, directories can be mutated
protected AbstractEntry(final Object identifier, final Object value) {
Validate.notNull(identifier, "identifier");
@ -181,10 +181,10 @@ public abstract class AbstractEntry implements Entry {
@Override
public String toString() {
String name = getFieldName();
String nameStr = name != null ? "/" + name + "" : "";
String nameStr = name != null ? String.format("/%s", name) : "";
String type = getTypeName();
String typeStr = type != null ? " (" + type + ")" : "";
String typeStr = type != null ? String.format(" (%s)", type) : "";
return String.format("%s%s: %s%s", getNativeIdentifier(), nameStr, getValueAsString(), typeStr);
}

View File

@ -46,6 +46,8 @@ final class EXIFEntry extends AbstractEntry {
if (type < 1 || type > TIFF.TYPE_NAMES.length) {
throw new IllegalArgumentException(String.format("Illegal EXIF type: %s", type));
}
// TODO: Validate that type is applicable to value?
this.type = type;
}

View File

@ -110,7 +110,6 @@ public final class EXIFReader extends MetadataReader {
// Read linked IFDs
if (nextOffset != 0) {
// TODO: This is probably not okay anymore.. Replace recursion with while loop
AbstractCompoundDirectory next = (AbstractCompoundDirectory) readDirectory(pInput, nextOffset);
for (int i = 0; i < next.directoryCount(); i++) {
ifds.add((IFD) next.getDirectory(i));
@ -298,7 +297,7 @@ public final class EXIFReader extends MetadataReader {
long pos = pInput.getStreamPosition();
switch (pType) {
case 2: // ASCII
case TIFF.TYPE_ASCII:
// TODO: This might be UTF-8 or ISO-8859-x, even though spec says NULL-terminated 7 bit ASCII
// TODO: Fail if unknown chars, try parsing with ISO-8859-1 or file.encoding
if (pCount == 0) {
@ -308,17 +307,17 @@ public final class EXIFReader extends MetadataReader {
pInput.readFully(ascii);
int len = ascii[ascii.length - 1] == 0 ? ascii.length - 1 : ascii.length;
return StringUtil.decode(ascii, 0, len, "UTF-8"); // UTF-8 is ASCII compatible
case 1: // BYTE
case TIFF.TYPE_BYTE:
if (pCount == 1) {
return pInput.readUnsignedByte();
}
// else fall through
case 6: // SBYTE
case TIFF.TYPE_SBYTE:
if (pCount == 1) {
return pInput.readByte();
}
// else fall through
case 7: // UNDEFINED
case TIFF.TYPE_UNDEFINED:
byte[] bytes = new byte[pCount];
pInput.readFully(bytes);
@ -326,11 +325,11 @@ public final class EXIFReader extends MetadataReader {
// binary data and we want to keep that as a byte array for clients to parse futher
return bytes;
case 3: // SHORT
case TIFF.TYPE_SHORT:
if (pCount == 1) {
return pInput.readUnsignedShort();
}
case 8: // SSHORT
case TIFF.TYPE_SSHORT:
if (pCount == 1) {
return pInput.readShort();
}
@ -338,21 +337,22 @@ public final class EXIFReader extends MetadataReader {
short[] shorts = new short[pCount];
pInput.readFully(shorts, 0, shorts.length);
if (pType == 3) {
if (pType == TIFF.TYPE_SHORT) {
int[] ints = new int[pCount];
for (int i = 0; i < pCount; i++) {
ints[i] = shorts[i] & 0xffff;
}
return ints;
}
return shorts;
case 13: // IFD
case 4: // LONG
case TIFF.TYPE_IFD:
case TIFF.TYPE_LONG:
if (pCount == 1) {
return pInput.readUnsignedInt();
}
case 9: // SLONG
case TIFF.TYPE_SLONG:
if (pCount == 1) {
return pInput.readInt();
}
@ -360,16 +360,17 @@ public final class EXIFReader extends MetadataReader {
int[] ints = new int[pCount];
pInput.readFully(ints, 0, ints.length);
if (pType == 4 || pType == 13) {
if (pType == TIFF.TYPE_LONG || pType == TIFF.TYPE_IFD) {
long[] longs = new long[pCount];
for (int i = 0; i < pCount; i++) {
longs[i] = ints[i] & 0xffffffffL;
}
return longs;
}
return ints;
case 11: // FLOAT
case TIFF.TYPE_FLOAT:
if (pCount == 1) {
return pInput.readFloat();
}
@ -377,7 +378,7 @@ public final class EXIFReader extends MetadataReader {
float[] floats = new float[pCount];
pInput.readFully(floats, 0, floats.length);
return floats;
case 12: // DOUBLE
case TIFF.TYPE_DOUBLE:
if (pCount == 1) {
return pInput.readDouble();
}
@ -386,7 +387,7 @@ public final class EXIFReader extends MetadataReader {
pInput.readFully(doubles, 0, doubles.length);
return doubles;
case 5: // RATIONAL
case TIFF.TYPE_RATIONAL:
if (pCount == 1) {
return createSafeRational(pInput.readUnsignedInt(), pInput.readUnsignedInt());
}
@ -397,7 +398,7 @@ public final class EXIFReader extends MetadataReader {
}
return rationals;
case 10: // SRATIONAL
case TIFF.TYPE_SRATIONAL:
if (pCount == 1) {
return createSafeRational(pInput.readInt(), pInput.readInt());
}
@ -445,7 +446,7 @@ public final class EXIFReader extends MetadataReader {
return new Rational(numerator, denominator);
}
private int getValueLength(final int pType, final int pCount) {
static int getValueLength(final int pType, final int pCount) {
if (pType > 0 && pType <= TIFF.TYPE_LENGTHS.length) {
return TIFF.TYPE_LENGTHS[pType - 1] * pCount;
}

View File

@ -37,8 +37,25 @@ package com.twelvemonkeys.imageio.metadata.exif;
*/
@SuppressWarnings("UnusedDeclaration")
public interface TIFF {
short BYTE_ORDER_MARK_BIG_ENDIAN = ('M' << 8) | 'M';
short BYTE_ORDER_MARK_LITTLE_ENDIAN = ('I' << 8) | 'I';
int TIFF_MAGIC = 42;
short TYPE_BYTE = 1;
short TYPE_ASCII = 2;
short TYPE_SHORT = 3;
short TYPE_LONG = 4;
short TYPE_RATIONAL = 5;
short TYPE_SBYTE = 6;
short TYPE_UNDEFINED = 7;
short TYPE_SSHORT = 8;
short TYPE_SLONG = 9;
short TYPE_SRATIONAL = 10;
short TYPE_FLOAT = 11;
short TYPE_DOUBLE = 12;
short TYPE_IFD = 13;
/*
1 = BYTE 8-bit unsigned integer.
2 = ASCII 8-bit byte that contains a 7-bit ASCII code; the last byte

View File

@ -77,6 +77,8 @@ public final class JPEGSegment implements Serializable {
return marker >= 0xFFE0 && marker <= 0xFFEF;
}
// TODO: Consider returning an ImageInputStream and use ByteArrayImageInputStream directly, for less wrapping and better performance
// TODO: BUT: Must find a way to skip padding in/after segment identifier (eg: Exif has null-term + null-pad, ICC_PROFILE has only null-term). Is data always word-aligned?
public InputStream data() {
return data != null ? new ByteArrayInputStream(data, offset(), length()) : null;
}