/**
  * Constructs a random access stream around the given handle, and with the associated file path.
  */
 public RandomAccessInputStream(
     final Context context, final IRandomAccess handle, final String file) throws IOException {
   scifio = new SCIFIO(context);
   log = scifio.log();
   if (log.isTrace()) {
     log.trace("RandomAccessInputStream " + hashCode() + " OPEN");
   }
   this.file = file;
   raf = handle;
   raf.setOrder(ByteOrder.BIG_ENDIAN);
   seek(0);
   length = -1;
 }
示例#2
0
  /**
   * The CodecOptions parameter should have the following fields set: {@link CodecOptions#width
   * width} {@link CodecOptions#height height}
   *
   * @see Codec#decompress(RandomAccessInputStream, CodecOptions)
   */
  @Override
  public byte[] decompress(final RandomAccessInputStream in, CodecOptions options)
      throws FormatException, IOException {
    if (in == null) throw new IllegalArgumentException("No data to decompress.");
    if (options == null) options = CodecOptions.getDefaultOptions();

    in.skipBytes(8);

    final int plane = options.width * options.height;

    stride = options.width;
    final int rowInc = stride - 4;
    short opcode;
    int nBlocks;
    int colorA = 0, colorB;
    final int[] color4 = new int[4];
    int index, idx;
    int ta, tb;
    int blockPtr = 0;
    rowPtr = pixelPtr = 0;
    int pixelX, pixelY;

    final int[] pixels = new int[plane];
    final byte[] rtn = new byte[plane * 3];

    while (in.read() != (byte) 0xe1) {
      /* Read to block metadata */
    }
    in.skipBytes(3);

    //		totalBlocks = ((options.width + 3) / 4) * ((options.height + 3) / 4);

    while (in.getFilePointer() + 2 < in.length()) {
      opcode = in.readByte();
      nBlocks = (opcode & 0x1f) + 1;

      if ((opcode & 0x80) == 0) {
        if (in.getFilePointer() >= in.length()) break;
        colorA = (opcode << 8) | in.read();
        opcode = 0;
        if (in.getFilePointer() >= in.length()) break;
        if ((in.read() & 0x80) != 0) {
          opcode = 0x20;
          nBlocks = 1;
        }
        in.seek(in.getFilePointer() - 1);
      }

      switch (opcode & 0xe0) {
        case 0x80:
          while (nBlocks-- > 0) {
            updateBlock(options.width);
          }
          break;
        case 0xa0:
          if (in.getFilePointer() + 2 >= in.length()) break;
          colorA = in.readShort();
          while (nBlocks-- > 0) {
            blockPtr = rowPtr + pixelPtr;
            for (pixelY = 0; pixelY < 4; pixelY++) {
              for (pixelX = 0; pixelX < 4; pixelX++) {
                if (blockPtr >= pixels.length) break;
                pixels[blockPtr] = colorA;

                final short s = (short) (pixels[blockPtr] & 0x7fff);
                unpack(s, rtn, blockPtr, pixels.length);
                blockPtr++;
              }
              blockPtr += rowInc;
            }
            updateBlock(options.width);
          }
          break;
        case 0xc0:
        case 0x20:
          if (in.getFilePointer() + 2 >= in.length()) break;
          if ((opcode & 0xe0) == 0xc0) {
            colorA = in.readShort();
          }

          colorB = in.readShort();

          color4[0] = colorB;
          color4[1] = 0;
          color4[2] = 0;
          color4[3] = colorA;

          ta = (colorA >> 10) & 0x1f;
          tb = (colorB >> 10) & 0x1f;
          color4[1] |= ((11 * ta + 21 * tb) >> 5) << 10;
          color4[2] |= ((21 * ta + 11 * tb) >> 5) << 10;

          ta = (colorA >> 5) & 0x1f;
          tb = (colorB >> 5) & 0x1f;
          color4[1] |= ((11 * ta + 21 * tb) >> 5) << 5;
          color4[2] |= ((21 * ta + 11 * tb) >> 5) << 5;

          ta = colorA & 0x1f;
          tb = colorB & 0x1f;
          color4[1] |= (11 * ta + 21 * tb) >> 5;
          color4[2] |= (21 * ta + 11 * tb) >> 5;

          while (nBlocks-- > 0) {
            blockPtr = rowPtr + pixelPtr;
            for (pixelY = 0; pixelY < 4; pixelY++) {
              if (in.getFilePointer() >= in.length()) break;
              index = in.read();
              for (pixelX = 0; pixelX < 4; pixelX++) {
                idx = (index >> (2 * (3 - pixelX))) & 3;
                if (blockPtr >= pixels.length) break;
                pixels[blockPtr] = color4[idx];

                final short s = (short) (pixels[blockPtr] & 0x7fff);
                unpack(s, rtn, blockPtr, pixels.length);
                blockPtr++;
              }
              blockPtr += rowInc;
            }
            updateBlock(options.width);
          }
          break;
        case 0x00:
          blockPtr = rowPtr + pixelPtr;
          for (pixelY = 0; pixelY < 4; pixelY++) {
            for (pixelX = 0; pixelX < 4; pixelX++) {
              if ((pixelY != 0) || (pixelX != 0)) {
                if (in.getFilePointer() + 2 >= in.length()) break;
                colorA = in.readShort();
              }
              if (blockPtr >= pixels.length) break;
              pixels[blockPtr] = colorA;

              final short s = (short) (pixels[blockPtr] & 0x7fff);
              unpack(s, rtn, blockPtr, pixels.length);
              blockPtr++;
            }
            blockPtr += rowInc;
          }
          updateBlock(options.width);
          break;
      }
    }
    return rtn;
  }
示例#3
0
  /**
   * The CodecOptions parameter should have the following fields set: {@link
   * CodecOptions#interleaved interleaved} {@link CodecOptions#littleEndian littleEndian}
   *
   * @see Codec#decompress(RandomAccessInputStream, CodecOptions)
   */
  @Override
  public byte[] decompress(final RandomAccessInputStream in, CodecOptions options)
      throws FormatException, IOException {
    BufferedImage b;
    final long fp = in.getFilePointer();
    try {
      try {
        while (in.read() != (byte) 0xff || in.read() != (byte) 0xd8) {
          /* Read to data. */
        }
        in.seek(in.getFilePointer() - 2);
      } catch (final EOFException e) {
        in.seek(fp);
      }

      b = ImageIO.read(new BufferedInputStream(new DataInputStream(in), 8192));
    } catch (final IOException exc) {
      // probably a lossless JPEG; delegate to LosslessJPEGCodec
      in.seek(fp);
      return new LosslessJPEGCodec().decompress(in, options);
    }

    if (options == null) options = CodecOptions.getDefaultOptions();

    final byte[][] buf = AWTImageTools.getPixelBytes(b, options.littleEndian);

    // correct for YCbCr encoding, if necessary
    if (options.ycbcr && buf.length == 3) {
      final int nBytes = buf[0].length / (b.getWidth() * b.getHeight());
      final int mask = (int) (Math.pow(2, nBytes * 8) - 1);
      for (int i = 0; i < buf[0].length; i += nBytes) {
        final int y = DataTools.bytesToInt(buf[0], i, nBytes, options.littleEndian);
        int cb = DataTools.bytesToInt(buf[1], i, nBytes, options.littleEndian);
        int cr = DataTools.bytesToInt(buf[2], i, nBytes, options.littleEndian);

        cb = Math.max(0, cb - 128);
        cr = Math.max(0, cr - 128);

        final int red = (int) (y + 1.402 * cr) & mask;
        final int green = (int) (y - 0.34414 * cb - 0.71414 * cr) & mask;
        final int blue = (int) (y + 1.772 * cb) & mask;

        DataTools.unpackBytes(red, buf[0], i, nBytes, options.littleEndian);
        DataTools.unpackBytes(green, buf[1], i, nBytes, options.littleEndian);
        DataTools.unpackBytes(blue, buf[2], i, nBytes, options.littleEndian);
      }
    }

    byte[] rtn = new byte[buf.length * buf[0].length];
    if (buf.length == 1) rtn = buf[0];
    else {
      if (options.interleaved) {
        int next = 0;
        for (int i = 0; i < buf[0].length; i++) {
          for (int j = 0; j < buf.length; j++) {
            rtn[next++] = buf[j][i];
          }
        }
      } else {
        for (int i = 0; i < buf.length; i++) {
          System.arraycopy(buf[i], 0, rtn, i * buf[0].length, buf[i].length);
        }
      }
    }
    return rtn;
  }
 @Override
 public void reset() throws IOException {
   if (markedPos < 0) throw new IOException("No mark set");
   seek(markedPos);
 }
  /**
   * Reads or skips a string ending with one of the given terminating substrings, using the
   * specified block size for buffering.
   *
   * @param saveString Whether to collect the string from the current file pointer to the
   *     terminating bytes, and return it. If false, returns null.
   * @param blockSize The block size to use when reading bytes in chunks.
   * @param terminators The strings for which to search.
   * @throws IOException If saveString flag is set and the maximum search length (512 MB) is
   *     exceeded.
   * @return The string from the initial position through the end of the terminating sequence, or
   *     through the end of the stream if no terminating sequence is found, or null if saveString
   *     flag is unset.
   */
  public String findString(
      final boolean saveString, final int blockSize, final String... terminators)
      throws IOException {
    final StringBuilder out = new StringBuilder();
    final long startPos = getFilePointer();
    long bytesDropped = 0;
    final long inputLen = length();
    long maxLen = inputLen - startPos;
    final boolean tooLong = saveString && maxLen > MAX_SEARCH_SIZE;
    if (tooLong) maxLen = MAX_SEARCH_SIZE;
    boolean match = false;
    int maxTermLen = 0;
    for (final String term : terminators) {
      final int len = term.length();
      if (len > maxTermLen) maxTermLen = len;
    }

    final InputStreamReader in = new InputStreamReader(this, encoding);
    final char[] buf = new char[blockSize];
    long loc = 0;
    while (loc < maxLen && getFilePointer() < length() - 1) {
      // if we're not saving the string, drop any old, unnecessary output
      if (!saveString) {
        final int outLen = out.length();
        if (outLen >= maxTermLen) {
          final int dropIndex = outLen - maxTermLen + 1;
          final String last = out.substring(dropIndex, outLen);
          out.setLength(0);
          out.append(last);
          bytesDropped += dropIndex;
        }
      }

      // read block from stream
      final int r = in.read(buf, 0, blockSize);
      if (r <= 0) throw new IOException("Cannot read from stream: " + r);

      // append block to output
      out.append(buf, 0, r);

      // check output, returning smallest possible string
      int min = Integer.MAX_VALUE, tagLen = 0;
      for (final String t : terminators) {
        final int len = t.length();
        final int start = (int) (loc - bytesDropped - len);
        final int value = out.indexOf(t, start < 0 ? 0 : start);
        if (value >= 0 && value < min) {
          match = true;
          min = value;
          tagLen = len;
        }
      }

      if (match) {
        // reset stream to proper location
        seek(startPos + bytesDropped + min + tagLen);

        // trim output string
        if (saveString) {
          out.setLength(min + tagLen);
          return out.toString();
        }
        return null;
      }

      loc += r;
    }

    // no match
    if (tooLong) throw new IOException("Maximum search length reached.");
    return saveString ? out.toString() : null;
  }