Java: Bufferedimage to Byte Array and Back

Java: BufferedImage to byte array and back

This is recommended to convert to a byte array

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(img, "jpg", baos);
byte[] bytes = baos.toByteArray();

How I can convert BufferedImage to a byte array without using files

You can use ByteArrayOutputStream class and write data from BufferedImage object using following code,

BufferedImage image = null; // you have the data in this object
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(image, "fileformat like png or jpg", baos);
baos.flush();
byte[] imageInByte = baos.toByteArray(); // you have the data in byte array
baos.close();

And all of this just in memory without using any disk io or writing to files.

Returning byte[] instead of BufferedImage in Java?

You'll need to use something like ByteArrayOutputStream

public static byte[] toByteArray(BufferedImage bi, String format)
throws IOException {

ByteArrayOutputStream baos = new ByteArrayOutputStream();
ImageIO.write(bi, format, baos);
byte[] bytes = baos.toByteArray();
return bytes;

Ref: https://mkyong.com/java/how-to-convert-bufferedimage-to-byte-in-java/
}

Getting a RGBA byte array from a BufferedImage Java

The easy way is to use BufferedImage.getRGB (which despite its name gives you ARGB values), and convert the packed int[] to byte[] four times as long. Input can be any file ImageIO can read, a PNG will work fine.

public static void main(String[] args) throws IOException {
BufferedImage image = ImageIO.read(new File(args[0]));

int[] argb = image.getRGB(0, 0, image.getWidth(), image.getHeight(), null, 0, image.getWidth());
byte[] rgba = intARGBtoByteRGBA(argb);
}

private static byte[] intARGBtoByteRGBA(int[] argb) {
byte[] rgba = new byte[argb.length * 4];

for (int i = 0; i < argb.length; i++) {
rgba[4 * i ] = (byte) ((argb[i] >> 16) & 0xff); // R
rgba[4 * i + 1] = (byte) ((argb[i] >> 8) & 0xff); // G
rgba[4 * i + 2] = (byte) ((argb[i] ) & 0xff); // B
rgba[4 * i + 3] = (byte) ((argb[i] >> 24) & 0xff); // A
}

return rgba;
}

A slightly more fun way, is to create a BufferedImage that is backed by a byte[] already in RGBA format, like this:

public static void main(String[] args) throws IOException {
BufferedImage image = ImageIO.read(new File(args[0]));

ComponentColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, image.getWidth(), image.getHeight(), image.getWidth() * 4, 4, new int[] {0, 1, 2, 3}, null); // R, G, B, A order
BufferedImage imageToo = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);

// This array will be in the same R, G, B, A order
byte[] rgbaToo = ((DataBufferByte) raster.getDataBuffer()).getData();

// Draw the image onto the RGBA buffer, which will be updated immediately
Graphics2D g = imageToo.createGraphics();
try {
g.setComposite(AlphaComposite.Src);
g.drawImage(image, 0, 0, null);
}
finally {
g.dispose();
}
}

Which one of the above examples is better to use, depends on the use case.

  • If you just need a one time conversion, the first one is probably easier to reason about and works just fine.

  • If you need to update the buffer many times over, the second approach might yield better performance.

PS: I get the exact same results using both alternatives for all my test inputs, except the ones where the original is in grayscale (using ColorSpace.CS_GRAY). I believe this is a known issue that has troubled Java2D users for ages...



Related Topics



Leave a reply



Submit