예제 #1
0
  // TODO: Candidate util method
  private static long skipToEOF(final ImageInputStream stream) throws IOException {
    long length = stream.length();

    if (length > 0) {
      // Known length, skip there and we're done.
      stream.seek(length);
    } else {
      // Otherwise, seek to EOF the hard way.
      // First, store stream position...
      long pos = stream.getStreamPosition();

      // ...skip 1k blocks until we're passed EOF...
      while (stream.skipBytes(1024l) > 0) {
        if (stream.read() == -1) {
          break;
        }

        pos = stream.getStreamPosition();
      }

      // ...go back to last known pos...
      stream.seek(pos);

      // ...finally seek until EOF one byte at a time. Done.
      while (stream.read() != -1) {}
    }

    return stream.getStreamPosition();
  }
예제 #2
0
  public boolean canDecodeInput(Object source) throws IOException {
    if (!(source instanceof ImageInputStream)) {
      return false;
    }

    ImageInputStream stream = (ImageInputStream) source;

    stream.mark();
    int type = stream.readByte(); // TypeField
    byte fixHeaderField = stream.readByte();

    int width = ImageUtil.readMultiByteInteger(stream);
    int height = ImageUtil.readMultiByteInteger(stream);

    long remainingBytes = stream.length() - stream.getStreamPosition();
    stream.reset();

    // check WBMP "header"
    if (type != 0 || fixHeaderField != 0) {
      // while WBMP reader does not support ext WBMP headers
      return false;
    }

    // check image dimension
    if (width <= 0 || height <= 0) {
      return false;
    }

    long scanSize = (width / 8) + ((width % 8) == 0 ? 0 : 1);

    return (remainingBytes == scanSize * height);
  }
예제 #3
0
  private void readFile() {
    // Do not allow this header to be read more than once.

    if (readFile) return;

    // Make sure that the application has set the input source.

    if (stream == null) throw new IllegalStateException("No input stream!");

    // Read the header.

    decoder = new JBIG2Decoder();

    try {
      byte[] data;
      int size = (int) stream.length();
      if (size == -1) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] temp = new byte[8192];
        for (int len = 0; (len = stream.read(temp)) > 0; ) {
          bos.write(temp, 0, len);
        }
        bos.close();
        data = bos.toByteArray();
      } else {
        data = new byte[size];
        stream.readFully(data);
      }

      decoder.decodeJBIG2(data);

    } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    } catch (JBIG2Exception e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }

    readFile = true;
  }
예제 #4
0
  private long getTileOrStripByteCount(int tileIndex) throws IOException {
    TIFFField f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_TILE_BYTE_COUNTS);
    if (f == null) {
      f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_STRIP_BYTE_COUNTS);
    }
    if (f == null) {
      f = imageMetadata.getTIFFField(BaselineTIFFTagSet.TAG_JPEG_INTERCHANGE_FORMAT_LENGTH);
    }

    long tileOrStripByteCount;
    if (f != null) {
      tileOrStripByteCount = f.getAsLong(tileIndex);
    } else {
      processWarningOccurred(
          "TIFF directory contains neither StripByteCounts nor TileByteCounts field: attempting to calculate from strip or tile width and height.");

      // Initialize to number of bytes per strip or tile assuming
      // no compression.
      int bitsPerPixel = bitsPerSample[0];
      for (int i = 1; i < samplesPerPixel; i++) {
        bitsPerPixel += bitsPerSample[i];
      }
      int bytesPerRow = (getTileOrStripWidth() * bitsPerPixel + 7) / 8;
      tileOrStripByteCount = bytesPerRow * getTileOrStripHeight();

      // Clamp to end of stream if possible.
      long streamLength = stream.length();
      if (streamLength != -1) {
        tileOrStripByteCount =
            Math.min(tileOrStripByteCount, streamLength - getTileOrStripOffset(tileIndex));
      } else {
        processWarningOccurred(
            "Stream length is unknown: cannot clamp estimated strip or tile byte count to EOF.");
      }
    }

    return tileOrStripByteCount;
  }
 @Override
 public long length() throws IOException {
   return iis.length();
 }
예제 #6
0
  private void readHeader() throws IOException {
    if (gotHeader) {
      iis.seek(128);
      return;
    }

    metadata = new PCXMetadata();

    manufacturer = iis.readByte(); // manufacturer
    if (manufacturer != MANUFACTURER) throw new IllegalStateException("image is not a PCX file");
    metadata.version = iis.readByte(); // version
    encoding = iis.readByte(); // encoding
    if (encoding != ENCODING)
      throw new IllegalStateException("image is not a PCX file, invalid encoding " + encoding);

    metadata.bitsPerPixel = iis.readByte();

    metadata.xmin = iis.readShort();
    metadata.ymin = iis.readShort();
    xmax = iis.readShort();
    ymax = iis.readShort();

    metadata.hdpi = iis.readShort();
    metadata.vdpi = iis.readShort();

    iis.readFully(smallPalette);

    iis.readByte(); // reserved

    colorPlanes = iis.readByte();
    bytesPerLine = iis.readShort();
    paletteType = iis.readShort();

    metadata.hsize = iis.readShort();
    metadata.vsize = iis.readShort();

    iis.skipBytes(54); // skip filler

    width = xmax - metadata.xmin + 1;
    height = ymax - metadata.ymin + 1;

    if (colorPlanes == 1) {
      if (paletteType == PALETTE_GRAYSCALE) {
        ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
        int[] nBits = {8};
        colorModel =
            new ComponentColorModel(
                cs, nBits, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
        sampleModel =
            new ComponentSampleModel(DataBuffer.TYPE_BYTE, width, height, 1, width, new int[] {0});
      } else {
        if (metadata.bitsPerPixel == 8) {
          // read palette from end of file, then reset back to image data
          iis.mark();

          if (iis.length() == -1) {
            // read until eof, and work backwards
            while (iis.read() != -1) ;
            iis.seek(iis.getStreamPosition() - 256 * 3 - 1);
          } else {
            iis.seek(iis.length() - 256 * 3 - 1);
          }

          int palletteMagic = iis.read();
          if (palletteMagic != 12)
            processWarningOccurred(
                "Expected palette magic number 12; instead read "
                    + palletteMagic
                    + " from this image.");

          iis.readFully(largePalette);
          iis.reset();

          colorModel = new IndexColorModel(metadata.bitsPerPixel, 256, largePalette, 0, false);
          sampleModel = colorModel.createCompatibleSampleModel(width, height);
        } else {
          int msize = metadata.bitsPerPixel == 1 ? 2 : 16;
          colorModel = new IndexColorModel(metadata.bitsPerPixel, msize, smallPalette, 0, false);
          sampleModel = colorModel.createCompatibleSampleModel(width, height);
        }
      }
    } else {
      ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
      int[] nBits = {8, 8, 8};
      colorModel =
          new ComponentColorModel(
              cs, nBits, false, false, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
      sampleModel =
          new ComponentSampleModel(
              DataBuffer.TYPE_BYTE,
              width,
              height,
              1,
              width * colorPlanes,
              new int[] {0, width, width * 2});
    }

    originalSampleModel = sampleModel;
    originalColorModel = colorModel;

    gotHeader = true;
  }
예제 #7
0
  private void decodeTile(int ti, int tj, int band) throws IOException {
    if (DEBUG) {
      System.out.println("decodeTile(" + ti + "," + tj + "," + band + ")");
    }

    // Compute the region covered by the strip or tile
    Rectangle tileRect =
        new Rectangle(
            ti * tileOrStripWidth, tj * tileOrStripHeight, tileOrStripWidth, tileOrStripHeight);

    // Clip against the image bounds if the image is not tiled. If it
    // is tiled, the tile may legally extend beyond the image bounds.
    if (!isImageTiled(currIndex)) {
      tileRect = tileRect.intersection(new Rectangle(0, 0, width, height));
    }

    // Return if the intersection is empty.
    if (tileRect.width <= 0 || tileRect.height <= 0) {
      return;
    }

    int srcMinX = tileRect.x;
    int srcMinY = tileRect.y;
    int srcWidth = tileRect.width;
    int srcHeight = tileRect.height;

    // Determine dest region that can be derived from the
    // source region

    dstMinX = iceil(srcMinX - sourceXOffset, srcXSubsampling);
    int dstMaxX = ifloor(srcMinX + srcWidth - 1 - sourceXOffset, srcXSubsampling);

    dstMinY = iceil(srcMinY - sourceYOffset, srcYSubsampling);
    int dstMaxY = ifloor(srcMinY + srcHeight - 1 - sourceYOffset, srcYSubsampling);

    dstWidth = dstMaxX - dstMinX + 1;
    dstHeight = dstMaxY - dstMinY + 1;

    dstMinX += dstXOffset;
    dstMinY += dstYOffset;

    // Clip against image bounds

    Rectangle dstRect =
        new Rectangle(
            dstMinX, dstMinY,
            dstWidth, dstHeight);
    dstRect = dstRect.intersection(theImage.getRaster().getBounds());

    dstMinX = dstRect.x;
    dstMinY = dstRect.y;
    dstWidth = dstRect.width;
    dstHeight = dstRect.height;

    if (dstWidth <= 0 || dstHeight <= 0) {
      return;
    }

    // Backwards map dest region to source to determine
    // active source region

    int activeSrcMinX = (dstMinX - dstXOffset) * srcXSubsampling + sourceXOffset;
    int sxmax = (dstMinX + dstWidth - 1 - dstXOffset) * srcXSubsampling + sourceXOffset;
    int activeSrcWidth = sxmax - activeSrcMinX + 1;

    int activeSrcMinY = (dstMinY - dstYOffset) * srcYSubsampling + sourceYOffset;
    int symax = (dstMinY + dstHeight - 1 - dstYOffset) * srcYSubsampling + sourceYOffset;
    int activeSrcHeight = symax - activeSrcMinY + 1;

    decompressor.setSrcMinX(srcMinX);
    decompressor.setSrcMinY(srcMinY);
    decompressor.setSrcWidth(srcWidth);
    decompressor.setSrcHeight(srcHeight);

    decompressor.setDstMinX(dstMinX);
    decompressor.setDstMinY(dstMinY);
    decompressor.setDstWidth(dstWidth);
    decompressor.setDstHeight(dstHeight);

    decompressor.setActiveSrcMinX(activeSrcMinX);
    decompressor.setActiveSrcMinY(activeSrcMinY);
    decompressor.setActiveSrcWidth(activeSrcWidth);
    decompressor.setActiveSrcHeight(activeSrcHeight);

    int tileIndex = tj * tilesAcross + ti;

    if (planarConfiguration == BaselineTIFFTagSet.PLANAR_CONFIGURATION_PLANAR) {
      tileIndex += band * tilesAcross * tilesDown;
    }

    long offset = getTileOrStripOffset(tileIndex);
    long byteCount = getTileOrStripByteCount(tileIndex);

    //
    // Attempt to handle truncated streams, i.e., where reading the
    // compressed strip or tile would result in an EOFException. The
    // number of bytes to read is clamped to the number available
    // from the stream starting at the indicated position in the hope
    // that the decompressor will handle it.
    //
    long streamLength = stream.length();
    if (streamLength > 0 && offset + byteCount > streamLength) {
      processWarningOccurred("Attempting to process truncated stream.");
      if (Math.max(byteCount = streamLength - offset, 0) == 0) {
        processWarningOccurred("No bytes in strip/tile: skipping.");
        return;
      }
    }

    decompressor.setStream(stream);
    decompressor.setOffset(offset);
    decompressor.setByteCount((int) byteCount);

    decompressor.beginDecoding();

    stream.mark();
    decompressor.decode();
    stream.reset();
  }
  /** Reads the header. Does nothing if the header has already been loaded. */
  private void readHeader() throws IOException {
    if (numImages == -1) {
      ImageInputStream in = (ImageInputStream) getInput();
      in.seek(0);
      er = new EXIFReader(in);
      er.setFirstImageOnly(false);
      er.read();

      // Get some information that is easy to obtain through a map
      {
        HashMap<TIFFTag, TIFFField> m = er.getMetaDataMap();
        TIFFField mde;
        if ((mde = m.get(MPFTagSet.get(MPFTagSet.TAG_NumberOfImages))) != null) {
          numImages = ((Number) mde.getData()).intValue();
        } else {
          numImages = 1;
        }
        if ((mde = m.get(EXIFTagSet.PixelXDimension)) != null) {
          width = ((Number) mde.getData()).intValue();
        }
        if ((mde = m.get(EXIFTagSet.PixelYDimension)) != null) {
          height = ((Number) mde.getData()).intValue();
        }
      }
      imageOffsets = new long[numImages];
      imageLengths = new long[numImages];
      if (numImages == 1) {
        imageOffsets[0] = 0;
        imageLengths[0] = in.length();
      }

      // Get now at the tough part
      int index = 0;
      for (Iterator<TIFFNode> e = er.getMetaDataTree().preorderIterator(); e.hasNext(); ) {
        TIFFNode n = e.next();
        if (n instanceof TIFFDirectory) {
          TIFFDirectory dir = (TIFFDirectory) n;
          // System.out.println("dir:" + dir.getName());
          if (dir.getName() != null && dir.getName().equals("MPEntry")) {
            long dirOffset = dir.getFileSegments().get(0).getOffset();
            TIFFField offsetField = dir.getField(MPEntryTagSet.IndividualImageDataOffset);
            TIFFField lengthField = dir.getField(MPEntryTagSet.IndividualImageSize);
            if (offsetField != null && lengthField != null) {
              long dataOffset = (Long) offsetField.getData();
              imageOffsets[index] = dataOffset == 0 ? 0 : dirOffset + dataOffset;
              imageLengths[index] = (Long) lengthField.getData();
              index++;
            }
          }
        }
      }

      // Store metadata for later access
      String formatName = "com_sun_media_imageio_plugins_tiff_image_1.0";
      imageMetadata = new IIOMetadata[numImages];
      for (int i = 0; i < numImages; i++) {
        imageMetadata[i] = new DefaultIIOMetadata(formatName, er.getIIOMetadataTree(formatName, i));
      }

      in.seek(0);
    }
  }