0

I have a byte array, where each byte describes one pixel (256 colors). Here is bitmask that I use: 0xRRRGGGBB So there are 3 bits for R and G components and 2 bits for B component. How can I construct BufferedImage from that array assuming that I know width and height of the image?

ddms
  • 50
  • 6
  • Why do you need three bits for red and green? The usual bitmask is "RRGGBBAA" (or "AARRGGBB") where "A" stands for alpha. – Tom Jul 03 '17 at 15:49
  • I don't need alpha component for my purpose. I construct color model: `DirectColorModel model = new DirectColorModel(8, 0b00000000000000000000000011100000, 0b00000000000000000000000000011100, 0b00000000000000000000000000000011)` and buffer: `DataBufferByte buffer = new DataBufferByte(data, data.length)` but then I don't know how to construct raster – ddms Jul 03 '17 at 15:56
  • And how would I construct BufferedImage assuming that I had RRGGBBAA mask? – ddms Jul 03 '17 at 16:04
  • 1
    You could simply construct a matching palette and use IndexedColorModel – Durandal Jul 03 '17 at 16:14

1 Answers1

3

First, we must create a data buffer with your data
DataBufferByte buffer = new DataBufferByte(data, data.length);

Next, we need to declare "bandMasks" so the raster can understand your format
int[] bandMasks = {0b11100000, 0b00011100, 0b00000011};

Now, we can create the raster
WritableRaster raster = Raster.createPackedRaster(buffer, width, height, width, bandMasks, null); (FYI, width is specified twice because it is the scansize)

Now we can create the image with the buffer, raster and Color Model
BufferedImage image = new BufferedImage(new DirectColorModel(8, 0b11100000, 0b00011100, 0b00000011), raster, false, null);
Also, you can trim off the proceeding 0's in binary literals because those bits will be 0 by default (0b00000011 is the same as 0b11 or (in decimal) 00029 is the same as 29) you don't need to specify all 32 bits in an integer

I verified the previous code works using this entire segment:

    byte[] data = new byte[]{
        (byte) 0b00000011/*Blue*/, (byte) 0b11100011/*Purple*/,
        (byte) 0b11100011/*Purple*/, (byte) 0b11111111/*White*/};//This is the "image"

    int width = 2, height = 2;

    DataBufferByte buffer = new DataBufferByte(data, data.length);
    int[] bandMasks = {0b11100000, 0b00011100, 0b00000011};

    WritableRaster raster = Raster.createPackedRaster(buffer, width, height, width, bandMasks, null);

    BufferedImage image = new BufferedImage(new DirectColorModel(8, 0b11100000, 0b00011100, 0b00000011), raster, false, null);

    JFrame frame = new JFrame("Test");
    Canvas c = new Canvas();
    frame.add(c);
    frame.setSize(1440, 810);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setVisible(true);
    while (true) {
        Graphics g = c.getGraphics();
        g.drawImage(image, 0, 0, image.getWidth() * 40, image.getHeight() * 40, null);
    }

I hope this helps!

Troy Neubauer
  • 126
  • 1
  • 5