예제 #1
0
  ImageFileDirectory(BufferedInputStream bufferedIn, long positionAfterTIFFHeader, boolean reverse)
      throws IOException {
    bufferedIn.reset();
    if (JPEGMarkerInputStream.skipFully(bufferedIn, positionAfterTIFFHeader)
        != positionAfterTIFFHeader) throw new IOException();

    byte[] array = new byte[4];
    if (JPEGMarkerInputStream.readFully(bufferedIn, array, 2, reverse) != 2)
      throw new IOException("Corrupt image file directory.");

    int numberOfEntries = (array[0] & 0xff) * 256 + (array[1] & 0xff);

    entries = new DirectoryEntry[numberOfEntries];
    for (int a = 0; a < numberOfEntries; a++) {
      try {
        DirectoryEntry entry = new DirectoryEntry(bufferedIn, reverse);
        entries[a] = (entry);
      } catch (RuntimeException e) {
        System.err.println(a + " / " + numberOfEntries);
        throw e;
      }
    }

    /**
     * According to the specs: what is supposed to follow is a 4-byte pointer to the next IFD.
     * However I found an APP1 block that omits these 4 bytes and instead contains some
     * DirectoryEntries.
     *
     * <p>So first I'll scan through the entries and see if any of them believe they should start
     * here, and if so we just assume there is no next IFD to point to. (If anything this errs on
     * the side of omitting data, instead of trying to read data where the isn't any.)
     */
    long positionToExpectIFDPtr = positionAfterTIFFHeader + 2 + 12 * numberOfEntries;
    boolean missingIFDPtr = false;
    for (int a = 0; a < numberOfEntries && (!missingIFDPtr); a++) {
      int k = entries[a].positionAfterTIFFHeader();
      if (k != -1 && k == positionToExpectIFDPtr) {
        missingIFDPtr = true;
      }
    }

    if (missingIFDPtr) {
      // there is no space for the IFD position to be, so assume it's zero.
      nextIFDPosition = 0;
    } else {
      if (JPEGMarkerInputStream.readFully(bufferedIn, array, 4, reverse) != 4)
        throw new IOException("Corrupt image file directory.");

      nextIFDPosition =
          ((array[0] & 0xff) << 24)
              + ((array[1] & 0xff) << 16)
              + ((array[2] & 0xff) << 8)
              + (array[3] & 0xff);
    }
  }
예제 #2
0
    DirectoryEntry(InputStream in, boolean reverse) throws IOException {
      byte[] array = new byte[4];

      if (JPEGMarkerInputStream.readFully(in, array, 2, reverse) != 2) throw new IOException();
      tagNumber = (array[0] & 0xff) * 256 + (array[1] & 0xff);

      if (JPEGMarkerInputStream.readFully(in, array, 2, reverse) != 2) throw new IOException();
      dataFormat = (array[0] & 0xff) * 256 + (array[1] & 0xff);

      if (JPEGMarkerInputStream.readFully(in, array, 4, reverse) != 4) throw new IOException();
      componentCount =
          ((array[0] & 0xff) << 24)
              + ((array[1] & 0xff) << 16)
              + ((array[2] & 0xff) << 8)
              + ((array[3] & 0xff) << 0);

      fieldValue = new byte[4];
      if (JPEGMarkerInputStream.readFully(in, fieldValue, 4, reverse) != 4) throw new IOException();
    }
예제 #3
0
    /**
     * @param in a BufferedInputStream that was last marked at the start of the TIFF header.
     * @throws IOException
     */
    void resolveValue(BufferedInputStream in) throws IOException {
      int byteLength = getValueByteLength();
      byte[] data;
      if (byteLength > 4) {
        // we have to read this data:
        byte[] newData = new byte[byteLength];
        int positionAfterTIFFHeader = readLong(fieldValue, 0);
        in.reset();
        if (JPEGMarkerInputStream.skipFully(in, positionAfterTIFFHeader) != positionAfterTIFFHeader)
          throw new IOException();
        JPEGMarkerInputStream.readFully(in, newData, byteLength, false);
        data = newData;
      } else {
        data = fieldValue;
      }

      if (dataFormat == 7 || dataFormat == 0) { // UNDEFINED
        value = data;
        return;
      } else if (dataFormat == 2) { // ASCII
        StringBuffer buffer = new StringBuffer();
        for (int a = 0; a < componentCount; a++) {
          int i = (data[a] & 0xff);
          if (i == 0) {
            break;
          }
          char c = (char) i;
          buffer.append(c);
        }
        value = buffer.toString();
        return;
      }
      Object[] valueArray;
      if (dataFormat == 1
          || // BYTE
          dataFormat == 6
          || // SIGNED BYTE
          dataFormat == 3
          || // SHORT
          dataFormat == 8
          || // SIGNED SHORT
          dataFormat == 4
          || // LONG
          dataFormat == 9) { // SIGNED LONG
        valueArray = new Integer[componentCount];
      } else if (dataFormat == 5
          || // RATIONAL
          dataFormat == 10) { // SIGNED RATIONAL
        valueArray = new Double[componentCount];
      } else {
        throw new RuntimeException("unexpected data format (" + dataFormat + ")");
      }

      for (int a = 0; a < componentCount; a++) {
        switch (dataFormat) {
          case 1: // byte
            valueArray[a] = new Integer(readByte(data, a * 1));
            break;
          case 6: // signed byte
            valueArray[a] = new Integer(readSignedByte(data, a * 1));
            break;
          case 3: // short
            valueArray[a] = new Integer(readShort(data, a * 2));
            break;
          case 8: // signed short
            valueArray[a] = new Integer(readSignedShort(data, a * 2));
            break;
          case 4: // long
            valueArray[a] = new Integer(readLong(data, a * 4));
            break;
          case 9: // signed long
            valueArray[a] = new Integer(readSignedLong(data, a * 4));
            break;
          case 5: // rational
            double numerator = readLong(data, a * 4);
            double denominator = readLong(data, a * 4 + 4);
            valueArray[a] = new Double(numerator / denominator);
            break;
          case 10: // signed rational
            double numerator2 = readSignedLong(data, a * 4);
            double denominator2 = readSignedLong(data, a * 4 + 4);
            valueArray[a] = new Double(numerator2 / denominator2);
            break;
          default:
            throw new RuntimeException("Unexpected condition.");
        }
      }

      if (valueArray.length == 1) {
        value = valueArray[0];
      } else {
        value = valueArray;
      }
    }