Java2D Alpha映射图像 [英] Java2D Alpha Mapping images

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

问题描述

使用Graphics2D,我如何拍摄黑白图像,并用它来定义应该在另一个图像上显示的内容和内容?

例如,如果我有一个说,一个领域的图像,在该领域是一头牛,而在另一个相同尺寸的图像上,我在黑色背景上绘制了一个白色方框,与母牛的坐标相同,使用Java渲染时,图像会全是黑色的,除了那个我有白色盒子的牛?

解决方案


编辑:基于在聊天中的长时间讨论中,很明显,对意图存在误解,原始问题出现在



(阴影在这里给出了一个更清晰的边框,以便更清晰地看到效果)

  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;
导入javax.swing.SwingUtilities;

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


$ b public LightEffectTest3()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane()。add(new LightEffectPanel3());
f.setSize(600,600);
f.setVisible(true);




class LightEffectPanel3扩展JPanel实现MouseMotionListener
{
private Point point = new Point(0,0);
私有BufferedImage图像;
私有BufferedImage影子;

public LightEffectPanel3()
{
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 );
图形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);
颜色c =新颜色(
random.nextInt(255),
random.nextInt(255),
random.nextInt(255));
g.setColor(c);
g.fillOval(x-20,y-20,40,40);
}
g.dispose();
返回图片;



@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,新点(200,200));
drawLight(g,point);
drawShadow(g,new Point(250,250));

g.dispose();


private void drawLight(Graphics2D g,Point pt)
{
float radius = 150;
g.setComposite(AlphaComposite.DstOut);
Point2D center = new Point2D.Float(pt.x,pt.y);
float [] dist = {0.0f,1.0f};
颜色[]颜色= {新颜色(255,255,255,255),新颜色(0,0,0,0)};
RadialGradientPaint p =
新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);


private void drawShadow(Graphics2D g,Point pt)
{
float radius = 75;
g.setComposite(AlphaComposite.DstOver);
Point2D center = new Point2D.Float(pt.x,pt.y);
float [] dist = {0.0f,0.7f,1.0f};
颜色[]颜色= {
新颜色(0,0,0,200),
新颜色(0,0,0,150),
新颜色(255,255,255,0)} ;
RadialGradientPaint p =
新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();
}
}


Using Graphics2D, how can I take a black and white image, and use to define what should and what shouldn't rendered on another image?

E.g if I had an image of say, a field, and on that field is a cow, and on another image of the same dimensions I draw a white box on a black background, at the same coordinates of the cow, when rendered in Java the image would be all black, apart from the cow where I had the white box?

解决方案

EDIT: Based on a long discussion in the chat, it became clear that there was a misunderstanding about the intention, and the original question suffered from the XY-Problem: The question of how to compose an image with a masking image was only about one solution attempt for the actual problem - namely painting some shadow/light effects on a tile map. The original versions of the post can be seen in the revision history.

The actual goal was obviously to add a "light effect" over the image. Here is an example of how this can be achieved:

  • The original image is painted in the background
  • A "shadow image" is painted over the image.

The "shadow image" is initially a nearly opaqe, nearly black image. The lights are painted into this image, with a RadialGradientPaint. The colors for this paint are chosen so that they make the shadow image less opaque and less black at the places where the lights should be. This causes these areas to appear lighted, while the other parts remain dark.

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


(late) EDIT For the request in the comments:

To add another shadow (regardless of the existing lights), one can create a drawShadow method that re-applies the shadows after the lights have been drawn. It basically uses another RadialGradientPaint that partially "restores" the original, opaqe, dark shadow image.

(The shadow is given a somewhat sharper border here, to make the effect more visible)

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 LightEffectTest3
{
    public static void main(String args[])
    {
        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                new LightEffectTest3();
            }
        });
    }


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


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

    public LightEffectPanel3()
    {
        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(200,200));
        drawLight(g, point);
        drawShadow(g, new Point(250,250));

        g.dispose();
    }

    private void drawLight(Graphics2D g, Point pt)
    {
        float radius = 150;
        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);
    }

    private void drawShadow(Graphics2D g, Point pt)
    {
        float radius = 75;
        g.setComposite(AlphaComposite.DstOver);
        Point2D center = new Point2D.Float(pt.x, pt.y);
        float[] dist = {0.0f, 0.7f, 1.0f};
        Color[] colors = { 
            new Color(0,0,0,200),
            new Color(0,0,0,150),
            new Color(255,255,255,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();
    }
}

这篇关于Java2D Alpha映射图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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