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.
LVL 3
xelousAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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

or do nothing :-)
cavey79Commented:
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.
Learn Ruby Fundamentals

This course will introduce you to Ruby, as well as teach you about classes, methods, variables, data structures, loops, enumerable methods, and finishing touches.

xelousAuthor Commented:
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.

Mick BarryJava DeveloperCommented:
> 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.





Mick BarryJava DeveloperCommented:
> 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.
xelousAuthor Commented:
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.

xelousAuthor Commented:
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.
Mick BarryJava DeveloperCommented:
> 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.

xelousAuthor Commented:
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.

Mick BarryJava DeveloperCommented:
> That's the point I am loading the images before I display the component,

OK, it wasn't clear from your earlier calls that getIcon() was being called before the component was created.

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

Yes but you still have to read the bytes :)  I would not imagine that your code to read the bytes would be any faster than getImage()'s.

> jesus the lagg now with all the icons being loaded was massive.

Will need to see more of your code to determine where the problem is.
Though I suspect you are not using MediaTracker to wait for the images to be completely loaded. getImage() does not actually perform the load it simply queues it for asynchronous loading, and loading will not commence until the image is actually needed.


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
xelousAuthor Commented:
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....
Mick BarryJava DeveloperCommented:
Easiest way to load image is to use ImageIcon class which will wait until image is completely loaded.
xelousAuthor Commented:
ImageIcon don't have the background functionality I use... in fact is has none....
xelousAuthor Commented:
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.
Mick BarryJava DeveloperCommented:
> .... 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


Mick BarryJava DeveloperCommented:
> 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.
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Web Graphics Software

From novice to tech pro — start learning today.