public void writeToStream(ImageOutputStream stream, final boolean isBTIFF) throws IOException { long nextSpace; if (!isBTIFF) { int numFields = getNumTIFFFields(); stream.writeShort(numFields); nextSpace = stream.getStreamPosition() + 12 * numFields + 4; } else { long numFields = getNumTIFFFields(); stream.writeLong(numFields); nextSpace = stream.getStreamPosition() + 20 * numFields + 8; } Iterator iter = iterator(); while (iter.hasNext()) { TIFFField f = (TIFFField) iter.next(); TIFFTag tag = f.getTag(); int type = f.getType(); int count = f.getCount(); // Hack to deal with unknown tags if (type == 0) { type = TIFFTag.TIFF_UNDEFINED; } int size = count * TIFFTag.getSizeOfType(type); if (type == TIFFTag.TIFF_ASCII) { int chars = 0; for (int i = 0; i < count; i++) { chars += f.getAsString(i).length() + 1; } count = chars; size = count; } int tagNumber = f.getTagNumber(); stream.writeShort(tagNumber); stream.writeShort(type); if (isBTIFF) { stream.writeLong(count); stream.writeLong(0); stream.mark(); // Mark beginning of next field stream.skipBytes(-8); } else { stream.writeInt(count); stream.writeInt(0); stream.mark(); // Mark beginning of next field stream.skipBytes(-4); } long pos; if (!isBTIFF) { if (size > 4 || tag.isIFDPointer()) { // Ensure IFD or value is written on a word boundary nextSpace = (nextSpace + 3) & ~0x3; stream.writeInt((int) nextSpace); stream.seek(nextSpace); pos = nextSpace; if (tag.isIFDPointer()) { TIFFIFD subIFD = (TIFFIFD) f.getData(); subIFD.writeToStream(stream, isBTIFF); nextSpace = subIFD.lastPosition; } else { writeTIFFFieldToStream(f, stream); nextSpace = stream.getStreamPosition(); } } else { pos = stream.getStreamPosition(); writeTIFFFieldToStream(f, stream); } } else { if (size > 8 || tag.isIFDPointer()) { // Ensure IFD or value is written on a Long boundary nextSpace = (nextSpace + 7) & ~0x7; stream.writeLong(nextSpace); stream.seek(nextSpace); pos = nextSpace; if (tag.isIFDPointer()) { TIFFIFD subIFD = (TIFFIFD) f.getData(); subIFD.writeToStream(stream, isBTIFF); nextSpace = subIFD.lastPosition; } else { writeTIFFFieldToStream(f, stream); nextSpace = stream.getStreamPosition(); } } else { pos = stream.getStreamPosition(); writeTIFFFieldToStream(f, stream); } } // If we are writing the data for the // StripByteCounts, TileByteCounts, StripOffsets, // TileOffsets, JPEGInterchangeFormat, or // JPEGInterchangeFormatLength fields, record the current stream // position for backpatching if (tagNumber == BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS || tagNumber == BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS || tagNumber == BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH) { this.stripOrTileByteCountsPosition = pos; } else if (tagNumber == BaselineTIFFTagSet.TAG_STRIP_OFFSETS || tagNumber == BaselineTIFFTagSet.TAG_TILE_OFFSETS || tagNumber == BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT) { this.stripOrTileOffsetsPosition = pos; } stream.reset(); // Go to marked position of next field } this.lastPosition = nextSpace; }
/** * Returns a <code>TIFFIFD</code> wherein all fields from the <code>BaselineTIFFTagSet</code> are * copied by value and all other fields copied by reference. */ public TIFFIFD getShallowClone() { // Get the baseline TagSet. TIFFTagSet baselineTagSet = BaselineTIFFTagSet.getInstance(); // If the baseline TagSet is not included just return. List tagSetList = getTagSetList(); if (!tagSetList.contains(baselineTagSet)) { return this; } // Create a new object. TIFFIFD shallowClone = new TIFFIFD(tagSetList, getParentTag()); // Get the tag numbers in the baseline set. Set baselineTagNumbers = baselineTagSet.getTagNumbers(); // Iterate over the fields in this IFD. Iterator fields = iterator(); while (fields.hasNext()) { // Get the next field. TIFFField field = (TIFFField) fields.next(); // Get its tag number. Integer tagNumber = new Integer(field.getTagNumber()); // Branch based on membership in baseline set. TIFFField fieldClone; if (baselineTagNumbers.contains(tagNumber)) { // Copy by value. Object fieldData = field.getData(); int fieldType = field.getType(); try { switch (fieldType) { case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_SBYTE: case TIFFTag.TIFF_UNDEFINED: fieldData = ((byte[]) fieldData).clone(); break; case TIFFTag.TIFF_ASCII: fieldData = ((String[]) fieldData).clone(); break; case TIFFTag.TIFF_SHORT: fieldData = ((char[]) fieldData).clone(); break; case TIFFTag.TIFF_LONG: case TIFFTag.TIFF_IFD_POINTER: fieldData = ((long[]) fieldData).clone(); break; case TIFFTag.TIFF_RATIONAL: fieldData = ((long[][]) fieldData).clone(); break; case TIFFTag.TIFF_SSHORT: fieldData = ((short[]) fieldData).clone(); break; case TIFFTag.TIFF_SLONG: fieldData = ((int[]) fieldData).clone(); break; case TIFFTag.TIFF_SRATIONAL: fieldData = ((int[][]) fieldData).clone(); break; case TIFFTag.TIFF_FLOAT: fieldData = ((float[]) fieldData).clone(); break; case TIFFTag.TIFF_DOUBLE: fieldData = ((double[]) fieldData).clone(); break; default: // Shouldn't happen but do nothing ... } } catch (Exception e) { // Ignore it and copy by reference ... } fieldClone = new TIFFField( field.getTag(), fieldType, field.getCount(), fieldData); } else { // Copy by reference. fieldClone = field; } // Add the field to the clone. shallowClone.addTIFFField(fieldClone); } // Set positions. shallowClone.setPositions( stripOrTileOffsetsPosition, stripOrTileByteCountsPosition, lastPosition); return shallowClone; }
private static void writeTIFFFieldToStream(TIFFField field, ImageOutputStream stream) throws IOException { int count = field.getCount(); Object data = field.getData(); switch (field.getType()) { case TIFFTag.TIFF_ASCII: for (int i = 0; i < count; i++) { String s = ((String[]) data)[i]; int length = s.length(); for (int j = 0; j < length; j++) { stream.writeByte(s.charAt(j) & 0xff); } stream.writeByte(0); } break; case TIFFTag.TIFF_UNDEFINED: case TIFFTag.TIFF_BYTE: case TIFFTag.TIFF_SBYTE: stream.write((byte[]) data); break; case TIFFTag.TIFF_SHORT: stream.writeChars((char[]) data, 0, ((char[]) data).length); break; case TIFFTag.TIFF_SSHORT: stream.writeShorts((short[]) data, 0, ((short[]) data).length); break; case TIFFTag.TIFF_SLONG: stream.writeInts((int[]) data, 0, ((int[]) data).length); break; case TIFFTag.TIFF_LONG: for (int i = 0; i < count; i++) { stream.writeInt((int) (((long[]) data)[i])); } break; case TIFFTag.TIFF_LONG8: stream.writeLongs((long[]) data, 0, ((long[]) data).length); break; case TIFFTag.TIFF_IFD_POINTER: stream.writeInt(0); // will need to be backpatched break; case TIFFTag.TIFF_FLOAT: stream.writeFloats((float[]) data, 0, ((float[]) data).length); break; case TIFFTag.TIFF_DOUBLE: stream.writeDoubles((double[]) data, 0, ((double[]) data).length); break; case TIFFTag.TIFF_SRATIONAL: for (int i = 0; i < count; i++) { stream.writeInt(((int[][]) data)[i][0]); stream.writeInt(((int[][]) data)[i][1]); } break; case TIFFTag.TIFF_RATIONAL: for (int i = 0; i < count; i++) { long num = ((long[][]) data)[i][0]; long den = ((long[][]) data)[i][1]; stream.writeInt((int) num); stream.writeInt((int) den); } break; default: // error } }