Java Code Examples for javax.imageio.plugins.jpeg.JPEGImageWriteParam#setCompressionQuality()

The following examples show how to use javax.imageio.plugins.jpeg.JPEGImageWriteParam#setCompressionQuality() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: ScalablePicture.java    From netcdf-java with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
/**
 * This static method writes the indicated renderedImage (BufferedImage)
 * to the indicated file.
 *
 * @param writeFile The File that shall receive the jpg data
 * @param renderedImage The RenderedImage (BufferedImage) to be written
 * @param jpgQuality The quality with which to compress to jpg
 */
public static void writeJpg(File writeFile, RenderedImage renderedImage, float jpgQuality) {
  Iterator writers = ImageIO.getImageWritersByFormatName("jpg");
  ImageWriter writer = (ImageWriter) writers.next();
  JPEGImageWriteParam params = new JPEGImageWriteParam(null);
  params.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
  params.setCompressionQuality(jpgQuality);
  params.setProgressiveMode(ImageWriteParam.MODE_DISABLED);
  params.setDestinationType(new ImageTypeSpecifier(java.awt.image.IndexColorModel.getRGBdefault(),
      IndexColorModel.getRGBdefault().createCompatibleSampleModel(16, 16)));

  try (ImageOutputStream ios = ImageIO.createImageOutputStream(new FileOutputStream(writeFile))) {
    writer.setOutput(ios);
    writer.write(null, new IIOImage(renderedImage, null, null), params);
    ios.close();
  } catch (IOException e) {
    // Tools.log("ScalablePicture.writeJpg caught IOException: " + e.getMessage() + "\nwhile writing " +
    // writeFile.toString());
    e.printStackTrace();
  }
  // writer = null;
  writer.dispose(); // 1.4.1 documentation says to do this.
}
 
Example 2
Source File: ImageUtil.java    From openstego with GNU General Public License v2.0 6 votes vote down vote up
private static void writeJpegImage(ImageHolder image, OutputStream os) throws OpenStegoException {
    try {
        JPEGImageWriteParam jpegParams = new JPEGImageWriteParam(null);
        jpegParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        jpegParams.setOptimizeHuffmanTables(true);
        Float qual = UserPreferences.getFloat("image.writer.jpeg.quality");
        if (qual == null) {
            qual = 0.75f;
        }
        jpegParams.setCompressionQuality(qual);

        ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next();
        writer.setOutput(ImageIO.createImageOutputStream(os));
        writer.write(null, new IIOImage(image.getImage(), null, image.getMetadata()), jpegParams);
    } catch (IOException e) {
        throw new OpenStegoException(e);
    }
}
 
Example 3
Source File: ImageIOJPEGImageWriter.java    From victor with Apache License 2.0 6 votes vote down vote up
/** {@inheritDoc} */
@Override
protected ImageWriteParam getDefaultWriteParam(
        ImageWriter iiowriter, RenderedImage image,
        ImageWriterParams params) {
    JPEGImageWriteParam param = new JPEGImageWriteParam(iiowriter.getLocale());
    param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
    param.setCompressionQuality(params.getJPEGQuality());
    if (params.getCompressionMethod() != null
            && !"JPEG".equals(params.getCompressionMethod())) {
        throw new IllegalArgumentException(
                "No compression method other than JPEG is supported for JPEG output!");
    }
    if (params.getJPEGForceBaseline()) {
        param.setProgressiveMode(JPEGImageWriteParam.MODE_DISABLED);
    }
    return param;
}
 
Example 4
Source File: JmeDesktopSystem.java    From jmonkeyengine with BSD 3-Clause "New" or "Revised" License 6 votes vote down vote up
@Override
public void writeImageFile(OutputStream outStream, String format, ByteBuffer imageData, int width, int height) throws IOException {
    BufferedImage awtImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_BGR);
    Screenshots.convertScreenShot2(imageData.asIntBuffer(), awtImage);

    ImageWriter writer = ImageIO.getImageWritersByFormatName(format).next();
    ImageWriteParam writeParam = writer.getDefaultWriteParam();

    if (format.equals("jpg")) {
        JPEGImageWriteParam jpegParam = (JPEGImageWriteParam) writeParam;
        jpegParam.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
        jpegParam.setCompressionQuality(0.95f);
    }

    awtImage = verticalFlip(awtImage);
    
    ImageOutputStream imgOut = new MemoryCacheImageOutputStream(outStream);
    writer.setOutput(imgOut);
    IIOImage outputImage = new IIOImage(awtImage, null, null);
    try {
        writer.write(null, outputImage, writeParam);
    } finally {
        imgOut.close();
        writer.dispose();
    }
}
 
Example 5
Source File: ChartPanel.java    From MeteoInfo with GNU Lesser General Public License v3.0 5 votes vote down vote up
public boolean saveImage_Jpeg(String file, int width, int height, int dpi) {
    double scaleFactor = dpi / 72.0;
    BufferedImage bufferedImage = new BufferedImage((int)(width * scaleFactor), (int)(height * scaleFactor), BufferedImage.TYPE_INT_RGB);
    Graphics2D g = bufferedImage.createGraphics();
    AffineTransform at = g.getTransform();
    at.scale(scaleFactor, scaleFactor);
    g.setTransform(at);
    paintGraphics(g, width, height);

    try {
        // Image writer 
        ImageWriter imageWriter = ImageIO.getImageWritersBySuffix("jpeg").next();
        ImageOutputStream ios = ImageIO.createImageOutputStream(new File(file));
        imageWriter.setOutput(ios);

        // Compression
        JPEGImageWriteParam jpegParams = (JPEGImageWriteParam) imageWriter.getDefaultWriteParam();
        jpegParams.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT);
        jpegParams.setCompressionQuality(0.85f);

        // Metadata (dpi)
        IIOMetadata data = imageWriter.getDefaultImageMetadata(new ImageTypeSpecifier(bufferedImage), jpegParams);
        Element tree = (Element) data.getAsTree("javax_imageio_jpeg_image_1.0");
        Element jfif = (Element) tree.getElementsByTagName("app0JFIF").item(0);
        jfif.setAttribute("Xdensity", Integer.toString(dpi));
        jfif.setAttribute("Ydensity", Integer.toString(dpi));
        jfif.setAttribute("resUnits", "1"); // density is dots per inch	
        data.setFromTree("javax_imageio_jpeg_image_1.0", tree);

        // Write and clean up
        imageWriter.write(null, new IIOImage(bufferedImage, null, data), jpegParams);
        ios.close();
        imageWriter.dispose();
    } catch (Exception e) {
        return false;
    }
    g.dispose();

    return true;
}
 
Example 6
Source File: MapLayout.java    From MeteoInfo with GNU Lesser General Public License v3.0 5 votes vote down vote up
private boolean saveImage_Jpeg(String file, int width, int height, int dpi) {
    double scaleFactor = dpi / 72.0;
    BufferedImage bufferedImage = new BufferedImage((int)(width * scaleFactor), (int)(height * scaleFactor), BufferedImage.TYPE_INT_RGB);
    Graphics2D g = bufferedImage.createGraphics();
    AffineTransform at = g.getTransform();
    at.scale(scaleFactor, scaleFactor);
    g.setTransform(at);
    paintGraphics(g);

    try {
        // Image writer 
        ImageWriter imageWriter = ImageIO.getImageWritersBySuffix("jpeg").next();
        ImageOutputStream ios = ImageIO.createImageOutputStream(new File(file));
        imageWriter.setOutput(ios);

        // Compression
        JPEGImageWriteParam jpegParams = (JPEGImageWriteParam) imageWriter.getDefaultWriteParam();
        jpegParams.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT);
        jpegParams.setCompressionQuality(0.85f);

        // Metadata (dpi)
        IIOMetadata data = imageWriter.getDefaultImageMetadata(new ImageTypeSpecifier(bufferedImage), jpegParams);
        Element tree = (Element) data.getAsTree("javax_imageio_jpeg_image_1.0");
        Element jfif = (Element) tree.getElementsByTagName("app0JFIF").item(0);
        jfif.setAttribute("Xdensity", Integer.toString(dpi));
        jfif.setAttribute("Ydensity", Integer.toString(dpi));
        jfif.setAttribute("resUnits", "1"); // density is dots per inch	
        data.setFromTree("javax_imageio_jpeg_image_1.0", tree);

        // Write and clean up
        imageWriter.write(null, new IIOImage(bufferedImage, null, data), jpegParams);
        ios.close();
        imageWriter.dispose();
    } catch (Exception e) {
        return false;
    }
    g.dispose();

    return true;
}
 
Example 7
Source File: JPEGFilter.java    From GIFKR with GNU Lesser General Public License v3.0 5 votes vote down vote up
@Override
public BufferedImage apply(BufferedImage img) {

	if(compressionLevel == 0f)
		return img;
	
	try {
		ImageWriter iw = ImageIO.getImageWritersByFormatName("jpeg").next();
		JPEGImageWriteParam iwp = (JPEGImageWriteParam) iw.getDefaultWriteParam();
		iwp.setOptimizeHuffmanTables(false);
		iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
		iwp.setProgressiveMode(ImageWriteParam.MODE_DISABLED);
		iwp.setCompressionQuality(1f-compressionLevel);


		ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
		iw.setOutput(new MemoryCacheImageOutputStream(baos)); 

		IIOImage outputImage = new IIOImage(img, null, null);
		iw.write(null, outputImage, iwp);
		iw.dispose();
		
		baos.flush(); 
		byte[] returnImage = baos.toByteArray(); 
		baos.close();
		
		
		BufferedImage img2 = ImageIO.read(new ByteArrayInputStream(returnImage));
		
		if(img2 == null)
			throw new Exception();
		else
			img = img2;

	} catch (Exception e) {
		e.printStackTrace();
	}

	return img;
}
 
Example 8
Source File: DefaultDrawerImageUtils.java    From dss with GNU Lesser General Public License v2.1 5 votes vote down vote up
private static ImageAndResolution convertToInputStreamJPG(BufferedImage buffImage, int dpi) throws IOException {
	ImageWriter writer = getImageWriter("jpeg");

	JPEGImageWriteParam jpegParams = (JPEGImageWriteParam) writer.getDefaultWriteParam();
	jpegParams.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
	jpegParams.setCompressionQuality(1);

	ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
	IIOMetadata metadata = writer.getDefaultImageMetadata(typeSpecifier, jpegParams);

	initDpiJPG(metadata, dpi);

	return getImageAndResolution(buffImage, dpi, writer, jpegParams, metadata);
}
 
Example 9
Source File: AbstractJaiTest.java    From java-image-processing-survival-guide with Apache License 2.0 5 votes vote down vote up
@Override
public void writeBufferedImage(BufferedImage bufferedImage, float quality, int dpi, String formatName, File targetFile) throws Exception {

    if (formatName.equalsIgnoreCase("jpg") || formatName.equalsIgnoreCase("jpeg")) {
        JPEGImageWriter imageWriter = (JPEGImageWriter) ImageIO.getImageWritersBySuffix(formatName).next();
        ImageWriteParam writeParam = imageWriter.getDefaultWriteParam();
        ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
        IIOMetadata metadata = imageWriter.getDefaultImageMetadata(typeSpecifier, writeParam);

        if (formatName.equalsIgnoreCase("jpg") || formatName.equalsIgnoreCase("jpeg")) {

            Element tree = (Element) metadata.getAsTree("javax_imageio_jpeg_image_1.0");
            Element jfif = (Element) tree.getElementsByTagName("app0JFIF").item(0);
            jfif.setAttribute("Xdensity", Integer.toString(dpi));
            jfif.setAttribute("Ydensity", Integer.toString(dpi));
            jfif.setAttribute("resUnits", "1");
            metadata.setFromTree("javax_imageio_jpeg_image_1.0", tree);
        }

        if (quality >= 0 && quality <= 1f) {

            JPEGImageWriteParam jpegParams = (JPEGImageWriteParam) imageWriter.getDefaultWriteParam();
            jpegParams.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT);
            jpegParams.setCompressionQuality(quality);

        }

        FileOutputStream os = new FileOutputStream(targetFile);
        final ImageOutputStream stream = ImageIO.createImageOutputStream(os);

        try {
            imageWriter.setOutput(stream);
            imageWriter.write(metadata, new IIOImage(bufferedImage, null, metadata), writeParam);
        } finally {
            stream.close();
        }
    } else {
        writeBufferedImage(bufferedImage, formatName, targetFile);
    }
}
 
Example 10
Source File: BaseImageIoTest.java    From java-image-processing-survival-guide with Apache License 2.0 5 votes vote down vote up
@Override
public void writeBufferedImage(BufferedImage bufferedImage, float quality, int dpi, String formatName, File targetFile) throws Exception {

    System.out.println("Saving " + targetFile.getPath());

    if (formatName.equalsIgnoreCase("jpg") || formatName.equalsIgnoreCase("jpeg")) {
        JPEGImageWriter imageWriter = (JPEGImageWriter) ImageIO.getImageWritersBySuffix(formatName).next();
        ImageWriteParam writeParam = imageWriter.getDefaultWriteParam();
        ImageTypeSpecifier typeSpecifier = ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_INT_RGB);
        IIOMetadata metadata = imageWriter.getDefaultImageMetadata(typeSpecifier, writeParam);

        if (formatName.equalsIgnoreCase("jpg") || formatName.equalsIgnoreCase("jpeg")) {
            Element tree = (Element) metadata.getAsTree("javax_imageio_jpeg_image_1.0");
            Element jfif = (Element) tree.getElementsByTagName("app0JFIF").item(0);
            jfif.setAttribute("Xdensity", Integer.toString(dpi));
            jfif.setAttribute("Ydensity", Integer.toString(dpi));
            jfif.setAttribute("resUnits", "1");
            metadata.setFromTree("javax_imageio_jpeg_image_1.0", tree);
        }

        if (quality >= 0 && quality <= 1f) {
            JPEGImageWriteParam jpegParams = (JPEGImageWriteParam) imageWriter.getDefaultWriteParam();
            jpegParams.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT);
            jpegParams.setCompressionQuality(quality);
        }

        FileOutputStream os = new FileOutputStream(targetFile);
        final ImageOutputStream stream = ImageIO.createImageOutputStream(os);

        try {
            imageWriter.setOutput(stream);
            imageWriter.write(metadata, new IIOImage(bufferedImage, null, metadata), writeParam);
        } finally {
            stream.close();
        }
    } else {
        writeBufferedImage(bufferedImage, formatName, targetFile);
    }
}
 
Example 11
Source File: JpegImageWriter.java    From sejda with GNU Affero General Public License v3.0 5 votes vote down vote up
@Override
ImageWriteParam newImageWriterParams(PdfToJpegParameters params) {
    JPEGImageWriteParam param = new JPEGImageWriteParam(writer.getLocale());
    param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
    param.setCompressionQuality((float) params.getQuality() / 100);
    return param;
}
 
Example 12
Source File: ToolImageResize.java    From protools with Apache License 2.0 4 votes vote down vote up
/**
 * 缩放gif图片
 *
 * @param originalFile
 *         原图片
 * @param resizedFile
 *         缩放后的图片
 * @param newWidth
 *         宽度
 * @param quality
 *         缩放比例 (等比例)
 *
 * @throws IOException
 */
private static void resize(File originalFile, File resizedFile, int newWidth, float quality) throws IOException {
    if (quality < 0 || quality > 1) {
        throw new IllegalArgumentException("Quality has to be between 0 and 1");
    }
    ImageIcon ii = new ImageIcon(originalFile.getCanonicalPath());

    Image i = ii.getImage();
    Image resizedImage = null;
    int iWidth = i.getWidth(null);
    int iHeight = i.getHeight(null);
    if (iWidth > iHeight) {
        resizedImage = i.getScaledInstance(newWidth, (newWidth * iHeight) / iWidth, Image.SCALE_SMOOTH);
    } else {
        resizedImage = i.getScaledInstance((newWidth * iWidth) / iHeight, newWidth, Image.SCALE_SMOOTH);
    }
    // This code ensures that all the pixels in the image are loaded.
    Image temp = new ImageIcon(resizedImage).getImage();
    // Create the buffered image.
    BufferedImage bufferedImage = new BufferedImage(temp.getWidth(null), temp.getHeight(null), BufferedImage.TYPE_INT_RGB);
    // Copy image to buffered image.
    Graphics g = bufferedImage.createGraphics();
    // Clear background and paint the image.
    g.setColor(Color.white);
    g.fillRect(0, 0, temp.getWidth(null), temp.getHeight(null));
    g.drawImage(temp, 0, 0, null);
    g.dispose();
    // Soften.
    float softenFactor = 0.05f;
    float[] softenArray = {0, softenFactor, 0, softenFactor, 1 - (softenFactor * 4), softenFactor, 0, softenFactor, 0};
    Kernel kernel = new Kernel(3, 3, softenArray);
    ConvolveOp cOp = new ConvolveOp(kernel, ConvolveOp.EDGE_NO_OP, null);
    bufferedImage = cOp.filter(bufferedImage, null);
    // Write the jpeg to a file.
    try (
            FileOutputStream out = new FileOutputStream(resizedFile)) {

        ImageWriter imageWriter = ImageIO.getImageWritersBySuffix("jpg").next();
        ImageOutputStream ios = ImageIO.createImageOutputStream(out);
        imageWriter.setOutput(ios);
        //and metadata
        IIOMetadata imageMetaData = imageWriter.getDefaultImageMetadata(new ImageTypeSpecifier(bufferedImage), null);

        JPEGImageWriteParam jpegParams = (JPEGImageWriteParam) imageWriter.getDefaultWriteParam();
        jpegParams.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT);
        jpegParams.setCompressionQuality(quality);
        imageWriter.write(imageMetaData, new IIOImage(bufferedImage, null, null), jpegParams);
    }
}
 
Example 13
Source File: JPEGFactory.java    From gcs with Mozilla Public License 2.0 4 votes vote down vote up
private static void encodeImageToJPEGStream(BufferedImage image, float quality, int dpi,
                                            OutputStream out) throws IOException
{
    // encode to JPEG
    ImageOutputStream ios = null;
    ImageWriter imageWriter = null;
    try
    {
        // find JAI writer
        imageWriter = getJPEGImageWriter();
        ios = ImageIO.createImageOutputStream(out);
        imageWriter.setOutput(ios);

        // add compression
        JPEGImageWriteParam jpegParam = (JPEGImageWriteParam)imageWriter.getDefaultWriteParam();
        jpegParam.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT);
        jpegParam.setCompressionQuality(quality);

        // add metadata
        ImageTypeSpecifier imageTypeSpecifier = new ImageTypeSpecifier(image);
        IIOMetadata data = imageWriter.getDefaultImageMetadata(imageTypeSpecifier, jpegParam);
        Element tree = (Element)data.getAsTree("javax_imageio_jpeg_image_1.0");
        Element jfif = (Element)tree.getElementsByTagName("app0JFIF").item(0);
        jfif.setAttribute("Xdensity", Integer.toString(dpi));
        jfif.setAttribute("Ydensity", Integer.toString(dpi));
        jfif.setAttribute("resUnits", "1"); // 1 = dots/inch

        // write
        imageWriter.write(data, new IIOImage(image, null, null), jpegParam);
    }
    finally
    {
        // clean up
        IOUtils.closeQuietly(out);
        if (ios != null)
        {
            ios.close();
        }
        if (imageWriter != null)
        {
            imageWriter.dispose();
        }
    }
}
 
Example 14
Source File: ImageShrinker.java    From triplea with GNU General Public License v3.0 4 votes vote down vote up
private void runInternal(final String[] args) throws IOException {
  handleCommandLineArgs(args);
  JOptionPane.showMessageDialog(
      null,
      new JLabel(
          "<html>"
              + "This is the ImageShrinker, it will create a smallMap.jpeg file for you. "
              + "<br>Put in your base map or relief map, and it will spit out a small "
              + "scaled copy of it."
              + "<br>Please note that the quality of the image will be worse than if you use a "
              + "real painting program."
              + "<br>So we suggest you instead shrink the image with paint.net or photoshop or "
              + "gimp, etc, then clean it up before saving."
              + "</html>"));
  final File mapFile =
      new FileOpen("Select The Large Image", mapFolderLocation, ".gif", ".png").getFile();
  if (mapFile == null || !mapFile.exists()) {
    throw new IllegalStateException(mapFile + "File does not exist");
  }
  if (mapFolderLocation == null) {
    mapFolderLocation = mapFile.getParentFile();
  }
  final String input = JOptionPane.showInputDialog(null, "Select scale");
  final float scale = Float.parseFloat(input);
  final Image baseImg = ImageIO.read(mapFile);
  final int thumbWidth = (int) (baseImg.getWidth(null) * scale);
  final int thumbHeight = (int) (baseImg.getHeight(null) * scale);
  // based on code from
  // http://www.geocities.com/marcoschmidt.geo/java-save-jpeg-thumbnail.html
  // draw original image to thumbnail image object and scale it to the new size on-the-fly
  final BufferedImage thumbImage =
      new BufferedImage(thumbWidth, thumbHeight, BufferedImage.TYPE_INT_RGB);
  final Graphics2D graphics2D = thumbImage.createGraphics();
  graphics2D.setRenderingHint(
      RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
  graphics2D.drawImage(baseImg, 0, 0, thumbWidth, thumbHeight, null);
  // save thumbnail image to OUTFILE
  final File file =
      new File(new File(mapFile.getPath()).getParent() + File.separatorChar + "smallMap.jpeg");
  try (ImageOutputStream out = new FileImageOutputStream(file)) {
    final ImageWriter encoder = ImageIO.getImageWritersByFormatName("JPEG").next();
    final JPEGImageWriteParam param = new JPEGImageWriteParam(null);
    param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
    param.setCompressionQuality((float) 1.0);
    encoder.setOutput(out);
    encoder.write(null, new IIOImage(thumbImage, null, null), param);
  }
  log.info("Image successfully written to " + file.getPath());
}
 
Example 15
Source File: ImageOptimizer.java    From sejda with GNU Affero General Public License v3.0 4 votes vote down vote up
/**
 * Takes an image and creates an optimized version of it.
 *
 * If the image is larger than maxWidthOrHeight pixels, it is downsized to fit the maxWidthOrHeight rectangle (keeping its aspect ratio). Image is saved as JPEG with specified
 * quality (1.0 is best/leave unchanged, 0.0 is worst). Image DPI is changed to dpi specified.
 */
public static File optimize(BufferedImage bufferedImage, float quality, int dpi, int width, int height,
        boolean gray) throws IOException {
    long start = System.currentTimeMillis();
    File outputFile = File.createTempFile("pdfimage", ".jpeg");
    outputFile.deleteOnExit();

    try {
        int relevantDelta = 20;
        boolean isResizeRelevant = Math.abs(bufferedImage.getWidth() - width) > relevantDelta
                && Math.abs(bufferedImage.getHeight() - height) > relevantDelta;
        boolean isShirinking = bufferedImage.getHeight() > height || bufferedImage.getWidth() > width;

        if (isResizeRelevant && isShirinking) {
            // we resize down, we don't resize up
            LOG.debug("Resizing image from {}x{} to {}x{}", bufferedImage.getWidth(), bufferedImage.getHeight(),
                    width, height);
            bufferedImage = Scalr.resize(bufferedImage, Scalr.Method.BALANCED, width, height);
        }

        // PNG read fix when converting to JPEG
        BufferedImage newImage = new BufferedImage(bufferedImage.getWidth(), bufferedImage.getHeight(),
                gray ? BufferedImage.TYPE_BYTE_GRAY : BufferedImage.TYPE_INT_RGB);

        Graphics2D g2d = newImage.createGraphics();
        g2d.drawImage(bufferedImage, 0, 0, Color.WHITE, null);
        g2d.dispose();

        ImageWriter imageWriter = ImageIO.getImageWritersBySuffix("jpeg").next();
        ImageOutputStream ios = ImageIO.createImageOutputStream(outputFile);
        imageWriter.setOutput(ios);

        // compression
        JPEGImageWriteParam jpegParams = (JPEGImageWriteParam) imageWriter.getDefaultWriteParam();
        jpegParams.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT);
        jpegParams.setCompressionQuality(quality);

        IIOMetadata imageMetaData = null;
        try {
            // new metadata
            imageMetaData = imageWriter.getDefaultImageMetadata(new ImageTypeSpecifier(newImage), jpegParams);
            Element tree = (Element) imageMetaData.getAsTree("javax_imageio_jpeg_image_1.0");
            Element jfif = (Element) tree.getElementsByTagName("app0JFIF").item(0);
            jfif.setAttribute("Xdensity", Integer.toString(dpi));
            jfif.setAttribute("Ydensity", Integer.toString(dpi));
            jfif.setAttribute("resUnits", "1");
            imageMetaData.setFromTree("javax_imageio_jpeg_image_1.0", tree);
        } catch (Exception e) {
            LOG.warn("Failed to set DPI for image, metadata manipulation failed", e);
        }

        try {
            imageWriter.write(null, new IIOImage(newImage, null, imageMetaData), jpegParams);
        } finally {
            IOUtils.closeQuietly(ios);
            imageWriter.dispose();
        }

        return outputFile;
    } finally {
        bufferedImage.flush();
        long elapsed = System.currentTimeMillis() - start;
        if (elapsed > 500)
            LOG.trace("Optimizing image took " + elapsed + "ms");
    }
}