Clearing BufferedImage

Discussion in 'Java' started by Will Clark, Nov 27, 2003.

  1. Will Clark

    Will Clark Guest

    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?
     
    Will Clark, Nov 27, 2003
    #1
    1. Advertisements

  2. Will Clark

    Chris Smith Guest

    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
     
    Chris Smith, Nov 28, 2003
    #2
    1. Advertisements

  3. Will Clark

    Will Clark Guest

    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
     
    Will Clark, Nov 28, 2003
    #3
  4. 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.
     
    Knute Johnson, Nov 28, 2003
    #4
  5. Will Clark

    Will Clark Guest

    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
     
    Will Clark, Nov 29, 2003
    #5
  6. 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).
     
    Knute Johnson, Nov 29, 2003
    #6
  7. Will Clark

    Will Clark Guest

    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
     
    Will Clark, Dec 2, 2003
    #7
  8. 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.
     
    Knute Johnson, Dec 7, 2003
    #8
  9. Will Clark

    Will Clark Guest

    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
     
    Will Clark, Dec 9, 2003
    #9
  10. Will Clark

    Mike Guest

    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.
     
    Mike, Dec 10, 2003
    #10
  11. Will Clark

    Will Clark Guest

    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
     
    Will Clark, Dec 10, 2003
    #11
  12. Will Clark

    bluescales

    Joined:
    Nov 20, 2010
    Messages:
    1
    Likes Received:
    0
    Try this :)


    Code (Text):
    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();
     
    bluescales, Nov 20, 2010
    #12
    1. Advertisements

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 (here). After that, you can post your question and our members will help you out.