7

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

2
  • Eventually I did not find anything better then: for(int y=0; y<height; y++) { for(int x=0; x<width; x++) { int i0 = (y*width+x)*3; frameImg.setRGB(x, y, ((data[i0]&0xFF) | ((data[i0+1]&0xFF)<<8) | ((data[i0+2]&0xFF)<<16))); } } Commented Jul 17, 2009 at 15:38
  • What are the dimensions of the array of bytes? Is it a 1-dimensional array, a 2-dimensional array, or a 3-dimensional array? Commented Jun 10, 2013 at 7:53

5 Answers 5

10

You can do it using Raster class. It's better because it does not require iterating and copying of byte arrays.

 byte[] raw = new byte[width*height*3]; // raw bytes of our image
 DataBuffer buffer = new DataBufferByte(raw, raw.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);

 BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
 image.setData(raster);
Sign up to request clarification or add additional context in comments.

Comments

6

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

10 Comments

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?
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.
You can also do: int rgb = ((int)colors[in] << 24) + ((int)colors[in+1] << 8) + (int)colors[in]
That way you can solve sign/unsign problem: frameImg.setRGB(x, y, ((data[i0]&0xFF) | ((data[i0+1]&0xFF)<<8) | (data[i0+2]&0xFF)<<16)));
It doesn't seem like this answer is correct, despite being accepted. If colors is an RGB array (where R, G, & B are individual bytes), shouldn't index be getting incremented by more than 1 per loop?
|
2

folkyatina's approach works if your RGB values are in B,G,R order, but if they are in R,G,B order I have found the following code to work:

    DataBuffer rgbData = new DataBufferByte(rgbs, rgbs.length);

    WritableRaster raster = Raster.createInterleavedRaster(
        rgbData, width, height,
        width * 3, // scanlineStride
        3, // pixelStride
        new int[]{0, 1, 2}, // bandOffsets
        null);

    ColorModel colorModel = new ComponentColorModel(
        ColorSpace.getInstance(ColorSpace.CS_sRGB),
        new int[]{8, 8, 8}, // bits
        false, // hasAlpha
        false, // isPreMultiplied
        ComponentColorModel.OPAQUE,
        DataBuffer.TYPE_BYTE);

    return new BufferedImage(colorModel, raster, false, null);

Comments

1

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.

Comments

1

Assuming that your raw data is a 1d array like:

byte[] imageBytes = new byte[1024];
// transform to bufferImage
BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(imageBytes));
// if you want to do some operations to the image, like resize, 
// use the lib (net.coobird.thumbnailator)
BufferedImage image = Thumbnails.of(bufferedImage).forceSize(WIDTH, HEIGHT)
                                .outputFormat("bmp").asBufferedImage();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.