blob: 54d8dc54ed65756093fcc502ff1b6cabad03d67d [file] [log] [blame]
/*
* Copyright (c) 2014-2021 by Wen Yu
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License, v. 2.0 are satisfied: GNU General Public License, version 2
* or any later version.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
*/
package pixy.image.tiff;
import java.io.IOException;
import pixy.io.RandomAccessOutputStream;
import pixy.string.StringUtils;
/**
* IFD (Image File Directory) field.
* <p>
* We could have used a TiffTag enum as the first parameter of the constructor, but this
* will not work with unknown tags of tag type TiffTag.UNKNOWN. In that case, we cannot
* use the tag values to sort the fields or as keys for a hash map as used by {@link IFD}.
*
* @author Wen Yu, yuwen_66@yahoo.com
* @version 1.0 01/04/2013
*/
public abstract class TiffField<T> implements Comparable<TiffField<?>>{
private final short tag;
private final FieldType fieldType;
private final int length;
protected T data;
protected IFD parent;
protected static final int MAX_STRING_REPR_LEN = 10; // Default length for string representation
protected int dataOffset;
public TiffField(IFD parent, short tag, FieldType fieldType, int length) {
this(tag, fieldType, length);
this.parent = parent;
}
public TiffField(short tag, FieldType fieldType, int length) {
this.tag = tag;
this.fieldType = fieldType;
this.length = length;
}
public int compareTo(TiffField<?> that) {
return (this.tag&0xffff) - (that.tag&0xffff);
}
public T getData() {
return data;
}
public IFD getParent() {
return new IFD(parent);
}
/** Return an integer array representing TIFF long field */
public int[] getDataAsLong() {
throw new UnsupportedOperationException("getDataAsLong() method is only supported by"
+ " short, long, and rational data types");
}
/**
* @return a String representation of the field data
*/
public abstract String getDataAsString();
public int getLength() {
return length;
}
/**
* Used to update field data when necessary.
* <p>
* This method should be called only after the field has been written to the underlying RandomOutputStream.
*
* @return the stream position where actual data starts to write
*/
public int getDataOffset() {
return dataOffset;
}
public short getTag() {
return tag;
}
public FieldType getType() {
return this.fieldType;
}
@Override public String toString() {
short tag = this.getTag();
Tag tagEnum = TiffTag.fromShort(tag);
if (tagEnum != TiffTag.UNKNOWN)
return tagEnum.toString();
return tagEnum.toString() + " [TiffTag value: "+ StringUtils.shortToHexStringMM(tag) + "]";
}
public final int write(RandomAccessOutputStream os, int toOffset) throws IOException {
// Write the header first
os.writeShort(this.tag);
os.writeShort(getType().getValue());
os.writeInt(getLength());
// Then the actual data
return writeData(os, toOffset);
}
protected abstract int writeData(RandomAccessOutputStream os, int toOffset) throws IOException;
}