Search code examples
javapngalpha

Saving my PNG destroys the alpha channel


Im trying to save a PNG image with a alpha channel, but after doing some pixel wise manipulation and saving it, the alpha channel went back to 255 on every pixel. heres my code:

first the pixel manipulation:

public BufferedImage apply(BufferedImage image) {
    int pixel;

    for (int y = 0; y < image.getHeight(); y++) {
        for (int x = 0; x < image.getWidth(); x++) {
            pixel = image.getRGB(x, y);

            if (threshold < getAverageRGBfromPixel(pixel)) {
                image.setRGB(x, y, new Color(0f, 0f, 0f, 0f).getRGB());
            }               
        }
    }


    return image;
}

NOTE: the pixel that should be transparent are black, so i definetly hit them.

and heres the code for the saving.

@Test
public void testGrayscaleFilter() {
    ThresholdFilter thresholdFilter = new ThresholdFilter();

    testImage = thresholdFilter.apply(testImage);

    File outputFile = new File(TEST_DIR + "/testGrayPicture" + ".png");

    try {
        // retrieve image
        ImageIO.write(testImage, "png", outputFile);
    } catch (IOException e) {
}  

can anyone please tell me what i'm doing wrong?


Solution

  • By looking through the documentation of the BufferedImage class the only reason it wouldn't write to the alpha channel is if the original BufferedImage object has type of TYPE_INT_RGB rather than TYPE_INT_ARGB.

    One solution would be to create a new BufferedImage object with the same height and width but with type TYPE_INT_ARGB and when you change the pixel data copy it over with an else statement.

    public BufferedImage apply(BufferedImage image) {
    int pixel;
    BufferedImage newImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
    
    for (int y = 0; y < image.getHeight(); y++) {
        for (int x = 0; x < image.getWidth(); x++) {
            pixel = image.getRGB(x, y);
    
            if (threshold < getAverageRGBfromPixel(pixel)) {
                newImage.setRGB(x, y, new Color(0f, 0f, 0f, 0f).getRGB());
            }
            else {
                // Not sure about this line
                newImage.setRGB(x, y, pixel);
            }
        }
    }
    
    
    return image;
    

    }