Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to fade FG without losing BG?

3 views
Skip to first unread message

Andrew Thompson

unread,
Jul 21, 2006, 12:34:43 AM7/21/06
to
In this example, I am attempting (and failing) to fade
the foreground BufferedImage (an animated red ball),
without losing the BufferedImage in the background
(white with a black 'X').

As it is, the ball in the foreground image fades, but
the background fades to black along with it.

Is there any way I can 'have my cake and eat it too'?

<sscce>
import java.awt.*;
import java.awt.image.*;
import javax.swing.*;

public class FadeComponent
extends JPanel
implements Runnable {

BufferedImage bg;
BufferedImage fg;
BufferedImage buffer;
int w = 300;
int h = w;

int x=0;
int y=0;
int size = 10;

FadeComponent() {
bg = new BufferedImage(
w, h, BufferedImage.TYPE_INT_ARGB );
Graphics gBG = bg.getGraphics();
gBG.setColor(Color.WHITE);
gBG.fillRect(0,0,w,h);
gBG.setColor(Color.BLACK);
gBG.drawLine(0,0,w,h);
gBG.drawLine(0,h,w,0);

fg = new BufferedImage(
w, h, BufferedImage.TYPE_INT_ARGB );
Graphics gFG = bg.getGraphics();
gFG.setColor(Color.RED);
gFG.fillOval(x,y,size,size);

buffer = new BufferedImage(
w, h, BufferedImage.TYPE_INT_ARGB );

Thread t = new Thread(this);
t.start();
}

public void run() {
while(true) {
repaint();
try {
Thread.sleep(40);
} catch(InterruptedException ie) {
// continue..
}
}
}

public Dimension getPreferredSize() {
return new Dimension(300,300);
}

public void paintComponent(Graphics g) {
Graphics gBuffer = buffer.getGraphics();
gBuffer.drawImage( bg,0,0,w,h,null );

Graphics gFG = fg.getGraphics();
gFG.setColor( new Color(0,0,0,10) );
gFG.fillRect( 0,0,w,h );
gFG.setColor(Color.RED);
gFG.fillOval(++x,++y,size,size);

gBuffer.drawImage( fg,0,0,w,h,null );

g.drawImage( buffer,0,0,w,h,null );
if (x>w) {
x=0;
y=0;
}
}

public static void main(String[] args) {
JFrame f = new JFrame( "Fade Test" );
FadeComponent fc = new FadeComponent();
f.getContentPane().add(fc);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}
</sscce>

Andrew T.

Andrey Kuznetsov

unread,
Jul 21, 2006, 2:16:24 AM7/21/06
to
> In this example, I am attempting (and failing) to fade
> the foreground BufferedImage (an animated red ball),
> without losing the BufferedImage in the background
> (white with a black 'X').
>
> As it is, the ball in the foreground image fades, but
> the background fades to black along with it.

don't draw bg image to buffer, draw it to fg and throw away black rect.

I optimized also a bit your code (caching of Graphics):


import java.awt.*;
import java.awt.image.*;
import javax.swing.*;

public class FadeComponent extends JPanel implements Runnable {

BufferedImage bg;

BufferedImage fg;
Graphics2D gFG;

BufferedImage buffer;
Graphics gBuffer;

AlphaComposite composite =
AlphaComposite.getInstance(AlphaComposite.SRC_OVER, .1f);

int w = 300;
int h = w;

int x = 0;
int y = 0;
int size = 10;

FadeComponent() {
bg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
Graphics gBG = bg.getGraphics();
gBG.setColor(Color.WHITE);
gBG.fillRect(0, 0, w, h);
gBG.setColor(Color.BLACK);
gBG.drawLine(0, 0, w, h);
gBG.drawLine(0, h, w, 0);

fg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);

gFG = fg.createGraphics();

gFG.setColor(Color.RED);
gFG.fillOval(x, y, size, size);

buffer = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
gBuffer = buffer.createGraphics();

Thread t = new Thread(this);
t.start();
}

public void run() {
while (true) {
repaint();
try {
Thread.sleep(40);
}

catch (InterruptedException ie) {
// continue..
}
}
}

public Dimension getPreferredSize() {
return new Dimension(300, 300);
}

public void paintComponent(Graphics g) {
gFG.setComposite(composite);
gFG.drawImage(bg, 0, 0, null);
gFG.setPaintMode();

gFG.setColor(Color.RED);
gFG.fillOval(++x, ++y, size, size);

gBuffer.drawImage(fg, 0, 0, w, h, null);

g.drawImage(buffer, 0, 0, w, h, null);
if (x > w) {
x = 0;
y = 0;
}
}

public static void main(String[] args) {
JFrame f = new JFrame("Fade Test");
FadeComponent fc = new FadeComponent();
f.getContentPane().add(fc);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}

--
Andrey Kuznetsov
http://uio.imagero.com Unified I/O for Java
http://reader.imagero.com Java image reader
http://jgui.imagero.com Java GUI components and utilities


Andrew Thompson

unread,
Jul 21, 2006, 2:35:09 AM7/21/06
to
Andrey Kuznetsov wrote:
..

> I optimized also a bit your code (caching of Graphics):
...

Thank you, thank you, thank you. That is exactly as
I imagined it.

Once more you've come through for me, Andrey.. :-)

Andrew T.

Knute Johnson

unread,
Jul 21, 2006, 2:39:49 AM7/21/06
to

Graphics gFG = fg.getGraphics(); // I changed this to fg?
gFG.setColor(Color.RED);
gFG.fillOval(x,y,size,size);

buffer = new BufferedImage(
w, h, BufferedImage.TYPE_INT_ARGB );

Thread t = new Thread(this);
t.start();
}

public void run() {
while(true) {
repaint();
try {
Thread.sleep(40);
} catch(InterruptedException ie) {
// continue..
}
}
}

public Dimension getPreferredSize() {
return new Dimension(300,300);
}

public void paintComponent(Graphics g) {
Graphics gBuffer = buffer.getGraphics();
gBuffer.drawImage( bg,0,0,w,h,null );

Graphics2D gFG = (Graphics2D)fg.getGraphics();
gFG.setColor(new Color(255,255,255,10)); // can be 0,0,0,10
gFG.fillRect(0,0,w,h);
gFG.setColor(Color.RED);
gFG.fillOval(++x,++y,size,size);

gBuffer.setColor(new Color(255,255,255,10)); // can be 0,0,0,10
gBuffer.setXORMode(new Color(255,255,255,0));
gBuffer.drawImage( fg,0,0,w,h,null );
gBuffer.setPaintMode();

g.drawImage( buffer,0,0,w,h,null );
if (x>w) {
x=0;
y=0;
}
}

public static void main(String[] args) {
JFrame f = new JFrame( "Fade Test" );
FadeComponent fc = new FadeComponent();
f.getContentPane().add(fc);
f.pack();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
}

--

Knute Johnson
email s/nospam/knute/

Andrew Thompson

unread,
Jul 21, 2006, 2:52:53 AM7/21/06
to
Knute Johnson wrote:
..

> Graphics gFG = fg.getGraphics(); // I changed this to fg?

Yeah! (chuckles) that's one solution.

Unfortunately - the actual situation I need it for is
a 'Milky Way' background with 'Zooming Stars'
in the foreground. It just doesn't quite work for
me if the milky way is on top!

Andrey pointed me in the right direction with the
AlphaComposite.

Thanks for your response.

Andrew T.

Andrey Kuznetsov

unread,
Jul 21, 2006, 4:11:20 AM7/21/06
to
> That is exactly as I imagined it.
However red circle moving on black background was very impressive.
I liked it.

> Once more you've come through for me, Andrey.. :-)

;-)

Andrey

--

Andrew Thompson

unread,
Jul 21, 2006, 4:14:28 AM7/21/06
to
The final result using the AlphaComposite fix suggested
by Andrey, can be viewed here..
<http://www.javasaver.com/testjs/xsl/07/starzoom/>
Click the JNLP to see it.

It's around 100Kb (waggles hand) to get it on-screen,
unless you're using Java <1.5 (sorry, the underlying
SaverBeans API is 1.5+).

Andrew T.

Andrey Kuznetsov

unread,
Jul 21, 2006, 5:04:27 AM7/21/06
to
> The final result using the AlphaComposite fix suggested
> by Andrey, can be viewed here..
> <http://www.javasaver.com/testjs/xsl/07/starzoom/>

just 2 notes:

1) you forgot to exit application on frame closure
2) after frame resizing the animation is brocken, so you can
i) make frame unresizable or
ii) do some reset after resizing

Andrew Thompson

unread,
Jul 21, 2006, 5:34:57 AM7/21/06
to
Andrey Kuznetsov wrote:
> > The final result using the AlphaComposite fix suggested
> > by Andrey, can be viewed here..
> > <http://www.javasaver.com/testjs/xsl/07/starzoom/>
>
> just 2 notes:
>
> 1) you forgot to exit application on frame closure

* I'll have to fix that.**

> 2) after frame resizing the animation is brocken, so you can
> i) make frame unresizable or

Aaaah.. yes.

* The ScreensaverFrame (part of the SaverBeans API),
was intended originally as a component that was purely
for testing Screensavers during development.

As its role has expanded into the WebStart previews,
it has had to undergo a number of changes.

One more change it needs is to allow the frame size
to be locked, ...

> ii) do some reset after resizing

..as screensavers themselves never have to deal with
the screen changing size - so many (including
StarZoom) don't.

** The ScreensaverFrame is part of the SaverBeans API,
(an incubator project at JDIC) but the person making
(or suggesting) the most changes to it, is me.
The version shown in that preview is already heavily
modified from the version in the standard API.

Andrew T.

0 new messages