Mark Stephens

Mark Stephens has been working with Java and PDF since 1999 and has diversified into HTML5, SVG and JavaFX.

He also enjoys speaking at conferences and has been a Speaker at user groups, Business of Software, Seybold and JavaOne conferences. He has a very dry sense of humor and an MA in Medieval History for which he has not yet found a practical use.

Replacing the deprecated Java JPEG classes for Java 7

1 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.

I have been checking our code against the new Java 7 (release 4) build for the Mac and it now appears that the old JPEG classes have finally been removed. So I have updated my code to use ImageIO. Here is my updated version with both 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();
 
}

Otherwise, Java 7 looks to be a definite progression over Java 6. What do you think of it?

Mark Stephens

Mark Stephens has been working with Java and PDF since 1999 and has diversified into HTML5, SVG and JavaFX.

He also enjoys speaking at conferences and has been a Speaker at user groups, Business of Software, Seybold and JavaOne conferences. He has a very dry sense of humor and an MA in Medieval History for which he has not yet found a practical use.

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 *