Beispiel #1
0
  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;
  }
Beispiel #2
0
  /**
   * 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;
  }
Beispiel #3
0
  public void initialize(
      ImageInputStream stream, boolean ignoreUnknownFields, final boolean isBTIFF)
      throws IOException {
    removeTIFFFields();

    List tagSetList = getTagSetList();

    final long numEntries;
    if (isBTIFF) numEntries = stream.readLong();
    else numEntries = stream.readUnsignedShort();

    for (int i = 0; i < numEntries; i++) {
      // Read tag number, value type, and value count.
      int tag = stream.readUnsignedShort();
      int type = stream.readUnsignedShort();
      int count;
      if (isBTIFF) {
        long count_ = stream.readLong();
        count = (int) count_;
        if (count != count_)
          throw new IllegalArgumentException("unable to use long number of values");
      } else count = (int) stream.readUnsignedInt();

      // Get the associated TIFFTag.
      TIFFTag tiffTag = getTag(tag, tagSetList);

      // Ignore unknown fields.
      if (ignoreUnknownFields && tiffTag == null) {
        // Skip the value/offset so as to leave the stream
        // position at the start of the next IFD entry.

        if (isBTIFF) stream.skipBytes(8);
        else stream.skipBytes(4);

        // XXX Warning message ...

        // Continue with the next IFD entry.
        continue;
      }

      long nextTagOffset;

      if (isBTIFF) {
        nextTagOffset = stream.getStreamPosition() + 8;
        int sizeOfType = TIFFTag.getSizeOfType(type);
        if (count * sizeOfType > 8) {
          long value = stream.readLong();
          stream.seek(value);
        }
      } else {
        nextTagOffset = stream.getStreamPosition() + 4;
        int sizeOfType = TIFFTag.getSizeOfType(type);
        if (count * sizeOfType > 4) {
          long value = stream.readUnsignedInt();
          stream.seek(value);
        }
      }

      if (tag == BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS
          || tag == BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS
          || tag == BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH) {
        this.stripOrTileByteCountsPosition = stream.getStreamPosition();
        if (LAZY_LOADING) {
          type = type == TIFFTag.TIFF_LONG ? TIFFTag.TIFF_LAZY_LONG : TIFFTag.TIFF_LAZY_LONG8;
        }
      } else if (tag == BaselineTIFFTagSet.TAG_STRIP_OFFSETS
          || tag == BaselineTIFFTagSet.TAG_TILE_OFFSETS
          || tag == BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT) {
        this.stripOrTileOffsetsPosition = stream.getStreamPosition();
        if (LAZY_LOADING) {
          type = type == TIFFTag.TIFF_LONG ? TIFFTag.TIFF_LAZY_LONG : TIFFTag.TIFF_LAZY_LONG8;
        }
      }

      Object obj = null;

      try {
        switch (type) {
          case TIFFTag.TIFF_BYTE:
          case TIFFTag.TIFF_SBYTE:
          case TIFFTag.TIFF_UNDEFINED:
          case TIFFTag.TIFF_ASCII:
            byte[] bvalues = new byte[count];
            stream.readFully(bvalues, 0, count);

            if (type == TIFFTag.TIFF_ASCII) {
              // Can be multiple strings
              final List<String> v = new ArrayList<String>();
              boolean inString = false;
              int prevIndex = 0;
              for (int index = 0; index <= count; index++) {
                if (index < count && bvalues[index] != 0) {
                  if (!inString) {
                    // start of string
                    prevIndex = index;
                    inString = true;
                  }
                } else { // null or special case at end of string
                  if (inString) {
                    // end of string
                    final String s = new String(bvalues, prevIndex, index - prevIndex);
                    v.add(s);
                    inString = false;
                  }
                }
              }

              count = v.size();
              String[] strings;
              if (count != 0) {
                strings = new String[count];
                for (int c = 0; c < count; c++) {
                  strings[c] = v.get(c);
                }
              } else {
                // This case has been observed when the value of
                // 'count' recorded in the field is non-zero but
                // the value portion contains all nulls.
                count = 1;
                strings = new String[] {""};
              }

              obj = strings;
            } else {
              obj = bvalues;
            }
            break;

          case TIFFTag.TIFF_SHORT:
            char[] cvalues = new char[count];
            for (int j = 0; j < count; j++) {
              cvalues[j] = (char) (stream.readUnsignedShort());
            }
            obj = cvalues;
            break;

          case TIFFTag.TIFF_LONG:
          case TIFFTag.TIFF_IFD_POINTER:
            long[] lvalues = new long[count];
            for (int j = 0; j < count; j++) {
              lvalues[j] = stream.readUnsignedInt();
            }
            obj = lvalues;
            break;

          case TIFFTag.TIFF_RATIONAL:
            long[][] llvalues = new long[count][2];
            for (int j = 0; j < count; j++) {
              llvalues[j][0] = stream.readUnsignedInt();
              llvalues[j][1] = stream.readUnsignedInt();
            }
            obj = llvalues;
            break;

          case TIFFTag.TIFF_SSHORT:
            short[] svalues = new short[count];
            for (int j = 0; j < count; j++) {
              svalues[j] = stream.readShort();
            }
            obj = svalues;
            break;

          case TIFFTag.TIFF_SLONG:
            int[] ivalues = new int[count];
            for (int j = 0; j < count; j++) {
              ivalues[j] = stream.readInt();
            }
            obj = ivalues;
            break;

          case TIFFTag.TIFF_SRATIONAL:
            int[][] iivalues = new int[count][2];
            for (int j = 0; j < count; j++) {
              iivalues[j][0] = stream.readInt();
              iivalues[j][1] = stream.readInt();
            }
            obj = iivalues;
            break;

          case TIFFTag.TIFF_FLOAT:
            float[] fvalues = new float[count];
            for (int j = 0; j < count; j++) {
              fvalues[j] = stream.readFloat();
            }
            obj = fvalues;
            break;

          case TIFFTag.TIFF_DOUBLE:
            double[] dvalues = new double[count];
            for (int j = 0; j < count; j++) {
              dvalues[j] = stream.readDouble();
            }
            obj = dvalues;
            break;

          case TIFFTag.TIFF_LONG8:
          case TIFFTag.TIFF_SLONG8:
          case TIFFTag.TIFF_IFD8:
            long[] lBvalues = new long[count];
            for (int j = 0; j < count; j++) {
              lBvalues[j] = stream.readLong();
            }
            obj = lBvalues;
            break;

          case TIFFTag.TIFF_LAZY_LONG8:
          case TIFFTag.TIFF_LAZY_LONG:
            obj = new TIFFLazyData(stream, type, count);
            break;
          default:
            // XXX Warning
            break;
        }
      } catch (EOFException eofe) {
        // The TIFF 6.0 fields have tag numbers less than or equal
        // to 532 (ReferenceBlackWhite) or equal to 33432 (Copyright).
        // If there is an error reading a baseline tag, then re-throw
        // the exception and fail; otherwise continue with the next
        // field.
        if (BaselineTIFFTagSet.getInstance().getTag(tag) == null) {
          throw eofe;
        }
      }

      if (tiffTag == null) {
        // XXX Warning: unknown tag
      } else if (!tiffTag.isDataTypeOK(type)) {
        // XXX Warning: bad data type
      } else if (tiffTag.isIFDPointer() && obj != null) {
        stream.mark();
        stream.seek(((long[]) obj)[0]);

        List tagSets = new ArrayList(1);
        tagSets.add(tiffTag.getTagSet());
        TIFFIFD subIFD = new TIFFIFD(tagSets);

        // XXX Use same ignore policy for sub-IFD fields?
        subIFD.initialize(stream, ignoreUnknownFields);
        obj = subIFD;
        stream.reset();
      }

      if (tiffTag == null) {
        tiffTag = new TIFFTag(null, tag, 1 << type, null);
      }

      // Add the field if its contents have been initialized which
      // will not be the case if an EOF was ignored above.
      if (obj != null) {
        TIFFField f = new TIFFField(tiffTag, type, count, obj);
        addTIFFField(f);
      }

      stream.seek(nextTagOffset);
    }

    this.lastPosition = stream.getStreamPosition();
  }