3

I'm looking to send over an Object that has a BufferedImage through a socket. BufferedImage is not serializable, so it needs to be converted to a serializable data type, and then back again. I have looked a lot online, and byte[] seems to be the go to send just a BuffereImage, but I'm trying to send an entire object so I'm leaning more towards int[]. I thought I ran across an answer that explained this on here a few weeks ago, but after 2.5 hours of searching I could not find it. I have tried the Java Oracle, but quickly got lost.

If there is a better way please excuse my ignorance, as I have not really worked a lot with sockets and BufferedImage manipulation.

Dak31
  • 82
  • 8
  • why are you not using `byte[]` – Ramanlfc Jun 14 '16 at 04:30
  • Because most of the instances I see it being used is sending just a buffeted image, not the entire object, through a socket... Unless I'm completely wrong – Dak31 Jun 14 '16 at 04:32
  • When you say "entire object", what extra fields do you mean? Obviously there's the image itself (an array of bytes), but do you mean Width and Height etc.? Palette? The problem comes when you try to use a multi-byte value between different platforms: sending `int`s over networks is messy... – John Burger Jun 14 '16 at 04:39
  • 3
    Use ImageIO for this, unless you are very, very certain you want to be sending raw image raster data across the wire. (you're not, based on your question =) https://docs.oracle.com/javase/7/docs/api/javax/imageio/ImageIO.html – BadZen Jun 14 '16 at 04:51
  • 4
    you could use the ImageIO class to convert the BufferedImage to a PNG image (lossless, supports transparency, has some lossless compression). You should be able to do this with a line or two of code. it will save the image dimensions etc as well, which a raw array wont do. This is what image formats such as PNG are for (storage and transmission of images). – slipperyseal Jun 14 '16 at 04:51
  • i think i was writing my response as BadZen was :) – slipperyseal Jun 14 '16 at 04:51
  • Thanks for the help, but I need to draw the image on a jComponent, and I don't think i can use g.drawImage for that, right? – Dak31 Jun 14 '16 at 04:57
  • 3
    You use ImageIO to convert the BufferedImage to the binary data you send over the socket (a PNG or whatever). Then, on the other side you use ImageIO to convert that back to a BufferedImage – slipperyseal Jun 14 '16 at 05:00
  • ok, thanks. I'll look into – Dak31 Jun 14 '16 at 05:03

2 Answers2

4

Basically a BufferedImage is an array. The pixels are stored into the DataBuffer, which is an array.

BufferedImage source = //...
switch ( source.getType() )
    {
    case BufferedImage.TYPE_BYTE_GRAY :
    case BufferedImage.TYPE_3BYTE_BGR :
    case BufferedImage.TYPE_4BYTE_ABGR :
        final byte[] bb = ((DataBufferByte)source.getRaster().getDataBuffer()).getData() ;
        //...
        break ;
    case BufferedImage.TYPE_USHORT_GRAY :
        final short[] sb = ((DataBufferUShort)source.getRaster().getDataBuffer()).getData() ;
        //...
        break ;
    case BufferedImage.TYPE_INT_RGB :
    case BufferedImage.TYPE_INT_BGR :
    case BufferedImage.TYPE_INT_ARGB :
        final int[] ib = ((DataBufferInt)source.getRaster().getDataBuffer()).getData() ;
        break ;
    // etc.
    }

You will also need to send the image dimensions, plus the number of channels.

FiReTiTi
  • 5,597
  • 12
  • 30
  • 58
  • The drawback of having a large array (and *not* knowing the size of the image itself) that has to be transferred over the network (compared to PNG compressed data) was already mentioned in the comments. Additionally, obtaining the data buffer data like this causes the image to become "untrackable" (sometimes called "unmanaged"), and can significantly reduce the painting performance for this image. Apart from that, this is a reasonable answer to the question, regardless of whether the approach that was intended by the asker is the best one or not... – Marco13 Jun 14 '16 at 10:48
  • Yes, I was answering the basic question "convert an image to int[]". And yes, send compressed data would be much faster. – FiReTiTi Jun 14 '16 at 15:45
1

Send the image across as a PNG:

// BufferedImage -> byte sequence
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img, "PNG", baos);
byte[] imageData = baos.toByteArray();
// byte sequence -> BufferedImage
ByteArrayInputStream bais = new ByteArrayInputStream(imageData);
BufferedImage img = ImageIO.read(bais);
Zarkonnen
  • 22,200
  • 14
  • 65
  • 81