views:

1523

answers:

3

Hi,

What is the right way to convert raw array of bytes into Image in Java SE. array consist of bytes, where each three bytes represent one pixel, with each byte for corresponding RGB component.

Can anybody suggest a code sample?

Thanks, Mike

+4  A: 

Assuming you know the height and width of the image.

BufferedImage img=new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
for(int r=0; r<height; r++)
for(int c=0; c<width; c++)
{
  int index=r*width+c;
  int red=colors[index] & 0xFF;
  int green=colors[index+1] & 0xFF;
  int blue=colors[index+2] & 0xFF;
  int rgb = (red << 16) | (green << 8) | blue;
  img.setRGB(c, r, rgb);
}

Roughly. This assumes the pixel data is encoded as a set of rows; and that the length of colors is 3 * width * height (which should be valid).

CoderTao
so iterating through the array is my best option here? It feels that there got to be some method which accepts array as a parameter and populates/recreate the image in one go. Maybe something to do with Raster class?
Ma99uS
Not to my knowledge, though Raster is unfamiliar to me. If this followed a standard image format, you could use the ImageIO class, but that's the limit of my knowledge.
CoderTao
You can also do: `int rgb = ((int)colors[in] << 24) + ((int)colors[in+1] << 8) + (int)colors[in]`
notnoop
Ahh... those were the magic numbers. When I wrote it the first time I had red at 16, which failed miserably, so I went to the Color.getRGB route.
CoderTao
oops... sorry, it is supposed to be `(0xFF << 24) + ((int)color[in] << 16) ...`. You need to pass the alpha in the int
notnoop
Two unfortunate things about the bit shift method though, are that it handles neither the negative values of the components, or when red is >127. One of many times that it would be nice to have unsigned data type in java.
CoderTao
Which... now the comment about red is invalid. Bah. Though it's odd that it looks at the alpha component at all, as it is supposed to be a soley RGB image.
CoderTao
That way you can solve sign/unsign problem:frameImg.setRGB(x, y, ((data[i0]
Ma99uS
That I did not know...
CoderTao
A: 

There is a setRGB variant which accepts an int array of RGBA values:

BufferedImage img=new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
int[] raw = new int[data.length * 4 / 3];
for (int i = 0; i < data.length / 3; i++) {
    raw[i] = 0xFF000000 | 
        ((data[3 * i + 0] & 0xFF) << 16) |
        ((data[3 * i + 1] & 0xFF) << 8) |
        ((data[3 * i + 2] & 0xFF));
}
img.setRGB(0, 0, width, height, raw, 0, width);

The performance characteristics is similar to CoderTao's solution.

kd304
A: 

You can do this with Raster class, like this. It's better because it does not require iterating and copying of byte arays

 byte[] raw = new byte[width*heigth*3];
 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
 file.read(frame);
 DataBuffer buffer = new DataBufferByte(frame, frame.length);

 //The most difficult part of awt api for me to learn
 SampleModel sampleModel = new ComponentSampleModel(DataBuffer.TYPE_BYTE, width, height, 3, width*3, new int[]{2,1,0});

 Raster raster = Raster.createRaster(sampleModel, buffer, null);
 image.setData(raster);
folkyatina