PDA

View Full Version : I fixed a Bug in WaitingImageObserver



Anonymous
07-13-2002, 05:56 PM
Hi, JFreeReport Developers

when using your lib I discovered a strange behaviour.
I created a report which contains a gif-Image.
When I opened that report twice, something inside the lib froze and the second report didn't show up.
After some time of research I found that the class WaitingImageObserver is the problem.
It waits for an Image to be finished loading even if the Image doesn't have to be loaded because it is already in use and can be drawn a second time immediately. So WaitingImageObserver waits for something to be finished that didn't even start. The result is an endless loop.
It took me some time to fix it, but here is my new WaitingImageObserver.

Sorry for not posting it directly to the CVS-Rep, but unfortunatly I'm not very familiar with that tool.
So please add the code posted below for me to the rep.

This code is a modified version 1.6, which I just download via CVS Browsing. I marked my changes with "//SP"-comments.

One remark about the implementation of the Interface Runnable:
The class doesn't have to implement this interface because it isn't started as a Thread.
When it is used in ImageReference "obs.run()" is called, but a Thread should be started with

Thread t = new Thread(obs);
t.start();
//Waiting for the thread to finish is done by
t.join();

But that's not necessary. So my version of WaitingImageObserver doesn't implement Runnable any longer and the run()-Method is now called "wait()", just to prevent confusion with Runnable.
So can you please change the run()-call in ImageReference (constructor)?

But enough of talking, here we go...

Best regards, Stefan


/**
* =============================================================
* JFreeReport : an open source reporting class library for Java
* =============================================================
*
* Project Info: http://www.object-refinery.com/jfreereport;
* Project Lead: David Gilbert (david.gilbert@jrefinery.com);
*
* (C) Copyright 2000-2002, by Simba Management Limited and Contributors.
*
* This library is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* ----------------
* WaitingImageObserver.java
* ----------------
* (C)opyright 2000-2002, by Simba Management Limited.
*
* Original Author: Thomas Morger
* Contributor(s): Stefan Prange;
*
* $Id: WaitingImageObserver.java,v 1.6 2002/07/03 18:49:46 taqua Exp $
*
* Changes (from 8-Feb-2002)
* -------------------------
* 13-Jul-2002 : fixed bug in wait() (former run()) //SP
* 15-Apr-2002 : first version used by ImageElement.
* 16-May-2002 : Line delimiters adjusted
* 04-Jun-2002 : Documentation and added a NullPointerCheck for the constructor.
*/
package com.jrefinery.report;

import java.awt.Graphics;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.io.Serializable;

/**
* This image observer blocks until the image is completly loaded. AWT
* deferres the loading of images until they are painted on a graphic.
*
* While printing reports it is not very nice not to know whether a image
* was completely loaded, so this observer forces the loading of the image
* until a final state (either ALLBITS, ABORT or ERROR) is reached.
*/
public class WaitingImageObserver implements ImageObserver, Serializable, Cloneable //SP: removed Runnable
{
private boolean lock;
private Image image;

/**
* Creates a new ImageObserver for the given Image. The Oberver has to be started
* by an external thread.
*
* @throws NullPointerException if the given image is null.
*/
public WaitingImageObserver (Image image)
{
if (image == null) throw new NullPointerException ();
this.image = image;
lock = true;
}

/**
* Callback function used by AWT to inform that more data is availiable. The observer
* waits until either all data is loaded or AWT signals that the image cannot be loaded.
*/
public boolean imageUpdate (
Image img,
int infoflags,
int x,
int y,
int width,
int height)
{
if ((infoflags & ImageObserver.ALLBITS) == ImageObserver.ALLBITS
|| (infoflags & ImageObserver.ABORT) == ImageObserver.ABORT
|| (infoflags & ImageObserver.ERROR) == ImageObserver.ERROR)
{
lock = false;
}
return true;
}

/**
* The workerthread. Simply draws the image to an BufferedImage's Graphics-Object
* and waits for the AWT to load the image.
*/
public void wait () //SP: renamed to wait(), TODO: change method's comment
{
BufferedImage img = new BufferedImage (1, 1, BufferedImage.TYPE_INT_RGB);
Graphics g = img.getGraphics ();

while (lock)
{
boolean finishedLoading = g.drawImage (image, 0, 0, this); //SP: used other drawImage-Method because the Observer isn't interested in width and height
if (finishedLoading) { //SP: if drawImage is immediately able to draw the image, it returns
//SP: true and the Imageobserver never gets imformed via imageUpdate
this.lock=false;
continue; //SP: abort loop
}

try
{
Thread.currentThread ().sleep (200);
}
catch (InterruptedException e)
{
}
}
}

public Object clone () throws CloneNotSupportedException
{
WaitingImageObserver obs = (WaitingImageObserver) super.clone ();
return obs;
}
}

Anonymous
07-14-2002, 06:03 PM
Hi,

thanks for this fix. It is included in the cvs now. I had to rename the wait() function to waitImageLoaded() as wait() is also used in java.lang.Object to implement Object-locking.

Thank you for this fix, this is great. I hadn't noticed this one, it seems that this bug depended on the Java-Implementation.Arrrgh :)

Have more fun,
said Thomas