0

I recently discovered that the ImageIO library I was using was writing images to byte arrays/streams incredibly slowly and switched from

BufferedImage img;//initialized elsewhere
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img,"png",baos);

to

BufferedImage img;//initialized elsewhere
byte[] argb = ((DataBufferByte) img.getRaster().getDataBuffer()).getData();

While this second method is almost 70 times faster, I cannot find a quick way to recreate a BufferedImage from this argb byte array.

codersarepeople
  • 1,971
  • 3
  • 20
  • 25
  • i take it reading it back similar to your old impl is not an option? – radai Sep 19 '13 at 04:21
  • 1
    previously I used ImageIO.read to read it back, but that depends on the byte stream having been encoded with ImageIO.write. The byte array in the second code example is simply a dump of all the pixel values, not an encoded bytestream. – codersarepeople Sep 19 '13 at 04:32
  • wouldnt that make it simply a BMP then? that should make it possible to do something like this - http://stackoverflow.com/questions/4234703/how-to-create-a-bufferedimage-from-raw-data or maybe this - http://stackoverflow.com/questions/6319465/fast-loading-and-drawing-of-rgb-data-in-bufferedimage – radai Sep 19 '13 at 04:40
  • It seems a common problem that the standard Java ImageIO PNG writer is slow. Try googling for "fast png decoder java", and you'll find a few replacements, like objectplanet, fastpng and sixlegs. Have you tried writing another format (like BMP)?. In any case, you can recreate your image from the raw pixels (there's tons of questions about it on SO already), but you need to know things like color model, width, height etc, that are normally stored in the file format's header. – Harald K Sep 19 '13 at 07:44
  • PS: Just want to point out that the code in the second array is not a dump of the pixels, it *is the pixels*. The code is insanely fast, because it's just a single assignment. You can create a new image from these pixels, but if you do so without copying (which takes a bit more time), changes to one image will be reflected in the other. – Harald K Sep 20 '13 at 19:49
  • Well I will need to copy these eventually, as I am sending them across a network. My question is how to create a new BufferedImage object given a copy of that byte array. – codersarepeople Sep 21 '13 at 00:18
  • Do you know for sure that your images are a) always using databuffer byte b) have the same color model c) have the same dimensions? Otherwise you will need this information as well. And you end up creating your own proprietary image format. – Harald K Sep 22 '13 at 07:59
  • Yes I can be assured that they will always be the same. – codersarepeople Sep 22 '13 at 21:22

1 Answers1

0

Well, I'm not going to say that passing raw pixels around is generally a good idea, but it might fit this particular use case.

Based on the discussion in the comments, it should be as hard as:

DataBuffer buffer = new DataBufferByte(argb, argb.length); // arg is your input array
ColorModel cm = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), new int[]{8, 8, 8, 8}, true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);

return new BufferedImage(cm, Raster.createInterleavedRaster(buffer, width, height, width * 4, 4, new int[] {0, 1, 2, 3}, null), false, null);

All assuming you really have ARGB pixels in the argb array, and that width and heightis known. Make all arrays and the color model constant for better performance.

Harald K
  • 26,314
  • 7
  • 65
  • 111