Search code examples
javarasterbufferedimagebytebuffer

Create a bufferedImage backed by a ByteBuffer


I want to create a BufferedImage that uses a pre-allocated ByteBuffer as its storage or is "backed" by it.

I've read about people suggesting to write a custom WritableRaster but I've seen no proper example involving ByteBuffers. Most of these web pages are defunct now as well.

How would I go about doing this?


Solution

  • Have a look at my MappedImageFactory and MappedFileBuffer classes here. They are made for using memory-mapped file buffers, but as they use the same interface (java.nio.Buffer), you should easily be able to modify them to use pre-allocated ByteBuffers.

    These images probably won't be super-fast to render and display, but may be "good enough".

    See this answer, using IntBuffers for more ideas. Here's that code modified for ByteBuffer:

    public class ByteBufferTest {
        public static void main(String[] args) {
            Dimension dim = new Dimension(100, 100);
            int size = dim.width * dim.height * 4;
    
            final ByteBuffer buf = ByteBuffer.allocate(size);
    
            DataBuffer dbuf = new DataBuffer(DataBuffer.TYPE_BYTE, size) {
                @Override
                public void setElem(int bank, int i, int val) {
                    buf.put(i, (byte) val);
                }
    
                @Override
                public int getElem(int bank, int i) {
                    return buf.get(i);
                }
            };
    
            ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
            ColorModel cm = new ComponentColorModel(cs, new int[]{8, 8, 8, 8}, true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
    
            SampleModel sm = cm.createCompatibleSampleModel(dim.width, dim.height);
            WritableRaster raster = new WritableRaster(sm, dbuf, new Point()) {};
            BufferedImage img = new BufferedImage(cm, raster, false, null);
    
            System.err.println("img: " + img);
        }
    }
    

    Output:

    img: BufferedImage@4f3f5b24: type = 0 ColorModel: #pixelBits = 32 numComponents = 4 color space = java.awt.color.ICC_ColorSpace@15aeb7ab transparency = 1 has alpha = true isAlphaPre = false ByteBufferTest$2@7b23ec81
    

    If your ByteBuffers are allocated using Java arrays (heap), you could probably also use completely standard BufferedImages, by creating a normal DataBubfferByte around the buffer's array().