Exemple #1
0
 // returns a value specifying some kind of average brightness in the image.
 protected int getAverageBrightness(BufferedImage img) {
   Raster r = img.getData();
   int total = 0;
   for (int y = 0; y < r.getHeight(); y++) {
     for (int x = 0; x < r.getWidth(); x++) {
       total += r.getSample(r.getMinX() + x, r.getMinY() + y, 0);
     }
   }
   return (int) (total / ((r.getWidth() / factorD) * (r.getHeight() / factorD)));
 }
  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);
  }
  /**
   * Ipp filter.
   *
   * @param src the src.
   * @param dst the dst.
   * @param imageType the image type.
   * @return the int.
   */
  @SuppressWarnings("unused")
  private int ippFilter(Raster src, WritableRaster dst, int imageType) {
    int srcStride, dstStride;
    boolean skipChannel = false;
    int channels;
    int offsets[] = null;

    switch (imageType) {
      case BufferedImage.TYPE_INT_RGB:
      case BufferedImage.TYPE_INT_BGR:
        {
          channels = 4;
          srcStride = src.getWidth() * 4;
          dstStride = dst.getWidth() * 4;
          skipChannel = true;
          break;
        }

      case BufferedImage.TYPE_INT_ARGB:
      case BufferedImage.TYPE_INT_ARGB_PRE:
      case BufferedImage.TYPE_4BYTE_ABGR:
      case BufferedImage.TYPE_4BYTE_ABGR_PRE:
        {
          channels = 4;
          srcStride = src.getWidth() * 4;
          dstStride = dst.getWidth() * 4;
          break;
        }

      case BufferedImage.TYPE_BYTE_GRAY:
      case BufferedImage.TYPE_BYTE_INDEXED:
        {
          channels = 1;
          srcStride = src.getWidth();
          dstStride = dst.getWidth();
          break;
        }

      case BufferedImage.TYPE_3BYTE_BGR:
        {
          channels = 3;
          srcStride = src.getWidth() * 3;
          dstStride = dst.getWidth() * 3;
          break;
        }

      case BufferedImage.TYPE_USHORT_GRAY: // TODO - could be done in
        // native code?
      case BufferedImage.TYPE_USHORT_565_RGB:
      case BufferedImage.TYPE_USHORT_555_RGB:
      case BufferedImage.TYPE_BYTE_BINARY:
        {
          return slowFilter(src, dst);
        }

      default:
        {
          SampleModel srcSM = src.getSampleModel();
          SampleModel dstSM = dst.getSampleModel();

          if (srcSM instanceof PixelInterleavedSampleModel
              && dstSM instanceof PixelInterleavedSampleModel) {
            // Check PixelInterleavedSampleModel
            if (srcSM.getDataType() != DataBuffer.TYPE_BYTE
                || dstSM.getDataType() != DataBuffer.TYPE_BYTE) {
              return slowFilter(src, dst);
            }

            channels = srcSM.getNumBands(); // Have IPP functions for 1,
            // 3 and 4 channels
            if (channels != 1 && channels != 3 && channels != 4) {
              return slowFilter(src, dst);
            }

            int dataTypeSize = DataBuffer.getDataTypeSize(srcSM.getDataType()) / 8;

            srcStride = ((ComponentSampleModel) srcSM).getScanlineStride() * dataTypeSize;
            dstStride = ((ComponentSampleModel) dstSM).getScanlineStride() * dataTypeSize;
          } else if (srcSM instanceof SinglePixelPackedSampleModel
              && dstSM instanceof SinglePixelPackedSampleModel) {
            // Check SinglePixelPackedSampleModel
            SinglePixelPackedSampleModel sppsm1 = (SinglePixelPackedSampleModel) srcSM;
            SinglePixelPackedSampleModel sppsm2 = (SinglePixelPackedSampleModel) dstSM;

            // No IPP function for this type
            if (sppsm1.getDataType() == DataBuffer.TYPE_USHORT) {
              return slowFilter(src, dst);
            }

            channels = sppsm1.getNumBands();
            // Have IPP functions for 1, 3 and 4 channels
            if (channels != 1 && channels != 3 && channels != 4) {
              return slowFilter(src, dst);
            }

            // Check compatibility of sample models
            if (sppsm1.getDataType() != sppsm2.getDataType()
                || !Arrays.equals(sppsm1.getBitOffsets(), sppsm2.getBitOffsets())
                || !Arrays.equals(sppsm1.getBitMasks(), sppsm2.getBitMasks())) {
              return slowFilter(src, dst);
            }

            for (int i = 0; i < channels; i++) {
              if (sppsm1.getSampleSize(i) != 8) {
                return slowFilter(src, dst);
              }
            }

            if (channels == 3) {
              channels = 4;
            }

            int dataTypeSize = DataBuffer.getDataTypeSize(sppsm1.getDataType()) / 8;

            srcStride = sppsm1.getScanlineStride() * dataTypeSize;
            dstStride = sppsm2.getScanlineStride() * dataTypeSize;
          } else {
            return slowFilter(src, dst);
          }

          // Fill offsets if there's a child raster
          if (src.getParent() != null || dst.getParent() != null) {
            if (src.getSampleModelTranslateX() != 0
                || src.getSampleModelTranslateY() != 0
                || dst.getSampleModelTranslateX() != 0
                || dst.getSampleModelTranslateY() != 0) {
              offsets = new int[4];
              offsets[0] = -src.getSampleModelTranslateX() + src.getMinX();
              offsets[1] = -src.getSampleModelTranslateY() + src.getMinY();
              offsets[2] = -dst.getSampleModelTranslateX() + dst.getMinX();
              offsets[3] = -dst.getSampleModelTranslateY() + dst.getMinY();
            }
          }
        }
    }

    double m00 = at.getScaleX();
    double m01 = at.getShearX();
    double m02 = at.getTranslateX();
    double m10 = at.getShearY();
    double m11 = at.getScaleY();
    double m12 = at.getTranslateY();

    Object srcData, dstData;
    AwtImageBackdoorAccessor dbAccess = AwtImageBackdoorAccessor.getInstance();
    try {
      srcData = dbAccess.getData(src.getDataBuffer());
      dstData = dbAccess.getData(dst.getDataBuffer());
    } catch (IllegalArgumentException e) {
      return -1; // Unknown data buffer type
    }

    return ippAffineTransform(
        m00,
        m01,
        m02,
        m10,
        m11,
        m12,
        srcData,
        src.getWidth(),
        src.getHeight(),
        srcStride,
        dstData,
        dst.getWidth(),
        dst.getHeight(),
        dstStride,
        iType,
        channels,
        skipChannel,
        offsets);
  }
  @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;
  }