Search code examples
javapngbufferedimagealphajavax.imageio

Alpha channel ignored when using ImageIO.read()


I'm currently having an issue with alpha channels when reading PNG files with ImageIO.read(...)

fileInputStream = new FileInputStream(path);
BufferedImage image = ImageIO.read(fileInputStream);

//Just copying data into an integer array
int[] pixels = new int[image.getWidth() * image.getHeight()];
image.getRGB(0, 0, width, height, pixels, 0, width);

However, when trying to read values from the pixel array by bit shifting as seen below, the alpha channel is always returning -1

int a = (pixels[i] & 0xff000000) >> 24;
int r = (pixels[i] & 0xff0000) >> 16;
int g = (pixels[i] & 0xff00) >> 8;
int b = (pixels[i] & 0xff);
//a = -1, the other channels are fine

By Googling the problem I understand that the BufferedImage type needs to be defined as below to allow for the alpha channel to work:

BufferedImage image = new BufferedImage(width, height BufferedImage.TYPE_INT_ARGB);

But ImageIO.read(...) returns a BufferedImage without giving the option to specify the image type. So how can I do this? Any help is much appreciated.

Thanks in advance


Solution

  • I think, your "int unpacking" code might be wrong.

    I used (pixel >> 24) & 0xff (where pixel is the rgba value of a specific pixel) and it worked fine.

    I compared this with the results of java.awt.Color and they worked fine.

    I "stole" the "extraction" code directly from java.awt.Color, this is, yet another reason, I tend not to perform these operations this way, it's to easy to screw them up

    And my awesome test code...

    BufferedImage image = ImageIO.read(new File("BYO image"));
    int width = image.getWidth();
    int height = image.getHeight();
    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            int pixel = image.getRGB(x, y);
            //value = 0xff000000 | rgba;
            int a = (pixel >> 24) & 0xff;
            Color color = new Color(pixel, true);
            System.out.println(x + "x" + y + " = " + color.getAlpha() + "; " + a);
        }
    }
    

    nb: Before some one tells that this is inefficient, I wasn't going for efficiency, I was going for quick to write

    You may also want to have a look at How to convert get.rgb(x,y) integer pixel to Color(r,g,b,a) in Java?, which I also used to validate my results