Fix types written to some tags using the new EXIF writing interface.
Rename TagInfoText to TagIntoGpsText. Add TagInfoXpText for fields
like XPTITLE, and encode/decode it using UTF-16LE like Windows does.
Copy the new high-level EXIF interface to TiffImageMetadata too.
Jira issue key: SANSELAN-7
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/sanselan/trunk@1290963 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/commons/sanselan/formats/tiff/TiffDirectory.java b/src/main/java/org/apache/commons/sanselan/formats/tiff/TiffDirectory.java
index 6869b31..d4118a3 100644
--- a/src/main/java/org/apache/commons/sanselan/formats/tiff/TiffDirectory.java
+++ b/src/main/java/org/apache/commons/sanselan/formats/tiff/TiffDirectory.java
@@ -31,6 +31,7 @@
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoByte;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoDouble;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoFloat;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoGpsText;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoLong;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoRational;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoSByte;
@@ -38,6 +39,7 @@
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoSRational;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoSShort;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoShort;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoXpString;
public class TiffDirectory extends TiffElement implements TiffConstants
//extends BinaryFileFunctions
@@ -329,6 +331,22 @@
return tag.getValue(field.byteOrder, bytes);
}
+ public String getFieldValue(TagInfoGpsText tag) throws ImageReadException {
+ TiffField field = findField(tag);
+ if (field == null) {
+ return null;
+ }
+ return tag.getValue(field);
+ }
+
+ public String getFieldValue(TagInfoXpString tag) throws ImageReadException {
+ TiffField field = findField(tag);
+ if (field == null) {
+ return null;
+ }
+ return tag.getValue(field);
+ }
+
public final class ImageDataElement extends TiffElement
{
public ImageDataElement(int offset, int length)
diff --git a/src/main/java/org/apache/commons/sanselan/formats/tiff/TiffImageMetadata.java b/src/main/java/org/apache/commons/sanselan/formats/tiff/TiffImageMetadata.java
index a232e1e..a4ac6dd 100644
--- a/src/main/java/org/apache/commons/sanselan/formats/tiff/TiffImageMetadata.java
+++ b/src/main/java/org/apache/commons/sanselan/formats/tiff/TiffImageMetadata.java
@@ -33,6 +33,19 @@
import org.apache.commons.sanselan.formats.tiff.constants.TiffDirectoryType;
import org.apache.commons.sanselan.formats.tiff.fieldtypes.FieldType;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfo;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoAscii;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoByte;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoDouble;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoFloat;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoGpsText;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoLong;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoRational;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoSByte;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoSLong;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoSRational;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoSShort;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoShort;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoXpString;
import org.apache.commons.sanselan.formats.tiff.write.TiffOutputDirectory;
import org.apache.commons.sanselan.formats.tiff.write.TiffOutputField;
import org.apache.commons.sanselan.formats.tiff.write.TiffOutputSet;
@@ -307,6 +320,160 @@
return null;
}
+
+ public Object getFieldValue(TagInfo tag) throws ImageReadException {
+ TiffField field = findField(tag);
+ if (field == null) {
+ return null;
+ }
+ return field.getValue();
+ }
+
+ public byte[] getFieldValue(TagInfoByte tag) throws ImageReadException {
+ TiffField field = findField(tag);
+ if (field == null) {
+ return null;
+ }
+ if (!tag.dataTypes.contains(field.fieldType)) {
+ return null;
+ }
+ return field.fieldType.getRawBytes(field);
+ }
+
+ public String[] getFieldValue(TagInfoAscii tag) throws ImageReadException {
+ TiffField field = findField(tag);
+ if (field == null) {
+ return null;
+ }
+ if (!tag.dataTypes.contains(field.fieldType)) {
+ return null;
+ }
+ byte[] bytes = field.fieldType.getRawBytes(field);
+ return tag.getValue(field.byteOrder, bytes);
+ }
+
+ public short[] getFieldValue(TagInfoShort tag) throws ImageReadException {
+ TiffField field = findField(tag);
+ if (field == null) {
+ return null;
+ }
+ if (!tag.dataTypes.contains(field.fieldType)) {
+ return null;
+ }
+ byte[] bytes = field.fieldType.getRawBytes(field);
+ return tag.getValue(field.byteOrder, bytes);
+ }
+
+ public int[] getFieldValue(TagInfoLong tag) throws ImageReadException {
+ TiffField field = findField(tag);
+ if (field == null) {
+ return null;
+ }
+ if (!tag.dataTypes.contains(field.fieldType)) {
+ return null;
+ }
+ byte[] bytes = field.fieldType.getRawBytes(field);
+ return tag.getValue(field.byteOrder, bytes);
+ }
+
+ public RationalNumber[] getFieldValue(TagInfoRational tag) throws ImageReadException {
+ TiffField field = findField(tag);
+ if (field == null) {
+ return null;
+ }
+ if (!tag.dataTypes.contains(field.fieldType)) {
+ return null;
+ }
+ byte[] bytes = field.fieldType.getRawBytes(field);
+ return tag.getValue(field.byteOrder, bytes);
+ }
+
+ public byte[] getFieldValue(TagInfoSByte tag) throws ImageReadException {
+ TiffField field = findField(tag);
+ if (field == null) {
+ return null;
+ }
+ if (!tag.dataTypes.contains(field.fieldType)) {
+ return null;
+ }
+ return field.fieldType.getRawBytes(field);
+ }
+
+ public short[] getFieldValue(TagInfoSShort tag) throws ImageReadException {
+ TiffField field = findField(tag);
+ if (field == null) {
+ return null;
+ }
+ if (!tag.dataTypes.contains(field.fieldType)) {
+ return null;
+ }
+ byte[] bytes = field.fieldType.getRawBytes(field);
+ return tag.getValue(field.byteOrder, bytes);
+ }
+
+ public int[] getFieldValue(TagInfoSLong tag) throws ImageReadException {
+ TiffField field = findField(tag);
+ if (field == null) {
+ return null;
+ }
+ if (!tag.dataTypes.contains(field.fieldType)) {
+ return null;
+ }
+ byte[] bytes = field.fieldType.getRawBytes(field);
+ return tag.getValue(field.byteOrder, bytes);
+ }
+
+ public RationalNumber[] getFieldValue(TagInfoSRational tag) throws ImageReadException {
+ TiffField field = findField(tag);
+ if (field == null) {
+ return null;
+ }
+ if (!tag.dataTypes.contains(field.fieldType)) {
+ return null;
+ }
+ byte[] bytes = field.fieldType.getRawBytes(field);
+ return tag.getValue(field.byteOrder, bytes);
+ }
+
+ public float[] getFieldValue(TagInfoFloat tag) throws ImageReadException {
+ TiffField field = findField(tag);
+ if (field == null) {
+ return null;
+ }
+ if (!tag.dataTypes.contains(field.fieldType)) {
+ return null;
+ }
+ byte[] bytes = field.fieldType.getRawBytes(field);
+ return tag.getValue(field.byteOrder, bytes);
+ }
+
+ public double[] getFieldValue(TagInfoDouble tag) throws ImageReadException {
+ TiffField field = findField(tag);
+ if (field == null) {
+ return null;
+ }
+ if (!tag.dataTypes.contains(field.fieldType)) {
+ return null;
+ }
+ byte[] bytes = field.fieldType.getRawBytes(field);
+ return tag.getValue(field.byteOrder, bytes);
+ }
+
+ public String getFieldValue(TagInfoGpsText tag) throws ImageReadException {
+ TiffField field = findField(tag);
+ if (field == null) {
+ return null;
+ }
+ return tag.getValue(field);
+ }
+
+ public String getFieldValue(TagInfoXpString tag) throws ImageReadException {
+ TiffField field = findField(tag);
+ if (field == null) {
+ return null;
+ }
+ return tag.getValue(field);
+ }
public TiffDirectory findDirectory(int directoryType)
{
diff --git a/src/main/java/org/apache/commons/sanselan/formats/tiff/constants/ExifTagConstants.java b/src/main/java/org/apache/commons/sanselan/formats/tiff/constants/ExifTagConstants.java
index 3c48556..b5acc91 100644
--- a/src/main/java/org/apache/commons/sanselan/formats/tiff/constants/ExifTagConstants.java
+++ b/src/main/java/org/apache/commons/sanselan/formats/tiff/constants/ExifTagConstants.java
@@ -27,6 +27,7 @@
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoByteOrShort;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoDouble;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoFloat;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoGpsText;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoLong;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoRational;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoSLong;
@@ -36,9 +37,9 @@
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoShortOrLong;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoShortOrLongOrRational;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoShortOrRational;
-import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoText;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoUndefined;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoUnknown;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoXpString;
/**
* References:
@@ -799,7 +800,7 @@
// skipping Maker Note!
public static final TagInfoUndefined EXIF_TAG_MAKER_NOTE = new TagInfoUndefined("Maker Note",
0x927c, 1, TiffDirectoryType.EXIF_DIRECTORY_EXIF_IFD);
- public static final TagInfoText EXIF_TAG_USER_COMMENT = new TagInfoText(
+ public static final TagInfoGpsText EXIF_TAG_USER_COMMENT = new TagInfoGpsText(
"UserComment", 0x9286, FIELD_TYPE_UNDEFINED, 1,
TiffDirectoryType.EXIF_DIRECTORY_EXIF_IFD);
public static final TagInfoAscii EXIF_TAG_SUB_SEC_TIME = new TagInfoAscii(
@@ -814,15 +815,15 @@
public static final TagInfoUndefined EXIF_TAG_IMAGE_SOURCE_DATA = new TagInfoUndefined(
"Image Source Data", 0x935c, 1,
TiffDirectoryType.EXIF_DIRECTORY_IFD0);
- public static final TagInfoByte EXIF_TAG_XPTITLE = new TagInfoByte("XPTitle",
+ public static final TagInfoXpString EXIF_TAG_XPTITLE = new TagInfoXpString("XPTitle",
0x9c9b, -1, TiffDirectoryType.EXIF_DIRECTORY_IFD0);
- public static final TagInfoByte EXIF_TAG_XPCOMMENT = new TagInfoByte("XPComment",
+ public static final TagInfoXpString EXIF_TAG_XPCOMMENT = new TagInfoXpString("XPComment",
0x9c9c, -1, TiffDirectoryType.EXIF_DIRECTORY_IFD0);
- public static final TagInfoByte EXIF_TAG_XPAUTHOR = new TagInfoByte("XPAuthor",
+ public static final TagInfoXpString EXIF_TAG_XPAUTHOR = new TagInfoXpString("XPAuthor",
0x9c9d, -1, TiffDirectoryType.EXIF_DIRECTORY_IFD0);
- public static final TagInfoByte EXIF_TAG_XPKEYWORDS = new TagInfoByte("XPKeywords",
+ public static final TagInfoXpString EXIF_TAG_XPKEYWORDS = new TagInfoXpString("XPKeywords",
0x9c9e, -1, TiffDirectoryType.EXIF_DIRECTORY_IFD0);
- public static final TagInfoByte EXIF_TAG_XPSUBJECT = new TagInfoByte("XPSubject",
+ public static final TagInfoXpString EXIF_TAG_XPSUBJECT = new TagInfoXpString("XPSubject",
0x9c9f, -1, TiffDirectoryType.EXIF_DIRECTORY_IFD0);
public static final TagInfoUndefined EXIF_TAG_FLASHPIX_VERSION = new TagInfoUndefined(
"Flashpix Version", 0xa000, 1,
diff --git a/src/main/java/org/apache/commons/sanselan/formats/tiff/constants/GpsTagConstants.java b/src/main/java/org/apache/commons/sanselan/formats/tiff/constants/GpsTagConstants.java
index b64ea04..86fbe96 100644
--- a/src/main/java/org/apache/commons/sanselan/formats/tiff/constants/GpsTagConstants.java
+++ b/src/main/java/org/apache/commons/sanselan/formats/tiff/constants/GpsTagConstants.java
@@ -25,7 +25,7 @@
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoByte;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoRational;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoShort;
-import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoText;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoGpsText;
public interface GpsTagConstants
extends
@@ -192,12 +192,12 @@
TiffDirectoryType.EXIF_DIRECTORY_GPS);
// ************************************************************
- public static final TagInfoText GPS_TAG_GPS_PROCESSING_METHOD = new TagInfoText(
+ public static final TagInfoGpsText GPS_TAG_GPS_PROCESSING_METHOD = new TagInfoGpsText(
"GPS Processing Method", 0x001b, FIELD_TYPE_UNKNOWN,
-1, TiffDirectoryType.EXIF_DIRECTORY_GPS);
// ************************************************************
- public static final TagInfoText GPS_TAG_GPS_AREA_INFORMATION = new TagInfoText(
+ public static final TagInfoGpsText GPS_TAG_GPS_AREA_INFORMATION = new TagInfoGpsText(
"GPS Area Information", 0x001c, FIELD_TYPE_UNKNOWN, -1,
TiffDirectoryType.EXIF_DIRECTORY_GPS);
diff --git a/src/main/java/org/apache/commons/sanselan/formats/tiff/taginfos/TagInfoText.java b/src/main/java/org/apache/commons/sanselan/formats/tiff/taginfos/TagInfoGpsText.java
similarity index 75%
rename from src/main/java/org/apache/commons/sanselan/formats/tiff/taginfos/TagInfoText.java
rename to src/main/java/org/apache/commons/sanselan/formats/tiff/taginfos/TagInfoGpsText.java
index 4a9a734..798389b 100644
--- a/src/main/java/org/apache/commons/sanselan/formats/tiff/taginfos/TagInfoText.java
+++ b/src/main/java/org/apache/commons/sanselan/formats/tiff/taginfos/TagInfoGpsText.java
@@ -26,9 +26,9 @@
import org.apache.commons.sanselan.formats.tiff.fieldtypes.FieldType;
import org.apache.commons.sanselan.util.Debug;
-public final class TagInfoText extends TagInfo
+public final class TagInfoGpsText extends TagInfo
{
- public TagInfoText(String name, int tag, FieldType dataType, int length,
+ public TagInfoGpsText(String name, int tag, FieldType dataType, int length,
TiffDirectoryType exifDirectory)
{
super(name, tag, dataType, length, exifDirectory);
@@ -51,36 +51,37 @@
}
}
- private static final TagInfoText.TextEncoding TEXT_ENCODING_ASCII = new TextEncoding(
+ private static final TagInfoGpsText.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 TagInfoText.TextEncoding TEXT_ENCODING_JIS = new TextEncoding(
+ private static final TagInfoGpsText.TextEncoding TEXT_ENCODING_JIS = new TextEncoding(
new byte[]{
0x4A, 0x49, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00,
}, "JIS"); // JIS X208-1990
- private static final TagInfoText.TextEncoding TEXT_ENCODING_UNICODE = new TextEncoding(
+ private static final TagInfoGpsText.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 TagInfoText.TextEncoding TEXT_ENCODING_UNDEFINED = new TextEncoding(
+ private static final TagInfoGpsText.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 TagInfoText.TextEncoding TEXT_ENCODINGS[] = {
+ private static final TagInfoGpsText.TextEncoding TEXT_ENCODINGS[] = {
TEXT_ENCODING_ASCII, //
TEXT_ENCODING_JIS, //
TEXT_ENCODING_UNICODE, //
TEXT_ENCODING_UNDEFINED, //
};
+ @Override
public byte[] encodeValue(FieldType fieldType, Object value,
int byteOrder) throws ImageWriteException
{
if (!(value instanceof String))
- throw new ImageWriteException("Text value not String: " + value
+ throw new ImageWriteException("GPS text value not String: " + value
+ " (" + Debug.getType(value) + ")");
String s = (String) value;
@@ -124,25 +125,33 @@
}
}
- public Object getValue(TiffField entry) throws ImageReadException
+ @Override
+ public String 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
- {
+ if (entry.type == FIELD_TYPE_ASCII.type) {
+ Object object = FIELD_TYPE_ASCII.getSimpleValue(entry);
+ if (object instanceof String) {
+ return (String) object;
+ } else if (object instanceof String[]) {
+ // Use of arrays with the ASCII type
+ // should be extremely rare, and use of
+ // ASCII type in GPS fields should be
+ // forbidden. So assume the 2 never happen
+ // together and return incomplete strings if they do.
+ return ((String[]) object)[0];
+ } else {
+ throw new ImageReadException("Unexpected ASCII type decoded");
+ }
+ } else if (entry.type == FIELD_TYPE_UNDEFINED.type) {
+ /* later */
+ } else if (entry.type == FIELD_TYPE_BYTE.type) {
+ /* later */
+ } 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.");
+ throw new ImageReadException("GPS text field not encoded as bytes.");
}
byte bytes[] = entry.fieldType.getRawBytes(entry);
@@ -156,19 +165,18 @@
catch (UnsupportedEncodingException e)
{
throw new ImageReadException(
- "Text field missing encoding prefix.");
+ "GPS text field missing encoding prefix.");
}
}
for (int i = 0; i < TEXT_ENCODINGS.length; i++)
{
- TagInfoText.TextEncoding encoding = TEXT_ENCODINGS[i];
+ TagInfoGpsText.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);
@@ -180,12 +188,6 @@
}
}
- // 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.
@@ -193,7 +195,7 @@
}
catch (UnsupportedEncodingException e)
{
- throw new ImageReadException("Unknown text encoding prefix.");
+ throw new ImageReadException("Unknown GPS text encoding prefix.");
}
}
diff --git a/src/main/java/org/apache/commons/sanselan/formats/tiff/taginfos/TagInfoXpString.java b/src/main/java/org/apache/commons/sanselan/formats/tiff/taginfos/TagInfoXpString.java
new file mode 100644
index 0000000..bc3e684
--- /dev/null
+++ b/src/main/java/org/apache/commons/sanselan/formats/tiff/taginfos/TagInfoXpString.java
@@ -0,0 +1,64 @@
+/*
+ * 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.taginfos;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Arrays;
+
+import org.apache.commons.sanselan.ImageReadException;
+import org.apache.commons.sanselan.ImageWriteException;
+import org.apache.commons.sanselan.formats.tiff.TiffField;
+import org.apache.commons.sanselan.formats.tiff.constants.TiffDirectoryType;
+import org.apache.commons.sanselan.formats.tiff.fieldtypes.FieldType;
+import org.apache.commons.sanselan.util.Debug;
+
+/**
+ * Windows XP onwards store some tags using UTF-16LE, but the field type is byte -
+ * here we deal with this.
+ */
+public class TagInfoXpString extends TagInfo {
+ public TagInfoXpString(String name, int tag, int length, TiffDirectoryType directoryType) {
+ super(name, tag, Arrays.asList(FIELD_TYPE_UNDEFINED), length, directoryType);
+ }
+
+ @Override
+ 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 {
+ return s.getBytes("UTF-16LE");
+ } catch (UnsupportedEncodingException cannotHappen) {
+ return null;
+ }
+ }
+
+ @Override
+ public String getValue(TiffField entry) throws ImageReadException {
+ if (entry.type != FIELD_TYPE_BYTE.type) {
+ throw new ImageReadException("Text field not encoded as bytes.");
+ }
+ try {
+ return new String(entry.getByteArrayValue(), "UTF-16LE");
+ } catch (UnsupportedEncodingException cannotHappen) {
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/apache/commons/sanselan/formats/tiff/write/TiffOutputDirectory.java b/src/main/java/org/apache/commons/sanselan/formats/tiff/write/TiffOutputDirectory.java
index deca567..b9b3207 100644
--- a/src/main/java/org/apache/commons/sanselan/formats/tiff/write/TiffOutputDirectory.java
+++ b/src/main/java/org/apache/commons/sanselan/formats/tiff/write/TiffOutputDirectory.java
@@ -41,6 +41,7 @@
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoByteOrShort;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoDouble;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoFloat;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoGpsText;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoLong;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoRational;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoSByte;
@@ -51,7 +52,7 @@
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoShortOrLong;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoShortOrLongOrRational;
import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoShortOrRational;
-import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoText;
+import org.apache.commons.sanselan.formats.tiff.taginfos.TagInfoXpString;
public final class TiffOutputDirectory extends TiffOutputItem implements
TiffConstants
@@ -200,7 +201,7 @@
}
byte[] bytes = tagInfo.encodeValue(byteOrder, values);
TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo,
- TiffFieldTypeConstants.FIELD_TYPE_SHORT, values.length, bytes);
+ TiffFieldTypeConstants.FIELD_TYPE_BYTE, values.length, bytes);
add(tiffOutputField);
}
@@ -222,7 +223,7 @@
}
byte[] bytes = tagInfo.encodeValue(byteOrder, values);
TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo,
- TiffFieldTypeConstants.FIELD_TYPE_LONG, values.length, bytes);
+ TiffFieldTypeConstants.FIELD_TYPE_SHORT, values.length, bytes);
add(tiffOutputField);
}
@@ -244,7 +245,7 @@
}
byte[] bytes = tagInfo.encodeValue(byteOrder, values);
TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo,
- TiffFieldTypeConstants.FIELD_TYPE_RATIONAL, values.length, bytes);
+ TiffFieldTypeConstants.FIELD_TYPE_SHORT, values.length, bytes);
add(tiffOutputField);
}
@@ -255,7 +256,7 @@
}
byte[] bytes = tagInfo.encodeValue(byteOrder, values);
TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo,
- TiffFieldTypeConstants.FIELD_TYPE_RATIONAL, values.length, bytes);
+ TiffFieldTypeConstants.FIELD_TYPE_LONG, values.length, bytes);
add(tiffOutputField);
}
@@ -277,7 +278,7 @@
}
byte[] bytes = tagInfo.encodeValue(byteOrder, values);
TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo,
- TiffFieldTypeConstants.FIELD_TYPE_RATIONAL, values.length, bytes);
+ TiffFieldTypeConstants.FIELD_TYPE_SHORT, values.length, bytes);
add(tiffOutputField);
}
@@ -292,10 +293,17 @@
add(tiffOutputField);
}
- public void add(TagInfoText tagInfo, String value) throws ImageWriteException {
+ public void add(TagInfoGpsText tagInfo, String value) throws ImageWriteException {
byte[] bytes = tagInfo.encodeValue(TiffFieldTypeConstants.FIELD_TYPE_UNKNOWN, value, byteOrder);
TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo,
- TiffFieldTypeConstants.FIELD_TYPE_UNKNOWN, bytes.length, bytes);
+ tagInfo.dataTypes.get(0), bytes.length, bytes);
+ add(tiffOutputField);
+ }
+
+ public void add(TagInfoXpString tagInfo, String value) throws ImageWriteException {
+ byte[] bytes = tagInfo.encodeValue(TiffFieldTypeConstants.FIELD_TYPE_BYTE, value, byteOrder);
+ TiffOutputField tiffOutputField = new TiffOutputField(tagInfo.tag, tagInfo,
+ TiffFieldTypeConstants.FIELD_TYPE_BYTE, bytes.length, bytes);
add(tiffOutputField);
}