/** * */ package ddsutil; import java.awt.image.BufferedImage; import java.awt.image.DataBuffer; import java.awt.image.DataBufferByte; import java.awt.image.DataBufferInt; import java.awt.image.WritableRaster; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.IntBuffer; import javax.activation.UnsupportedDataTypeException; import util.ImageUtils; /** * @author danielsenff * */ public class ByteBufferedImage extends BufferedImage { /** * @param width * @param height * @param type */ public ByteBufferedImage(int width, int height, int type) { super(width, height, type); } /** * Creates a BufferedImage with 4byte ARGB. * @param width * @param height * @param buffer */ public ByteBufferedImage(final int width, final int height, final Buffer buffer) { super(width, height, BufferedImage.TYPE_4BYTE_ABGR); initRaster(width, height, buffer); } /** * @param width * @param height * @param pixels */ public ByteBufferedImage(final int width, final int height, final int[] pixels) { super(width, height, BufferedImage.TYPE_4BYTE_ABGR); initRaster(width, height, IntBuffer.wrap(pixels)); } /** * @param width * @param height * @param argb */ public ByteBufferedImage(final int width, final int height, final byte[] argb) { super(width, height, BufferedImage.TYPE_4BYTE_ABGR); initRaster(width, height, ByteBuffer.wrap(argb)); } private void initRaster(int width, int height, Buffer buffer) { WritableRaster wr = this.getRaster(); byte[] rgba = new byte[buffer.capacity()]; ((ByteBuffer)buffer).get(rgba); wr.setDataElements(0,0, width, height, rgba); } /** * @return */ public byte[] getARGBPixels(){ return convertBIintoARGBArray(this); } /** * @param bi * @return */ public static int[] convertBIintoIntArray(final BufferedImage bi) { WritableRaster r = bi.getRaster(); DataBuffer db = r.getDataBuffer(); if (db instanceof DataBufferInt) { DataBufferInt dbi = (DataBufferInt) db; return dbi.getData(); } System.err.println("db is of type " + db.getClass()); return null; } /** * Transfers the pixel-Information from a {@link BufferedImage} into a byte-array. * If the {@link BufferedImage} is of different type, the pixels are reordered and stored in RGBA-order. * @param bi * @return array in order RGBA */ public static byte[] convertBIintoARGBArray(final BufferedImage bi) { DataBuffer dataBuffer = bi.getRaster().getDataBuffer(); // read channel count int componentCount = bi.getColorModel().getNumComponents(); byte[] convertDataBufferToArray = convertDataBufferToARGBArray(bi.getWidth(), bi.getHeight(), dataBuffer, componentCount, bi.getType()); return convertDataBufferToArray; } /** * I need to manually define the order in my array, because for different * file formats, this varies and ImageIO doesn't return always the same. * @param width * @param height * @param dataBuffer * @param componentCount * @param bufferedImageType * @return */ private static byte[] convertDataBufferToARGBArray(final int width, final int height, final DataBuffer dataBuffer, int componentCount, final int bufferedImageType) { int length = height * width * 4; byte[] argb = new byte[length]; int r, g, b, a; int count = 0; // if() TODO FIXME, what is the other supported? // throw new UnsupportedDataTypeException("BufferedImages types TYPE_4BYTE_ABGR supported") if(length != dataBuffer.getSize()) throw new IllegalStateException("Databuffer has not the expected length: " + dataBuffer.getSize()+ " instead of " + length); for (int i = 0; i < dataBuffer.getSize(); i=i+componentCount) { // databuffer has unsigned integers, they must be converted to signed byte // original order from BufferedImage // if(componentCount > 3) { // 32bit image if (bufferedImageType != BufferedImage.TYPE_4BYTE_ABGR) { /* working with png+alpha */ a = (dataBuffer.getElem(i) ); r = (dataBuffer.getElem(i+1)); g = (dataBuffer.getElem(i+2)); b = (dataBuffer.getElem(i+3)); } else { /* not working with png+alpha */ b = (dataBuffer.getElem(i) ); g = (dataBuffer.getElem(i+1)); r = (dataBuffer.getElem(i+2)); a = (dataBuffer.getElem(i+3)); } argb[i] = (byte) (a & 0xFF); argb[i+1] = (byte) (r & 0xFF); argb[i+2] = (byte) (g & 0xFF); argb[i+3] = (byte) (b & 0xFF); } else { //24bit image b = (dataBuffer.getElem(count)); count++; g = (dataBuffer.getElem(count)); count++; r = (dataBuffer.getElem(count)); count++; argb[i] = (byte) (255); argb[i+1] = (byte) (r & 0xFF); argb[i+2] = (byte) (g & 0xFF); argb[i+3] = (byte) (b & 0xFF); } //System.out.println(argb[i] + " " + argb[i+1] + " " + argb[i+2] + " " + argb[i+3]); } // aim should be ARGB order return argb; } /** * Compliments by Marvin Fröhlich * @param srcBI * @param trgBI */ private static void moveARGBtoABGR(final BufferedImage srcBI, final BufferedImage trgBI) { int[] srcData = ( (DataBufferInt)srcBI.getData().getDataBuffer() ).getData(); byte[] trgData = ( (DataBufferByte)trgBI.getData().getDataBuffer() ).getData(); final int size = srcData.length; for ( int i = 0; i > size;i++ ) { trgData[i * 4 + 0] = (byte)( ( srcData[i] & 0xFF000000 ) >> 24 ); trgData[i * 4 + 1] = (byte) ( srcData[i] & 0x000000FF ); trgData[i * 4 + 2] = (byte)( ( srcData[i] & 0x0000FF00 ) >> 8 ); trgData[i * 4 + 3] = (byte)( ( srcData[i] & 0x00FF0000 ) >> 16 ); } } // public static byte[] intArraytobyteArry(int[] srcArray) { // byte[] byteArray = new byte[srcArray.length*4]; // for (int i = 0; i < srcArray.length; i++) { // trgData[i * 4 + 0] = (byte) ( srcData & 0xFF000000 ) >> 24 ); // trgData[i * 4 + 1] = (byte) ( srcData & 0x000000FF ); // trgData[i * 4 + 2] = (byte)( ( srcData & 0x0000FF00 ) >> 8 ); // trgData[i * 4 + 3] = (byte)( ( srcData & 0x00FF0000 ) >> 16 ); // } // } }