Convert byte array of data type TYPE_4BYTE_ABGR to BufferedImage

前端 未结 2 1368
说谎
说谎 2021-01-25 10:38

I have a byte array with type TYPE_4BYTE_ABGR, and I know its width and height, I want to change it to BufferedImage, any ideas?

相关标签:
2条回答
  • 2021-01-25 11:17

    Might not be very efficient, but a BufferedImage can be converted to another type this way:

    public static BufferedImage convertToType(BufferedImage image, int type) {
        BufferedImage newImage = new BufferedImage(image.getWidth(), image.getHeight(), type);
        Graphics2D graphics = newImage.createGraphics();
        graphics.drawImage(image, 0, 0, null);
        graphics.dispose();
        return newImage;
    }
    

    About the method you want to be implemented, you would have to know the width or height of the image to convert a byte[] to a BufferedImage.

    Edit:
    One way is converting the byte[] to int[] (data type TYPE_INT_ARGB) and using setRGB:

    int[] dst = new int[width * height];
    for (int i = 0, j = 0; i < dst.length; i++) {
        int a = src[j++] & 0xff;
        int b = src[j++] & 0xff;
        int g = src[j++] & 0xff;
        int r = src[j++] & 0xff;
        dst[i] = (a << 24) | (r << 16) | (g << 8) | b;
    }
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
    image.setRGB(0, 0, width, height, dst, 0, width);
    
    0 讨论(0)
  • 2021-01-25 11:28

    The fastest way to create a BufferedImage from a byte array in TYPE_4BYTE_ABGR form, is to wrap the array in a DataBufferByte and create an interleaved WritableRaster from that. This will make sure there are no additional byte array allocations. Then create the BufferedImage from the raster, and a matching color model:

    public static void main(String[] args) {
        int width = 300;
        int height = 200;
    
        int samplesPerPixel = 4; // This is the *4BYTE* in TYPE_4BYTE_ABGR
        int[] bandOffsets = {3, 2, 1, 0}; // This is the order (ABGR) part in TYPE_4BYTE_ABGR
    
        byte[] abgrPixelData = new byte[width * height * samplesPerPixel];
    
        DataBuffer buffer = new DataBufferByte(abgrPixelData, abgrPixelData.length);
        WritableRaster raster = Raster.createInterleavedRaster(buffer, width, height, samplesPerPixel * width, samplesPerPixel, bandOffsets, null);
    
        ColorModel colorModel = new ComponentColorModel(ColorSpace.getInstance(ColorSpace.CS_sRGB), true, false, Transparency.TRANSLUCENT, DataBuffer.TYPE_BYTE);
    
        BufferedImage image = new BufferedImage(colorModel, raster, colorModel.isAlphaPremultiplied(), null);
        System.out.println("image: " + image); // Should print: image: BufferedImage@<hash>: type = 6 ...
    }
    

    Note however, that this image will be "unmanaged" (some HW accelerations will be disabled), because you have direct access to the pixel array.

    To avoid this, create the WritableRaster without the pixels, and copy the pixels into it. This will use twice as much memory, but will keep the image "managed" and thus possible better display performance:

    // Skip creating the data buffer
    WritableRaster raster = Raster.createInterleavedRaster(DataBuffer.TYPE_BYTE, width, height, samplesPerPixel * width, samplesPerPixel, bandOffsets, null);
    raster.setDataElements(0, 0, width, height, abgrPixelData);
    // ...rest of code as above.
    

    You could even do this (which might be more familiar):

    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
    WritableRaster raster = image.getRaster();
    raster.setDataElements(0, 0, width, height, abgrPixelData);
    
    0 讨论(0)
提交回复
热议问题