Java2D Alpha映射图像

Java2D Alpha映射图像,java,swing,graphics,Java,Swing,Graphics,使用Graphics2D,我如何拍摄黑白图像,并使用它定义应该在另一个图像上渲染什么和不应该在另一个图像上渲染什么 例如,如果我有一个图像,比如说,一个字段,在该字段上是一头奶牛,在另一个相同尺寸的图像上,我在黑色背景上,在奶牛的相同坐标处绘制一个白色框,当用Java渲染时,除了我有白色框的奶牛之外,图像将全部为黑色 编辑:根据聊天中的长时间讨论,很明显对意图存在误解,最初的问题是:如何使用遮罩图像合成图像的问题只是实际问题的一个解决方案尝试-即在瓷砖地图上绘制一些阴影/灯光效果。文章的原始版本

使用Graphics2D,我如何拍摄黑白图像,并使用它定义应该在另一个图像上渲染什么和不应该在另一个图像上渲染什么

例如,如果我有一个图像,比如说,一个字段,在该字段上是一头奶牛,在另一个相同尺寸的图像上,我在黑色背景上,在奶牛的相同坐标处绘制一个白色框,当用Java渲染时,除了我有白色框的奶牛之外,图像将全部为黑色

编辑:根据聊天中的长时间讨论,很明显对意图存在误解,最初的问题是:如何使用遮罩图像合成图像的问题只是实际问题的一个解决方案尝试-即在瓷砖地图上绘制一些阴影/灯光效果。文章的原始版本可以在修订历史中看到

实际目标显然是在图像上添加灯光效果。以下是如何实现这一目标的示例:

原始图像绘制在背景中 在图像上绘制阴影图像。 阴影图像最初是一个近乎不透明、近乎黑色的图像。使用RadialGradientPaint将灯光绘制到此图像中。选择此绘制的颜色是为了使阴影图像在灯光应该出现的位置不那么不透明和黑色。这会使这些区域看起来亮起,而其他部分保持黑暗

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MultipleGradientPaint.CycleMethod;
import java.awt.Point;
import java.awt.RadialGradientPaint;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class LightEffectTest2
{
    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new LightEffectTest2();
            }
        });
    }


    public LightEffectTest2()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(new LightEffectPanel2());
        f.setSize(600,600);
        f.setVisible(true);
    }
}


class LightEffectPanel2 extends JPanel implements MouseMotionListener
{
    private Point point = new Point(0,0);
    private BufferedImage image;
    private BufferedImage shadow;

    public LightEffectPanel2()
    {
        image = createExampleImage(600,600);
        shadow = new BufferedImage(image.getWidth(), image.getHeight(),
            BufferedImage.TYPE_INT_ARGB);

        addMouseMotionListener(this);
    }

    private static BufferedImage createExampleImage(int w, int h)
    {
        BufferedImage image = new BufferedImage(w, h, 
            BufferedImage.TYPE_INT_ARGB);
        Graphics g = image.getGraphics();
        Random random = new Random(0);
        for (int i=0; i<200; i++)
        {
            int x = random.nextInt(w);
            int y = random.nextInt(h);
            Color c = new Color(
                random.nextInt(255),
                random.nextInt(255),
                random.nextInt(255));
            g.setColor(c);
            g.fillOval(x-20, y-20, 40, 40);
        }
        g.dispose();
        return image;
    }


    @Override
    protected void paintComponent(Graphics gr)
    {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D)gr;
        g.drawImage(image, 0,0,null);

        drawLights();

        g.drawImage(shadow, 0,0, null);
    }

    private void drawLights()
    {
        Graphics2D g = shadow.createGraphics();
        g.setComposite(AlphaComposite.Src);
        g.setColor(new Color(0,0,16,240));
        g.fillRect(0,0,getWidth(),getHeight());

        drawLight(g, new Point(100,100));
        drawLight(g, point);

        g.dispose();
    }

    private void drawLight(Graphics2D g, Point pt)
    {
        float radius = 100;
        g.setComposite(AlphaComposite.DstOut);
        Point2D center = new Point2D.Float(pt.x, pt.y);
        float[] dist = {0.0f, 1.0f};
        Color[] colors = {new Color(255,255,255,255), new Color(0,0,0,0) };
        RadialGradientPaint p =
            new RadialGradientPaint(
                center, radius, dist, colors, CycleMethod.NO_CYCLE);
        g.setPaint(p);
        g.fillOval(pt.x-(int)radius,pt.y-(int)radius,(int)radius*2,(int)radius*2);
    }



    @Override
    public void mouseDragged(MouseEvent e) {
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        point = e.getPoint();
        repaint();
    }
}
编辑:根据聊天中的长时间讨论,很明显对意图存在误解,最初的问题是:如何使用遮罩图像合成图像的问题只是实际问题的一个解决方案尝试-即在瓷砖地图上绘制一些阴影/灯光效果。文章的原始版本可以在修订历史中看到

实际目标显然是在图像上添加灯光效果。以下是如何实现这一目标的示例:

原始图像绘制在背景中 在图像上绘制阴影图像。 阴影图像最初是一个近乎不透明、近乎黑色的图像。使用RadialGradientPaint将灯光绘制到此图像中。选择此绘制的颜色是为了使阴影图像在灯光应该出现的位置不那么不透明和黑色。这会使这些区域看起来亮起,而其他部分保持黑暗

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MultipleGradientPaint.CycleMethod;
import java.awt.Point;
import java.awt.RadialGradientPaint;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class LightEffectTest2
{
    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new LightEffectTest2();
            }
        });
    }


    public LightEffectTest2()
    {
        JFrame f = new JFrame();
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(new LightEffectPanel2());
        f.setSize(600,600);
        f.setVisible(true);
    }
}


class LightEffectPanel2 extends JPanel implements MouseMotionListener
{
    private Point point = new Point(0,0);
    private BufferedImage image;
    private BufferedImage shadow;

    public LightEffectPanel2()
    {
        image = createExampleImage(600,600);
        shadow = new BufferedImage(image.getWidth(), image.getHeight(),
            BufferedImage.TYPE_INT_ARGB);

        addMouseMotionListener(this);
    }

    private static BufferedImage createExampleImage(int w, int h)
    {
        BufferedImage image = new BufferedImage(w, h, 
            BufferedImage.TYPE_INT_ARGB);
        Graphics g = image.getGraphics();
        Random random = new Random(0);
        for (int i=0; i<200; i++)
        {
            int x = random.nextInt(w);
            int y = random.nextInt(h);
            Color c = new Color(
                random.nextInt(255),
                random.nextInt(255),
                random.nextInt(255));
            g.setColor(c);
            g.fillOval(x-20, y-20, 40, 40);
        }
        g.dispose();
        return image;
    }


    @Override
    protected void paintComponent(Graphics gr)
    {
        super.paintComponent(gr);
        Graphics2D g = (Graphics2D)gr;
        g.drawImage(image, 0,0,null);

        drawLights();

        g.drawImage(shadow, 0,0, null);
    }

    private void drawLights()
    {
        Graphics2D g = shadow.createGraphics();
        g.setComposite(AlphaComposite.Src);
        g.setColor(new Color(0,0,16,240));
        g.fillRect(0,0,getWidth(),getHeight());

        drawLight(g, new Point(100,100));
        drawLight(g, point);

        g.dispose();
    }

    private void drawLight(Graphics2D g, Point pt)
    {
        float radius = 100;
        g.setComposite(AlphaComposite.DstOut);
        Point2D center = new Point2D.Float(pt.x, pt.y);
        float[] dist = {0.0f, 1.0f};
        Color[] colors = {new Color(255,255,255,255), new Color(0,0,0,0) };
        RadialGradientPaint p =
            new RadialGradientPaint(
                center, radius, dist, colors, CycleMethod.NO_CYCLE);
        g.setPaint(p);
        g.fillOval(pt.x-(int)radius,pt.y-(int)radius,(int)radius*2,(int)radius*2);
    }



    @Override
    public void mouseDragged(MouseEvent e) {
    }

    @Override
    public void mouseMoved(MouseEvent e) {
        point = e.getPoint();
        repaint();
    }
}

遮罩的实际颜色是否有任何影响,或者始终存在完全黑色或完全白色的像素?您是否对如何创建或表示遮罩有任何影响,即遮罩是否也可以存储为alpha值?。如果面具被描述成一个形状,这会对你有好处吗?这会容易得多,还是它必须是一个图像?是否要创建遮罩图像然后进行绘制,还是要在绘制原始图像时应用遮罩进行绘制?如果你有更好的方法,请推荐一些。我只想用它来创建一个照明贴图,这样我就可以有一个级别的瓷砖,然后我的照明贴图和瓷砖的亮度取决于照明贴图。有人告诉我Alpha合成是一种很好的方法。遮罩的实际颜色是否会有任何影响,还是总是有完全黑色或完全白色的像素?您是否对如何创建或表示遮罩有任何影响,即遮罩是否也可以存储为alpha值?。如果面具被描述成一个形状,这会对你有好处吗?这会容易得多,还是它必须是一个图像?是否要创建遮罩图像然后进行绘制,还是要在绘制原始图像时应用遮罩进行绘制?如果你有更好的方法,请推荐一些。我只想用它来创建一个照明贴图,这样我就可以有一个级别的瓷砖,然后我的照明贴图和瓷砖的亮度取决于照明贴图。我被告知Alpha合成是一种很好的方法,所以我画了基础图像,将合成设置为DstOut,然后画了遮罩?在这种情况下,是的。这取决于如何定义遮罩。但是当应该可见的部分由不透明度0定义,而应该隐藏的部分由不透明度255定义时,则可以这样做。大多数图像编辑软件将alpha贴图表示为黑白图像,这一定是我感到困惑的地方。我正在像这样绘制我的光照图:lightmap.getGraphics.setColornew Color0,0,0;lightMap.getGraphics.fillRect0,01080720;lightMap.getGraphics.setColornew Color0,0,0;lightMap.getGraphics.fillrect300300300;屏幕仍然是全黑的吗?@KisnardOnline关于图像,我曾经创建过这个示例,我基本上是结合了
它们需要构建,但后者使用多个灯光来实现稍微柔和的阴影,这太慢了,无法在实践中使用。但是,将这两种方法与单个灯光和硬阴影相结合是完全可行的。也许有一天我会把这些都扔到GitHub上,似乎有这样的需求……所以我画了基础图像,将合成设置为DstOut,然后画了遮罩?在这种情况下,是的。这取决于如何定义遮罩。但是当应该可见的部分由不透明度0定义,而应该隐藏的部分由不透明度255定义时,则可以这样做。大多数图像编辑软件将alpha贴图表示为黑白图像,这一定是我感到困惑的地方。我正在像这样绘制我的光照图:lightmap.getGraphics.setColornew Color0,0,0;lightMap.getGraphics.fillRect0,01080720;lightMap.getGraphics.setColornew Color0,0,0;lightMap.getGraphics.fillrect300300300;屏幕仍然是全黑的吗?@KisnardOnline关于图像,我曾经创建过这个示例,我基本上将它们组合起来构建,但后者使用多个灯光来实现一些柔和的阴影,这太慢了,无法在实践中使用。但是,将这两种方法与单个灯光和硬阴影相结合是完全可行的。也许有一天我会把这一切都扔到GitHub上,似乎有这样的需求。。。。