Search code examples
javafxgrayscaleargb

javafx argb to grayscale conversion


I know there are similar questions to this but those ones don't answer my question. As the title reads, I am using JavaFX Image class, not bufferedImage.

I used the answer to this other question, but the resulting image is empty.

This is my code:

public static Image toGrayScale(Image sourceImage) {
    PixelReader pixelReader = sourceImage.getPixelReader();

    int width = (int) sourceImage.getWidth();
    int height = (int) sourceImage.getHeight();

    WritableImage grayImage = new WritableImage(width, height);

    for (int y = 0; y < height; y++) {
        for (int x = 0; x < width; x++) {
            int pixel = pixelReader.getArgb(x, y);

            int red = ((pixel >> 16) & 0xff);
            int green = ((pixel >> 8) & 0xff);
            int blue = (pixel & 0xff);

            int grayLevel = (int) (0.2162 * red + 0.7152 * green + 0.0722 * blue) / 3;
            int gray = (grayLevel << 16) + (grayLevel << 8) + grayLevel;

            grayImage.getPixelWriter().setArgb(x, y, gray);

    }
    return grayImage;
}

can anyone tell me what the problem is.


Solution

  • I got your code working by doing the following, but I haven't entirely figured out WHY this has to be the case. It's something to do with the value of the int required for storage in the Image. You need to invert the gray level value and store the -gray integer. Maybe a Little/Big Endian issue. May be safer using a ColorAdjust.

        // Put this outside the loops
        // so we have easier access to the writer.
        PixelWriter pixelWriter = grayImage.getPixelWriter(); 
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                int pixel = pixelReader.getArgb(x, y);
    
                int red = ((pixel >> 16) & 0xff);
                int green = ((pixel >> 8) & 0xff);
                int blue = (pixel & 0xff);
    
                int grayLevel = (int) (0.2162 * (double)red + 0.7152 * (double)green + 0.0722 * (double)blue) / 3;
                grayLevel = 255 - grayLevel; // Inverted the grayLevel value here.
                int gray = (grayLevel << 16) + (grayLevel << 8) + grayLevel;
    
                pixelWriter.setArgb(x, y, -gray); // AMENDED TO -gray here.
            }
        }