witty
asked on
BufferedImage looks incomplete
Hi!
please read this to the end, to understand my problem!
I'm using ptolemy's plot-package to generate 2D-dataplots.
(downloadable at http://devnull.at/?EOO73 )
what I do:
I create an instance of Plot ('Plot p = new Plot();'), and fill data into it (points, title, names of axes, legend ...)
then I do:
p.validate();
p.repaint();
// try{ Thread.sleep(10);}catch (Exception e){};
BufferedImage image = p.exportImage();
image.flush();
If I run this, 9 out of 10 times the image is not complete (sometimes the title is missing, sometimes the points ...).
BUT: If I uncomment the sleep line, the image looks correct 20 out of 21 times. The sleep is only 10ms!!
What's going on - any hint???
witty
please read this to the end, to understand my problem!
I'm using ptolemy's plot-package to generate 2D-dataplots.
(downloadable at http://devnull.at/?EOO73 )
what I do:
I create an instance of Plot ('Plot p = new Plot();'), and fill data into it (points, title, names of axes, legend ...)
then I do:
p.validate();
p.repaint();
// try{ Thread.sleep(10);}catch (Exception e){};
BufferedImage image = p.exportImage();
image.flush();
If I run this, 9 out of 10 times the image is not complete (sometimes the title is missing, sometimes the points ...).
BUT: If I uncomment the sleep line, the image looks correct 20 out of 21 times. The sleep is only 10ms!!
What's going on - any hint???
witty
The actual painting is handled in the asynchronously by another thread and may not have completed.
I can't find any mention of the exportImage() method?
ASKER
thanks object:
here you can find the exportImage()-method of PlotBox: http://devnull.at/?IZ2LQ (there is a little version-jam on this website!)
Plot is a direct subclass of PlotBox!
Is it possible to wait for all threads are finished???
What would you recommend?
thanks
witty
here you can find the exportImage()-method of PlotBox: http://devnull.at/?IZ2LQ (there is a little version-jam on this website!)
Plot is a direct subclass of PlotBox!
Is it possible to wait for all threads are finished???
What would you recommend?
thanks
witty
ASKER
also to mention:
I tried
p.paintImmediately(p.getBo unds());
before exportImage()
but without a result!!!
paintImmediately(Rectangle r) is a method of class javax.swing.JComponent ( http://devnull.at/?GVSU6 )
I also found this article on (a)synchronous paint:
http://devnull.at/?IW6AJ (look for "Synchronous Painting")
so, how to do synchronous painting???
witty
I tried
p.paintImmediately(p.getBo
before exportImage()
but without a result!!!
paintImmediately(Rectangle
I also found this article on (a)synchronous paint:
http://devnull.at/?IW6AJ (look for "Synchronous Painting")
so, how to do synchronous painting???
witty
Maybe they don't wait for the image to complete being painted. Try using MediaTracker to wait for the image to complete loading when it is returned:
BufferedImage image = p.exportImage();
mt.addImage(image, 0);
mt.waitForID(0);
// image should be loaded now
If this doesn't help then their may be a bug in the plot code and would suggests asking the author(s) about it.
BufferedImage image = p.exportImage();
mt.addImage(image, 0);
mt.waitForID(0);
// image should be loaded now
If this doesn't help then their may be a bug in the plot code and would suggests asking the author(s) about it.
ASKER
thanks again!
the mt did'nt change anything either :-( !!
I think the problem is AFTER repaint() and BEFORE exportImage(). The sleep inbetween returns almost ever the correct image!!!
I thought, this line should do it (is p.getBounds() ok to get the correct Rectangle?)
p.paintImmediately(p.getBo unds());
thanks
witty
the mt did'nt change anything either :-( !!
I think the problem is AFTER repaint() and BEFORE exportImage(). The sleep inbetween returns almost ever the correct image!!!
I thought, this line should do it (is p.getBounds() ok to get the correct Rectangle?)
p.paintImmediately(p.getBo
thanks
witty
It's strange, cause I would expect that the exportImage() method would be passing the image graphics context to paint().
paint(image.getGraphics()) ;
paint(image.getGraphics())
why don't you e-mail the authors of the package ?
ASKER
you don't know, what I have done three times in the last two weeks!!!
... and I think I have found a solution! it's a java-thing!!!
... and I think I have found a solution! it's a java-thing!!!
ASKER
yes - I have made it!!!
the point is: no one is generating server-side images with java!!!
I have found a way to control the repaint() (so I know when it has finished!!!)
thanks to all of you!!!
I won't delete ths quiestion - perhaps someone has a better solution :-)
the point is: no one is generating server-side images with java!!!
I have found a way to control the repaint() (so I know when it has finished!!!)
thanks to all of you!!!
I won't delete ths quiestion - perhaps someone has a better solution :-)
> the point is: no one is generating server-side images with java!!!
I have generated Images from servlets without any problem ?
>I have found a way to control the repaint() (so I know when it has finished!!!)
how do you 'control' repaint() ?
I have generated Images from servlets without any problem ?
>I have found a way to control the repaint() (so I know when it has finished!!!)
how do you 'control' repaint() ?
> no one is generating server-side images with java!!!
Yes they are :)
And what has this got to do with the problem?
> I have found a way to control the repaint()
> (so I know when it has finished!!!)
I would think the repaint() has nothing to do with it, it is involved with painting to the screen not to an offscreen image.
Yes they are :)
And what has this got to do with the problem?
> I have found a way to control the repaint()
> (so I know when it has finished!!!)
I would think the repaint() has nothing to do with it, it is involved with painting to the screen not to an offscreen image.
ASKER
if you want to write a component to an image, you have to call repaint() at least once (explicitly or by calling another method).
but:
YOU CAN NEVER be sure, whether repaint() has finished, or is still "scheduled" (and this is exactly the problem!). in an application it doesn't matter whether you "see" the repaint()-result now or in 5ms - when you write the component to an image, it does matter at what time you write the image (this can occur before the repaint() has finished - so the image would leak of the last paintings!)
this problem primarily arises with (very) fast machines (I have a dual processor machine (AMD Athlon(TM) MP 2100+))!
some javasources (which are in use for online websites) were mailed to me, where images are created for servlets. on slower machines (as my AMD Athlon(TM) XP 1800+) this code is no problem, but my dual-processor-machine is too fast for this code! so I had to find a solution, to be sure, the repaint() has finished, the moment I create my image!
witty
but:
YOU CAN NEVER be sure, whether repaint() has finished, or is still "scheduled" (and this is exactly the problem!). in an application it doesn't matter whether you "see" the repaint()-result now or in 5ms - when you write the component to an image, it does matter at what time you write the image (this can occur before the repaint() has finished - so the image would leak of the last paintings!)
this problem primarily arises with (very) fast machines (I have a dual processor machine (AMD Athlon(TM) MP 2100+))!
some javasources (which are in use for online websites) were mailed to me, where images are created for servlets. on slower machines (as my AMD Athlon(TM) XP 1800+) this code is no problem, but my dual-processor-machine is too fast for this code! so I had to find a solution, to be sure, the repaint() has finished, the moment I create my image!
witty
> if you want to write a component to an image, you have
> to call repaint()
Why??? All repaint() does is queue a paint request to paint the component to the *screen*.
To write a component to an image, you simply call:
component.paint(image.getG raphics()) ;
> to call repaint()
Why??? All repaint() does is queue a paint request to paint the component to the *screen*.
To write a component to an image, you simply call:
component.paint(image.getG
I agree with objects
ASKER
if I edit a component and do a paint straight afterwards - then the last edit won't be visible (on the fast machine)!
as said: everything works fine on an ordinary machine!
witty
as said: everything works fine on an ordinary machine!
witty
Can you post the method that is creating and saving the image.
Here is the exportImage code that draws the image by simply passing the image cgraphics context to _drawPlot, which is the same method called by paintComponent().
public synchronized BufferedImage exportImage(
BufferedImage bufferedImage,
Rectangle rectangle,
RenderingHints hints,
boolean transparent) {
Graphics2D graphics = bufferedImage.createGraphi cs();
graphics.addRenderingHints (_defaultI mageRender ingHints() );
if ( !transparent ) {
graphics.setColor(Color.wh ite); // set the background color
graphics.fill(rectangle);
}
_drawPlot(graphics, false , rectangle);
return bufferedImage;
}
public synchronized BufferedImage exportImage(
BufferedImage bufferedImage,
Rectangle rectangle,
RenderingHints hints,
boolean transparent) {
Graphics2D graphics = bufferedImage.createGraphi
graphics.addRenderingHints
if ( !transparent ) {
graphics.setColor(Color.wh
graphics.fill(rectangle);
}
_drawPlot(graphics, false , rectangle);
return bufferedImage;
}
> when you write the component to an image, it does matter
> at what time you write the image (this can occur before
> the repaint() has finished - so the image would leak of
> the last paintings!)
That's partly true, though the painting of the component and the image are in a way seperate. They are just performed by the same code. So what actually appears on the screen is not used to produce the image. And calling repaint() has no effect on the image, it only affects painting to the screen.
To ensure that the painting of the image is complete can be achieved using MediaTracker as I mentioned above.
> at what time you write the image (this can occur before
> the repaint() has finished - so the image would leak of
> the last paintings!)
That's partly true, though the painting of the component and the image are in a way seperate. They are just performed by the same code. So what actually appears on the screen is not used to produce the image. And calling repaint() has no effect on the image, it only affects painting to the screen.
To ensure that the painting of the image is complete can be achieved using MediaTracker as I mentioned above.
ASKER
here is the code:
--cut--
Plot p = new Plot();
boolean first = true;
for(int a = -1 ; a <= 100 ;a++){
p.addPoint(0, a, a*a, !first);
first = false;
}
p.addLegend(0, "Legend 0");
p.setTitle("T I T L E");
p.setXLabel("XLabel");
p.setYLabel("YLabel");
java.awt.image.BufferedIma ge image = p.exportImage();
--cut--
then the image is encoded into a jpg, png ...
if I look at this image, something is ever missing - title, axes, legend, datapoints ...
if I create subclass "class MyPlot extends Plot" and overwrite the exportImage()-method with my code, everything works fine when using MyPlot instead of Plot (and the same code as above!!!)!!!
what I do in my exportImage():
* create a ComponentListener and add it to p
* start a thread X (X waits on the ComponentEvent componentShown())
* p.setVisible(false)
* p.setVisible(true) -> the componentShown()-method is triggered and this method notifies X)
* X.join()
because setVisible() calls repaint(), and the repaint() isn't done immediatly, I have to wait till the thread has finished (join()) and this happens because the thread is notified by the ComponentListener
witty
--cut--
Plot p = new Plot();
boolean first = true;
for(int a = -1 ; a <= 100 ;a++){
p.addPoint(0, a, a*a, !first);
first = false;
}
p.addLegend(0, "Legend 0");
p.setTitle("T I T L E");
p.setXLabel("XLabel");
p.setYLabel("YLabel");
java.awt.image.BufferedIma
--cut--
then the image is encoded into a jpg, png ...
if I look at this image, something is ever missing - title, axes, legend, datapoints ...
if I create subclass "class MyPlot extends Plot" and overwrite the exportImage()-method with my code, everything works fine when using MyPlot instead of Plot (and the same code as above!!!)!!!
what I do in my exportImage():
* create a ComponentListener and add it to p
* start a thread X (X waits on the ComponentEvent componentShown())
* p.setVisible(false)
* p.setVisible(true) -> the componentShown()-method is triggered and this method notifies X)
* X.join()
because setVisible() calls repaint(), and the repaint() isn't done immediatly, I have to wait till the thread has finished (join()) and this happens because the thread is notified by the ComponentListener
witty
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
No comment has been added lately, so it's time to clean up this TA.
I will leave a recommendation in the Cleanup topic area that this
question is:
- points to objects
Please leave any comments here within the
next seven days.
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER !
girionis
Cleanup Volunteer
I will leave a recommendation in the Cleanup topic area that this
question is:
- points to objects
Please leave any comments here within the
next seven days.
PLEASE DO NOT ACCEPT THIS COMMENT AS AN ANSWER !
girionis
Cleanup Volunteer