BufferedImage 意外改变颜色
BufferedImage unexpectedly changing color
我有以下代码,它创建灰度 BufferedImage,然后设置每个像素的随机颜色。
import java.awt.image.BufferedImage;
public class Main {
public static void main(String[] args) {
BufferedImage right = new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY);
int correct = 0, error = 0;
for (int i = 0; i < right.getWidth(); i++) {
for (int j = 0; j < right.getHeight(); j++) {
int average = (int) (Math.random() * 255);
int color = (0xff << 24) | (average << 16) | (average << 8) | average;
right.setRGB(i, j, color);
if(color != right.getRGB(i, j)) {
error++;
} else {
correct++;
}
}
}
System.out.println(correct + ", " + error);
}
}
在大约 25-30% 的像素中出现了奇怪的行为,我设置了颜色,之后它的值与之前设置的不同。我设置颜色的方式有误吗?
我认为您的问题与图像类型有关(BufferedImage 构造函数的第三个参数)。如果将类型更改为 BufferedImage.TYPE_INT_ARGB
,那么您将获得 100% 正确的结果。
查看 BufferedImage.getRGB(int,int)
的文档,当您获得不是默认颜色的 RGB 时,会进行一些转换 space
Returns an integer pixel in the default RGB color model (TYPE_INT_ARGB) and default sRGB colorspace. Color conversion takes place if this default model does not match the image ColorModel.
所以您可能看到了由于转换导致的不匹配。
胡乱猜测:
移除(0xff << 24)|这是 alpha 通道,intransparent/opaque 颜色如何。鉴于 yes/no 透明和平均 < 或 >= 128 透明度应用,25% 可能是错误的颜色映射(非常大胆的猜测)。
这是您的解决方案:禁止 getRGB 并使用 Raster(比 getRGB 更快更容易)或更好的 DataBuffer(最快但您必须处理编码):
import java.awt.image.BufferedImage;
public class Main
{
public static void main(String[] args)
{
BufferedImage right = new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY);
int correct = 0, error = 0;
for (int x=0 ; x < right.getWidth(); x++)
for (int j = 0; j < right.getHeight(); j++)
{
int average = (int) (Math.random() * 255) ;
right.getRaster().setSample(x, y, 0, average) ;
if ( average != right.getRaster().getSample(x, y, 0) ) error++ ;
else correct++;
}
System.out.println(correct + ", " + error);
}
}
在你的情况下,getRGB 很糟糕,因为编码是一个字节数组(8 位),你必须使用 getRGB 来操作 RGB 值。栅格为您完成所有转换工作。
我有以下代码,它创建灰度 BufferedImage,然后设置每个像素的随机颜色。
import java.awt.image.BufferedImage;
public class Main {
public static void main(String[] args) {
BufferedImage right = new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY);
int correct = 0, error = 0;
for (int i = 0; i < right.getWidth(); i++) {
for (int j = 0; j < right.getHeight(); j++) {
int average = (int) (Math.random() * 255);
int color = (0xff << 24) | (average << 16) | (average << 8) | average;
right.setRGB(i, j, color);
if(color != right.getRGB(i, j)) {
error++;
} else {
correct++;
}
}
}
System.out.println(correct + ", " + error);
}
}
在大约 25-30% 的像素中出现了奇怪的行为,我设置了颜色,之后它的值与之前设置的不同。我设置颜色的方式有误吗?
我认为您的问题与图像类型有关(BufferedImage 构造函数的第三个参数)。如果将类型更改为 BufferedImage.TYPE_INT_ARGB
,那么您将获得 100% 正确的结果。
查看 BufferedImage.getRGB(int,int)
的文档,当您获得不是默认颜色的 RGB 时,会进行一些转换 space
Returns an integer pixel in the default RGB color model (TYPE_INT_ARGB) and default sRGB colorspace. Color conversion takes place if this default model does not match the image ColorModel.
所以您可能看到了由于转换导致的不匹配。
胡乱猜测:
移除(0xff << 24)|这是 alpha 通道,intransparent/opaque 颜色如何。鉴于 yes/no 透明和平均 < 或 >= 128 透明度应用,25% 可能是错误的颜色映射(非常大胆的猜测)。
这是您的解决方案:禁止 getRGB 并使用 Raster(比 getRGB 更快更容易)或更好的 DataBuffer(最快但您必须处理编码):
import java.awt.image.BufferedImage;
public class Main
{
public static void main(String[] args)
{
BufferedImage right = new BufferedImage(100, 100, BufferedImage.TYPE_BYTE_GRAY);
int correct = 0, error = 0;
for (int x=0 ; x < right.getWidth(); x++)
for (int j = 0; j < right.getHeight(); j++)
{
int average = (int) (Math.random() * 255) ;
right.getRaster().setSample(x, y, 0, average) ;
if ( average != right.getRaster().getSample(x, y, 0) ) error++ ;
else correct++;
}
System.out.println(correct + ", " + error);
}
}
在你的情况下,getRGB 很糟糕,因为编码是一个字节数组(8 位),你必须使用 getRGB 来操作 RGB 值。栅格为您完成所有转换工作。