将 BufferedImage 绘制到另一个 BufferedImage 正在更改 RGBA 值
Drawing a BufferedImage to another BufferedImage is changing RGBA values
我在尝试复制 BufferedImage
对象时遇到问题。
我正在使用 drawImage (BufferedImage image, int x, int y, ImageObserver observer)
方法在新图像上绘制原始图像,并且我为每个图像设置 BufferedImage.TYPE_INT_ARGB
,但是,当我打印新图像颜色的值时, RGBA值略有不同。
我需要制作原始图像的副本,因为我有一个 JPanel
持有要绘制为背景的图像。在我的应用程序的其他部分,我必须从面板获取图像,但我想 return 一份副本以避免从其他地方修改图像。
我该如何解决这个问题?
代码:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
public class BufferedImageColorBug
{
public static void main (String [] a) {
Color [] colors = {
new Color (202,230,186,14),
new Color (254,65,188,214),
new Color (247,104,197,198),
new Color (158,93,79,239),
new Color (235,45,57,194),
new Color (155,77,126,150),
new Color (164,237,20,172),
new Color (184,106,97,191),
new Color (187,249,135,85),
new Color (236,112,98,24)
};
BufferedImage image = new BufferedImage (colors.length, 1, BufferedImage.TYPE_INT_ARGB);
for (int x = 0; x < colors.length; x ++) image.setRGB (x, 0, colors [x].getRGB ());
BufferedImage copy = new BufferedImage (image.getWidth (), image.getHeight (), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = copy.createGraphics ();
g2d.drawImage (image, 0, 0, null);
g2d.dispose ();
for (int x = 0; x < colors.length; x ++) {
Color color = new Color (copy.getRGB (x, 0), true);
System.out.println (color.getRed () + "," + color.getGreen () + "," + color.getBlue () + "," + color.getAlpha ());
}
}
}
这是我得到的输出:
200,237,182,14
254,66,188,214
247,104,197,198
158,93,79,239
235,45,57,194
155,76,126,150
165,237,19,172
184,105,97,191
186,249,135,85
234,117,96,24
编辑
我谈到了克隆图像,因为这是我的目标,但有了这个问题,我想了解 为什么 rgba 值在图像之间不同。
我已经尝试使用 BufferedImage.TYPE_INT_ARGB_PRE
,但没有用。
要创建图像的精确副本(假设它们都是同一类型),您可以稍微更改代码:
BufferedImage copy = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
copy.setData(image.getRaster()); // getRaster() is faster than getData(), as no copy is created
for (int x = 0; x < colors.length; x++) {
Color color = new Color(copy.getRGB(x, 0), true);
System.out.println(color.getRed() + "," + color.getGreen() + "," + color.getBlue() + "," + color.getAlpha());
}
这将打印与原始 colors
数组中相同的颜色。
PS:我最初认为这是一个错误,但现在意识到它可能不是。
经过一些测试,我发现您的代码与我通常用于克隆图像的代码之间存在细微差别。如果将 alpha 合成规则更改为 Src
(意味着只有源会贡献并完全替换目标处的像素),您也会得到预期的结果:
BufferedImage copy = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = copy.createGraphics();
g2d.setComposite(AlphaComposite.Src); // Completely replace, default is SrcOver
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
for (int x = 0; x < colors.length; x++) {
Color color = new Color(copy.getRGB(x, 0), true);
System.out.println(color.getRed() + "," + color.getGreen() + "," + color.getBlue() + "," + color.getAlpha());
}
原因是在将半透明像素合成到完全透明像素上时,目标处的原始透明像素将影响最终结果,从而改变 RGBA 值。
我在尝试复制 BufferedImage
对象时遇到问题。
我正在使用 drawImage (BufferedImage image, int x, int y, ImageObserver observer)
方法在新图像上绘制原始图像,并且我为每个图像设置 BufferedImage.TYPE_INT_ARGB
,但是,当我打印新图像颜色的值时, RGBA值略有不同。
我需要制作原始图像的副本,因为我有一个 JPanel
持有要绘制为背景的图像。在我的应用程序的其他部分,我必须从面板获取图像,但我想 return 一份副本以避免从其他地方修改图像。
我该如何解决这个问题?
代码:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
public class BufferedImageColorBug
{
public static void main (String [] a) {
Color [] colors = {
new Color (202,230,186,14),
new Color (254,65,188,214),
new Color (247,104,197,198),
new Color (158,93,79,239),
new Color (235,45,57,194),
new Color (155,77,126,150),
new Color (164,237,20,172),
new Color (184,106,97,191),
new Color (187,249,135,85),
new Color (236,112,98,24)
};
BufferedImage image = new BufferedImage (colors.length, 1, BufferedImage.TYPE_INT_ARGB);
for (int x = 0; x < colors.length; x ++) image.setRGB (x, 0, colors [x].getRGB ());
BufferedImage copy = new BufferedImage (image.getWidth (), image.getHeight (), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = copy.createGraphics ();
g2d.drawImage (image, 0, 0, null);
g2d.dispose ();
for (int x = 0; x < colors.length; x ++) {
Color color = new Color (copy.getRGB (x, 0), true);
System.out.println (color.getRed () + "," + color.getGreen () + "," + color.getBlue () + "," + color.getAlpha ());
}
}
}
这是我得到的输出:
200,237,182,14
254,66,188,214
247,104,197,198
158,93,79,239
235,45,57,194
155,76,126,150
165,237,19,172
184,105,97,191
186,249,135,85
234,117,96,24
编辑
我谈到了克隆图像,因为这是我的目标,但有了这个问题,我想了解 为什么 rgba 值在图像之间不同。
我已经尝试使用 BufferedImage.TYPE_INT_ARGB_PRE
,但没有用。
要创建图像的精确副本(假设它们都是同一类型),您可以稍微更改代码:
BufferedImage copy = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
copy.setData(image.getRaster()); // getRaster() is faster than getData(), as no copy is created
for (int x = 0; x < colors.length; x++) {
Color color = new Color(copy.getRGB(x, 0), true);
System.out.println(color.getRed() + "," + color.getGreen() + "," + color.getBlue() + "," + color.getAlpha());
}
这将打印与原始 colors
数组中相同的颜色。
PS:我最初认为这是一个错误,但现在意识到它可能不是。
经过一些测试,我发现您的代码与我通常用于克隆图像的代码之间存在细微差别。如果将 alpha 合成规则更改为 Src
(意味着只有源会贡献并完全替换目标处的像素),您也会得到预期的结果:
BufferedImage copy = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics2D g2d = copy.createGraphics();
g2d.setComposite(AlphaComposite.Src); // Completely replace, default is SrcOver
g2d.drawImage(image, 0, 0, null);
g2d.dispose();
for (int x = 0; x < colors.length; x++) {
Color color = new Color(copy.getRGB(x, 0), true);
System.out.println(color.getRed() + "," + color.getGreen() + "," + color.getBlue() + "," + color.getAlpha());
}
原因是在将半透明像素合成到完全透明像素上时,目标处的原始透明像素将影响最终结果,从而改变 RGBA 值。