mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-08-03 11:35:29 -04:00
TMI-METADATA: Minor clean-up, preparing for read/write of metadata.
Now uses proper constants for TIFF types.
This commit is contained in:
parent
5531c863cf
commit
cdc832623a
@ -44,7 +44,7 @@ import java.util.Arrays;
|
|||||||
public abstract class AbstractEntry implements Entry {
|
public abstract class AbstractEntry implements Entry {
|
||||||
|
|
||||||
private final Object identifier;
|
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) {
|
protected AbstractEntry(final Object identifier, final Object value) {
|
||||||
Validate.notNull(identifier, "identifier");
|
Validate.notNull(identifier, "identifier");
|
||||||
@ -181,10 +181,10 @@ public abstract class AbstractEntry implements Entry {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
String name = getFieldName();
|
String name = getFieldName();
|
||||||
String nameStr = name != null ? "/" + name + "" : "";
|
String nameStr = name != null ? String.format("/%s", name) : "";
|
||||||
|
|
||||||
String type = getTypeName();
|
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);
|
return String.format("%s%s: %s%s", getNativeIdentifier(), nameStr, getValueAsString(), typeStr);
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,8 @@ final class EXIFEntry extends AbstractEntry {
|
|||||||
throw new IllegalArgumentException(String.format("Illegal EXIF type: %s", type));
|
throw new IllegalArgumentException(String.format("Illegal EXIF type: %s", type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Validate that type is applicable to value?
|
||||||
|
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +110,6 @@ public final class EXIFReader extends MetadataReader {
|
|||||||
|
|
||||||
// Read linked IFDs
|
// Read linked IFDs
|
||||||
if (nextOffset != 0) {
|
if (nextOffset != 0) {
|
||||||
// TODO: This is probably not okay anymore.. Replace recursion with while loop
|
|
||||||
AbstractCompoundDirectory next = (AbstractCompoundDirectory) readDirectory(pInput, nextOffset);
|
AbstractCompoundDirectory next = (AbstractCompoundDirectory) readDirectory(pInput, nextOffset);
|
||||||
for (int i = 0; i < next.directoryCount(); i++) {
|
for (int i = 0; i < next.directoryCount(); i++) {
|
||||||
ifds.add((IFD) next.getDirectory(i));
|
ifds.add((IFD) next.getDirectory(i));
|
||||||
@ -298,7 +297,7 @@ public final class EXIFReader extends MetadataReader {
|
|||||||
long pos = pInput.getStreamPosition();
|
long pos = pInput.getStreamPosition();
|
||||||
|
|
||||||
switch (pType) {
|
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: 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
|
// TODO: Fail if unknown chars, try parsing with ISO-8859-1 or file.encoding
|
||||||
if (pCount == 0) {
|
if (pCount == 0) {
|
||||||
@ -308,17 +307,17 @@ public final class EXIFReader extends MetadataReader {
|
|||||||
pInput.readFully(ascii);
|
pInput.readFully(ascii);
|
||||||
int len = ascii[ascii.length - 1] == 0 ? ascii.length - 1 : ascii.length;
|
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
|
return StringUtil.decode(ascii, 0, len, "UTF-8"); // UTF-8 is ASCII compatible
|
||||||
case 1: // BYTE
|
case TIFF.TYPE_BYTE:
|
||||||
if (pCount == 1) {
|
if (pCount == 1) {
|
||||||
return pInput.readUnsignedByte();
|
return pInput.readUnsignedByte();
|
||||||
}
|
}
|
||||||
// else fall through
|
// else fall through
|
||||||
case 6: // SBYTE
|
case TIFF.TYPE_SBYTE:
|
||||||
if (pCount == 1) {
|
if (pCount == 1) {
|
||||||
return pInput.readByte();
|
return pInput.readByte();
|
||||||
}
|
}
|
||||||
// else fall through
|
// else fall through
|
||||||
case 7: // UNDEFINED
|
case TIFF.TYPE_UNDEFINED:
|
||||||
byte[] bytes = new byte[pCount];
|
byte[] bytes = new byte[pCount];
|
||||||
pInput.readFully(bytes);
|
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
|
// binary data and we want to keep that as a byte array for clients to parse futher
|
||||||
|
|
||||||
return bytes;
|
return bytes;
|
||||||
case 3: // SHORT
|
case TIFF.TYPE_SHORT:
|
||||||
if (pCount == 1) {
|
if (pCount == 1) {
|
||||||
return pInput.readUnsignedShort();
|
return pInput.readUnsignedShort();
|
||||||
}
|
}
|
||||||
case 8: // SSHORT
|
case TIFF.TYPE_SSHORT:
|
||||||
if (pCount == 1) {
|
if (pCount == 1) {
|
||||||
return pInput.readShort();
|
return pInput.readShort();
|
||||||
}
|
}
|
||||||
@ -338,21 +337,22 @@ public final class EXIFReader extends MetadataReader {
|
|||||||
short[] shorts = new short[pCount];
|
short[] shorts = new short[pCount];
|
||||||
pInput.readFully(shorts, 0, shorts.length);
|
pInput.readFully(shorts, 0, shorts.length);
|
||||||
|
|
||||||
if (pType == 3) {
|
if (pType == TIFF.TYPE_SHORT) {
|
||||||
int[] ints = new int[pCount];
|
int[] ints = new int[pCount];
|
||||||
for (int i = 0; i < pCount; i++) {
|
for (int i = 0; i < pCount; i++) {
|
||||||
ints[i] = shorts[i] & 0xffff;
|
ints[i] = shorts[i] & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ints;
|
return ints;
|
||||||
}
|
}
|
||||||
|
|
||||||
return shorts;
|
return shorts;
|
||||||
case 13: // IFD
|
case TIFF.TYPE_IFD:
|
||||||
case 4: // LONG
|
case TIFF.TYPE_LONG:
|
||||||
if (pCount == 1) {
|
if (pCount == 1) {
|
||||||
return pInput.readUnsignedInt();
|
return pInput.readUnsignedInt();
|
||||||
}
|
}
|
||||||
case 9: // SLONG
|
case TIFF.TYPE_SLONG:
|
||||||
if (pCount == 1) {
|
if (pCount == 1) {
|
||||||
return pInput.readInt();
|
return pInput.readInt();
|
||||||
}
|
}
|
||||||
@ -360,16 +360,17 @@ public final class EXIFReader extends MetadataReader {
|
|||||||
int[] ints = new int[pCount];
|
int[] ints = new int[pCount];
|
||||||
pInput.readFully(ints, 0, ints.length);
|
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];
|
long[] longs = new long[pCount];
|
||||||
for (int i = 0; i < pCount; i++) {
|
for (int i = 0; i < pCount; i++) {
|
||||||
longs[i] = ints[i] & 0xffffffffL;
|
longs[i] = ints[i] & 0xffffffffL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return longs;
|
return longs;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ints;
|
return ints;
|
||||||
case 11: // FLOAT
|
case TIFF.TYPE_FLOAT:
|
||||||
if (pCount == 1) {
|
if (pCount == 1) {
|
||||||
return pInput.readFloat();
|
return pInput.readFloat();
|
||||||
}
|
}
|
||||||
@ -377,7 +378,7 @@ public final class EXIFReader extends MetadataReader {
|
|||||||
float[] floats = new float[pCount];
|
float[] floats = new float[pCount];
|
||||||
pInput.readFully(floats, 0, floats.length);
|
pInput.readFully(floats, 0, floats.length);
|
||||||
return floats;
|
return floats;
|
||||||
case 12: // DOUBLE
|
case TIFF.TYPE_DOUBLE:
|
||||||
if (pCount == 1) {
|
if (pCount == 1) {
|
||||||
return pInput.readDouble();
|
return pInput.readDouble();
|
||||||
}
|
}
|
||||||
@ -386,7 +387,7 @@ public final class EXIFReader extends MetadataReader {
|
|||||||
pInput.readFully(doubles, 0, doubles.length);
|
pInput.readFully(doubles, 0, doubles.length);
|
||||||
return doubles;
|
return doubles;
|
||||||
|
|
||||||
case 5: // RATIONAL
|
case TIFF.TYPE_RATIONAL:
|
||||||
if (pCount == 1) {
|
if (pCount == 1) {
|
||||||
return createSafeRational(pInput.readUnsignedInt(), pInput.readUnsignedInt());
|
return createSafeRational(pInput.readUnsignedInt(), pInput.readUnsignedInt());
|
||||||
}
|
}
|
||||||
@ -397,7 +398,7 @@ public final class EXIFReader extends MetadataReader {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return rationals;
|
return rationals;
|
||||||
case 10: // SRATIONAL
|
case TIFF.TYPE_SRATIONAL:
|
||||||
if (pCount == 1) {
|
if (pCount == 1) {
|
||||||
return createSafeRational(pInput.readInt(), pInput.readInt());
|
return createSafeRational(pInput.readInt(), pInput.readInt());
|
||||||
}
|
}
|
||||||
@ -445,7 +446,7 @@ public final class EXIFReader extends MetadataReader {
|
|||||||
return new Rational(numerator, denominator);
|
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) {
|
if (pType > 0 && pType <= TIFF.TYPE_LENGTHS.length) {
|
||||||
return TIFF.TYPE_LENGTHS[pType - 1] * pCount;
|
return TIFF.TYPE_LENGTHS[pType - 1] * pCount;
|
||||||
}
|
}
|
||||||
|
@ -37,8 +37,25 @@ package com.twelvemonkeys.imageio.metadata.exif;
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("UnusedDeclaration")
|
@SuppressWarnings("UnusedDeclaration")
|
||||||
public interface TIFF {
|
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;
|
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.
|
1 = BYTE 8-bit unsigned integer.
|
||||||
2 = ASCII 8-bit byte that contains a 7-bit ASCII code; the last byte
|
2 = ASCII 8-bit byte that contains a 7-bit ASCII code; the last byte
|
||||||
|
@ -77,6 +77,8 @@ public final class JPEGSegment implements Serializable {
|
|||||||
return marker >= 0xFFE0 && marker <= 0xFFEF;
|
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() {
|
public InputStream data() {
|
||||||
return data != null ? new ByteArrayInputStream(data, offset(), length()) : null;
|
return data != null ? new ByteArrayInputStream(data, offset(), length()) : null;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user