我写了一个修改图像的程序。
首先,我得到图像,并得到它的绘图上下文:
BufferedImage image;
try {
image = ImageIO.read(inputFile);
} catch (IOException ioe) { /* exception handling ... */ }
Graphics g = image.createGraphics();
然后我像这样修改图像:
for (int x = 0; x < image.getWidth(); x++) {
for (int y = 0; y < image.getHeight(); y++) {
g.setColor( /* calculate color ... */ );
g.fillRect(x, y, 1, 1);
}
}
完成图像修改后,我将图像保存为:
try {
ImageIO.write(image, "PNG", save.getSelectedFile());
} catch (IOException ioe) { /* exception handling ... */ }
现在大部分时间这都很好。
然而,当我尝试重新着色此纹理时
到这个
我得到了这个:
在调试器内部,Graphics
的颜色是我想要的粉红色。
评论似乎表明用户打开的图像可能有一些颜色限制,而且由于我正在绘制我正在阅读的相同图像,因此我的程序必须遵守这些限制。示例图像似乎是非常灰度级的,显然它的位深度是8位。也许我正在绘制的粉红色转换为灰度,因为图像必须保持8位?
答案 0 :(得分:0)
正如评论中所建议的,这里的主要问题确实是错误的颜色模型。加载原始图像时,打印一些有关它的信息......
BufferedImage image = ImageIO.read(
new URL("https://i.stack.imgur.com/pSUFR.png"));
System.out.println(image);
它会说
BufferedImage@5419f379: type = 13 IndexColorModel: #pixelBits = 8 numComponents = 3 color space = java.awt.color.ICC_ColorSpace@7dc7cbad transparency = 1 transIndex = -1 has alpha = false isAlphaPre = false ByteInterleavedRaster: width = 128 height = 128 #numDataElements 1 dataOff[0] = 0
IndexColorModel
不一定支持所有颜色,只支持其中的一部分。 (基本上,图像仅支持“需要”的颜色,这样可以实现更紧凑的存储)。
此处的解决方案是将图像转换为具有适当颜色模型的图像。以下示例显示了一种通用方法:
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import javax.imageio.ImageIO;
public class ImageColors
{
public static void main(String[] args) throws IOException
{
BufferedImage image = ImageIO.read(
new URL("https://i.stack.imgur.com/pSUFR.png"));
// This will show that the image has an IndexColorModel.
// This does not necessarily support all colors.
System.out.println(image);
// Convert the image to a generic ARGB image
image = convertToARGB(image);
// Now, the image has a DirectColorModel, supporting all colors
System.out.println(image);
Graphics2D g = image.createGraphics();
g.setColor(Color.PINK);
g.fillRect(50, 50, 50, 50);
g.dispose();
ImageIO.write(image, "PNG", new File("RightColors.png"));
}
public static BufferedImage convertToARGB(BufferedImage image)
{
BufferedImage newImage = new BufferedImage(
image.getWidth(), image.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = newImage.createGraphics();
g.drawImage(image, 0, 0, null);
g.dispose();
return newImage;
}
}