protected static BufferedImage getDestination(
      ImageReadParam param, Iterator imageTypes, int width, int height) throws IIOException {
    if (imageTypes == null || !imageTypes.hasNext()) {
      throw new IllegalArgumentException("imageTypes null or empty!");
    }

    BufferedImage dest = null;
    ImageTypeSpecifier imageType = null;

    // If param is non-null, use it
    if (param != null) {
      // Try to get the image itself
      dest = param.getDestination();
      if (dest != null) {
        return dest;
      }

      // No image, get the image type
      imageType = param.getDestinationType();
    }

    // No info from param, use fallback image type
    if (imageType == null) {
      Object o = imageTypes.next();
      if (!(o instanceof ImageTypeSpecifier)) {
        throw new IllegalArgumentException("Non-ImageTypeSpecifier retrieved from imageTypes!");
      }
      imageType = (ImageTypeSpecifier) o;
    } else {
      boolean foundIt = false;
      while (imageTypes.hasNext()) {
        ImageTypeSpecifier type = (ImageTypeSpecifier) imageTypes.next();
        if (type.equals(imageType)) {
          foundIt = true;
          break;
        }
      }

      if (!foundIt) {
        throw new IIOException("Destination type from ImageReadParam does not match!");
      }
    }

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

    int destWidth = destRegion.x + destRegion.width;
    int destHeight = destRegion.y + destRegion.height;
    // Create a new image based on the type specifier

    if ((long) destWidth * destHeight > Integer.MAX_VALUE) {
      throw new IllegalArgumentException("width*height > Integer.MAX_VALUE!");
    }

    return imageType.createBufferedImage(destWidth, destHeight);
  }
Exemple #2
0
 public void compressJpegFile(
     File infile, File outfile, float compressionQuality, int widthCanvas, int heightCanvas)
     throws IOException {
   // Retrieve jpg image to be compressed
   BufferedImage rendImage = ImageIO.read(infile);
   widthFile = rendImage.getWidth();
   heightFile = rendImage.getHeight();
   double aspectRatioCanvas = widthCanvas / heightCanvas;
   double aspectRatioFile = widthFile / heightFile;
   widthFile = widthCanvas;
   heightFile = widthCanvas / aspectRatioFile;
   if (heightFile > heightCanvas) {
     heightFile = heightCanvas;
     widthFile = heightCanvas * aspectRatioFile;
   }
   this.width = (int) widthFile;
   this.height = (int) heightFile;
   ImageTypeSpecifier its = ImageTypeSpecifier.createFromRenderedImage(rendImage);
   BufferedImage outImage = its.createBufferedImage(width, height);
   Graphics2D graphics2D = outImage.createGraphics();
   graphics2D.setRenderingHint(
       RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
   //         graphics2D.drawRenderedImage(rendImage, new AffineTransform());
   graphics2D.drawImage(rendImage, 0, 0, width, height, null);
   // Find a jpeg writer
   ImageWriter writer = null;
   Iterator iter = ImageIO.getImageWritersByFormatName("jpg");
   if (iter.hasNext()) {
     writer = (ImageWriter) iter.next();
   }
   // Prepare output file
   ImageOutputStream ios = ImageIO.createImageOutputStream(outfile);
   writer.setOutput(ios);
   // Set the compression quality
   ImageWriteParam iwparam = new JPEGImageWriteParam(Locale.getDefault());
   iwparam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
   iwparam.setCompressionQuality(compressionQuality);
   // Write the image
   writer.write(null, new IIOImage(outImage, null, null), iwparam);
   // infile.delete();
   // Cleanup
   ios.flush();
   writer.dispose();
   ios.close();
   // return
 }
  @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;
  }