use of it.geosolutions.imageio.plugins.tiff.TIFFTag in project imageio-ext by geosolutions-it.
the class TIFFIFD method getTag.
public static TIFFTag getTag(int tagNumber, List tagSets) {
Iterator iter = tagSets.iterator();
while (iter.hasNext()) {
TIFFTagSet tagSet = (TIFFTagSet) iter.next();
TIFFTag tag = tagSet.getTag(tagNumber);
if (tag != null) {
return tag;
}
}
return null;
}
use of it.geosolutions.imageio.plugins.tiff.TIFFTag in project imageio-ext by geosolutions-it.
the class EmptyImage method setupMetadata.
/**
* Sets up the output metadata adding, removing, and overriding fields
* as needed. The destination image dimensions are provided as parameters
* because these might differ from those of the source due to subsampling.
*
* @param cm The <code>ColorModel</code> of the image being written.
* @param sm The <code>SampleModel</code> of the image being written.
* @param destWidth The width of the written image after subsampling.
* @param destHeight The height of the written image after subsampling.
*/
void setupMetadata(ColorModel cm, SampleModel sm, int destWidth, int destHeight) throws IIOException {
// Get initial IFD from metadata
// Always emit these fields:
//
// Override values from metadata:
//
// planarConfiguration -> chunky (planar not supported on output)
//
// Override values from metadata with image-derived values:
//
// bitsPerSample (if not bilivel)
// colorMap (if palette color)
// photometricInterpretation (derive from image)
// imageLength
// imageWidth
//
// rowsPerStrip \ / tileLength
// stripOffsets | OR | tileOffsets
// stripByteCounts / | tileByteCounts
// \ tileWidth
//
//
// Override values from metadata with write param values:
//
// compression
// Use values from metadata if present for these fields,
// otherwise use defaults:
//
// resolutionUnit
// XResolution (take from metadata if present)
// YResolution
// rowsPerStrip
// sampleFormat
TIFFIFD rootIFD = imageMetadata.getRootIFD();
BaselineTIFFTagSet base = BaselineTIFFTagSet.getInstance();
// If PlanarConfiguration field present, set value to chunky.
TIFFField f = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_PLANAR_CONFIGURATION);
if (f != null && f.getAsInt(0) != BaselineTIFFTagSet.PLANAR_CONFIGURATION_CHUNKY) {
// XXX processWarningOccurred()
TIFFField planarConfigurationField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_PLANAR_CONFIGURATION), BaselineTIFFTagSet.PLANAR_CONFIGURATION_CHUNKY);
rootIFD.addTIFFField(planarConfigurationField);
}
char[] extraSamples = null;
this.photometricInterpretation = -1;
boolean forcePhotometricInterpretation = false;
f = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION);
if (f != null) {
photometricInterpretation = f.getAsInt(0);
if (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR && !(cm instanceof IndexColorModel)) {
photometricInterpretation = -1;
} else {
forcePhotometricInterpretation = true;
}
}
// f = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_EXTRA_SAMPLES);
// if (f != null) {
// extraSamples = f.getAsChars();
// }
// f = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE);
// if (f != null) {
// bitsPerSample = f.getAsChars();
// }
int[] sampleSize = sm.getSampleSize();
int numBands = sm.getNumBands();
int numExtraSamples = 0;
// cannot be zero.
if (numBands > 1 && cm != null && cm.hasAlpha()) {
--numBands;
numExtraSamples = 1;
extraSamples = new char[1];
if (cm.isAlphaPremultiplied()) {
extraSamples[0] = BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA;
} else {
extraSamples[0] = BaselineTIFFTagSet.EXTRA_SAMPLES_UNASSOCIATED_ALPHA;
}
}
if (numBands == 3) {
this.nativePhotometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB;
if (photometricInterpretation == -1) {
photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB;
}
} else if (sm.getNumBands() == 1 && cm instanceof IndexColorModel) {
IndexColorModel icm = (IndexColorModel) cm;
int r0 = icm.getRed(0);
int r1 = icm.getRed(1);
if (icm.getMapSize() == 2 && (r0 == icm.getGreen(0)) && (r0 == icm.getBlue(0)) && (r1 == icm.getGreen(1)) && (r1 == icm.getBlue(1)) && (r0 == 0 || r0 == 255) && (r1 == 0 || r1 == 255) && (r0 != r1)) {
if (r0 == 0) {
nativePhotometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO;
} else {
nativePhotometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO;
}
// WhiteIsZero or BlackIsZero, leave it alone
if (photometricInterpretation != BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO && photometricInterpretation != BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO) {
photometricInterpretation = r0 == 0 ? BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO : BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO;
}
} else {
nativePhotometricInterpretation = photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR;
}
} else {
if (cm != null) {
switch(cm.getColorSpace().getType()) {
case ColorSpace.TYPE_Lab:
nativePhotometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CIELAB;
break;
case ColorSpace.TYPE_YCbCr:
nativePhotometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR;
break;
case ColorSpace.TYPE_CMYK:
nativePhotometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CMYK;
break;
default:
nativePhotometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO;
}
} else {
nativePhotometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO;
}
if (photometricInterpretation == -1) {
photometricInterpretation = nativePhotometricInterpretation;
}
}
// Set the compressor and color converter.
this.compressor = null;
this.colorConverter = null;
if (param instanceof TIFFImageWriteParam) {
TIFFImageWriteParam tparam = (TIFFImageWriteParam) param;
if (tparam.getCompressionMode() == tparam.MODE_EXPLICIT) {
compressor = tparam.getTIFFCompressor();
String compressionType = param.getCompressionType();
if (compressor != null && !compressor.getCompressionType().equals(compressionType)) {
// Unset the TIFFCompressor if its compression type is
// not the one selected.
compressor = null;
}
} else {
// Compression mode not MODE_EXPLICIT.
compressor = null;
}
colorConverter = tparam.getColorConverter();
if (colorConverter != null) {
photometricInterpretation = tparam.getPhotometricInterpretation();
}
}
// Emit compression tag
int compressionMode = param instanceof TIFFImageWriteParam ? param.getCompressionMode() : ImageWriteParam.MODE_DEFAULT;
switch(compressionMode) {
case ImageWriteParam.MODE_EXPLICIT:
{
String compressionType = param.getCompressionType();
if (compressionType == null) {
this.compression = BaselineTIFFTagSet.COMPRESSION_NONE;
} else {
// Determine corresponding compression tag value.
int len = compressionTypes.length;
for (int i = 0; i < len; i++) {
if (compressionType.equals(compressionTypes[i])) {
this.compression = compressionNumbers[i];
}
}
}
// with the precedence described in TIFFImageWriteParam.
if (compressor != null && compressor.getCompressionTagValue() != this.compression) {
// Does not match: unset the compressor.
compressor = null;
}
}
break;
case ImageWriteParam.MODE_COPY_FROM_METADATA:
{
TIFFField compField = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_COMPRESSION);
if (compField != null) {
this.compression = compField.getAsInt(0);
break;
}
}
case ImageWriteParam.MODE_DEFAULT:
case ImageWriteParam.MODE_DISABLED:
default:
this.compression = BaselineTIFFTagSet.COMPRESSION_NONE;
}
TIFFField predictorField = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_PREDICTOR);
if (predictorField != null) {
this.predictor = predictorField.getAsInt(0);
// We only support Horizontal Predictor for a bitDepth of 8
if (sampleSize[0] != 8 || // Check the value of the tag for validity
(predictor != BaselineTIFFTagSet.PREDICTOR_NONE && predictor != BaselineTIFFTagSet.PREDICTOR_HORIZONTAL_DIFFERENCING)) {
// XXX processWarningOccured ???
// Set to default
predictor = BaselineTIFFTagSet.PREDICTOR_NONE;
// Emit this changed predictor value to metadata
TIFFField newPredictorField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_PREDICTOR), predictor);
rootIFD.addTIFFField(newPredictorField);
}
// XXX Do we need to ensure that predictor is not passed on if
// the compression is not either Deflate or LZW?
}
TIFFField compressionField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_COMPRESSION), compression);
rootIFD.addTIFFField(compressionField);
// Set EXIF flag. Note that there is no way to determine definitively
// when an uncompressed thumbnail is being written as the EXIF IFD
// pointer field is optional for thumbnails.
boolean isEXIF = false;
if (numBands == 3 && sampleSize[0] == 8 && sampleSize[1] == 8 && sampleSize[2] == 8) {
// Three bands with 8 bits per sample.
if (rootIFD.getTIFFField(EXIFParentTIFFTagSet.TAG_EXIF_IFD_POINTER) != null) {
// EXIF IFD pointer present.
if (compression == BaselineTIFFTagSet.COMPRESSION_NONE && (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB || photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR)) {
// Uncompressed RGB or YCbCr.
isEXIF = true;
} else if (compression == BaselineTIFFTagSet.COMPRESSION_OLD_JPEG) {
// Compressed.
isEXIF = true;
}
} else if (compressionMode == ImageWriteParam.MODE_EXPLICIT && EXIF_JPEG_COMPRESSION_TYPE.equals(param.getCompressionType())) {
// EXIF IFD pointer absent but EXIF JPEG compression set.
isEXIF = true;
}
}
// Initialize JPEG interchange format flag which is used to
// indicate that the image is stored as a single JPEG stream.
// This flag is separated from the 'isEXIF' flag in case JPEG
// interchange format is eventually supported for non-EXIF images.
boolean isJPEGInterchange = isEXIF && compression == BaselineTIFFTagSet.COMPRESSION_OLD_JPEG;
if (compressor == null) {
if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_RLE) {
if (PackageUtil.isCodecLibAvailable()) {
try {
compressor = new TIFFCodecLibRLECompressor();
if (DEBUG) {
System.out.println("Using codecLib RLE compressor");
}
} catch (RuntimeException e) {
if (DEBUG) {
System.out.println(e);
}
}
}
if (compressor == null) {
compressor = new TIFFRLECompressor();
if (DEBUG) {
System.out.println("Using Java RLE compressor");
}
}
if (!forcePhotometricInterpretation) {
photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO;
}
} else if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_4) {
if (PackageUtil.isCodecLibAvailable()) {
try {
compressor = new TIFFCodecLibT4Compressor();
if (DEBUG) {
System.out.println("Using codecLib T.4 compressor");
}
} catch (RuntimeException e) {
if (DEBUG) {
System.out.println(e);
}
}
}
if (compressor == null) {
compressor = new TIFFT4Compressor();
if (DEBUG) {
System.out.println("Using Java T.4 compressor");
}
}
if (!forcePhotometricInterpretation) {
photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO;
}
} else if (compression == BaselineTIFFTagSet.COMPRESSION_CCITT_T_6) {
if (PackageUtil.isCodecLibAvailable()) {
try {
compressor = new TIFFCodecLibT6Compressor();
if (DEBUG) {
System.out.println("Using codecLib T.6 compressor");
}
} catch (RuntimeException e) {
if (DEBUG) {
System.out.println(e);
}
}
}
if (compressor == null) {
compressor = new TIFFT6Compressor();
if (DEBUG) {
System.out.println("Using Java T.6 compressor");
}
}
if (!forcePhotometricInterpretation) {
photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO;
}
} else if (compression == BaselineTIFFTagSet.COMPRESSION_LZW) {
compressor = new TIFFLZWCompressor(predictor);
} else if (compression == BaselineTIFFTagSet.COMPRESSION_OLD_JPEG) {
if (isEXIF) {
compressor = new TIFFEXIFJPEGCompressor(param);
} else {
throw new IIOException("Old JPEG compression not supported!");
}
} else if (compression == BaselineTIFFTagSet.COMPRESSION_JPEG) {
if (numBands == 3 && sampleSize[0] == 8 && sampleSize[1] == 8 && sampleSize[2] == 8) {
photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR;
} else if (numBands == 1 && sampleSize[0] == 8) {
photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO;
} else {
throw new IIOException("JPEG compression supported for 1- and 3-band byte images only!");
}
compressor = new TIFFJPEGCompressor(param);
} else if (compression == BaselineTIFFTagSet.COMPRESSION_ZLIB) {
compressor = new TIFFZLibCompressor(param, predictor);
} else if (compression == BaselineTIFFTagSet.COMPRESSION_PACKBITS) {
compressor = new TIFFPackBitsCompressor();
} else if (compression == BaselineTIFFTagSet.COMPRESSION_DEFLATE) {
compressor = new TIFFDeflateCompressor(param, predictor);
} else {
// Determine inverse fill setting.
f = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_FILL_ORDER);
boolean inverseFill = (f != null && f.getAsInt(0) == 2);
if (inverseFill) {
compressor = new TIFFLSBCompressor();
} else {
compressor = new TIFFNullCompressor();
}
}
// compression == ?
}
if (DEBUG) {
if (param != null && param.getCompressionMode() == param.MODE_EXPLICIT) {
System.out.println("compressionType = " + param.getCompressionType());
}
if (compressor != null) {
System.out.println("compressor = " + compressor.getClass().getName());
}
}
if (colorConverter == null) {
if (cm != null && cm.getColorSpace().getType() == ColorSpace.TYPE_RGB) {
//
if (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR && compression != BaselineTIFFTagSet.COMPRESSION_JPEG) {
//
// Convert RGB to YCbCr only if compression type is not
// JPEG in which case this is handled implicitly by the
// compressor.
//
colorConverter = new TIFFYCbCrColorConverter(imageMetadata);
} else if (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CIELAB) {
colorConverter = new TIFFCIELabColorConverter();
}
}
}
//
if (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR && compression != BaselineTIFFTagSet.COMPRESSION_JPEG) {
// Remove old subsampling and positioning fields.
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_Y_CB_CR_SUBSAMPLING);
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_Y_CB_CR_POSITIONING);
// Add unity chrominance subsampling factors.
rootIFD.addTIFFField(new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_Y_CB_CR_SUBSAMPLING), TIFFTag.TIFF_SHORT, 2, new char[] { (char) 1, (char) 1 }));
// Add cosited positioning.
rootIFD.addTIFFField(new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_Y_CB_CR_POSITIONING), TIFFTag.TIFF_SHORT, 1, new char[] { (char) BaselineTIFFTagSet.Y_CB_CR_POSITIONING_COSITED }));
}
TIFFField photometricInterpretationField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION), photometricInterpretation);
rootIFD.addTIFFField(photometricInterpretationField);
this.bitsPerSample = new char[numBands + numExtraSamples];
this.bitDepth = 0;
for (int i = 0; i < numBands; i++) {
this.bitDepth = Math.max(bitDepth, sampleSize[i]);
}
if (bitDepth == 3) {
bitDepth = 4;
} else if (bitDepth > 4 && bitDepth <= 8) {
bitDepth = 8;
} else if (bitDepth > 8 && bitDepth <= 16) {
bitDepth = 16;
} else if (bitDepth > 16 && bitDepth <= 32) {
bitDepth = 32;
} else if (bitDepth > 32) {
bitDepth = 64;
}
for (int i = 0; i < bitsPerSample.length; i++) {
bitsPerSample[i] = (char) bitDepth;
}
// if already in the metadata and correct (count and value == 1).
if (bitsPerSample.length != 1 || bitsPerSample[0] != 1) {
TIFFField bitsPerSampleField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE), TIFFTag.TIFF_SHORT, bitsPerSample.length, bitsPerSample);
rootIFD.addTIFFField(bitsPerSampleField);
} else {
// bitsPerSample.length == 1 && bitsPerSample[0] == 1
TIFFField bitsPerSampleField = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE);
if (bitsPerSampleField != null) {
int[] bps = bitsPerSampleField.getAsInts();
if (bps == null || bps.length != 1 || bps[0] != 1) {
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE);
}
}
}
// Prepare SampleFormat field.
f = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_SAMPLE_FORMAT);
if (f == null && (bitDepth == 16 || bitDepth == 32 || bitDepth == 64)) {
// Set up default content for 16- and 32-bit cases.
char sampleFormatValue;
int dataType = sm.getDataType();
if (bitDepth == 16 && dataType == DataBuffer.TYPE_USHORT) {
sampleFormatValue = (char) BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER;
} else if (bitDepth == 32 && dataType == DataBuffer.TYPE_FLOAT) {
sampleFormatValue = (char) BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT;
} else if (bitDepth == 64 && dataType == DataBuffer.TYPE_DOUBLE) {
sampleFormatValue = (char) BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT;
} else {
sampleFormatValue = BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER;
}
this.sampleFormat = (int) sampleFormatValue;
char[] sampleFormatArray = new char[bitsPerSample.length];
Arrays.fill(sampleFormatArray, sampleFormatValue);
// Update the metadata.
TIFFTag sampleFormatTag = base.getTag(BaselineTIFFTagSet.TAG_SAMPLE_FORMAT);
TIFFField sampleFormatField = new TIFFField(sampleFormatTag, TIFFTag.TIFF_SHORT, sampleFormatArray.length, sampleFormatArray);
rootIFD.addTIFFField(sampleFormatField);
} else if (f != null) {
// Get whatever was provided.
sampleFormat = f.getAsInt(0);
} else {
// Set default value for internal use only.
sampleFormat = BaselineTIFFTagSet.SAMPLE_FORMAT_UNDEFINED;
}
if (extraSamples != null) {
TIFFField extraSamplesField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_EXTRA_SAMPLES), TIFFTag.TIFF_SHORT, extraSamples.length, extraSamples);
rootIFD.addTIFFField(extraSamplesField);
} else {
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_EXTRA_SAMPLES);
}
TIFFField samplesPerPixelField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL), bitsPerSample.length);
rootIFD.addTIFFField(samplesPerPixelField);
// Emit ColorMap if image is of palette color type
if (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR && cm instanceof IndexColorModel) {
char[] colorMap = new char[3 * (1 << bitsPerSample[0])];
IndexColorModel icm = (IndexColorModel) cm;
// mapSize is determined by BitsPerSample, not by incoming ICM.
int mapSize = 1 << bitsPerSample[0];
int indexBound = Math.min(mapSize, icm.getMapSize());
for (int i = 0; i < indexBound; i++) {
colorMap[i] = (char) ((icm.getRed(i) * 65535) / 255);
colorMap[mapSize + i] = (char) ((icm.getGreen(i) * 65535) / 255);
colorMap[2 * mapSize + i] = (char) ((icm.getBlue(i) * 65535) / 255);
}
TIFFField colorMapField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_COLOR_MAP), TIFFTag.TIFF_SHORT, colorMap.length, colorMap);
rootIFD.addTIFFField(colorMapField);
} else {
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_COLOR_MAP);
}
// metadata and the ColorSpace is non-standard ICC.
if (cm != null && rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_ICC_PROFILE) == null && ImageUtil.isNonStandardICCColorSpace(cm.getColorSpace())) {
ICC_ColorSpace iccColorSpace = (ICC_ColorSpace) cm.getColorSpace();
byte[] iccProfileData = iccColorSpace.getProfile().getData();
TIFFField iccProfileField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_ICC_PROFILE), TIFFTag.TIFF_UNDEFINED, iccProfileData.length, iccProfileData);
rootIFD.addTIFFField(iccProfileField);
}
// Always emit XResolution and YResolution.
TIFFField XResolutionField = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_X_RESOLUTION);
TIFFField YResolutionField = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_Y_RESOLUTION);
if (XResolutionField == null && YResolutionField == null) {
long[][] resRational = new long[1][2];
resRational[0] = new long[2];
TIFFField ResolutionUnitField = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT);
// quantities is present.
if (ResolutionUnitField == null && rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_X_POSITION) == null && rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_Y_POSITION) == null) {
// Set resolution to unit and units to dimensionless.
resRational[0][0] = 1;
resRational[0][1] = 1;
ResolutionUnitField = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT), BaselineTIFFTagSet.RESOLUTION_UNIT_NONE);
rootIFD.addTIFFField(ResolutionUnitField);
} else {
// Set resolution to a value which would make the maximum
// image dimension equal to 4 inches as arbitrarily stated
// in the description of ResolutionUnit in the TIFF 6.0
// specification. If the ResolutionUnit field specifies
// "none" then set the resolution to unity (1/1).
int resolutionUnit = ResolutionUnitField != null ? ResolutionUnitField.getAsInt(0) : BaselineTIFFTagSet.RESOLUTION_UNIT_INCH;
int maxDimension = Math.max(destWidth, destHeight);
switch(resolutionUnit) {
case BaselineTIFFTagSet.RESOLUTION_UNIT_INCH:
resRational[0][0] = maxDimension;
resRational[0][1] = 4;
break;
case BaselineTIFFTagSet.RESOLUTION_UNIT_CENTIMETER:
// divide out 100
resRational[0][0] = 100L * maxDimension;
// 2.54 cm/inch * 100
resRational[0][1] = 4 * 254;
break;
default:
resRational[0][0] = 1;
resRational[0][1] = 1;
}
}
XResolutionField = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION), TIFFTag.TIFF_RATIONAL, 1, resRational);
rootIFD.addTIFFField(XResolutionField);
YResolutionField = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION), TIFFTag.TIFF_RATIONAL, 1, resRational);
rootIFD.addTIFFField(YResolutionField);
} else if (XResolutionField == null && YResolutionField != null) {
// Set XResolution to YResolution.
long[] yResolution = (long[]) YResolutionField.getAsRational(0).clone();
XResolutionField = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION), TIFFTag.TIFF_RATIONAL, 1, yResolution);
rootIFD.addTIFFField(XResolutionField);
} else if (XResolutionField != null && YResolutionField == null) {
// Set YResolution to XResolution.
long[] xResolution = (long[]) XResolutionField.getAsRational(0).clone();
YResolutionField = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION), TIFFTag.TIFF_RATIONAL, 1, xResolution);
rootIFD.addTIFFField(YResolutionField);
}
// Set mandatory fields, overriding metadata passed in
int width = destWidth;
TIFFField imageWidthField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_IMAGE_WIDTH), width);
rootIFD.addTIFFField(imageWidthField);
int height = destHeight;
TIFFField imageLengthField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_IMAGE_LENGTH), height);
rootIFD.addTIFFField(imageLengthField);
// Determine rowsPerStrip
int rowsPerStrip;
TIFFField rowsPerStripField = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_ROWS_PER_STRIP);
if (rowsPerStripField != null) {
rowsPerStrip = rowsPerStripField.getAsInt(0);
if (rowsPerStrip < 0) {
rowsPerStrip = height;
}
} else {
int bitsPerPixel = bitDepth * (numBands + numExtraSamples);
int bytesPerRow = (bitsPerPixel * width + 7) / 8;
rowsPerStrip = Math.max(Math.max(DEFAULT_BYTES_PER_STRIP / bytesPerRow, 1), 8);
}
rowsPerStrip = Math.min(rowsPerStrip, height);
// Tiling flag.
boolean useTiling = false;
// Analyze tiling parameters
int tilingMode = param instanceof TIFFImageWriteParam ? param.getTilingMode() : ImageWriteParam.MODE_DEFAULT;
if (tilingMode == ImageWriteParam.MODE_DISABLED || tilingMode == ImageWriteParam.MODE_DEFAULT) {
this.tileWidth = width;
this.tileLength = rowsPerStrip;
useTiling = false;
} else if (tilingMode == ImageWriteParam.MODE_EXPLICIT) {
tileWidth = param.getTileWidth();
tileLength = param.getTileHeight();
useTiling = true;
} else if (tilingMode == ImageWriteParam.MODE_COPY_FROM_METADATA) {
f = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_TILE_WIDTH);
if (f == null) {
tileWidth = width;
useTiling = false;
} else {
tileWidth = f.getAsInt(0);
useTiling = true;
}
f = rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_TILE_LENGTH);
if (f == null) {
tileLength = rowsPerStrip;
} else {
tileLength = f.getAsInt(0);
useTiling = true;
}
} else {
throw new IIOException("Illegal value of tilingMode!");
}
if (compression == BaselineTIFFTagSet.COMPRESSION_JPEG) {
// Reset tile size per TTN2 spec for JPEG compression.
int subX;
int subY;
if (numBands == 1) {
subX = subY = 1;
} else {
subX = subY = TIFFJPEGCompressor.CHROMA_SUBSAMPLING;
}
if (useTiling) {
int MCUMultipleX = 8 * subX;
int MCUMultipleY = 8 * subY;
tileWidth = Math.max(MCUMultipleX * ((tileWidth + MCUMultipleX / 2) / MCUMultipleX), MCUMultipleX);
tileLength = Math.max(MCUMultipleY * ((tileLength + MCUMultipleY / 2) / MCUMultipleY), MCUMultipleY);
} else if (rowsPerStrip < height) {
int MCUMultiple = 8 * Math.max(subX, subY);
rowsPerStrip = tileLength = Math.max(MCUMultiple * ((tileLength + MCUMultiple / 2) / MCUMultiple), MCUMultiple);
}
} else if (isJPEGInterchange) {
// Force tile size to equal image size.
tileWidth = width;
tileLength = height;
} else if (useTiling) {
// Round tile size to multiple of 16 per TIFF 6.0 specification
// (see pages 67-68 of version 6.0.1 from Adobe).
int tileWidthRemainder = tileWidth % 16;
if (tileWidthRemainder != 0) {
// Round to nearest multiple of 16 not less than 16.
tileWidth = Math.max(16 * ((tileWidth + 8) / 16), 16);
// XXX insert processWarningOccurred(int,String);
}
int tileLengthRemainder = tileLength % 16;
if (tileLengthRemainder != 0) {
// Round to nearest multiple of 16 not less than 16.
tileLength = Math.max(16 * ((tileLength + 8) / 16), 16);
// XXX insert processWarningOccurred(int,String);
}
}
this.tilesAcross = (width + tileWidth - 1) / tileWidth;
this.tilesDown = (height + tileLength - 1) / tileLength;
if (!useTiling) {
this.isTiled = false;
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_TILE_WIDTH);
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_TILE_LENGTH);
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_TILE_OFFSETS);
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS);
rowsPerStripField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_ROWS_PER_STRIP), rowsPerStrip);
rootIFD.addTIFFField(rowsPerStripField);
TIFFField stripOffsetsField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_STRIP_OFFSETS), isBtiff ? TIFFTag.TIFF_LONG8 : TIFFTag.TIFF_LONG, tilesDown);
rootIFD.addTIFFField(stripOffsetsField);
TIFFField stripByteCountsField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS), isBtiff ? TIFFTag.TIFF_LONG8 : TIFFTag.TIFF_LONG, tilesDown);
rootIFD.addTIFFField(stripByteCountsField);
} else {
this.isTiled = true;
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_ROWS_PER_STRIP);
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_STRIP_OFFSETS);
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS);
TIFFField tileWidthField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_TILE_WIDTH), tileWidth);
rootIFD.addTIFFField(tileWidthField);
TIFFField tileLengthField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_TILE_LENGTH), tileLength);
rootIFD.addTIFFField(tileLengthField);
TIFFField tileOffsetsField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_TILE_OFFSETS), isBtiff ? TIFFTag.TIFF_LONG8 : TIFFTag.TIFF_LONG, tilesDown * tilesAcross);
rootIFD.addTIFFField(tileOffsetsField);
TIFFField tileByteCountsField = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS), isBtiff ? TIFFTag.TIFF_LONG8 : TIFFTag.TIFF_LONG, tilesDown * tilesAcross);
rootIFD.addTIFFField(tileByteCountsField);
}
if (isEXIF) {
//
// Ensure presence of mandatory fields and absence of prohibited
// fields and those that duplicate information in JPEG marker
// segments per tables 14-18 of the EXIF 2.2 specification.
//
// If an empty image is being written or inserted then infer
// that the primary IFD is being set up.
boolean isPrimaryIFD = isEncodingEmpty();
// Handle TIFF fields in order of increasing tag number.
if (compression == BaselineTIFFTagSet.COMPRESSION_OLD_JPEG) {
// ImageWidth
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_IMAGE_WIDTH);
// ImageLength
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_IMAGE_LENGTH);
// BitsPerSample
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE);
// Compression
if (isPrimaryIFD) {
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_COMPRESSION);
}
// PhotometricInterpretation
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION);
// StripOffsets
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_STRIP_OFFSETS);
// SamplesPerPixel
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL);
// RowsPerStrip
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_ROWS_PER_STRIP);
// StripByteCounts
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS);
// XResolution and YResolution are handled above for all TIFFs.
// PlanarConfiguration
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_PLANAR_CONFIGURATION);
// ResolutionUnit
if (rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT) == null) {
f = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT), BaselineTIFFTagSet.RESOLUTION_UNIT_INCH);
rootIFD.addTIFFField(f);
}
if (isPrimaryIFD) {
// JPEGInterchangeFormat
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT);
// JPEGInterchangeFormatLength
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
// YCbCrSubsampling
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_Y_CB_CR_SUBSAMPLING);
// YCbCrPositioning
if (rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_Y_CB_CR_POSITIONING) == null) {
f = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_Y_CB_CR_POSITIONING), TIFFTag.TIFF_SHORT, 1, new char[] { (char) BaselineTIFFTagSet.Y_CB_CR_POSITIONING_CENTERED });
rootIFD.addTIFFField(f);
}
} else {
// Thumbnail IFD
// JPEGInterchangeFormat
f = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT), TIFFTag.TIFF_LONG, 1);
rootIFD.addTIFFField(f);
// JPEGInterchangeFormatLength
f = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH), TIFFTag.TIFF_LONG, 1);
rootIFD.addTIFFField(f);
// YCbCrSubsampling
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_Y_CB_CR_SUBSAMPLING);
}
} else {
// ResolutionUnit
if (rootIFD.getTIFFField(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT) == null) {
f = new TIFFField(base.getTag(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT), BaselineTIFFTagSet.RESOLUTION_UNIT_INCH);
rootIFD.addTIFFField(f);
}
// JPEGInterchangeFormat
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT);
// JPEGInterchangeFormatLength
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
if (photometricInterpretation == BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB) {
// YCbCrCoefficients
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_Y_CB_CR_COEFFICIENTS);
// YCbCrSubsampling
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_Y_CB_CR_SUBSAMPLING);
// YCbCrPositioning
rootIFD.removeTIFFField(BaselineTIFFTagSet.TAG_Y_CB_CR_POSITIONING);
}
}
// Get EXIF tags.
TIFFTagSet exifTags = EXIFTIFFTagSet.getInstance();
// Retrieve or create the EXIF IFD.
TIFFIFD exifIFD = null;
f = rootIFD.getTIFFField(EXIFParentTIFFTagSet.TAG_EXIF_IFD_POINTER);
if (f != null) {
// Retrieve the EXIF IFD.
exifIFD = (TIFFIFD) f.getData();
} else if (isPrimaryIFD) {
// Create the EXIF IFD.
List exifTagSets = new ArrayList(1);
exifTagSets.add(exifTags);
exifIFD = new TIFFIFD(exifTagSets);
// Add it to the root IFD.
TIFFTagSet tagSet = EXIFParentTIFFTagSet.getInstance();
TIFFTag exifIFDTag = tagSet.getTag(EXIFParentTIFFTagSet.TAG_EXIF_IFD_POINTER);
rootIFD.addTIFFField(new TIFFField(exifIFDTag, TIFFTag.TIFF_LONG, 1, exifIFD));
}
if (exifIFD != null) {
// ExifVersion
if (exifIFD.getTIFFField(EXIFTIFFTagSet.TAG_EXIF_VERSION) == null) {
f = new TIFFField(exifTags.getTag(EXIFTIFFTagSet.TAG_EXIF_VERSION), TIFFTag.TIFF_UNDEFINED, 4, EXIFTIFFTagSet.EXIF_VERSION_2_2);
exifIFD.addTIFFField(f);
}
if (compression == BaselineTIFFTagSet.COMPRESSION_OLD_JPEG) {
// ComponentsConfiguration
if (exifIFD.getTIFFField(EXIFTIFFTagSet.TAG_COMPONENTS_CONFIGURATION) == null) {
f = new TIFFField(exifTags.getTag(EXIFTIFFTagSet.TAG_COMPONENTS_CONFIGURATION), TIFFTag.TIFF_UNDEFINED, 4, new byte[] { (byte) EXIFTIFFTagSet.COMPONENTS_CONFIGURATION_Y, (byte) EXIFTIFFTagSet.COMPONENTS_CONFIGURATION_CB, (byte) EXIFTIFFTagSet.COMPONENTS_CONFIGURATION_CR, (byte) 0 });
exifIFD.addTIFFField(f);
}
} else {
// ComponentsConfiguration
exifIFD.removeTIFFField(EXIFTIFFTagSet.TAG_COMPONENTS_CONFIGURATION);
// CompressedBitsPerPixel
exifIFD.removeTIFFField(EXIFTIFFTagSet.TAG_COMPRESSED_BITS_PER_PIXEL);
}
// FlashpixVersion
if (exifIFD.getTIFFField(EXIFTIFFTagSet.TAG_FLASHPIX_VERSION) == null) {
f = new TIFFField(exifTags.getTag(EXIFTIFFTagSet.TAG_FLASHPIX_VERSION), TIFFTag.TIFF_UNDEFINED, 4, new byte[] { (byte) '0', (byte) '1', (byte) '0', (byte) '0' });
exifIFD.addTIFFField(f);
}
// ColorSpace
if (exifIFD.getTIFFField(EXIFTIFFTagSet.TAG_COLOR_SPACE) == null) {
f = new TIFFField(exifTags.getTag(EXIFTIFFTagSet.TAG_COLOR_SPACE), TIFFTag.TIFF_SHORT, 1, new char[] { (char) EXIFTIFFTagSet.COLOR_SPACE_SRGB });
exifIFD.addTIFFField(f);
}
if (compression == BaselineTIFFTagSet.COMPRESSION_OLD_JPEG) {
// PixelXDimension
if (exifIFD.getTIFFField(EXIFTIFFTagSet.TAG_PIXEL_X_DIMENSION) == null) {
f = new TIFFField(exifTags.getTag(EXIFTIFFTagSet.TAG_PIXEL_X_DIMENSION), width);
exifIFD.addTIFFField(f);
}
// PixelYDimension
if (exifIFD.getTIFFField(EXIFTIFFTagSet.TAG_PIXEL_Y_DIMENSION) == null) {
f = new TIFFField(exifTags.getTag(EXIFTIFFTagSet.TAG_PIXEL_Y_DIMENSION), height);
exifIFD.addTIFFField(f);
}
} else {
exifIFD.removeTIFFField(EXIFTIFFTagSet.TAG_INTEROPERABILITY_IFD_POINTER);
}
}
}
// if(isEXIF)
}
use of it.geosolutions.imageio.plugins.tiff.TIFFTag in project imageio-ext by geosolutions-it.
the class TIFFImageMetadata method parseIFD.
public static TIFFIFD parseIFD(Node node) throws IIOInvalidTreeException {
if (!node.getNodeName().equals("TIFFIFD")) {
fatal(node, "Expected \"TIFFIFD\" node");
}
String tagSetNames = getAttribute(node, "tagSets");
List tagSets = new ArrayList(5);
if (tagSetNames != null) {
StringTokenizer st = new StringTokenizer(tagSetNames, ",");
while (st.hasMoreTokens()) {
String className = st.nextToken();
Object o = null;
try {
Class setClass = Class.forName(className);
Method getInstanceMethod = setClass.getMethod("getInstance", (Class[]) null);
o = getInstanceMethod.invoke(null, (Object[]) null);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
if (!(o instanceof TIFFTagSet)) {
fatal(node, "Specified tag set class \"" + className + "\" is not an instance of TIFFTagSet");
} else {
tagSets.add((TIFFTagSet) o);
}
}
}
TIFFIFD ifd = new TIFFIFD(tagSets);
node = node.getFirstChild();
while (node != null) {
String name = node.getNodeName();
TIFFField f = null;
if (name.equals("TIFFIFD")) {
TIFFIFD subIFD = parseIFD(node);
String parentTagName = getAttribute(node, "parentTagName");
String parentTagNumber = getAttribute(node, "parentTagNumber");
TIFFTag tag = null;
if (parentTagName != null) {
tag = TIFFIFD.getTag(parentTagName, tagSets);
} else if (parentTagNumber != null) {
int tagNumber = Integer.valueOf(parentTagNumber).intValue();
tag = TIFFIFD.getTag(tagNumber, tagSets);
}
if (tag == null) {
tag = new TIFFTag("unknown", 0, 0, null);
}
int type;
if (tag.isDataTypeOK(TIFFTag.TIFF_IFD_POINTER)) {
type = TIFFTag.TIFF_IFD_POINTER;
} else {
type = TIFFTag.TIFF_LONG;
}
f = new TIFFField(tag, type, 1, subIFD);
} else if (name.equals("TIFFField")) {
int number = Integer.parseInt(getAttribute(node, "number"));
TIFFTagSet tagSet = null;
Iterator iter = tagSets.iterator();
while (iter.hasNext()) {
TIFFTagSet t = (TIFFTagSet) iter.next();
if (t.getTag(number) != null) {
tagSet = t;
break;
}
}
f = TIFFField.createFromMetadataNode(tagSet, node);
} else {
fatal(node, "Expected either \"TIFFIFD\" or \"TIFFField\" node, got " + name);
}
ifd.addTIFFField(f);
node = node.getNextSibling();
}
return ifd;
}
use of it.geosolutions.imageio.plugins.tiff.TIFFTag in project imageio-ext by geosolutions-it.
the class TIFFImageMetadata method mergeStandardTree.
private void mergeStandardTree(Node root) throws IIOInvalidTreeException {
TIFFField f;
TIFFTag tag;
Node node = root;
if (!node.getNodeName().equals(IIOMetadataFormatImpl.standardMetadataFormatName)) {
fatal(node, "Root must be " + IIOMetadataFormatImpl.standardMetadataFormatName);
}
// Obtain the sample format and set the palette flag if appropriate.
String sampleFormat = null;
Node dataNode = getChildNode(root, "Data");
boolean isPaletteColor = false;
if (dataNode != null) {
Node sampleFormatNode = getChildNode(dataNode, "SampleFormat");
if (sampleFormatNode != null) {
sampleFormat = getAttribute(sampleFormatNode, "value");
isPaletteColor = sampleFormat.equals("Index");
}
}
// If palette flag not set check for palette.
if (!isPaletteColor) {
Node chromaNode = getChildNode(root, "Chroma");
if (chromaNode != null && getChildNode(chromaNode, "Palette") != null) {
isPaletteColor = true;
}
}
node = node.getFirstChild();
while (node != null) {
String name = node.getNodeName();
if (name.equals("Chroma")) {
String colorSpaceType = null;
String blackIsZero = null;
boolean gotPalette = false;
Node child = node.getFirstChild();
while (child != null) {
String childName = child.getNodeName();
if (childName.equals("ColorSpaceType")) {
colorSpaceType = getAttribute(child, "name");
} else if (childName.equals("NumChannels")) {
tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL);
int samplesPerPixel = isPaletteColor ? 1 : Integer.parseInt(getAttribute(child, "value"));
f = new TIFFField(tag, samplesPerPixel);
rootIFD.addTIFFField(f);
} else if (childName.equals("BlackIsZero")) {
blackIsZero = getAttribute(child, "value");
} else if (childName.equals("Palette")) {
Node entry = child.getFirstChild();
HashMap palette = new HashMap();
int maxIndex = -1;
while (entry != null) {
String entryName = entry.getNodeName();
if (entryName.equals("PaletteEntry")) {
String idx = getAttribute(entry, "index");
int id = Integer.parseInt(idx);
if (id > maxIndex) {
maxIndex = id;
}
char red = (char) Integer.parseInt(getAttribute(entry, "red"));
char green = (char) Integer.parseInt(getAttribute(entry, "green"));
char blue = (char) Integer.parseInt(getAttribute(entry, "blue"));
palette.put(new Integer(id), new char[] { red, green, blue });
gotPalette = true;
}
entry = entry.getNextSibling();
}
if (gotPalette) {
int mapSize = maxIndex + 1;
int paletteLength = 3 * mapSize;
char[] paletteEntries = new char[paletteLength];
Iterator paletteIter = palette.keySet().iterator();
while (paletteIter.hasNext()) {
Integer index = (Integer) paletteIter.next();
char[] rgb = (char[]) palette.get(index);
int idx = index.intValue();
paletteEntries[idx] = (char) ((rgb[0] * 65535) / 255);
paletteEntries[mapSize + idx] = (char) ((rgb[1] * 65535) / 255);
paletteEntries[2 * mapSize + idx] = (char) ((rgb[2] * 65535) / 255);
}
tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_COLOR_MAP);
f = new TIFFField(tag, TIFFTag.TIFF_SHORT, paletteLength, paletteEntries);
rootIFD.addTIFFField(f);
}
}
child = child.getNextSibling();
}
int photometricInterpretation = -1;
if ((colorSpaceType == null || colorSpaceType.equals("GRAY")) && blackIsZero != null && blackIsZero.equalsIgnoreCase("FALSE")) {
photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO;
} else if (colorSpaceType != null) {
if (colorSpaceType.equals("GRAY")) {
boolean isTransparency = false;
if (root instanceof IIOMetadataNode) {
IIOMetadataNode iioRoot = (IIOMetadataNode) root;
NodeList siNodeList = iioRoot.getElementsByTagName("SubimageInterpretation");
if (siNodeList.getLength() == 1) {
Node siNode = siNodeList.item(0);
String value = getAttribute(siNode, "value");
if (value.equals("TransparencyMask")) {
isTransparency = true;
}
}
}
if (isTransparency) {
photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_TRANSPARENCY_MASK;
} else {
photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_BLACK_IS_ZERO;
}
} else if (colorSpaceType.equals("RGB")) {
photometricInterpretation = gotPalette ? BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_PALETTE_COLOR : BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_RGB;
} else if (colorSpaceType.equals("YCbCr")) {
photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_Y_CB_CR;
} else if (colorSpaceType.equals("CMYK")) {
photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CMYK;
} else if (colorSpaceType.equals("Lab")) {
photometricInterpretation = BaselineTIFFTagSet.PHOTOMETRIC_INTERPRETATION_CIELAB;
}
}
if (photometricInterpretation != -1) {
tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_PHOTOMETRIC_INTERPRETATION);
f = new TIFFField(tag, photometricInterpretation);
rootIFD.addTIFFField(f);
}
} else if (name.equals("Compression")) {
Node child = node.getFirstChild();
while (child != null) {
String childName = child.getNodeName();
if (childName.equals("CompressionTypeName")) {
int compression = -1;
String compressionTypeName = getAttribute(child, "value");
if (compressionTypeName.equalsIgnoreCase("None")) {
compression = BaselineTIFFTagSet.COMPRESSION_NONE;
} else {
String[] compressionNames = TIFFImageWriter.compressionTypes;
for (int i = 0; i < compressionNames.length; i++) {
if (compressionNames[i].equalsIgnoreCase(compressionTypeName)) {
compression = TIFFImageWriter.compressionNumbers[i];
break;
}
}
}
if (compression != -1) {
tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_COMPRESSION);
f = new TIFFField(tag, compression);
rootIFD.addTIFFField(f);
// Lossless is irrelevant.
}
}
child = child.getNextSibling();
}
} else if (name.equals("Data")) {
Node child = node.getFirstChild();
while (child != null) {
String childName = child.getNodeName();
if (childName.equals("PlanarConfiguration")) {
String pc = getAttribute(child, "value");
int planarConfiguration = -1;
if (pc.equals("PixelInterleaved")) {
planarConfiguration = BaselineTIFFTagSet.PLANAR_CONFIGURATION_CHUNKY;
} else if (pc.equals("PlaneInterleaved")) {
planarConfiguration = BaselineTIFFTagSet.PLANAR_CONFIGURATION_PLANAR;
}
if (planarConfiguration != -1) {
tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_PLANAR_CONFIGURATION);
f = new TIFFField(tag, planarConfiguration);
rootIFD.addTIFFField(f);
}
} else if (childName.equals("BitsPerSample")) {
String bps = getAttribute(child, "value");
char[] bitsPerSample = listToCharArray(bps);
tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE);
if (isPaletteColor) {
f = new TIFFField(tag, TIFFTag.TIFF_SHORT, 1, new char[] { bitsPerSample[0] });
} else {
f = new TIFFField(tag, TIFFTag.TIFF_SHORT, bitsPerSample.length, bitsPerSample);
}
rootIFD.addTIFFField(f);
} else if (childName.equals("SampleMSB")) {
// Add FillOrder only if lsb-to-msb (right to left)
// for all bands, i.e., SampleMSB is zero for all
// channels.
String sMSB = getAttribute(child, "value");
int[] sampleMSB = listToIntArray(sMSB);
boolean isRightToLeft = true;
for (int i = 0; i < sampleMSB.length; i++) {
if (sampleMSB[i] != 0) {
isRightToLeft = false;
break;
}
}
int fillOrder = isRightToLeft ? BaselineTIFFTagSet.FILL_ORDER_RIGHT_TO_LEFT : BaselineTIFFTagSet.FILL_ORDER_LEFT_TO_RIGHT;
tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_FILL_ORDER);
f = new TIFFField(tag, fillOrder);
rootIFD.addTIFFField(f);
}
child = child.getNextSibling();
}
} else if (name.equals("Dimension")) {
float pixelAspectRatio = -1.0f;
boolean gotPixelAspectRatio = false;
float horizontalPixelSize = -1.0f;
boolean gotHorizontalPixelSize = false;
float verticalPixelSize = -1.0f;
boolean gotVerticalPixelSize = false;
boolean sizeIsAbsolute = false;
float horizontalPosition = -1.0f;
boolean gotHorizontalPosition = false;
float verticalPosition = -1.0f;
boolean gotVerticalPosition = false;
Node child = node.getFirstChild();
while (child != null) {
String childName = child.getNodeName();
if (childName.equals("PixelAspectRatio")) {
String par = getAttribute(child, "value");
pixelAspectRatio = Float.parseFloat(par);
gotPixelAspectRatio = true;
} else if (childName.equals("ImageOrientation")) {
String orientation = getAttribute(child, "value");
for (int i = 0; i < orientationNames.length; i++) {
if (orientation.equals(orientationNames[i])) {
char[] oData = new char[1];
oData[0] = (char) i;
f = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_ORIENTATION), TIFFTag.TIFF_SHORT, 1, oData);
rootIFD.addTIFFField(f);
break;
}
}
} else if (childName.equals("HorizontalPixelSize")) {
String hps = getAttribute(child, "value");
horizontalPixelSize = Float.parseFloat(hps);
gotHorizontalPixelSize = true;
} else if (childName.equals("VerticalPixelSize")) {
String vps = getAttribute(child, "value");
verticalPixelSize = Float.parseFloat(vps);
gotVerticalPixelSize = true;
} else if (childName.equals("HorizontalPosition")) {
String hp = getAttribute(child, "value");
horizontalPosition = Float.parseFloat(hp);
gotHorizontalPosition = true;
} else if (childName.equals("VerticalPosition")) {
String vp = getAttribute(child, "value");
verticalPosition = Float.parseFloat(vp);
gotVerticalPosition = true;
}
child = child.getNextSibling();
}
sizeIsAbsolute = gotHorizontalPixelSize || gotVerticalPixelSize;
// Fill in pixel size data from aspect ratio
if (gotPixelAspectRatio) {
if (gotHorizontalPixelSize && !gotVerticalPixelSize) {
verticalPixelSize = horizontalPixelSize / pixelAspectRatio;
gotVerticalPixelSize = true;
} else if (gotVerticalPixelSize && !gotHorizontalPixelSize) {
horizontalPixelSize = verticalPixelSize * pixelAspectRatio;
gotHorizontalPixelSize = true;
} else if (!gotHorizontalPixelSize && !gotVerticalPixelSize) {
horizontalPixelSize = pixelAspectRatio;
verticalPixelSize = 1.0f;
gotHorizontalPixelSize = true;
gotVerticalPixelSize = true;
}
}
// Compute pixels/centimeter
if (gotHorizontalPixelSize) {
float xResolution = (sizeIsAbsolute ? 10.0f : 1.0f) / horizontalPixelSize;
long[][] hData = new long[1][2];
hData[0] = new long[2];
hData[0][0] = (long) (xResolution * 10000.0f);
hData[0][1] = (long) 10000;
f = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_X_RESOLUTION), TIFFTag.TIFF_RATIONAL, 1, hData);
rootIFD.addTIFFField(f);
}
if (gotVerticalPixelSize) {
float yResolution = (sizeIsAbsolute ? 10.0f : 1.0f) / verticalPixelSize;
long[][] vData = new long[1][2];
vData[0] = new long[2];
vData[0][0] = (long) (yResolution * 10000.0f);
vData[0][1] = (long) 10000;
f = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_Y_RESOLUTION), TIFFTag.TIFF_RATIONAL, 1, vData);
rootIFD.addTIFFField(f);
}
// Emit ResolutionUnit tag
char[] res = new char[1];
res[0] = (char) (sizeIsAbsolute ? BaselineTIFFTagSet.RESOLUTION_UNIT_CENTIMETER : BaselineTIFFTagSet.RESOLUTION_UNIT_NONE);
f = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_RESOLUTION_UNIT), TIFFTag.TIFF_SHORT, 1, res);
rootIFD.addTIFFField(f);
// Position
if (sizeIsAbsolute) {
if (gotHorizontalPosition) {
// Convert from millimeters to centimeters via
// numerator multiplier = denominator/10.
long[][] hData = new long[1][2];
hData[0][0] = (long) (horizontalPosition * 10000.0f);
hData[0][1] = (long) 100000;
f = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_X_POSITION), TIFFTag.TIFF_RATIONAL, 1, hData);
rootIFD.addTIFFField(f);
}
if (gotVerticalPosition) {
// Convert from millimeters to centimeters via
// numerator multiplier = denominator/10.
long[][] vData = new long[1][2];
vData[0][0] = (long) (verticalPosition * 10000.0f);
vData[0][1] = (long) 100000;
f = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_Y_POSITION), TIFFTag.TIFF_RATIONAL, 1, vData);
rootIFD.addTIFFField(f);
}
}
} else if (name.equals("Document")) {
Node child = node.getFirstChild();
while (child != null) {
String childName = child.getNodeName();
if (childName.equals("SubimageInterpretation")) {
String si = getAttribute(child, "value");
int newSubFileType = -1;
if (si.equals("TransparencyMask")) {
newSubFileType = BaselineTIFFTagSet.NEW_SUBFILE_TYPE_TRANSPARENCY;
} else if (si.equals("ReducedResolution")) {
newSubFileType = BaselineTIFFTagSet.NEW_SUBFILE_TYPE_REDUCED_RESOLUTION;
} else if (si.equals("SinglePage")) {
newSubFileType = BaselineTIFFTagSet.NEW_SUBFILE_TYPE_SINGLE_PAGE;
}
if (newSubFileType != -1) {
tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_NEW_SUBFILE_TYPE);
f = new TIFFField(tag, newSubFileType);
rootIFD.addTIFFField(f);
}
}
if (childName.equals("ImageCreationTime")) {
String year = getAttribute(child, "year");
String month = getAttribute(child, "month");
String day = getAttribute(child, "day");
String hour = getAttribute(child, "hour");
String minute = getAttribute(child, "minute");
String second = getAttribute(child, "second");
StringBuffer sb = new StringBuffer();
sb.append(year);
sb.append(":");
if (month.length() == 1) {
sb.append("0");
}
sb.append(month);
sb.append(":");
if (day.length() == 1) {
sb.append("0");
}
sb.append(day);
sb.append(" ");
if (hour.length() == 1) {
sb.append("0");
}
sb.append(hour);
sb.append(":");
if (minute.length() == 1) {
sb.append("0");
}
sb.append(minute);
sb.append(":");
if (second.length() == 1) {
sb.append("0");
}
sb.append(second);
String[] dt = new String[1];
dt[0] = sb.toString();
f = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_DATE_TIME), TIFFTag.TIFF_ASCII, 1, dt);
rootIFD.addTIFFField(f);
}
child = child.getNextSibling();
}
} else if (name.equals("Text")) {
Node child = node.getFirstChild();
String theAuthor = null;
String theDescription = null;
String theTitle = null;
while (child != null) {
String childName = child.getNodeName();
if (childName.equals("TextEntry")) {
int tagNumber = -1;
NamedNodeMap childAttrs = child.getAttributes();
Node keywordNode = childAttrs.getNamedItem("keyword");
if (keywordNode != null) {
String keyword = keywordNode.getNodeValue();
String value = getAttribute(child, "value");
if (!keyword.equals("") && !value.equals("")) {
if (keyword.equalsIgnoreCase("DocumentName")) {
tagNumber = BaselineTIFFTagSet.TAG_DOCUMENT_NAME;
} else if (keyword.equalsIgnoreCase("ImageDescription")) {
tagNumber = BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION;
} else if (keyword.equalsIgnoreCase("Make")) {
tagNumber = BaselineTIFFTagSet.TAG_MAKE;
} else if (keyword.equalsIgnoreCase("Model")) {
tagNumber = BaselineTIFFTagSet.TAG_MODEL;
} else if (keyword.equalsIgnoreCase("PageName")) {
tagNumber = BaselineTIFFTagSet.TAG_PAGE_NAME;
} else if (keyword.equalsIgnoreCase("Software")) {
tagNumber = BaselineTIFFTagSet.TAG_SOFTWARE;
} else if (keyword.equalsIgnoreCase("Artist")) {
tagNumber = BaselineTIFFTagSet.TAG_ARTIST;
} else if (keyword.equalsIgnoreCase("HostComputer")) {
tagNumber = BaselineTIFFTagSet.TAG_HOST_COMPUTER;
} else if (keyword.equalsIgnoreCase("InkNames")) {
tagNumber = BaselineTIFFTagSet.TAG_INK_NAMES;
} else if (keyword.equalsIgnoreCase("Copyright")) {
tagNumber = BaselineTIFFTagSet.TAG_COPYRIGHT;
} else if (keyword.equalsIgnoreCase("author")) {
theAuthor = value;
} else if (keyword.equalsIgnoreCase("description")) {
theDescription = value;
} else if (keyword.equalsIgnoreCase("title")) {
theTitle = value;
}
if (tagNumber != -1) {
f = new TIFFField(rootIFD.getTag(tagNumber), TIFFTag.TIFF_ASCII, 1, new String[] { value });
rootIFD.addTIFFField(f);
}
}
}
}
child = child.getNextSibling();
}
// child != null
if (theAuthor != null && getTIFFField(BaselineTIFFTagSet.TAG_ARTIST) == null) {
f = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_ARTIST), TIFFTag.TIFF_ASCII, 1, new String[] { theAuthor });
rootIFD.addTIFFField(f);
}
if (theDescription != null && getTIFFField(BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION) == null) {
f = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_IMAGE_DESCRIPTION), TIFFTag.TIFF_ASCII, 1, new String[] { theDescription });
rootIFD.addTIFFField(f);
}
if (theTitle != null && getTIFFField(BaselineTIFFTagSet.TAG_DOCUMENT_NAME) == null) {
f = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_DOCUMENT_NAME), TIFFTag.TIFF_ASCII, 1, new String[] { theTitle });
rootIFD.addTIFFField(f);
}
} else if (name.equals("Transparency")) {
Node child = node.getFirstChild();
while (child != null) {
String childName = child.getNodeName();
if (childName.equals("Alpha")) {
String alpha = getAttribute(child, "value");
f = null;
if (alpha.equals("premultiplied")) {
f = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_EXTRA_SAMPLES), BaselineTIFFTagSet.EXTRA_SAMPLES_ASSOCIATED_ALPHA);
} else if (alpha.equals("nonpremultiplied")) {
f = new TIFFField(rootIFD.getTag(BaselineTIFFTagSet.TAG_EXTRA_SAMPLES), BaselineTIFFTagSet.EXTRA_SAMPLES_UNASSOCIATED_ALPHA);
}
if (f != null) {
rootIFD.addTIFFField(f);
}
}
child = child.getNextSibling();
}
}
node = node.getNextSibling();
}
// Set SampleFormat.
if (sampleFormat != null) {
// Derive the value.
int sf = -1;
if (sampleFormat.equals("SignedIntegral")) {
sf = BaselineTIFFTagSet.SAMPLE_FORMAT_SIGNED_INTEGER;
} else if (sampleFormat.equals("UnsignedIntegral")) {
sf = BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER;
} else if (sampleFormat.equals("Real")) {
sf = BaselineTIFFTagSet.SAMPLE_FORMAT_FLOATING_POINT;
} else if (sampleFormat.equals("Index")) {
sf = BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER;
}
if (sf != -1) {
// Derive the count.
int count = 1;
// Try SamplesPerPixel first.
f = getTIFFField(BaselineTIFFTagSet.TAG_SAMPLES_PER_PIXEL);
if (f != null) {
count = f.getAsInt(0);
} else {
// Try BitsPerSample.
f = getTIFFField(BaselineTIFFTagSet.TAG_BITS_PER_SAMPLE);
if (f != null) {
count = f.getCount();
}
}
char[] sampleFormatArray = new char[count];
Arrays.fill(sampleFormatArray, (char) sf);
// Add SampleFormat.
tag = rootIFD.getTag(BaselineTIFFTagSet.TAG_SAMPLE_FORMAT);
f = new TIFFField(tag, TIFFTag.TIFF_SHORT, sampleFormatArray.length, sampleFormatArray);
rootIFD.addTIFFField(f);
}
}
}
use of it.geosolutions.imageio.plugins.tiff.TIFFTag in project imageio-ext by geosolutions-it.
the class TIFFImageMetadata method getIFDAsTree.
private Node getIFDAsTree(TIFFIFD ifd, String parentTagName, int parentTagNumber) {
IIOMetadataNode IFDRoot = new IIOMetadataNode("TIFFIFD");
if (parentTagNumber != 0) {
IFDRoot.setAttribute("parentTagNumber", Integer.toString(parentTagNumber));
}
if (parentTagName != null) {
IFDRoot.setAttribute("parentTagName", parentTagName);
}
List tagSets = ifd.getTagSetList();
if (tagSets.size() > 0) {
Iterator iter = tagSets.iterator();
String tagSetNames = "";
while (iter.hasNext()) {
TIFFTagSet tagSet = (TIFFTagSet) iter.next();
tagSetNames += tagSet.getClass().getName();
if (iter.hasNext()) {
tagSetNames += ",";
}
}
IFDRoot.setAttribute("tagSets", tagSetNames);
}
Iterator iter = ifd.iterator();
while (iter.hasNext()) {
TIFFField f = (TIFFField) iter.next();
int tagNumber = f.getTagNumber();
TIFFTag tag = TIFFIFD.getTag(tagNumber, tagSets);
Node node = null;
if (tag == null) {
node = f.getAsNativeNode();
} else if (tag.isIFDPointer()) {
TIFFIFD subIFD = (TIFFIFD) f.getData();
// Recurse
node = getIFDAsTree(subIFD, tag.getName(), tag.getNumber());
} else {
node = f.getAsNativeNode();
}
if (node != null) {
IFDRoot.appendChild(node);
}
}
return IFDRoot;
}
Aggregations