Java images – 5 tips for Java ImageIO image performance

We have been doing a lot of work recently on images in Java and will be writing a series of articles on JPEG2000 support, access, bugs and other issues. First off, I want to take a look at performance.

When you are generating a PDF image a lot of time is spent in ImageIO, either decoding the DCTDecode image (which is a JPEG) and writing out the final image as a PNG. Here is what I have found out for trying to speed this up.

1. Doing the conversion in memory does not speed things up.

2. Using a BufferedOutputStream for ImageIO.write images seems to have a marginal improvement on some systems.

3. The ImageIO.write is optimised for Indexed Colorspaces so it is often quicker to convert the image to an Index Colorspace and then write it out. Here is some sample code.

BufferedImage indexedImage = new BufferedImage(image.getWidth(),
image.getHeight(), BufferedImage.TYPE_BYTE_INDEXED);
Graphics2D g = indexedImage.createGraphics();
g.drawImage(image, 0,0,null);
image=indexedImage;

4. JAI JPEG decoding seems to be much slower than ImageIO (certainly on my Mac).

5. ImageIO.setUseCache(true) is slower

Comparing the performance we get in Java compared to non-Java solutions also seems to be disappointing at the moment. So I hope it will be something Sun looks at for Java 8.

Do you have any tips for improving Java ImageIO performance?

Related Posts:

The following two tabs change content below.

Mark Stephens

System Architect and Lead Developer at IDRSolutions
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.
Markee174

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

7 thoughts on “Java images – 5 tips for Java ImageIO image performance

  1. Foo

    Read “Filthy Rich Clients” by Romain Guy and Chet Haase. It contains tons of tips for extracting every bit of performance out of Java Imaging.

  2. Nuno Ferreira

    Hi Mark,

    I believe you are the expert that i´m looking to try solving my problem. This problem relies on putting a CMYK image inside a PDF.
    This i´ve already done but only putting TIFF images (with a lot of space, +- 7 mb), but i want to put JPEG but i cant because i´m using ImageIO.write() and it seems this is the problem. Do you have any idea how can i convert a JPEG (RGB) to a JPEG (CMYK) without putting the image to almost black color?

    I´m sorry to put this on your blog but i´m desperate and nothing on the web can help me.

    Cheers,

    Nuno

    • Java does not understand CMYK so you need to manipulate it at the raster level which is messy. You might be better off using native code (ImageMagic of JPGLib). Have you looked at what features IText offers for substitution?

      • Nuno

        Hi Mark,

        Thanks for your acknowledge on this. I don´t know what you mention in ” Have you looked at what features IText offers for substitution?”, i´ve tried many things the best result at this moment is this code:


        TestCreatedPDFWithImage test = new TestCreatedPDFWithImage();
        Image image1 = Image.getInstance(test.convertImage());
        document.add(image1);
        document.close();

        public byte[] convertImage() throws IOException {
        BufferedImage rgbImage = ImageIO.read(new File("d:\\Temp\\IMG_1748x2480.jpg"));
        BufferedImage cmykImage = null;

        ColorSpace cpace = new ICC_ColorSpace(ICC_Profile.getInstance( TestConvertRGBToCMYK.class.getClassLoader().getResourceAsStream("CMYK_Profiles/ISOcoated_v2_300_eci.icc")));
        TestConvertRGBToCMYK.class.getClassLoader().getResourceAsStream("CMYK_Profiles/ISOcoated_v2_eci.icc")));

        ColorConvertOp op = new ColorConvertOp(rgbImage.getColorModel().getColorSpace(), cpace, null);
        cmykImage = op.filter(rgbImage, null);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        ImageIO.write( cmykImage, "TIFF", out);
        byte[] rawData = out.toByteArray();
        return rawData;
        }

        Other tests that i´ve made the picture appears like in your other blog message in YCCK (almost black).
        So if this is the only use that i made with the iText, i think my answer to you is no, i don´t try the iText substitutions, can you point me the right direction or show me some piece of code?

        Cheers

  3. You should probably experiment with working on Raster rather than BufferedImage.

  4. Yeah, imageio is painfully slow. I’m stuck with Java 6 now that oracle has dropped the com.sun.image.codec.jpeg classes becaus imageio is an order of magnitude slower: imageio takes 4 seconds to load a 4000×3000 jpeg, whereas the deprecated classes take 400ms.
    I’m not at all against dropping old code, but oracle should make sure there is a viable alternative before they do so.

  5. It is quite sad looking thorough the ImageIO code because there were alsorts of cool notes on things like tiling to add which never happened. Any Java’s image handling is not as good as other platforms.

Leave a Reply

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

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>