使用纯Java模仿JavaFX的ColorAdjust亮度

时间:2019-07-02 16:12:21

标签: java colors accessibility macos-darkmode

我正在尝试将彩色图像转换为可用的单色图像,但没有“锯齿状”的边缘。

从类似的问题asking to convert an image from color to black and white中,一个被接受的答案提供了一个使用setBrightness(-1)技术的JavaFX ColorAdjust类的简单技巧。此技术的好处是可以保持黑白之间的柔和边缘,例如支持高对比度主题而无需创建全新的图标集

注意:我的确理解“单色”一词的不准确性(会出现一些灰度),但是我不确定该如何描述这种技术。

使用纯Java模仿ColorAdust技术的方法是什么?

所需:

soft edges


不需要:

jagged edges

1 个答案:

答案 0 :(得分:1)

这是纯Java方法。无需Swing代码即可创建图像。而不是将图像更改为黑白,我们将图像更改为黑色和透明。这就是我们保留那些羽毛边缘的方式。

结果:enter image description here

如果您想要没有alpha的真实灰度图像,请创建一个graphics2d对象,用所需的背景色填充它,然后在其上绘制图像。

关于将白人保留为白人,可以做到这一点,但必须承认以下两点之一。您要么放弃黑白方面,采用真实的灰度图像,要么保留黑白,但是得到锯齿状的边缘,白色的羽毛会变成任何其他颜色。发生这种情况的原因是,一旦我们命中了浅色像素,我们如何知道它是浅色特征还是白色与另一种颜色之间的过渡像素。我不知道没有边缘检测即可解决此问题的方法。

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());
    }
}