// XResolution 282
// YResolution 283
// ResolutionUnit 296
// Create Directory
SortedSet fields = new TreeSet();
// Image Width
fields.add(new TIFFField(TIFFImageDecoder.TIFF_IMAGE_WIDTH,
TIFFField.TIFF_LONG, 1,
(Object)(new long[] {(long)width})));
// Image Length
fields.add(new TIFFField(TIFFImageDecoder.TIFF_IMAGE_LENGTH,
TIFFField.TIFF_LONG, 1,
new long[] {(long)height}));
fields.add(new TIFFField(TIFFImageDecoder.TIFF_BITS_PER_SAMPLE,
TIFFField.TIFF_SHORT, numBands,
intsToChars(sampleSize)));
fields.add(new TIFFField(TIFFImageDecoder.TIFF_COMPRESSION,
TIFFField.TIFF_SHORT, 1,
new char[] {(char)compression}));
fields.add(
new TIFFField(TIFFImageDecoder.TIFF_PHOTOMETRIC_INTERPRETATION,
TIFFField.TIFF_SHORT, 1,
new char[] {(char)photometricInterpretation}));
if(!isTiled) {
fields.add(new TIFFField(TIFFImageDecoder.TIFF_STRIP_OFFSETS,
TIFFField.TIFF_LONG, numTiles,
(long[])tileOffsets));
}
fields.add(new TIFFField(TIFFImageDecoder.TIFF_SAMPLES_PER_PIXEL,
TIFFField.TIFF_SHORT, 1,
new char[] {(char)numBands}));
if(!isTiled) {
fields.add(new TIFFField(TIFFImageDecoder.TIFF_ROWS_PER_STRIP,
TIFFField.TIFF_LONG, 1,
new long[] {(long)tileHeight}));
fields.add(new TIFFField(TIFFImageDecoder.TIFF_STRIP_BYTE_COUNTS,
TIFFField.TIFF_LONG, numTiles,
(long[])tileByteCounts));
}
if (colormap != null) {
fields.add(new TIFFField(TIFFImageDecoder.TIFF_COLORMAP,
TIFFField.TIFF_SHORT, sizeOfColormap,
intsToChars(colormap)));
}
if(isTiled) {
fields.add(new TIFFField(TIFFImageDecoder.TIFF_TILE_WIDTH,
TIFFField.TIFF_LONG, 1,
new long[] {(long)tileWidth}));
fields.add(new TIFFField(TIFFImageDecoder.TIFF_TILE_LENGTH,
TIFFField.TIFF_LONG, 1,
new long[] {(long)tileHeight}));
fields.add(new TIFFField(TIFFImageDecoder.TIFF_TILE_OFFSETS,
TIFFField.TIFF_LONG, numTiles,
(long[])tileOffsets));
fields.add(new TIFFField(TIFFImageDecoder.TIFF_TILE_BYTE_COUNTS,
TIFFField.TIFF_LONG, numTiles,
(long[])tileByteCounts));
}
if(numExtraSamples > 0) {
int[] extraSamples = new int[numExtraSamples];
for(int i = 0; i < numExtraSamples; i++) {
extraSamples[i] = extraSampleType;
}
fields.add(new TIFFField(TIFFImageDecoder.TIFF_EXTRA_SAMPLES,
TIFFField.TIFF_SHORT, numExtraSamples,
intsToChars(extraSamples)));
}
// Data Sample Format Extension fields.
if(dataType != DataBuffer.TYPE_BYTE) {
// SampleFormat
int[] sampleFormat = new int[numBands];
if(dataType == DataBuffer.TYPE_FLOAT) {
sampleFormat[0] = 3;
} else if(dataType == DataBuffer.TYPE_USHORT) {
sampleFormat[0] = 1;
} else {
sampleFormat[0] = 2;
}
for(int b = 1; b < numBands; b++) {
sampleFormat[b] = sampleFormat[0];
}
fields.add(new TIFFField(TIFFImageDecoder.TIFF_SAMPLE_FORMAT,
TIFFField.TIFF_SHORT, numBands,
intsToChars(sampleFormat)));
// NOTE: We don't bother setting the SMinSampleValue and
// SMaxSampleValue fields as these both default to the
// extrema of the respective data types. Probably we should
// check for the presence of the "extrema" property and
// use it if available.
}
// Bilevel compression variables.
boolean inverseFill = encodeParam.getReverseFillOrder();
boolean T4encode2D = encodeParam.getT4Encode2D();
boolean T4PadEOLs = encodeParam.getT4PadEOLs();
TIFFFaxEncoder faxEncoder = null;
// Add bilevel compression fields.
if((imageType == TIFF_BILEVEL_BLACK_IS_ZERO ||
imageType == TIFF_BILEVEL_WHITE_IS_ZERO) &&
(compression == COMP_GROUP3_1D ||
compression == COMP_GROUP3_2D ||
compression == COMP_GROUP4)) {
// Create the encoder.
faxEncoder = new TIFFFaxEncoder(inverseFill);
// FillOrder field.
fields.add(new TIFFField(TIFFImageDecoder.TIFF_FILL_ORDER,
TIFFField.TIFF_SHORT, 1,
new char[] {inverseFill ?
(char)2 : (char)1}));
if(compression == COMP_GROUP3_2D) {
// T4Options field.
long T4Options = 0x00000000;
if(T4encode2D) {
T4Options |= 0x00000001;
}
if(T4PadEOLs) {
T4Options |= 0x00000004;
}
fields.add(new TIFFField(TIFFImageDecoder.TIFF_T4_OPTIONS,
TIFFField.TIFF_LONG, 1,
new long[] {T4Options}));
} else if(compression == COMP_GROUP4) {
// T6Options field.
fields.add(new TIFFField(TIFFImageDecoder.TIFF_T6_OPTIONS,
TIFFField.TIFF_LONG, 1,
new long[] {(long)0x00000000}));
}
}
// Initialize some JPEG variables.
com.sun.image.codec.jpeg.JPEGEncodeParam jpegEncodeParam = null;
com.sun.image.codec.jpeg.JPEGImageEncoder jpegEncoder = null;
int jpegColorID = 0;
if(compression == COMP_JPEG_TTN2) {
// Initialize JPEG color ID.
jpegColorID =
com.sun.image.codec.jpeg.JPEGDecodeParam.COLOR_ID_UNKNOWN;
switch(imageType) {
case TIFF_GRAY:
case TIFF_PALETTE:
jpegColorID =
com.sun.image.codec.jpeg.JPEGDecodeParam.COLOR_ID_GRAY;
break;
case TIFF_RGB:
jpegColorID =
com.sun.image.codec.jpeg.JPEGDecodeParam.COLOR_ID_RGB;
break;
case TIFF_YCBCR:
jpegColorID =
com.sun.image.codec.jpeg.JPEGDecodeParam.COLOR_ID_YCbCr;
break;
}
// Get the JDK encoding parameters.
Raster tile00 = im.getTile(im.getMinTileX(), im.getMinTileY());
jpegEncodeParam =
com.sun.image.codec.jpeg.JPEGCodec.getDefaultJPEGEncodeParam(
tile00, jpegColorID);
// Modify per values passed in.
JPEGImageEncoder.modifyEncodeParam(jep, jpegEncodeParam, numBands);
// JPEGTables field.
if(jep.getWriteImageOnly()) {
// Write an abbreviated tables-only stream to JPEGTables field.
jpegEncodeParam.setImageInfoValid(false);
jpegEncodeParam.setTableInfoValid(true);
ByteArrayOutputStream tableStream =
new ByteArrayOutputStream();
jpegEncoder =
com.sun.image.codec.jpeg.JPEGCodec.createJPEGEncoder(
tableStream,
jpegEncodeParam);
jpegEncoder.encode(tile00);
byte[] tableData = tableStream.toByteArray();
fields.add(new TIFFField(TIFF_JPEG_TABLES,
TIFFField.TIFF_UNDEFINED,
tableData.length,
tableData));
// Reset encoder so it's recreated below.
jpegEncoder = null;
}
}
if(imageType == TIFF_YCBCR) {
// YCbCrSubSampling: 2 is the default so we must write 1 as
// we do not (yet) do any subsampling.
int subsampleH = 1;
int subsampleV = 1;
// If JPEG, update values.
if(compression == COMP_JPEG_TTN2) {
// Determine maximum subsampling.
subsampleH = jep.getHorizontalSubsampling(0);
subsampleV = jep.getVerticalSubsampling(0);
for(int i = 1; i < numBands; i++) {
int subH = jep.getHorizontalSubsampling(i);
if(subH > subsampleH) {
subsampleH = subH;
}
int subV = jep.getVerticalSubsampling(i);
if(subV > subsampleV) {
subsampleV = subV;
}
}
}
fields.add(new TIFFField(TIFF_YCBCR_SUBSAMPLING,
TIFFField.TIFF_SHORT, 2,
new char[] {(char)subsampleH,
(char)subsampleV}));
// YCbCr positioning.
fields.add(new TIFFField(TIFF_YCBCR_POSITIONING,
TIFFField.TIFF_SHORT, 1,
new char[] {compression == COMP_JPEG_TTN2 ?
(char)1 : (char)2}));
// Reference black/white.
long[][] refbw;
if(compression == COMP_JPEG_TTN2) {
refbw =
new long[][] { // no headroon/footroom
{0, 1}, {255, 1}, {128, 1}, {255, 1}, {128, 1}, {255, 1}
};
} else {
refbw =
new long[][] { // CCIR 601.1 headroom/footroom (presumptive)
{15, 1}, {235, 1}, {128, 1}, {240, 1}, {128, 1}, {240, 1}
};
}
fields.add(new TIFFField(TIFF_REF_BLACK_WHITE,
TIFFField.TIFF_RATIONAL, 6,
refbw));
}
// ---- No more automatically generated fields should be added
// after this point. ----
// Add extra fields specified via the encoding parameters.
TIFFField[] extraFields = encodeParam.getExtraFields();
if(extraFields != null) {
ArrayList extantTags = new ArrayList(fields.size());
Iterator fieldIter = fields.iterator();
while(fieldIter.hasNext()) {
TIFFField fld = (TIFFField)fieldIter.next();
extantTags.add(new Integer(fld.getTag()));
}
int numExtraFields = extraFields.length;
for(int i = 0; i < numExtraFields; i++) {
TIFFField fld = extraFields[i];
Integer tagValue = new Integer(fld.getTag());
if(!extantTags.contains(tagValue)) {
fields.add(fld);
extantTags.add(tagValue);
}
}
}