我找了一种简单的方法用Java调色图像,但我找不到任何适合我需要的东西。我采用了以下解决方案:
首先创建一个新图像,作为我想要着色的图像的副本,然后我创建第二个图像,它是我想要着色的图像的透明蒙版,然后在我的副本上绘制色调 - 蒙版返回副本:
public static BufferedImage tintImage(Image original, int r, int g, int b){
int width = original.getWidth(null);
int height = original.getHeight(null);
BufferedImage tinted = new BufferedImage(width, height, BufferedImage.TRANSLUCENT);
Graphics2D graphics = (Graphics2D) tinted.getGraphics();
graphics.drawImage(original, 0, 0, width, height, null);
Color c = new Color(r,g,b,128);
Color n = new Color(0,0,0,0);
BufferedImage tint = new BufferedImage(width, height, BufferedImage.TRANSLUCENT);
for(int i = 0 ; i < width ; i++){
for(int j = 0 ; j < height ; j++){
if(tinted.getRGB(i, j) != n.getRGB()){
tint.setRGB(i, j, c.getRGB());
}
}
}
graphics.drawImage(tint, 0, 0, null);
graphics.dispose();
return tinted;
}
没有透明像素的图像解决方案(例如没有使用alpha通道)只是在整个图像上使用fillRect(),但这对于具有透明像素的图像不起作用有选择的颜色,而不是仍然不可见。
有没有人知道如何更有效地做到这一点,因为我在这里找到的方法相当不满意,我打算对许多图像进行这种着色(大多数图像都有灰色调,因此它们很容易被着色)运行时间约为每秒50次。
预先生成启动时生成所有需要的图像和/或缓存生成的图像可能是一种解决方案,但在某些方面对我来说感觉很尴尬,但如果不能做任何事情就可以做任何事情。
有人联系到了这一点:http://www.javalobby.org/articles/ultimate-image/
这很有帮助,但没有涵盖着色。
答案 0 :(得分:6)
基本上,你需要使用一点黑魔法,手头上有一两个牺牲也不会有什么伤害......
public class TestTint {
public static void main(String[] args) {
new TestTint();
}
public TestTint() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public static GraphicsConfiguration getGraphicsConfiguration() {
return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration();
}
public static BufferedImage createCompatibleImage(int width, int height, int transparency) {
BufferedImage image = getGraphicsConfiguration().createCompatibleImage(width, height, transparency);
image.coerceData(true);
return image;
}
public static void applyQualityRenderingHints(Graphics2D g2d) {
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_PURE);
}
public static BufferedImage generateMask(BufferedImage imgSource, Color color, float alpha) {
int imgWidth = imgSource.getWidth();
int imgHeight = imgSource.getHeight();
BufferedImage imgMask = createCompatibleImage(imgWidth, imgHeight, Transparency.TRANSLUCENT);
Graphics2D g2 = imgMask.createGraphics();
applyQualityRenderingHints(g2);
g2.drawImage(imgSource, 0, 0, null);
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_IN, alpha));
g2.setColor(color);
g2.fillRect(0, 0, imgSource.getWidth(), imgSource.getHeight());
g2.dispose();
return imgMask;
}
public BufferedImage tint(BufferedImage master, BufferedImage tint) {
int imgWidth = master.getWidth();
int imgHeight = master.getHeight();
BufferedImage tinted = createCompatibleImage(imgWidth, imgHeight, Transparency.TRANSLUCENT);
Graphics2D g2 = tinted.createGraphics();
applyQualityRenderingHints(g2);
g2.drawImage(master, 0, 0, null);
g2.drawImage(tint, 0, 0, null);
g2.dispose();
return tinted;
}
public class TestPane extends JPanel {
private BufferedImage master;
private BufferedImage mask;
private BufferedImage tinted;
public TestPane() {
try {
master = ImageIO.read(new File("C:/Users/swhitehead/Documents/My Dropbox/MegaTokyo/Miho_Small.png"));
mask = generateMask(master, Color.RED, 0.5f);
tinted = tint(master, mask);
} catch (IOException exp) {
exp.printStackTrace();
}
}
@Override
public Dimension getPreferredSize() {
Dimension size = super.getPreferredSize();
if (master != null && mask != null) {
size = new Dimension(master.getWidth() + mask.getWidth() + tinted.getWidth(), Math.max(Math.max(master.getHeight(), mask.getHeight()), tinted.getHeight()));
}
return size;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int x = (getWidth() - (master.getWidth() + mask.getWidth() + tinted.getWidth())) / 2;
int y = (getHeight() - master.getHeight()) / 2;
g.drawImage(master, x, y, this);
x += mask.getWidth();
y = (getHeight() - mask.getHeight()) / 2;
g.drawImage(mask, x, y, this);
x += tinted.getWidth();
y = (getHeight() - tinted.getHeight()) / 2;
g.drawImage(tinted, x, y, this);
}
}
}
这种技术背后的一般想法是生成图像的“面具”,我不相信这个想法,我偷了它的网页,如果我能找到哪里,我会发布链接。
一旦有了面具,就可以将两个图像一起渲染。因为我已经在面具上应用了alpha级别,所以在完成后我不需要重新应用alpha合成。
PS - 我为此示例创建了兼容的图像。我这样做只是因为它会在图形设备上渲染得更快,这不是必需的,它只是我手边的代码;)