blob: 0cff2a213317b33974eaf278bcf2b9eda26f10f9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
package org.apache.commons.sanselan.formats.tiff.constants;
import java.io.UnsupportedEncodingException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import org.apache.commons.sanselan.ImageReadException;
import org.apache.commons.sanselan.ImageWriteException;
import org.apache.commons.sanselan.common.BinaryFileFunctions;
import org.apache.commons.sanselan.formats.tiff.TiffField;
import org.apache.commons.sanselan.formats.tiff.fieldtypes.FieldType;
import org.apache.commons.sanselan.util.Debug;
public class TagInfo implements TiffDirectoryConstants, TiffFieldTypeConstants
{
protected static final int LENGTH_UNKNOWN = -1;
public TagInfo(String name, int tag, FieldType dataType, int length,
TiffDirectoryType exifDirectory)
{
this(name, tag, new FieldType[]{
dataType
}, length, exifDirectory);
}
public TagInfo(String name, int tag, FieldType dataType, int length)
{
this(name, tag, new FieldType[]{
dataType
}, length, TiffDirectoryType.EXIF_DIRECTORY_UNKNOWN);
}
public TagInfo(String name, int tag, FieldType dataType,
String lengthDescription)
{
this(name, tag, new FieldType[]{
dataType
}, LENGTH_UNKNOWN, TiffDirectoryType.EXIF_DIRECTORY_UNKNOWN);
}
public TagInfo(String name, int tag, FieldType dataTypes[],
String lengthDescription)
{
this(name, tag, dataTypes, LENGTH_UNKNOWN, TiffDirectoryType.EXIF_DIRECTORY_UNKNOWN);
}
public TagInfo(String name, int tag, FieldType dataType)
{
this(name, tag, dataType, LENGTH_UNKNOWN, TiffDirectoryType.EXIF_DIRECTORY_UNKNOWN);
}
public TagInfo(String name, int tag, FieldType dataTypes[], int length,
String lengthDescription)
{
this(name, tag, dataTypes, length, TiffDirectoryType.EXIF_DIRECTORY_UNKNOWN);
}
public final String name;
public final int tag;
public final FieldType dataTypes[];
public final int length;
public final TiffDirectoryType directoryType;
// public final String lengthDescription;
public TagInfo(String name, int tag, FieldType dataTypes[], int length,
TiffDirectoryType exifDirectory
// , String lengthDescription
)
{
this.name = name;
this.tag = tag;
this.dataTypes = dataTypes;
this.length = length;
// this.lengthDescription = lengthDescription;
this.directoryType = exifDirectory;
}
public Object getValue(TiffField entry) throws ImageReadException
{
Object o = entry.fieldType.getSimpleValue(entry);
return o;
}
public byte[] encodeValue(FieldType fieldType, Object value, int byteOrder)
throws ImageWriteException
{
return fieldType.writeData(value, byteOrder);
}
public String getDescription()
{
return tag + " (0x" + Integer.toHexString(tag) + ": " + name + "): ";
}
public String toString()
{
return "[TagInfo. tag: " + tag + " (0x" + Integer.toHexString(tag)
+ ", name: " + name + "]";
}
public boolean isDate()
{
return false;
}
public boolean isOffset()
{
return false;
}
public boolean isText()
{
return false;
}
public boolean isUnknown()
{
return false;
}
public static class Offset extends TagInfo
{
public Offset(String name, int tag, FieldType dataTypes[], int length,
TiffDirectoryType exifDirectory)
{
super(name, tag, dataTypes, length, exifDirectory);
}
public Offset(String name, int tag, FieldType dataType, int length,
TiffDirectoryType exifDirectory)
{
super(name, tag, dataType, length, exifDirectory);
}
public Offset(String name, int tag, FieldType dataType, int length)
{
super(name, tag, dataType, length);
}
// "Exif Offset", 0x8769, FIELD_TYPE_DESCRIPTION_UNKNOWN, 1,
// EXIF_DIRECTORY_UNKNOWN);
public boolean isOffset()
{
return true;
}
}
public static class Date extends TagInfo
{
public Date(String name, int tag, FieldType dataType, int length)
{
super(name, tag, dataType, length);
}
private static final DateFormat DATE_FORMAT_1 = new SimpleDateFormat(
"yyyy:MM:dd HH:mm:ss");
private static final DateFormat DATE_FORMAT_2 = new SimpleDateFormat(
"yyyy:MM:dd:HH:mm:ss");
public Object getValue(TiffField entry) throws ImageReadException
{
Object o = entry.fieldType.getSimpleValue(entry);
String s = (String) o;
try
{
java.util.Date date = DATE_FORMAT_1.parse(s);
return date;
}
catch (Exception e)
{
// Debug.debug(e);
}
try
{
java.util.Date date = DATE_FORMAT_2.parse(s);
return date;
}
catch (Exception e)
{
Debug.debug(e);
}
return o;
}
public byte[] encodeValue(FieldType fieldType, Object value,
int byteOrder) throws ImageWriteException
{
throw new ImageWriteException("date encode value: " + value + " ("
+ Debug.getType(value) + ")");
// return fieldType.writeData(value, byteOrder);
// Object o = entry.fieldType.getSimpleValue(entry);
// byte bytes2[];
// if (tagInfo.isDate())
// bytes2 = fieldType.getRawBytes(srcField);
// else
// bytes2 = fieldType.writeData(value, byteOrder);
// return o;
}
public String toString()
{
return "[TagInfo. tag: " + tag + ", name: " + name + " (data)"
+ "]";
}
// TODO: use polymorphism
public boolean isDate()
{
return true;
}
}
public static final class Text extends TagInfo
{
public Text(String name, int tag, FieldType dataType, int length,
TiffDirectoryType exifDirectory)
{
super(name, tag, dataType, length, exifDirectory);
}
public Text(String name, int tag, FieldType dataTypes[], int length,
TiffDirectoryType exifDirectory)
{
super(name, tag, dataTypes, length, exifDirectory);
}
public boolean isText()
{
return true;
}
private static final class TextEncoding
{
public final byte prefix[];
public final String encodingName;
public TextEncoding(final byte[] prefix, final String encodingName)
{
this.prefix = prefix;
this.encodingName = encodingName;
}
}
private static final TextEncoding TEXT_ENCODING_ASCII = new TextEncoding(
new byte[]{
0x41, 0x53, 0x43, 0x49, 0x49, 0x00, 0x00, 0x00,
}, "US-ASCII"); // ITU-T T.50 IA5
private static final TextEncoding TEXT_ENCODING_JIS = new TextEncoding(
new byte[]{
0x4A, 0x49, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00,
}, "JIS"); // JIS X208-1990
private static final TextEncoding TEXT_ENCODING_UNICODE = new TextEncoding(
new byte[]{
0x55, 0x4E, 0x49, 0x43, 0x4F, 0x44, 0x45, 0x00,
// Which Unicode encoding to use, UTF-8?
}, "UTF-8"); // Unicode Standard
private static final TextEncoding TEXT_ENCODING_UNDEFINED = new TextEncoding(
new byte[]{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
// Try to interpret an undefined text as ISO-8859-1 (Latin)
}, "ISO-8859-1"); // Undefined
private static final TextEncoding TEXT_ENCODINGS[] = {
TEXT_ENCODING_ASCII, //
TEXT_ENCODING_JIS, //
TEXT_ENCODING_UNICODE, //
TEXT_ENCODING_UNDEFINED, //
};
public byte[] encodeValue(FieldType fieldType, Object value,
int byteOrder) throws ImageWriteException
{
if (!(value instanceof String))
throw new ImageWriteException("Text value not String: " + value
+ " (" + Debug.getType(value) + ")");
String s = (String) value;
try
{
// try ASCII, with NO prefix.
byte asciiBytes[] = s
.getBytes(TEXT_ENCODING_ASCII.encodingName);
String decodedAscii = new String(asciiBytes,
TEXT_ENCODING_ASCII.encodingName);
if (decodedAscii.equals(s))
{
// no unicode/non-ascii values.
byte result[] = new byte[asciiBytes.length
+ TEXT_ENCODING_ASCII.prefix.length];
System.arraycopy(TEXT_ENCODING_ASCII.prefix, 0, result, 0,
TEXT_ENCODING_ASCII.prefix.length);
System.arraycopy(asciiBytes, 0, result,
TEXT_ENCODING_ASCII.prefix.length,
asciiBytes.length);
return result;
}
else
{
// use unicode
byte unicodeBytes[] = s
.getBytes(TEXT_ENCODING_UNICODE.encodingName);
byte result[] = new byte[unicodeBytes.length
+ TEXT_ENCODING_UNICODE.prefix.length];
System.arraycopy(TEXT_ENCODING_UNICODE.prefix, 0, result,
0, TEXT_ENCODING_UNICODE.prefix.length);
System.arraycopy(unicodeBytes, 0, result,
TEXT_ENCODING_UNICODE.prefix.length,
unicodeBytes.length);
return result;
}
}
catch (UnsupportedEncodingException e)
{
throw new ImageWriteException(e.getMessage(), e);
}
}
public Object getValue(TiffField entry) throws ImageReadException
{
// Debug.debug("entry.type", entry.type);
// Debug.debug("entry.type", entry.getDescriptionWithoutValue());
// Debug.debug("entry.type", entry.fieldType);
if (entry.type == FIELD_TYPE_ASCII.type)
return FIELD_TYPE_ASCII.getSimpleValue(entry);
else if (entry.type == FIELD_TYPE_UNDEFINED.type)
{ /* do nothing */ }
else if (entry.type == FIELD_TYPE_BYTE.type)
{ /* do nothing */ }
else
{
Debug.debug("entry.type", entry.type);
Debug.debug("entry.directoryType", entry.directoryType);
Debug.debug("entry.type", entry.getDescriptionWithoutValue());
Debug.debug("entry.type", entry.fieldType);
throw new ImageReadException("Text field not encoded as bytes.");
}
byte bytes[] = entry.fieldType.getRawBytes(entry);
if (bytes.length < 8)
{
try
{
// try ASCII, with NO prefix.
return new String(bytes, "US-ASCII");
}
catch (UnsupportedEncodingException e)
{
throw new ImageReadException(
"Text field missing encoding prefix.");
}
}
for (int i = 0; i < TEXT_ENCODINGS.length; i++)
{
TextEncoding encoding = TEXT_ENCODINGS[i];
if (BinaryFileFunctions.compareBytes(bytes, 0, encoding.prefix,
0, encoding.prefix.length))
{
try
{
// Debug.debug("encodingName", encoding.encodingName);
return new String(bytes, encoding.prefix.length,
bytes.length - encoding.prefix.length,
encoding.encodingName);
}
catch (UnsupportedEncodingException e)
{
throw new ImageReadException(e.getMessage(), e);
}
}
}
// Debug.debug("entry.tag", entry.tag + " (0x" + Integer.toHexString(entry.tag ) +")");
// Debug.debug("entry.type", entry.type);
// Debug.debug("bytes", bytes, 10);
// throw new ImageReadException(
// "Unknown Text encoding prefix.");
try
{
// try ASCII, with NO prefix.
return new String(bytes, "US-ASCII");
}
catch (UnsupportedEncodingException e)
{
throw new ImageReadException("Unknown text encoding prefix.");
}
}
}
public static final class Unknown extends TagInfo
{
public Unknown(String name, int tag, FieldType dataTypes[], int length,
TiffDirectoryType exifDirectory)
{
super(name, tag, dataTypes, length, exifDirectory);
}
public boolean isUnknown()
{
return true;
}
public byte[] encodeValue(FieldType fieldType, Object value,
int byteOrder) throws ImageWriteException
{
// Debug.debug();
// Debug.debug("unknown tag(0x" + Integer.toHexString(tag) + ") ",
// this);
// Debug.debug("unknown tag fieldType", fieldType);
// Debug.debug("unknown tag value", value);
// Debug.debug("unknown tag value", Debug.getType(value));
byte result[] = super.encodeValue(fieldType, value, byteOrder);
// Debug.debug("unknown tag result", result);
return result;
}
public Object getValue(TiffField entry) throws ImageReadException
{
return super.getValue(entry);
}
}
}