Converting BufferedImage Into byte[ ] or maybe even String!

Converting BufferedImage Into byte[ ] or maybe even String!

Profiling applications can be fun. For the last few days I’m working constantly on my final year project and one day I have decided to do quite a strange thing. As my application client (MIDP application) has to display a map and it makes heavy use of web services I have designed and implemented a web service which provides the map tiles for the mobile phone. To cut a long story short main performance bottelneck was to convert an image into byte array and send it over the network as a SOAP message. What my application server does is to cut large image 1024×1024 into small tiles 16×16 pixels and serve them as byte arrays (actually Base64 strings).
As the client is a mobile application all the processing of the image is done on the server side. The speed of such an implementation depends on 3 things, first we have to create the tile, download it and create the image from downloaded data. Guess what? The slowest part of the whole process was to create the tile on the server side!!!.
Just for testing, creating 64×64 matrix of tiles took about 28 fat long seconds on my 2.0 GHz dual core 2GB RAM laptop which of course is unacceptable.
Looking here and there I started profiling to find out where is the main bottelneck.
The main problem with this application is the MIDP, which does its job but unfortuntelly supports only PNG format. This limitation leads to another problem, ImageIO class writes PNG as slow as snails. I have created and profiled three methods to see the difference, in all of them I use same PNG image 1024×104 read before convertion into BufferedImage object, first method:


public byte[] testImageIO(){
try {
baos = new ByteArrayOutputStream();
ImageIO.write(image, "png", baos);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
return baos.toByteArray();
}

This method with mentioned image size (format .png) takes about 1800 ms to convert. Same method but with “jpeg” attribute inside write method of ImageIO takes about 550 ms (you can see the difference already). As mentioned above althought this cannot be used for my application as I get exception on the client side converting it back into image.
I was looking quite a long time on the internet before I’ve found the answer to my troubles.
Here you have thrid method which uses JPEGImageEncoder to do the converstion:


public byte[] testJPEGEncoder() {
try {
baos = new ByteArrayOutputStream();
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(baos);
encoder.encode(image);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch (ImageFormatException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
return baos.toByteArray();
}

Guess what!? It still works on my mobile side, it is called JPEGImageEncoder and does no harm to my bytes along the way, but as we are talking about performance here the result from Netbeans profiler is…….
Take a deep breath!
230 ms!
From 18000 ms to 230 ms! Never go back to ImageIO! 😉

5 responses on “Converting BufferedImage Into byte[ ] or maybe even String!

  1. Anonymous September 4, 2008 at 2:01 pm

    Hi, i have problems about jpeg encoding/decoding.
    i read jpeg data from xml tree by
    str1 = imgEl.getChild(“jpegdata”).getText();
    and then decode it by
    imgBytes = Base64.decode(str1);
    then i truncate the 4-byte jpeg header and build the bufferedimage by
    imgData = truncateHeader(imgBytes);
    ImageIO.read(new ByteArrayInputStream(imgData));
    then i obey your suggestion about using jpegimageencoder
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(baos);
    encoder.encode(image);
    imgBytes2 = baos.toByteArray();

    now; when i compare the first byte representation with the last one, i get no equalty and get different lengths.
    boolean bool1 = imgBytes.toString().equals(imgBytes2.toString());
    i was expecting to get equal byte arrays with this process..so what might be wrong here? any suggestions?

  2. ooblogger September 4, 2008 at 2:17 pm

    Man, you shot me with this one, as you can see from the date of the last post on my blog I have no time for anything and unfortunatelly no time to check your code and simply don’t know straight away what is happening! Why do you check the strings for equality, my purpose was to simply see the image on the mobile phone and I haven’t really care what’s going on under the hood more that I needed to, is the image data valid after the encoding/decoding?

  3. Anonymous September 5, 2008 at 10:06 pm

    hmm i think its done after i have written the image to disk, and then reading it back from the disk by BufferedInputStream, and finally writing to xml. One thing i m confused about the swf is, i can handle jpeg image now, but what if the images are in png,gif,tiff or bmp format?

  4. ooblogger September 6, 2008 at 7:01 pm

    not really sure, but as far as I remember while I was doing it, I was actually using png and jpeg encoder, and what I remember is that I loose quite a lot on quality (I think it was converted to jpeg), you would have to consult java doc to find you what is going on under the hood)

  5. Anonymous September 25, 2008 at 11:12 pm

    “The main problem with this application is the MIDP, which does its job but unfortuntelly supports only PNG format.”

    but JPEG encoder creates JPEG image, not PNG.

Leave a Reply