Clearing BufferedImage


W

Will Clark

Is there any way of clearing a BufferedImage object? By which I mean
returning it to completely transparent, as when created using:

new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB)

I must have missed something really obvious, because there must be a simple
way to do it, and not by creating a new BufferedImage every time the image
needs redrawing...

Obviously, if it were not a transparent background, I could just use a
Graphics2D.fill(...) to fill the background in, say, white... but
unsurprisingly using this method with a "transparent" color doesn't work :eek:(

What I'd like is a BufferedImage.clear() function!

Any help would be great!

Cheers :eek:)

Will


P.S. I've also come across the following code fragment, which I haven't yet
tried to test:

// Clear image with transparent alpha by drawing a rectangle
g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
g2D.fill(new Rectangle(0, 0, w, h));

Is this the best way? Or is there a better way?
 
Ad

Advertisements

C

Chris Smith

Will said:
Is there any way of clearing a BufferedImage object? By which I mean
returning it to completely transparent, as when created using:

new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB)

I must have missed something really obvious, because there must be a simple
way to do it, and not by creating a new BufferedImage every time the image
needs redrawing...

Obviously, if it were not a transparent background, I could just use a
Graphics2D.fill(...) to fill the background in, say, white... but
unsurprisingly using this method with a "transparent" color doesn't work :eek:(

What I'd like is a BufferedImage.clear() function!

Not ideal (and not tested), but I think either of the
BufferedImage.setRGB methods could be used to accomplish this.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
W

Will Clark

Chris Smith said:
Not ideal (and not tested), but I think either of the
BufferedImage.setRGB methods could be used to accomplish this.

No, I don't think that's not really a possibility...

setRGB(int x, int y, int rgb)

would require each pixel set in a big loop, while

setRGB(int startX, int startY, int w, int h, int[] rgbArray, int offset, int
scansize)

would be marginally better but would require a huge array of int[] to be set
up each time I want to clear it.

Actually, it would only need to be set up once, and then used each time...
but it still wastes a lot of memory... and Java Image objects waste enough
as it is!

Hmm, difficult, this one :eek:)

Well, I'll try it anyway - it may be work out better than the other
approaches I've got!

Thanks!

Will
 
K

Knute Johnson

Will said:
Is there any way of clearing a BufferedImage object? By which I mean
returning it to completely transparent, as when created using:

new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB)

I must have missed something really obvious, because there must be a simple
way to do it, and not by creating a new BufferedImage every time the image
needs redrawing...

Obviously, if it were not a transparent background, I could just use a
Graphics2D.fill(...) to fill the background in, say, white... but
unsurprisingly using this method with a "transparent" color doesn't work :eek:(

What I'd like is a BufferedImage.clear() function!

Any help would be great!

Cheers :eek:)

Will


P.S. I've also come across the following code fragment, which I haven't yet
tried to test:

// Clear image with transparent alpha by drawing a rectangle
g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
g2D.fill(new Rectangle(0, 0, w, h));

Is this the best way? Or is there a better way?

It's not exactly clear what you are really trying to do. If you just
want to see only the background, why not just draw the background and
not draw the BufferedImage on top? If you want to change the alpha of
the image to partially show the background you can use the getRGB() and
setRGB() as Chris already said or you can use the
Graphics2D.setComposite() to draw with an arbitrary alpha value.

float alphaLevel;

paintComponent(Graphics g) {
Graphics2D g2D = (Graphics2D)g;
Composite oldcomp = g2D.getComposite();
// draw the background
Composite newcomp = AlphaComposite.getInstance(
AlphaComposite.SRC_OVER,alphaLevel);
g2D.setComposite(newcomp);
g2D.drawImage(image,0,0,null);
g2D.setComposite(oldcomp);
}

This still requires that you draw the background though. If you are
going to make the BufferedImage completely transparent there is no
reason to go through all this hassle.
 
W

Will Clark

Knute said:
It's not exactly clear what you are really trying to do...

Ah, sorry! What I have is effectively an "animated" image which is
transparent. But it is not a repeating sequence of "frames", therefore
cannot be handled by multiple BufferedImage objects.

On the other hand, I cannot just use the paint method and draw directly on
top of the component beneath as the BufferedImage drawing routine is
complicated and slow - hence buffered! To do it this way would cause the
background to "freeze".

Hence, I need a way of clearing the BufferedImage object, firstly, so that I
don't need to create more than one, and secondly, because each "frame" may
well be transparent in a different place to the last frame.

Cheers,

Will
 
K

Knute Johnson

Will said:
Ah, sorry! What I have is effectively an "animated" image which is
transparent. But it is not a repeating sequence of "frames", therefore
cannot be handled by multiple BufferedImage objects.

On the other hand, I cannot just use the paint method and draw directly on
top of the component beneath as the BufferedImage drawing routine is
complicated and slow - hence buffered! To do it this way would cause the
background to "freeze".

Hence, I need a way of clearing the BufferedImage object, firstly, so that I
don't need to create more than one, and secondly, because each "frame" may
well be transparent in a different place to the last frame.

Cheers,

Will

It's still not clear what you are doing. Are you displaying this image
in a Swing component? Are you sure it isn't buffered? Swing components
are buffered by default and it does take the flicker out of redraws. In
any case you can't make it go transparent without redrawing it. The
only way to improve rendering speed is to render less. You can improve
the actual draw to the screen with VolatileImage (it really flies under
Windows).
 
Ad

Advertisements

W

Will Clark

Knute Johnson said:
It's still not clear what you are doing.

Ok, imagine it like this... the BufferedImage is effectively a slow
animation, say a video clip running at approximately 5 frames a second (but
even this is too simplistic because it gives the idea of pre-rendered
scenes, which isn't the case: scenes are rendered on the fly), parts of
which are transparent, and overlays another (simpler) animation which runs
at around 25 frames a second.

If the slow animation is rendered directly on top of the fast animation then
the whole animation becomes jerky as the speed at which the slow animation
can be rendered is too low - hence the BufferedImage: the slow animation
frame is rendered to the BufferedImage and then this can be rendered on top
of the fast animation quickly, solving the problem - and this works
brilliantly! It doesn't matter how long it takes for the top animation to
render, because the BufferedImage object for the previous frame is painted
on top of the bottom animation until the rendering of the next one is
completed.

The only problem is that of memory consumption: how best to use the
BufferedImage object - which needs to be recreated every frame. Hence the
question, can it be cleared!?

Its really nothing to do with Swing or any other java Component api, simply
a case of animation rendering. Similarily, VolatileImage doesn't seem (on
first glance) to be the answer, but I will research it further.

But does it make more sense now? :eek:)

Cheers for your comments though.

Will
 
K

Knute Johnson

Will said:
Ok, imagine it like this... the BufferedImage is effectively a slow
animation, say a video clip running at approximately 5 frames a second (but
even this is too simplistic because it gives the idea of pre-rendered
scenes, which isn't the case: scenes are rendered on the fly), parts of
which are transparent, and overlays another (simpler) animation which runs
at around 25 frames a second.

If the slow animation is rendered directly on top of the fast animation then
the whole animation becomes jerky as the speed at which the slow animation
can be rendered is too low - hence the BufferedImage: the slow animation
frame is rendered to the BufferedImage and then this can be rendered on top
of the fast animation quickly, solving the problem - and this works
brilliantly! It doesn't matter how long it takes for the top animation to
render, because the BufferedImage object for the previous frame is painted
on top of the bottom animation until the rendering of the next one is
completed.

The only problem is that of memory consumption: how best to use the
BufferedImage object - which needs to be recreated every frame. Hence the
question, can it be cleared!?

Its really nothing to do with Swing or any other java Component api, simply
a case of animation rendering. Similarily, VolatileImage doesn't seem (on
first glance) to be the answer, but I will research it further.

But does it make more sense now? :eek:)

Cheers for your comments though.

Will

Sorry about the slow reply, I've been out of town the last week.

I think I understand what you are trying to do now. If you can
synchronize your rendering between the slow and the fast animation to
some ratio then I would render all the data at one time. Change the
fast animation every frame and the slow every 5 (or whatever ratio you
want) frames. This would probably be faster than rendering to multiple
components too.

The reason I think this is better than using a transparent BufferedImage
is that you will have to effectively do the same thing. And that is
draw your underlying animation, render to the BufferedImage and then
draw it over the backgroun. You will have to double buffer it too so
that you don't get background/foreground flicker.
 
W

Will Clark

Knute said:
Sorry about the slow reply, I've been out of town the last week.

Don't worry! :eek:)


I think you're right: I think that probably is the best way to do it.

Thank you for all your help and perseverance!

Will
 
M

Mike

In my case, I found that I needed to control a lot of pixels directly,
so I created an external JNI assembler library to allow me to
*quickly* change pixels.
 
W

Will Clark

Mike said:
In my case, I found that I needed to control a lot of pixels directly,
so I created an external JNI assembler library to allow me to
*quickly* change pixels.

Hmm, that may be a little overkill for what I have in mind, but it may be
helpful. I don't suppose you'd have the source code for that and would be
willing to part with it?

But don't worry about it! :eek:)

Will
 
Ad

Advertisements

Joined
Nov 20, 2010
Messages
1
Reaction score
0
Try this :)


Code:
BufferedImage buf = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);

Graphics2D g = buf.createGraphics();

g.setComposite(AlphaComposite.Src);

g.setColor(new Color(0, 0, 0, 0));

g.fillRect(0, 0, width, height);

g.dispose();
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top