尝试做一些相对简单的事情,给定512x512 png的地图,我试图绘制点。我的代码相当简单,我尝试使用setRGB函数和createGraphics函数返回的Graphics2D对象。我必须忽略一些简单的事情。编辑:我应该提到我不打算创建一个新的BufferedImage,我正在寻找修改现有的BufferedImage,因为连续的库调用将继续修改我正在使用的BufferedImage。 (在下面的示例代码中,我从文件中读取了BufferedImage,这是一种复制问题的简单方法。
File outputImage = new File("before.png");
BufferedImage img = ImageIO.read(outputImage);
img.setRGB(255, 255, new Color(0f, 1f, 0).getRGB());
File after = new File("after.png");
ImageIO.write(img, "png", after);
如果你放大得到的像素,它不是绿色,而是一些深灰色。由于这种行为与Graphics2D一致,我希望解决这个问题也能解决这个问题。
答案 0 :(得分:3)
BufferedImage的色彩空间必定会导致问题。
在下面的代码中,我使用原始图像并将其绘制为具有指定色彩空间的BufferedImage:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;
import java.io.*;
import javax.imageio.*;
import java.net.*;
public class SSCCE extends JPanel
{
SSCCE()
{
try
{
BufferedImage original = ImageIO.read( new File("map.png") );
int width = original.getWidth(null);
int height = original.getHeight(null);
int size = 100;
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = bi.createGraphics();
g2d.drawImage(original, 0, 0, null);
int color = new Color(0f, 1f, 0f).getRGB();
bi.setRGB(10, 10, color);
bi.setRGB(10, 11, color);
bi.setRGB(11, 10, color);
bi.setRGB(11, 11, color);
add( new JLabel( new ImageIcon(bi) ) );
}
catch(Exception e2) {}
}
private static void createAndShowGUI()
{
JFrame frame = new JFrame("SSCCE");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new SSCCE());
frame.pack();
frame.setLocationByPlatform( true );
frame.setVisible( true );
}
public static void main(String[] args)
{
EventQueue.invokeLater( () -> createAndShowGUI() );
/*
EventQueue.invokeLater(new Runnable()
{
public void run()
{
createAndShowGUI();
}
});
*/
}
}
答案 1 :(得分:1)
以下是根据评论中的讨论,尝试描述一些可以解决问题的方法:
问题是原始图像使用IndexColorModel
(或颜色贴图或“调色板”,如果您愿意)。没有绿色完全与您指定的颜色匹配,因此颜色模型会进行查找以获得“最接近”颜色到您指定的颜色(您可以不同意这种颜色是最接近的匹配,但它给出了使用的算法)。
如果将颜色设置为与图像颜色匹配的颜色,则可以使用该颜色进行绘制。对于浅绿色的,请尝试new Color(0.8f, 0.9019608f, 0.6392157f)
或RGB值0xffcce6a3
。使用new Color(0.6392157f, 0.8f, 1f)
或0xffa3ccff
作为浅蓝色。
如果您想知道我是如何找到这些值的,这就是解释。假设colorModel
是IndexColorModel
,您可以使用:
int[] rgbs = new int[colorModel.getMapSize()];
colorModel.getRGBs(rgbs);
...获取颜色图中的颜色。选择其中一种颜色应始终有效。
现在,如果你的“库”(你没有透露太多细节)使用固定的调色板来生成这些图像,那么你很好,并且可以使用我提到的颜色之一,或者使用所描述的方法获取颜色,并选择合适的颜色。如果没有,您需要动态找到最佳颜色。如果你真的没有运气,可能根本就没有合适的颜色(即,你的地图瓷砖都是海洋,唯一可用的颜色是海蓝色,不可能绘制绿点)。然后除了修改库之外别无他法解决这个问题。
一种完全不同的方法,可以类似于@ camickr的解决方案,您可以暂时将图像转换为真彩色(BufferedImage.TYPE_INT_RGB
或TYPE_3BYTE_BGR
),将您的更改绘制到此临时图像上,然后绘制图像回到原始。这个可能更好地工作的原因是,组合机制将使用抖动和更好的颜色查找算法。但是你仍然会遇到与上一段所述的可用颜色相关的问题。
这是一个代码示例,使用暖黄色和输出:
Color color = new Color(0.89411765f, 0.5686275f, 0.019607844f);
int argb = color.getRGB();
Graphics2D g = image.createGraphics();
try {
g.setColor(color);
g.fillRect(10, 10, 50, 50);
}
finally {
g.dispose();
}