Solved

BufferedImage looks incomplete

Posted on 2002-06-19
23
332 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
  • 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
 
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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
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

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

An old method to applying the Singleton pattern in your Java code is to check if a static instance, defined in the same class that needs to be instantiated once and only once, is null and then create a new instance; otherwise, the pre-existing insta…
Java functions are among the best things for programmers to work with as Java sites can be very easy to read and prepare. Java especially simplifies many processes in the coding industry as it helps integrate many forms of technology and different d…
Viewers learn about the third conditional statement “else if” and use it in an example program. Then additional information about conditional statements is provided, covering the topic thoroughly. Viewers learn about the third conditional statement …
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:

705 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

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now