4

I have a byte array containing pixel values from a .bmp file. It was generated by doing this:

BufferedImage readImage = ImageIO.read(new File(fileName));
byte imageData[] = ((DataBufferByte)readImage.getData().getDataBuffer()).getData();

Now I need to recreate the .bmp image. I tried to make a BufferedImage and set the pixels of the WritableRaster by calling the setPixels method. But there I have to provide an int[], float[] or double[] array. Maybe I need to convert the byte array into one of these. But I don't know how to do that. I also tried the setDataElements method. But I am not sure how to use this method either.

Can anyone explain how to create a bmp image from a byte array?

Edit: @Perception

This is what I have done so far:

private byte[] getPixelArrayToBmpByteArray(byte[] pixelData, int width, int height, int depth) throws Exception{ int[] pixels = byteToInt(pixelData); BufferedImage image = null; if(depth == 8) { image = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_GRAY); } else if(depth == 24){ image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); } WritableRaster raster = (WritableRaster) image.getData(); raster.setPixels(0, 0, width, height, pixels); image.setData(raster); return getBufferedImageToBmpByteArray(image); } private byte[] getBufferedImageToBmpByteArray(BufferedImage image) { byte[] imageData = null; try { ByteArrayOutputStream bas = new ByteArrayOutputStream(); ImageIO.write(image, "bmp", bas); imageData = bas.toByteArray(); bas.close(); } catch (Exception e) { e.printStackTrace(); } return imageData; } private int[] byteToInt(byte[] data) { int[] ints = new int[data.length]; for (int i = 0; i
Zain
  • 37,492
  • 7
  • 60
  • 84
  • Wheres your current code for setting the image data? – Perception Apr 08 '12 at 07:26
  • Do you really need to read from the `Raster`? Have you tried [reading/writing with a ByteArrayOutputStream](http://stackoverflow.com/a/356650/104223) ? – Leigh Apr 09 '12 at 01:47
  • @Leigh The link u gave is about making a image (of a particular type) from another image of different type. But the problem is I dont have the image, I have got the pixel part of the bmp image (along with the width and height in pixel). Thanks for ur effort.. – waiting_for_peace Apr 11 '12 at 06:17
  • how many bytes per pixel are there? width * height vs pixels.length? – daveb Apr 11 '12 at 07:01
  • @daveb For colored images the depth is 24, so 3 bytes per pixel. I didnt get your second question clearly. May be you are asking the byte array length.. The length is width * height * 3. Thanks for your time.. – waiting_for_peace Apr 11 '12 at 07:06
  • @waiting_for_peace - Yes, I know that method does not work with just pixel data. I was actually asking if you really needed to work with pixels, rather than the overall image binary? But it sounds like you do. – Leigh Apr 11 '12 at 16:07
  • I found this code works fine. http://www.java2s.com/Code/Java/Collections-Data-Structure/bytearraytointarray.htm – Mossaddeque Mahmood Dec 24 '12 at 10:54

2 Answers2

2

You need to pack three bytes into each integer you make. Depending on the format of the buffered image, this will be 0xRRGGBB.

byteToInt will have to consume three bytes like this:

private int[] byteToInt(byte[] data) {
    int[] ints = new int[data.length / 3];

    int byteIdx = 0;
    for (int pixel = 0; pixel < ints.length) {
        int rByte = (int) pixels[byteIdx++] & 0xFF;
        int gByte = (int) pixels[byteIdx++] & 0xFF;
        int bByte = (int) pixels[byteIdx++] & 0xFF;
        int rgb = (rByte << 16) | (gByte << 8) | bByte
        ints[pixel] = rgb;
    }
}

You can also use ByteBuffer.wrap(arr, offset, length).toInt()

daveb
  • 74,111
  • 6
  • 45
  • 51
0

Having just a byte array is not enough. You also need to construct a header (if you are reading from a raw format, such as inside a DICOM file).

Tommy Chan
  • 622
  • 7
  • 14