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.

Java images – 5 tips for Java ImageIO image performance

48 sec read

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?



Our software libraries allow you to

Convert PDF files to HTML
Use PDF Forms in a web browser
Convert PDF Documents to an image
Work with PDF Documents in Java
Read and write HEIC and other Image formats in Java
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.

What is JPEG XL?

Amy Pearson
1 min read

Should you travel by plane or train?

Why travel to Switzerland by train This year, my daughter set me the challenge to take the train rather than fly when I next...
Mark Stephens
1 min read

7 Replies to “Java images – 5 tips for Java ImageIO image…”

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

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

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

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

Comments are closed.