【问题标题】:Drawing to a BufferedImage sometimes, but consistently, yields wrong colors绘制到 BufferedImage 有时但始终会产生错误的颜色
【发布时间】:2017-11-30 23:33:33
【问题描述】:

我写了一个修改图片的程序。

首先,我得到图像,并像这样得到它的绘图上下文:

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 的颜色是我想要的粉色阴影。

cmets 似乎暗示用户打开的图像可能有一些颜色限制,并且由于我正在绘制相同的图像,因此我的程序必须遵守这些限制。示例图像似乎是相当灰度的,显然它的位深度是 8 位。所以也许我在上面画的粉红色被转换为灰度,因为图像必须保持 8 位?

【问题讨论】:

  • 有没有机会提供一个设置(即minimal reproducible example 和示例图片),以便可以重现此问题?
  • 颜色模型可能不支持您使用的颜色
  • @Marco13 我在我的问题中添加了一个示例。
  • @MadProgrammer 你的意思是我必须处理读取 BufferedImage 的图像的限制吗?就像从 GIF 中读取的一样,我必须使用它附带的 256 种颜色?
  • 我会更担心目标颜色模型

标签: java graphics bufferedimage


【解决方案1】:

正如 cmets 中所建议的,这里的主要问题确实是错误的颜色模型。当您加载原始图像并打印有关它的一些信息时......

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-04
    • 2011-10-07
    • 2012-07-01
    • 1970-01-01
    相关资源
    最近更新 更多