Exemplo n.º 1
0
  private Raster clipRowToRect(
      final Raster raster, final Rectangle rect, final int[] bands, final int xSub) {
    if (rect.contains(raster.getMinX(), 0, raster.getWidth(), 1)
        && xSub == 1
        && bands == null /* TODO: Compare bands with that of raster */) {
      return raster;
    }

    return raster.createChild(rect.x / xSub, 0, rect.width / xSub, 1, 0, 0, bands);
  }
Exemplo n.º 2
0
  @Override
  public BufferedImage read(final int imageIndex, final ImageReadParam param) throws IOException {
    Iterator<ImageTypeSpecifier> imageTypes = getImageTypes(imageIndex);
    ImageTypeSpecifier rawType = getRawImageType(imageIndex);

    if (header.getPaletteInfo() != PCX.PALETTEINFO_COLOR
        && header.getPaletteInfo() != PCX.PALETTEINFO_GRAY) {
      processWarningOccurred(
          String.format(
              "Unsupported color mode: %d, colors may look incorrect", header.getPaletteInfo()));
    }

    int width = getWidth(imageIndex);
    int height = getHeight(imageIndex);

    BufferedImage destination = getDestination(param, imageTypes, width, height);

    Rectangle srcRegion = new Rectangle();
    Rectangle destRegion = new Rectangle();
    computeRegions(param, width, height, destination, srcRegion, destRegion);

    WritableRaster destRaster =
        clipToRect(
            destination.getRaster(),
            destRegion,
            param != null ? param.getDestinationBands() : null);
    checkReadParamBandSettings(param, rawType.getNumBands(), destRaster.getNumBands());

    int compression = header.getCompression();

    // Wrap input (COMPRESSION_RLE is really the only value allowed)
    DataInput input =
        compression == PCX.COMPRESSION_RLE
            ? new DataInputStream(
                new DecoderStream(IIOUtil.createStreamAdapter(imageInput), new RLEDecoder()))
            : imageInput;

    int xSub = param != null ? param.getSourceXSubsampling() : 1;
    int ySub = param != null ? param.getSourceYSubsampling() : 1;

    processImageStarted(imageIndex);

    if (rawType.getColorModel() instanceof IndexColorModel && header.getChannels() > 1) {
      // Bit planes!
      // Create raster from a default 8 bit layout
      WritableRaster rowRaster = GRAYSCALE.createBufferedImage(header.getWidth(), 1).getRaster();

      // Clip to source region
      Raster clippedRow =
          clipRowToRect(
              rowRaster,
              srcRegion,
              param != null ? param.getSourceBands() : null,
              param != null ? param.getSourceXSubsampling() : 1);

      int planeWidth = header.getBytesPerLine();
      byte[] planeData = new byte[planeWidth * 8];

      byte[] rowDataByte = ((DataBufferByte) rowRaster.getDataBuffer()).getData();

      for (int y = 0; y < height; y++) {
        switch (header.getBitsPerPixel()) {
          case 1:
            readRowByte(
                input,
                srcRegion,
                xSub,
                ySub,
                planeData,
                0,
                planeWidth * header.getChannels(),
                destRaster,
                clippedRow,
                y);
            break;
          default:
            throw new AssertionError();
        }

        int pixelPos = 0;
        for (int planePos = 0; planePos < planeWidth; planePos++) {
          BitRotator.bitRotateCW(planeData, planePos, planeWidth, rowDataByte, pixelPos, 1);
          pixelPos += 8;
        }

        processImageProgress(100f * y / height);

        if (y >= srcRegion.y + srcRegion.height) {
          break;
        }

        if (abortRequested()) {
          processReadAborted();
          break;
        }
      }
    } else if (header.getBitsPerPixel() == 24 || header.getBitsPerPixel() == 32) {
      // Can't use width here, as we need to take bytesPerLine into account, and re-create a width
      // based on this
      int rowWidth = (header.getBytesPerLine() * 8) / header.getBitsPerPixel();
      WritableRaster rowRaster = rawType.createBufferedImage(rowWidth, 1).getRaster();

      // Clip to source region
      Raster clippedRow =
          clipRowToRect(
              rowRaster,
              srcRegion,
              param != null ? param.getSourceBands() : null,
              param != null ? param.getSourceXSubsampling() : 1);

      for (int y = 0; y < height; y++) {
        byte[] rowDataByte = ((DataBufferByte) rowRaster.getDataBuffer()).getData();
        readRowByte(
            input,
            srcRegion,
            xSub,
            ySub,
            rowDataByte,
            0,
            rowDataByte.length,
            destRaster,
            clippedRow,
            y);

        processImageProgress(100f * y / height);

        if (y >= srcRegion.y + srcRegion.height) {
          break;
        }

        if (abortRequested()) {
          processReadAborted();
          break;
        }
      }
    } else {
      // Can't use width here, as we need to take bytesPerLine into account, and re-create a width
      // based on this
      int rowWidth = (header.getBytesPerLine() * 8) / header.getBitsPerPixel();
      WritableRaster rowRaster = rawType.createBufferedImage(rowWidth, 1).getRaster();

      // Clip to source region
      Raster clippedRow =
          clipRowToRect(
              rowRaster,
              srcRegion,
              param != null ? param.getSourceBands() : null,
              param != null ? param.getSourceXSubsampling() : 1);

      for (int y = 0; y < height; y++) {
        for (int c = 0; c < header.getChannels(); c++) {
          WritableRaster destChannel =
              destRaster.createWritableChild(
                  destRaster.getMinX(),
                  destRaster.getMinY(),
                  destRaster.getWidth(),
                  destRaster.getHeight(),
                  0,
                  0,
                  new int[] {c});
          Raster srcChannel =
              clippedRow.createChild(
                  clippedRow.getMinX(), 0, clippedRow.getWidth(), 1, 0, 0, new int[] {c});

          switch (header.getBitsPerPixel()) {
            case 1:
            case 2:
            case 4:
            case 8:
              byte[] rowDataByte = ((DataBufferByte) rowRaster.getDataBuffer()).getData(c);
              readRowByte(
                  input,
                  srcRegion,
                  xSub,
                  ySub,
                  rowDataByte,
                  0,
                  rowDataByte.length,
                  destChannel,
                  srcChannel,
                  y);
              break;
            default:
              throw new AssertionError();
          }

          if (abortRequested()) {
            break;
          }
        }

        processImageProgress(100f * y / height);

        if (y >= srcRegion.y + srcRegion.height) {
          break;
        }

        if (abortRequested()) {
          processReadAborted();
          break;
        }
      }
    }

    processImageComplete();

    return destination;
  }