Hi Ken,
Ken Warner wrote:
Hi Jim,
You raise some interesting points. The reason I used Toolkit was
because of the simplicity of the code that I needed to write. I wrote
an early version of my applet using ImageIO and BufferedImage. The code
ended up being pretty complicated. Right now I use Toolkit; grab the
pixels; flush the image and do all my image manipulations on the raw one
dimensional byte array returned by the PixelGrabber.
Your code used a one dimensional int array - I'm presuming that was what
you meant above.
You could do something very similar with ImageIO, but you might have to
use some of the more specific API calls. You can request an image to be
read into a specific format of BufferedImage using the ImageReadParam,
but you need to get an ImageReader directly, query it for the default
ImageReadParam, and then change/set the destination. It's a few more
lines than ImageIO.read(File), but it gets you an image in the default
ARGB space that your PixelGrabber was using. Then you just need to dig
out the int array from the BufferedImage:
WritableRaster wr = bimg.getRaster();
DataBufferInt dbi = (DataBufferInt) wr.getDataBuffer();
int pixels[] = dbi.getData();
// voila - pixels in a one dimensional array
Note that the cast will cause a problem if you aren't using a
TYPE_INT_ARGB or TYPE_INT_RGB BufferedImage since the various formats
use different types of DataBuffer objects under the hood.
And I'm so far along in my development cycle that recoding for ImageIO
(which is really good stuf - no slight intended) that recoding for
ImageIO would set me back a month or more.
If you only need to grab an int array from an image then ImageIO should
be able to do that with just a few changes to your image loading code,
unless I'm missing something...?
The thing is, PixelGrabber implements the ImageConsumer interface. And
the doc's say an InterruptedException is supposed to be raised -- I
quote the doc's in my previous message -- but it's not. That's the
problem. If it was -- I'd be home free. The thread I do the
PixelGrabbing from is just suspended. All other threads are still up
and running.
The docs say that InterruptedException is raised if "this" thread is
interrupted (i.e. via an explicit call to Thread.interrupt()) which
isn't what is happening.
On the other hand, the method should return if the producer calls
imageComplete an ERROR flag. Unfortunately, the stack trace shows that
the ImageFetcher thread is in a suspended state due to the OOM
condition. In other words, the OOM was so severe that the thread could
not even continue executing. It's hard for the thread to notify you of
anything if the VM suspends it.
This goes back to what another person said about OOM being one of those
conditions that you can only cross your fingers and hope to survive.
Some code may be able to wind its way out of an OOM if it catches the
OOM in just the right place. Other code may be in the middle of a
situation that it cannot back out of. And in this case it looks like
even the VM can't figure out how to back out of the situation since it
couldn't even make space for some local variables so it suspended the
Thread.
To be clear -- the image is downloaded; the image has been decoded by
Toolkit; when I try to grab the pixels, my thread is suspended by
ImageFetcher.
It sounds like you are getting double copies of everything then since
the grabbed pixels are separate storage from the version that was loaded
by the Toolkit for use with drawImage. That's going to exacerbate your
memory usage and make OOM more likely to happen.
Also, your thread is not "suspended by ImageFetcher" per se - it is in a
wait() call waiting to be notified that the appropriate data has been
delivered - the data coming from the ImageFetcher thread. Once the
ImageFetcher gets hit with an OOM, it can get summarily suspended as in
the current case and cannot notify you of anything. That's not an easy
situation to code for.
There is a call to grabPixels that does take a timeout if you want to
use that to avoid permanent suspension of the calling thread, but at
that point your VM is so wedged that it had to suspend a system thread
so I don't think your program would return to too much functionality.
The way I fetch the image from the server is I just download it as a
byte array then give it to Toolkit to decode. Really simple code. It
all works with reasonable speed considering the usual constraints on
downloading a 1 meg file over the internet.
Giving it to ImageIO would only be a few more lines of code, not a
complete rewrite of your package.
Another handicap is that I don't have the source to
class sun.awt.image.ImageFetcher extends java.lang.Thread
It's one of those mystery classes. If I had source, a workaround might
pop out at me.
I'm afraid that this line from your stack trace:
Thread [Image Fetcher 0] (Suspended (exception OutOfMemoryError))
ImageFetcher.run() line: 149 [local variables unavailable]
pretty much says "System wedged, please exit and try again"...
Do you have the source to sun.awt.image.ImageFetcher or know where I can
get it???
The sources are published as part of the OpenJDK project:
http://openjdk.java.net/
...jim
===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff JAVA2D-INTEREST". For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".