在Java改进中着色图像 [英] Tinting Image in Java improvement

查看:203
本文介绍了在Java改进中着色图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我找了一种简单的方法在Java中为图像着色,但我发现没有什么能满足我的需求。我转到了以下解决方案:

I looked for an easy way to tint an image in Java but I found nothing that suited my needs. I went to the following solution:

首先创建一个新的Image作为我想要着色的Image的副本,然后我创建一个透明的第二个Image我想要着色的图像的掩码,然后在我的副本上绘制色调 - 掩码并返回副本:

First create a new Image that serves as a copy of the Image I want to tint, then I create a second Image that is a transparent mask of the Image I want to tint and then draw the tint - mask over my copy and return the copy:

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 - channel)只是在整个图像上使用fillRect(),但这对于具有透明像素的图像不起作用,因为那些具有所选颜色而不是仍然不可见。

A solution for images that had no transparent pixels (e.g. did not make use of the alpha - channel) was to simply use fillRect() on the whole image, but that didn't work on images with transparent pixels as those then had the chosen color instead of still being invisible.

有没有人知道如何更有效地做到这一点,因为我在这里找到的方法相当令人不满意,我打算在许多图像上进行这种着色(大多数图像都有灰色调,因此它们很容易被在运行时每秒约50次。

Does anyone know a way to do this more efficiently as methods I found here were rather unsatisfying and I plan on doing this tinting on many images (most having a grey-ish tone to them so they are easy to be tinted) at runtime about 50 times per second.

预先生成启动时生成所有需要的图像和/或缓存生成的图像可能是一个解决方案,但在某种程度上感觉很尴尬对我而言,如果无法做任何事情,那么就无法做任何事情。

Pre - Generating all needed images at startup and / or caching generated images might be a solution but it feels awkward in some way to me, though if nothing can be done then nothing can be done.

有人将此联系起来: http://www.javalobby.org/articles/ultimate-image/

这是helpf ul但是没有覆盖着色。

It was helpful but did not cover tinting.

推荐答案

基本上,你需要使用一点黑魔法并且不会有任何伤害一个或两个牺牲......

Essentially, you need to use a little black magic and it wouldn't hurt to have a sacrifice or two on hand...

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

    }

}



<这个技术背后的一般想法是生成图像的掩码,我不相信这个想法,我偷了它的网页,如果我能找到哪里,我会发布一个链接。

The general idea behind this technique is to generate a "mask" of the image, I take no credit of this idea, I stole it of the web, if I can find where, I'll post a link.

一旦有了掩码,就可以将两个图像一起渲染。因为我已经在面具上应用了alpha级别,所以一旦完成,我就不需要重新应用alpha合成。

Once you have the mask, you can then render the two images together. Because I've already applied a alpha level to the mask, I don't need to reapply a alpha composite once I'm done.

PS - 我创建一个兼容的这个例子的图像。我这样做只是因为它会在图形设备上渲染得更快,这不是必需的,它只是我手边的代码;)

PS - I create a compatible image for this example. I do this simply because it will render faster on the graphics device, this is not a requirement, it is simply the code I have on hand ;)

这篇关于在Java改进中着色图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆