Mark Stephens Mark has been working with Java and PDF since 1999 and is a big NetBeans fan. He enjoys speaking at conferences. He has an MA in Medieval History and a passion for reading.

Replacing the deprecated Java JPEG classes for Java 7

2 min read

In the early days of Java, Sun produced a really handy set of classes to handle JPEG images. These included some really nifty little features like the ability to easily set the amount of compression and the resolution. When ImageIO came along, the class was deprecated. This means that it is still in Java but not guaranteed to be in any later releases. ImageIO was more complicated to use for JPEG images and we felt the earlier code produced better results so we continued to use it.

How do I update my old code?

The old JPEG classes have now been removed and will no longer compile. Here is the old and new versions so you can see the changes if you are still using these classes.

public static void saveAsJPEG(String jpgFlag,BufferedImage image_to_save, float JPEGcompression, FileOutputStream fos) throws IOException {
 
    //useful documentation at http://docs.oracle.com/javase/7/docs/api/javax/imageio/metadata/doc-files/jpeg_metadata.html
    //useful example program at http://johnbokma.com/java/obtaining-image-metadata.html to output JPEG data
 
    //old jpeg class
    //com.sun.image.codec.jpeg.JPEGImageEncoder jpegEncoder = com.sun.image.codec.jpeg.JPEGCodec.createJPEGEncoder(fos);
    //com.sun.image.codec.jpeg.JPEGEncodeParam jpegEncodeParam = jpegEncoder.getDefaultJPEGEncodeParam(image_to_save);
 
    // Image writer
    JPEGImageWriter imageWriter = (JPEGImageWriter) ImageIO.getImageWritersBySuffix(“jpeg”).next();
    ImageOutputStream ios = ImageIO.createImageOutputStream(fos);
    imageWriter.setOutput(ios);
 
    //and metadata
    IIOMetadata imageMetaData = imageWriter.getDefaultImageMetadata(new ImageTypeSpecifier(image_to_save), null);
 
    if (jpgFlag != null){
 
        int dpi = 96;
 
        try {
            dpi = Integer.parseInt(jpgFlag);
        } catch (Exception e) {
            e.printStackTrace();
        }
 
        //old metadata
        //jpegEncodeParam.setDensityUnit(com.sun.image.codec.jpeg.JPEGEncodeParam.DENSITY_UNIT_DOTS_INCH);
        //jpegEncodeParam.setXDensity(dpi);
        //jpegEncodeParam.setYDensity(dpi);
 
        //new metadata
        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));
 
    }
 
    if(JPEGcompression>=0 && JPEGcompression<=1f){
 
        //old compression
        //jpegEncodeParam.setQuality(JPEGcompression,false);
 
        // new Compression
        JPEGImageWriteParam jpegParams = (JPEGImageWriteParam) imageWriter.getDefaultWriteParam();
        jpegParams.setCompressionMode(JPEGImageWriteParam.MODE_EXPLICIT);
        jpegParams.setCompressionQuality(JPEGcompression);
 
    }
 
    //old write and clean
    //jpegEncoder.encode(image_to_save, jpegEncodeParam);
 
    //new Write and clean up
    imageWriter.write(imageMetaData, new IIOImage(image_to_save, null, null), null);
    ios.close();
    imageWriter.dispose();
 
}

Are there any other alternatives?

We were not happy with ImageIO’s JPEG performance, so we developed our own solution called JDeli. You can find out how to read and write JPEG images in Java with JDeli and other libraries in these articles

Why use JDeli to read and write JPEG images in Java?

JDeli offers a range of advantages over ImageIO and alternatives, including:

  • prevent heap related JVM crashes
  • support for additional image formats such as Heic
  • reduce output file size
  • improve read/write performance
  • create smaller files
  • control over output
  • support threading
  • superior image scaling algorithms



Mark Stephens Mark has been working with Java and PDF since 1999 and is a big NetBeans fan. He enjoys speaking at conferences. He has an MA in Medieval History and a passion for reading.

11 Replies to “Replacing the deprecated Java JPEG classes for Java 7”

  1. Thank you very much for this post. This was very helpful!

    There is an error in the line with
    “imageWriter.write(imageMetaData, new IIOImage(image_to_save, null, null), null);”

    At the last argument you must provide “jpegParams” or otherwise the
    compression quality will not be applied and all resulting images will have
    the same file size (in my case @ Java 7u76).

  2. Thanks a lot for your code!
    I used it to set dpi of a jpg image but i had to make some changes to make it work.
    You get metadata as tree and modify dpi values, but you need to set the modified tree as metadata after changes. So i had to add this line after setting Xdensity and Ydensity attributes:
    imageMetaData.setFromTree(“javax_imageio_jpeg_image_1.0”, tree);

    Then, i had to modify one of the last lines in this way:
    imageWriter.write(imageMetaData, new IIOImage(image_to_save, null, imageMetaData), jpegParams);

    1. Thanks a lot for your code!But DPI settings are not valid.
      JPEGImageWriter imageWriter = (JPEGImageWriter) ImageIO.getImageWritersBySuffix(“jpg”).next();
      ImageOutputStream ios = ImageIO.createImageOutputStream(fos);
      imageWriter.setOutput(ios);
      IIOMetadata imageMetaData = imageWriter.getDefaultImageMetadata(new ImageTypeSpecifier(image), null);
      Element tree = (Element) imageMetaData.getAsTree(“javax_imageio_jpeg_image_1.0”);
      Element jfif = (Element) tree.getElementsByTagName(“app0JFIF”).item(0);
      for (int i = 0; i < jfif.getAttributes().getLength(); i++) {
      Node attribute = jfif.getAttributes().item(i);
      System.out.println(attribute.getNodeName() + "="
      + attribute.getNodeValue());
      }
      jfif.setAttribute("Xdensity", Integer.toString(dpi));
      jfif.setAttribute("Ydensity", Integer.toString(dpi));
      imageMetaData.setFromTree("javax_imageio_jpeg_image_1.0", tree);

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

      //imageWriter.write(imageMetaData, new IIOImage(image, null, null), null);
      imageWriter.write(imageMetaData, new IIOImage(image, null, imageMetaData), jpegParams);
      ios.close();
      imageWriter.dispose();

      1. // This is OK!!!!
        //JPEGImageEncoder jpegEncoder = com.sun.image.codec.jpeg.JPEGCodec.createJPEGEncoder(fos);
        //JPEGEncodeParam jpegEncodeParam = jpegEncoder.getDefaultJPEGEncodeParam(image);
        //jpegEncodeParam.setDensityUnit(JPEGEncodeParam.DENSITY_UNIT_DOTS_INCH);
        //jpegEncodeParam.setXDensity(dpi);
        //jpegEncodeParam.setYDensity(dpi);
        //jpegEncoder.encode(image, jpegEncodeParam);

        // Invalid DPI settings! Why???
        JPEGImageWriter imageWriter = (JPEGImageWriter) ImageIO.getImageWritersBySuffix(“jpg”).next();
        ImageOutputStream ios = ImageIO.createImageOutputStream(fos);
        imageWriter.setOutput(ios);
        IIOMetadata imageMetaData = imageWriter.getDefaultImageMetadata(new ImageTypeSpecifier(image), null);
        Element tree = (Element) imageMetaData.getAsTree(“javax_imageio_jpeg_image_1.0”);
        Element jfif = (Element) tree.getElementsByTagName(“app0JFIF”).item(0);
        for (int i = 0; i < jfif.getAttributes().getLength(); i++) {
        Node attribute = jfif.getAttributes().item(i);
        System.out.println(attribute.getNodeName() + "="
        + attribute.getNodeValue());
        }
        jfif.setAttribute("Xdensity", Integer.toString(dpi));
        jfif.setAttribute("Ydensity", Integer.toString(dpi));
        imageMetaData.setFromTree("javax_imageio_jpeg_image_1.0", tree);

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

        //imageWriter.write(imageMetaData, new IIOImage(image, null, null), null);
        imageWriter.write(imageMetaData, new IIOImage(image, null, imageMetaData), jpegParams);
        ios.close();
        imageWriter.dispose();

  3. Thanks for the post. Very helpful. I tried the same in my application and the image is getting written. My only concern is, in my existing code I have a line – jpegEncoder.setJPEGEncodeParam(jpegEncodeParam);

    Will this too be handled by the current code or do I have to write any additional code for the same?

      1. Thanks Mark for your time.
        It will be great if a sample (like the current blog) can be shared for the JDeli library.

      2. Thanks Mark, I would also like to know if the code jpegEncoder.setJPEGEncodeParam(jpegEncodeParam);
        gets handled as per the ImageIO code given in the current blog as we currently wish to continue with ImageIO

Leave a Reply

Your email address will not be published. Required fields are marked *

IDRsolutions Ltd 2021. All rights reserved.