使用纯 Java 模仿 JavaFX 的 ColorAdjust 亮度
Mimic JavaFX's ColorAdjust brightness using pure Java
我正在尝试将彩色图像转换为可用的单色图像,但没有 "jagged" 边缘。
来自类似的问题 , one of the accepted answers provides a simple trick from JavaFX's ColorAdjust
class 使用 setBrightness(-1)
技术。这种技术的好处是保持黑白之间的柔和边缘,例如 支持高对比度主题而不创建全新的图标集。
注意: 我确实理解 "monochrome" 一词的不准确性(会出现一些灰度),但我不确定如何描述此技术。
使用纯 Java 模仿 ColorAdust
技术的方法是什么?
期望:
不需要:
这是一种纯粹的 Java 方法。创建图像不需要 Swing 代码。我们没有将图像更改为黑色和白色,而是将图像更改为黑色和透明。这就是我们如何保护那些羽毛状的边缘。
结果:
如果您想要一个没有 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());
}
}
我正在尝试将彩色图像转换为可用的单色图像,但没有 "jagged" 边缘。
来自类似的问题 ColorAdjust
class 使用 setBrightness(-1)
技术。这种技术的好处是保持黑白之间的柔和边缘,例如 支持高对比度主题而不创建全新的图标集。
注意: 我确实理解 "monochrome" 一词的不准确性(会出现一些灰度),但我不确定如何描述此技术。
使用纯 Java 模仿 ColorAdust
技术的方法是什么?
期望:
不需要:
这是一种纯粹的 Java 方法。创建图像不需要 Swing 代码。我们没有将图像更改为黑色和白色,而是将图像更改为黑色和透明。这就是我们如何保护那些羽毛状的边缘。
结果:
如果您想要一个没有 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());
}
}