Search code examples
javafxrgbargb

Using PixelWriter.setargb


I have an issue regarding the creation of an JavaFX WritableImage using an byte array of gray scale image data.

I did write a working function for BufferedImage, but what seems to me to be an equivalent method for Image does return me an Image with all entries equal 0.

This is the working method:

private  static BufferedImage getBufferedImageFromData(int height, int width, byte[] data) {    
    BufferedImage result = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

    for(int i = 0; i < width * height; ++i){
        int a = 0xFF << 24;
        int r = (data[i] & 0xFF) << 16;
        int g = (data[i] & 0xFF) << 8;
        int b = data[i] & 0xFF;

        int x = i % width;
        int y = (i - x)/width;

        result.setRGB(x, y, a | r | g | b);
    }

    return result;      
}

And this is my attempt at an equivalent method for JavaFX (which returns an image with all pixels set to 0):

private static Image getImageFromData(int height, int width, byte[] data)     {
    WritableImage wr = new WritableImage(width, height);
    PixelWriter pw = wr.getPixelWriter();

    for(int i = 0; i < width * height; ++i) {
        int r = (data[i] & 0xFF) << 16;
        int g = (data[i] & 0xFF) << 8;
        int b = data[i] & 0xFF;

        int x = i % width;
        int y = (i - x)/width;

        pw.setArgb(x, y, r | g | b);
    }
    return wr;
}

Now, the only reason I could come up with up until now as to why I get an Image filled with 0s is that I did not format my values correctly, that is to say that BufferedImage.setRGB does format the given values and PixelWriter.argb expects to be given formated values.

I have no idea what exactly I would have to change for it to work

As to why I do not use PixelWriter.setPixels: It does seem to be very time intense in comparision with the method I tried, as it does need me to set up a new array 3x as big as the current and only then hand it over to the method. I did try it anyways, unsuccessfully.

Thanks for any help


Solution

  • You forgot about the a part of argb. This means you write a pixel with a 0 as alpha channel. This means all of your pixels are fully transparent. You need to set the alpha channel to 100% to create a fully opaque image:

    private static Image getImageFromData(int height, int width, byte[] data) {
        WritableImage wr = new WritableImage(width, height);
        PixelWriter pw = wr.getPixelWriter();
    
        for (int i = 0; i < width * height; ++i) {
            int value = data[i] & 0xFF;
            int r = value << 16;
            int g = value << 8;
            int b = value;
    
            int x = i % width;
            int y = i / width;
    
            // include alpha here
            pw.setArgb(x, y, (0xFF<<24) | r | g | b);
        }
        return wr;
    }
    

    Note that I've simplified (i - x)/width to i / width since integer divisions are truncated.