Esempio n. 1
0
  /**
   * The CodecOptions parameter should have the following fields set: {@link CodecOptions#width
   * width} {@link CodecOptions#height height} {@link CodecOptions#channels channels} {@link
   * CodecOptions#bitsPerSample bitsPerSample} {@link CodecOptions#interleaved interleaved} {@link
   * CodecOptions#littleEndian littleEndian} {@link CodecOptions#signed signed}
   *
   * @see Codec#compress(byte[], CodecOptions)
   */
  @Override
  public byte[] compress(final byte[] data, CodecOptions options) throws FormatException {
    if (data == null || data.length == 0) return data;
    if (options == null) options = CodecOptions.getDefaultOptions();

    if (options.bitsPerSample > 8) {
      throw new FormatException("> 8 bit data cannot be compressed with JPEG.");
    }

    final ByteArrayOutputStream out = new ByteArrayOutputStream();
    final BufferedImage img =
        AWTImageTools.makeImage(
            data,
            options.width,
            options.height,
            options.channels,
            options.interleaved,
            options.bitsPerSample / 8,
            false,
            options.littleEndian,
            options.signed);

    try {
      ImageIO.write(img, "jpeg", out);
    } catch (final IOException e) {
      throw new FormatException("Could not write JPEG data", e);
    }
    return out.toByteArray();
  }
  /**
   * The CodecOptions parameter should have the following fields set: {@link CodecOptions#width
   * width} {@link CodecOptions#height height}
   *
   * @see Codec#decompress(RandomAccessInputStream, CodecOptions)
   */
  public byte[] decompress(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);

    int plane = options.width * options.height;

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

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

    while (in.read() != (byte) 0xe1) ;
    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;

                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];

                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;

              short s = (short) (pixels[blockPtr] & 0x7fff);
              unpack(s, rtn, blockPtr, pixels.length);
              blockPtr++;
            }
            blockPtr += rowInc;
          }
          updateBlock(options.width);
          break;
      }
    }
    return rtn;
  }
Esempio n. 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;
  }