Mimic JavaFX's ColorAdjust brightness using pure Java

China☆狼群 提交于 2020-01-24 09:30:08

问题


I'm attempting to convert a color image to a useable monochrome image, but without the "jagged" edges.

From a similar question asking to convert an image from color to black and white, one of the accepted answers provides a simple trick from JavaFX's ColorAdjust class using a setBrightness(-1) technique. This technique has the benefit of maintaining the soft edges between black and white, such as supporting a high-contrast theme without creating all-new icons set.

Note: I do understand the inaccuracy of the word "monochrome" here (some grayscaling will occur) but I'm not sure how else to describe this technique.

What's a way to mimic the ColorAdust technique using pure Java?

Desired:


NOT Desired:


回答1:


This is a pure Java approach. The Swing code is not needed to create the image. Instead of changing the image to black and white, we are changing the image to black and transparent. That is how we preserve those feathered edges.

result:

If you want a true grayscale image with no alpha, make a graphics2d object, fill it with the desired background color, then draw the image onto it.

As for preserving whites as white, this can be done, but one of two thing must be conceded. Either you give up the black and white aspect and adopt a true grayscale image, or you keep your black and white, but get a jagged edge where white feathers into any other color. This occurs because once we hit a light color pixel, how do we know whether it is a light colored feature, or a transition pixel between white and another color. I don't know of a way to fix that without edge detection.

public class Main {
    private static void createAndShowGUI() {
        //swing stuff
        JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("Alpha Mask");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.PAGE_AXIS));

        JLabel picLabel = new JLabel(new ImageIcon(getImg()));
        frame.getContentPane().add(picLabel);

        BufferedImage alphaMask = createAlphaMask(getImg());

        JLabel maskLabel = new JLabel(new ImageIcon(alphaMask));
        frame.getContentPane().add(maskLabel);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static BufferedImage getImg() {
        try {
            return ImageIO.read(new URL("https://i.stack.imgur.com/UPmqE.png"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static BufferedImage createAlphaMask(BufferedImage img) {
        //TODO: deep copy img here if you actually use this
        int width = img.getWidth();
        int[] data = new int[width];

        for (int y = 0; y < img.getHeight(); y++) {
            // pull down a line if argb data
            img.getRGB(0, y, width, 1, data, 0, 1);
            for (int x = 0; x < width; x++) {
                //set color data to black, but preserve alpha, this will prevent harsh edges
                int color = data[x] & 0xFF000000;
                data[x] = color;
            }
            img.setRGB(0, y, width, 1, data, 0, 1);
        }
        return img;
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(() -> createAndShowGUI());
    }
}


来源:https://stackoverflow.com/questions/56856443/mimic-javafxs-coloradjust-brightness-using-pure-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!