Solved

BufferedImage looks incomplete

Posted on 2002-06-19
23
345 Views
Last Modified: 2010-03-31
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
0
Comment
Question by:witty
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 10
  • 8
  • 3
  • +1
23 Comments
 
LVL 92

Expert Comment

by:objects
ID: 7094231
The actual painting is handled in the asynchronously by another thread and may not have completed.
0
 
LVL 92

Expert Comment

by:objects
ID: 7094248
I can't find any mention of the exportImage() method?
0
 
LVL 1

Author Comment

by:witty
ID: 7094942
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
0
PeopleSoft Has Never Been Easier

PeopleSoft Adoption Made Smooth & Simple!

On-The-Job Training Is made Intuitive & Easy With WalkMe's On-Screen Guidance Tool.  Claim Your Free WalkMe Account Now

 
LVL 1

Author Comment

by:witty
ID: 7094996
also to mention:

I tried
p.paintImmediately(p.getBounds());
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
0
 
LVL 92

Expert Comment

by:objects
ID: 7095084
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.
0
 
LVL 1

Author Comment

by:witty
ID: 7095191
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.getBounds());

thanks
witty
0
 
LVL 92

Expert Comment

by:objects
ID: 7095219
It's strange, cause I would expect that the exportImage() method would be passing the image graphics context to paint().

paint(image.getGraphics());
0
 
LVL 16

Expert Comment

by:heyhey_
ID: 7097943
why don't you e-mail the authors of the package ?
0
 
LVL 1

Author Comment

by:witty
ID: 7098006
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!!!
0
 
LVL 1

Author Comment

by:witty
ID: 7098027
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 :-)
0
 
LVL 16

Expert Comment

by:heyhey_
ID: 7098031
> 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() ?
0
 
LVL 92

Expert Comment

by:objects
ID: 7098163
> 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.
0
 
LVL 1

Author Comment

by:witty
ID: 7098242
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
0
 
LVL 92

Expert Comment

by:objects
ID: 7098257
> 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.getGraphics());
0
 
LVL 16

Expert Comment

by:heyhey_
ID: 7098264
I agree with objects
0
 
LVL 1

Author Comment

by:witty
ID: 7098266
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
0
 
LVL 92

Expert Comment

by:objects
ID: 7098273
Can you post the method that is creating and saving the image.
0
 
LVL 92

Expert Comment

by:objects
ID: 7098303
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.createGraphics();
  graphics.addRenderingHints(_defaultImageRenderingHints());
  if ( !transparent ) {
     graphics.setColor(Color.white);     // set the background color
     graphics.fill(rectangle);
  }
  _drawPlot(graphics, false , rectangle);
  return bufferedImage;
}
0
 
LVL 92

Expert Comment

by:objects
ID: 7098333
> 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.
0
 
LVL 1

Author Comment

by:witty
ID: 7099003
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.BufferedImage 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
0
 
LVL 92

Accepted Solution

by:
objects earned 200 total points
ID: 7099702
java.awt.image.BufferedImage image = p.exportImage();

// You need to use use MediaTracker here to wait until
// image is complete before encoding.

--cut--  // What happens in here??

then the  image is encoded into a jpg, png ...
0
 
LVL 35

Expert Comment

by:girionis
ID: 8860576
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
0

Featured Post

Free Tool: Port Scanner

Check which ports are open to the outside world. Helps make sure that your firewall rules are working as intended.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Java Flight Recorder and Java Mission Control together create a complete tool chain to continuously collect low level and detailed runtime information enabling after-the-fact incident analysis. Java Flight Recorder is a profiling and event collectio…
Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
Video by: Michael
Viewers learn about how to reduce the potential repetitiveness of coding in main by developing methods to perform specific tasks for their program. Additionally, objects are introduced for the purpose of learning how to call methods in Java. Define …
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

726 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question