Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsWhite Papers
Discussion GroupsFirst AidDatabasesJavaBeansGUIJava 3DVirtual MachineCORBASecurityToolsGeneral
Java DirectoryOpen Source ProjectsSample Book ChaptersUser GroupsWeb Resources
Related Topics
Databases.NETMore Topics ...

Java Forum / First Aid / August 2005

Tip: Looking for answers? Try searching our database.

Drawing translucent masks

Thread view: 
Andreas Koch - 20 Jul 2005 21:33 GMT
Hi all,

i am a absolute java beginner, so please
forgive my errors :-)

I have a little working app that basically
does the following :

1. Load a lot of ImageIcons
2. Create a BufferedImage

Loop
3. Draw all those ImageIcons on the BufferedImage's
Graphics2D
4. Draw the BufferedImage on the paintComponents
Graphics.
/loop

This displays some sprites running over a scrolling
map.

Now i'd like to add "light".
A (variable sized) circular area around the sprites
should be visible, at higher distances the
map should become black.

I basically plan to create a second BufferedImage,
consisting of a solid rectangle with a transparent
hole:

           lightmap = (BufferedImage)(this.createImage(w, h));

           Graphics gi = lightmap.getGraphics();

           gi.setColor(new Color(0,0,0));
           gi.fillRect(0,0,gameImage.getWidth(),gameImage.getHeight());
           gi.setColor(new Color(255,255,255));
           gi.fillOval(0,0,100,100);
...
         gc.drawImage(lightmap,0,0,null);

This works perfectly for creating a white hole,
unfortunately i have no idea how to create a transparent hole
instead.

Googling didn't reveal anything usefull, mostly problems on
loading PNGs and GIFs. I can't just load an image because there
is an infinite amount of possible light sizes.

From windows programming i'd say, i have to "AND" the lightmap
and the target, but how?

Extra gimmick : Binary transparency would be ok, but gradual
translucency (perhaps even per channel, to get for example
warm red light for a fire) would be better :-)

Any suggestions? Using Java 1.5.0_03.

thanks,
  Andreas
Andrew Thompson - 20 Jul 2005 22:26 GMT
>             lightmap = (BufferedImage)(this.createImage(w, h));
>
[quoted text clipped - 3 lines]
>             gi.fillRect(0,0,gameImage.getWidth(),gameImage.getHeight());
>             gi.setColor(new Color(255,255,255));

gi.setColor(new Color(255,255,255, 50 ));

>             gi.fillOval(0,0,100,100);
> ...
[quoted text clipped - 3 lines]
> unfortunately i have no idea how to create a transparent hole
> instead.

Try that..

HTH

Signature

Andrew Thompson
physci.org 1point1c.org javasaver.com lensescapes.com athompson.info
Now Interactive!  Joystick Controls Fry's Left Ear.

Andreas Koch - 21 Jul 2005 17:50 GMT
>>            lightmap = (BufferedImage)(this.createImage(w, h));
>>            Graphics gi = lightmap.getGraphics();
[quoted text clipped - 8 lines]
>>          gc.drawImage(Fullmap,0,0,null);
>>          gc.drawImage(lightmap,0,0,null);

Thanks!
Well, particular success. I perhaps should have added, that i
draw the full picture first on gc, and then try to reduce
visibility by drawing the lightmap above it.

This draws a 50% translucent white oval on the black rectangle.
Unfortunately, gc.drawImage(lightmap doesn't seem to use the
transparency, so all i get when drawing the lightmap on
the level is a black rectangle witha grey oval ...

So, how to do a Graphics2D.drawImage(BufferedImage) with a
BufferedImage that contains translucency (assuming that the
fillOval created translucent pixels, not just gray)?

thanks a lot,
  Andreas
Andrew Thompson - 21 Jul 2005 18:01 GMT
> Thanks!

No worries..

> Well, particular success. I perhaps should have added,  ..

An SSCCE?  <http://www.physci.org/codes/sscce.jsp>

Signature

Andrew Thompson
physci.org 1point1c.org javasaver.com lensescapes.com athompson.info
Mr Bender's Wardrobe By ROBOTANY 500

Andreas Koch - 21 Jul 2005 19:21 GMT
>>Well, particular success. I perhaps should have added,  ..
> An SSCCE?  <http://www.physci.org/codes/sscce.jsp>

Ok. I'm not experienced enough to make that shorter than
86 lines. I ommited the lines that create the JFrame
instance.

---- Start code ----
package peti;
import javax.swing.JFrame;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import javax.swing.*;

public class TMainWindow extends JFrame {
    static final long serialVersionUID = 422323L;
    game gameFace;
    public static void main(String[] args) {
        JFrame windo = new TMainWindow();
        windo.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        windo.setVisible(true);
    }//end main
    public TMainWindow() {
        Container content = this.getContentPane();
        content.setLayout(new BorderLayout());
        gameFace = new game();
        content.add(gameFace, BorderLayout.CENTER);
        this.pack();
        gameFace.start();
    }//end constructor
}//end class gameAnalogBuf
class game extends JPanel {
    static final long serialVersionUID = 422324L;
    private static Image[] TileGfx;
    private BufferedImage gameImage,lightmap;
    private javax.swing.Timer t;
    private Graphics2D gc;
    public game() {
        this.setPreferredSize(new Dimension(694,612));
        this.setBackground(Color.white);
        this.setForeground(Color.black);
        t = new javax.swing.Timer(10,
              new ActionListener() {
                  public void actionPerformed(ActionEvent e) {
                      update();
                  }
              });
        TileGfx = new Image[1];
        ClassLoader loader = this.getClass().getClassLoader();
        // load a floor tile 32 x 32 pixelsj
        TileGfx[0] = new
ImageIcon(loader.getResource("peti/images/0196.png")).getImage();
     }//end constructor
    public void update() {
        this.repaint();
    }//end update
    public void start() {
        t.start();
    }//end start
    public void stop() {
        t.stop();
    }//end stop
    public void paintComponent(Graphics g) {
        super.paintComponent(g);  // paint background, borders
        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
        int w = getWidth();
        int h = getHeight();
        if (gameImage == null
                || gameImage.getWidth() != w
                || gameImage.getHeight() != h) {
            gameImage = (BufferedImage)(this.createImage(w, h));
                  }
        if (gc == null)
         { gc = gameImage.createGraphics();
           gc.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
           lightmap = (BufferedImage)(this.createImage(w, h));
           Graphics gi = lightmap.getGraphics();
           gi.setColor(new Color(0,0,0));
           gi.fillRect(0,0,gameImage.getWidth(),gameImage.getHeight());
           gi.setColor(new Color(255,255,255,90));
           gi.fillOval(0,0,100,100);
         }
       int x,y,ofs;
       for (x=0;x<15;x++) // draw tiles
         for (y=0;y<12;y++)
           gc.drawImage(TileGfx[0],18+x*32,8+(y*32),32,32,null);
       //gc.drawImage(lightmap,0,0,null); // mask with lightmap
       g2.drawImage(gameImage, null, 0, 0); // show result
    }//end paintComponent
}//endclass game

--- end code ---
This will show a map of 15*12 tiles (whatever 32x32 pixel
0196.png you provided).

If i uncomment the

       //gc.drawImage(lightmap,0,0,null); // mask with lightmap

line,

it shows a black rectangle with a gray circle instead.
What i want:
A gray circle filled with tiles, everything out of that
circle, black:

+--+--+--+
|  |  |  |
+--+--+--+
|  |  |  |
+--+--+--+
|  |  |  |
+--+--+--+

plus

##########
###  #####
##    ####
#      ###
#      ###
##    ####
###  #####

should become

##########
###| #####
##-+--####
#  |  |###
#--+--+###
## |  ####
###+-#####

Hope this makes things clear enough :-)

Any ideas, now?

thanks,
  Andreas
Knute Johnson - 22 Jul 2005 16:35 GMT
>>> Well, particular success. I perhaps should have added,  ..
>>
[quoted text clipped - 141 lines]
> thanks,
>   Andreas

Andreas:

Sorry I didn't look carefully at your post sooner.  Here is a simple
solution to what you want to do.  Draw your background color, set the
clip region to a Shape (ellipse in this case), and draw your image.  The
Grahpics2D classes have hundreds of very interesting methods for doing
just this sort of work.

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.awt.image.*;
import java.io.*;
import javax.imageio.*;

public class test8 extends Canvas {
    BufferedImage image;

    public test8() {
        try {
            image = ImageIO.read(new File("someimage.jpg"));
            setPreferredSize(new Dimension(image.getWidth(),
              image.getHeight()));
        } catch (IOException ioe) {
            System.out.println(ioe);
            System.exit(0);
        }
    }

    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D)g;
        g2d.setColor(Color.BLACK);
        g2d.fillRect(0,0,getWidth(),getHeight());
        g2d.clip(new Ellipse2D.Double(200.0,100.0,200.0,200.0));
        g2d.drawImage(image,0,0,this);
    }

    public static void main(String[] args) {
        Frame f = new Frame();
        f.addWindowListener(new WindowAdapter() {
            public void windowClosing(WindowEvent we) {
                System.exit(0);
            }
        });
        test8 t8 = new test8();
        f.add(t8,BorderLayout.CENTER);
        f.pack();
        f.setVisible(true);
    }
}

Signature

Knute Johnson
email s/nospam/knute/

Andreas Koch - 24 Jul 2005 10:09 GMT
Hi Knute,

thanks a lot for that example.
This allows a first minimalistic way to solve the issue.

Problems i still have:

1) The real game will have many light sources (circles)
I could draw them all by setting the clipping ellipse
(via SetClip) for each light source, draw the map through
it, repeat. I expect this to be pretty slow, and i want
the game to be usable on slow computers.

2) I could probably use Area-clipping for doing all
circles at once instead, but i found now way to add
Ellipse2D's to Area's.

3) While clipping is better than nothing, anything that
would allow me translucency (e.g. soft borders) or perhaps
colored translucency (for differenct light colors) would
look much better :-) Is there ANY way of doing this?
Can i (do i have to...) access the images at byte level
and manually do the calculations?

thanks,
  Andreas
Knute Johnson - 24 Jul 2005 16:54 GMT
> Hi Knute,
>
[quoted text clipped - 8 lines]
> it, repeat. I expect this to be pretty slow, and i want
> the game to be usable on slow computers.

It really depends on how many you want to draw and how fast.  Do you
need to redraw all of the circles every time?

> 2) I could probably use Area-clipping for doing all
> circles at once instead, but i found now way to add
> Ellipse2D's to Area's.

I don't think there is a way to do that.

> 3) While clipping is better than nothing, anything that
> would allow me translucency (e.g. soft borders) or perhaps
> colored translucency (for differenct light colors) would
> look much better :-) Is there ANY way of doing this?
> Can i (do i have to...) access the images at byte level
> and manually do the calculations?

    public void paint(Graphics g) {
        Graphics2D g2d = (Graphics2D)g;
        g2d.setColor(Color.BLACK);
        g2d.fillRect(0,0,getWidth(),getHeight());
        g2d.clip(new Ellipse2D.Double(200.0,100.0,200.0,200.0));
        g2d.drawImage(image,0,0,this);

g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,.5f));
        g2d.setColor(Color.RED);
        g2d.fillRect(0,0,getWidth(),getHeight());
    }

This adds a red overlay to the image.  You could also draw a color
underneath and AlphaComposite the drawing of the image.

> thanks,
>   Andreas

Signature

Knute Johnson
email s/nospam/knute/

Andreas Koch - 24 Jul 2005 17:40 GMT
Hi Knute,

>> 1) The real game will have many light sources (circles)
>> I could draw them all by setting the clipping ellipse
[quoted text clipped - 4 lines]
> It really depends on how many you want to draw and how fast.  Do you
> need to redraw all of the circles every time?

I will have a map (of which a part will be visible inside the
light circles) which i want to update as fast as possible, at least
20 times per second.

Then i have the lightmap which specifies which parts of the
map are visible and which parts have to be "clipped". That would
only have to change when a light moves (which could be between
once every map update or never, depending on what game objects
are moving...)

With my simple, scrolling, unmasked map i get ~100 fps.
Oh, just did a little testing. The performance hit is
measureable, but not as bad as i expected:

100x100 ellipses   fps
1                  99
2          99
3              99
4          99
5          91  (! nice jump...)
10          69
20          45
50              23
100          13

>     public void paint(Graphics g) {
>         Graphics2D g2d = (Graphics2D)g;
[quoted text clipped - 10 lines]
> This adds a red overlay to the image.  You could also draw a color
> underneath and AlphaComposite the drawing of the image.

Ahhh, that looks nice... BUT drops my framerate for a single 100x100
light from 100 fps to 53 fps (33 fps for 5 lights)

Plus, to get "soft" borders i would have to draw multiple ellipses
per light source :-/
Knute Johnson - 24 Jul 2005 18:49 GMT
> Hi Knute,
>
[quoted text clipped - 53 lines]
> Plus, to get "soft" borders i would have to draw multiple ellipses
> per light source :-/

You can increase the speed of some of this by using VolatileImages.  If
you want a fuzzy border, create an image to use as your overlay with
varying alpha and draw that on top instead of the fillRect.  Don't
repaint what you don't absolutely have to repaint.

Signature

Knute Johnson
email s/nospam/knute/

Sathish Kumar Raju - 01 Aug 2005 10:22 GMT
Hi All,
Iam new to this group and i know only basic fundas of Java. Iam writing
an java applet which connects to the database and retrieves data.
It runs when iam running from jdeveloper ..but when run thru a browser
it is giving the following exception.

java.security.AccessControlException: access denied
(java.net.SocketPermission ab123x1.us.xyz.com resolve)

And also Iam using File IO...i hope it will also won't work
since there is security issues..and the file is in the CLIENT side..

Please help me in this issue.

thnx,
Sathish


Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.