Link to home
Start Free TrialLog in
Avatar of xelous
xelousFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Image Flash and draw lag

Evening all,
I've got a problem I think with the Java AWT engine, not my code....

Now before you shout "DON'T USE AWT USE SWING.. " I can't I'm utilising Java3D and the Canvas3D object does not like to sit alongside Swing, while it's happy to sit along side AWT Components.

So...

My problem is I have a panel with an image on it.  The panel has a mouse listener and when I click the panel it alters to an alternate image, a little like an ImageButton..... however this is the panel background, not the foreground componets.

Anyway, the problem is the Image initially (for the first 3 clicks/exchanges) flashes... as if it's held in a slower part or heap location until it's been used n many times.

Is this the case? does it take time to cache the image into the AWT Heap or Graphics memory?  I'm a little bemused by the background rendering involvd in the AWT.

----------------------

Additional:

The image is loaded as a bulk read of a file stream, to a byte array.. then I use the Toolkit.creatImage... To give me an Image object from the raw bytes.  This action is seamless and does not lag like the getImage function.  I have checked this, and it would seem no MediaTracker is required.... but if I''m wrong let me know... though I doubt I am incorrect on this point.
Avatar of Mick Barry
Mick Barry
Flag of Australia image

Can you post your code that paints the image.
You also should override update() to simply call paint().
> You also should override update() to simply call paint().

or do nothing :-)
Avatar of cavey79
cavey79

You should use a media tracker...also for painting, override paint() if you're talking AWT.
You might want to check some double-buffering samples implemented in AWT - this would speed up your app.
Avatar of xelous

ASKER

Yeah I've overridden Paint.... it looks thus....


public void paint (Graphics g)
{
   g.clearRect (0,0,getWidth(),getHeight());
   g.drawImage (ImageConstants.getIcon(),0,0,this);
}

Repaint and update are not touched.

The Image Constants loads the image thusly.

public class ImageConstants
{
   public private Image TopLeftIcon = null;

   public Image getIcon ()
   {
        if ( TopLeftIcon == null )
        {
            LoadTopLeftIcon ();
        }
        return TopLeftIcon;
   }

   private void LoadTopLeftIcon ()
   {
      byte[] data;

       try {
          File f = new File ("C:\Icon.PNG");
          FileInputStream fis = new FileInputStream ();
          data = new byte[fis.available()];
          fis.read (data);
          fis.close();
      }
      catch (Exception e)
      {
            System.out.println ("It all went wrong in the read");
            System.exit (0);
      }
      TopLeftIcon = Toolkit.getDefaultToolkit().createImage (data);
   }

}


Give or take...

So you see I bulk loaded the bytes to get around the lagg of toolkit.getImage.... And I make it load once but still it lags....

I don't think I need a media tracker as I load the bytes form the disk myself.  However, I wonder if you need a media tracker while the JVM wors out the format of the image? Or is createImage the bottleneck??????

Let me know.

> g.clearRect (0,0,getWidth(),getHeight());

That could cause some flashing.

> Repaint and update are not touched.

Did you try overriding update() as I suggested?


> So you see I bulk loaded the bytes to get around the lagg of toolkit.getImage....
> And I make it load once but still it lags....

No real difference to using MediaTracker to wait for your image to load.





> public Image getIcon ()
>  {
>       if ( TopLeftIcon == null )
>       {
>           LoadTopLeftIcon ();
>       }
>       return TopLeftIcon;
>  }

Thats whats causing your lag. You wait until the image is completly loading before displaying it.

Using getImage() directly would enable your image to be loaded asynchronously.
Avatar of xelous

ASKER

I know there is some overhead in this, but the lag is down to 20ms while it was 150 odd with getImage.  But I think with the bulk load of the bytes from the image file and then the createImage it should be instantaneous.

There is no waiting in volved, it does a read of the whole file!!!!!!! getImage loads in chunks.... the FileInputSTream reads the bytes all together in one block.  Which is always quicker.

So I think the lag lies with the AWT.Image class in either interpreting the PNG format of my data, or in the createIMage class..... if it's with the createImage class what can i do?  are there alternatives?

It's not to do with the actual calling of my load.. my load does not "wait" for anything.... maybe the AWT does... advice please.

Avatar of xelous

ASKER

I'm going to try overloading update and reoving the clear rect.... I know clear rect does cause some flashing, but I do have other things drawn into the control (later on) which would need removing before the original icon is replaced.

Thought that's not even implemented yet, until I get the icon done....

The whole point is to open and display the icon instantly.  Not wait for anything to appear.  But the lag seems to be after the file load and before the first calll to paint.... there's nothing happening in my code (I've traced it)... it does off into java.AWT.... which I can't trace through - not sure why I can't).  Which is what makes me think maybe the lagg comes from interpreting the PNG format... I've altered the image to a GIF and a JPG also, but  still the lagg exists.

And the flashing just annoys me, I've added the line to ouput on the paint function, and it is only called once.
> while it was 150 odd with getImage

There is no (virtually) lag with getImage(). It loads the image asynchonously.

> But I think with the bulk load of the bytes from the image file and then the createImage it should be instantaneous.

Why do you think this?
createImage has to create an Image instance and decode the byte array.

> my load does not "wait" for anything

It does. It waits untiul the file has been completely read and then needs to decode the bytes.

Best way to remove the lag would be to load your images, before you display your components.

Avatar of xelous

ASKER

That's the point I am loading the images before I display the component, but the component background colour appears then later onthe image turns up... seemingly at it's own will... after 1 or 2 seconds I can then move the frame to make the whole thing "repaint" and the image repaits in about 1/2 the time... then it repaints instantly... this is part of the flashing.. I've took out the clearRect... it's just getting on my tits now... going to read some info about the background of the image...

But I've read the Toolkit class information and createImage and getImage decode a byte array... just you provide the array to createImage, while getImage has to load it itself.

Therefore I surmise providing the byte array is quicker than letting getImage open a file, read the bytes, close the file... decod the array.

Now how I get the byte array is up to me, and I do this with a bulk byte read... You seem to have issues with this... do you read files byte by byte or something?

File f = new File ("C:atextfile.txt");
FileInputStream fis = new FileInputStream (f);
int size = file.length();
byte[] data = new byte[size];
fis.read (data);
fis.close();

is quicker than

int index = 0;
int curr;
while ( (curr = fis.read()) != -1)
{
  data[index] = curr;
  index++;
}

I've had someone write code like this for work and it winds me up....  From what I've read the getImage file read reads in blocks of n bytes... I'm not sure how big this n value is, but if it's less than file.length it's going to take more than one iteration to complete the file read.

Now how can I justify all my windging above?  Well I just created a new loadAllIcons set of functions... just the same ones with a "2" at the end and I used getImage..... jesus the lagg now with all the icons being loaded was massive.

I think from reading the file stuff and the toolkit stuff and your suggestion above it must be the lag in decoding the PNG format?  I've only ever used JPG before. Maybe the Image Classes PNG decoder is pants.

I'm close to accepting your suggestion above if it is the decoer becuase you put me on its track, but I think the fault lies outside the scope of my code and within the AWT core.  I mean I've stepped through this and my code finishes and I get told there's nothing to do (in any of my threads) then I get the images appear on their own accord.

ASKER CERTIFIED SOLUTION
Avatar of Mick Barry
Mick Barry
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of xelous

ASKER

That's it... there's the wordss....... "until the image is actually needed"..... Eurrrikaaaaaa.... I gotta strip off have a run around the block and jump back in the bath...

The images are Paged... so to speak.... to until they are in scope of "view" they are not on screen... then the component is put on the screen....

That's it... my code finished.. all the Icons are created... but the images are just left pending loading "if needed"....

Then I add the icon to the screen and bing is crawls..... so it must be storing the byte arrays I provide and only decoding them on spec..... and I can't trace into that as I don't have the awt.java files.

Right.... I gotta go scratch my head....
Easiest way to load image is to use ImageIcon class which will wait until image is completely loaded.
Avatar of xelous

ASKER

ImageIcon don't have the background functionality I use... in fact is has none....
Avatar of xelous

ASKER

Oh and ImageIcon is SWING......

> Now before you shout "DON'T USE AWT USE SWING.. " I can't I'm utilising Java3D and the Canvas3D object does not like to
> sit alongside Swing, while it's happy to sit along side AWT Components.
> .... to until they are in scope of "view" they are not on screen
> ... then the component is put on the screen....

From what you have said you should really be using MediaTracker to wait for loading to complete anyway.

Thanks for the points.

http:://www.objects.com.au/staff/mick


> ImageIcon don't have the background functionality

You just use it to handle the loading.

> Oh and ImageIcon is SWING......

Doesn't make any difference in this context.