[EMAIL PROTECTED] wrote:
True - but thats an array. Depending on the internal representation of
DataBuffer (which I have not looked into yet), this could mean that the casting
has to be done for each element of the array.
Once you grab the Java array, you are done grabbing it and done casting.
If the image has only one bank (like TYPE_INT_*) then you only need to
grab one array.
setRGB() on the other hand, which is just a convenience API for setting
a few pixels (or even setting all of the pixels if the performance hit
isn't in a critical area) has to start from scratch on each operation
and must work on all BufferedImage types so it necessarily has to use a
lot of more general APIs and perform a lot of duplicate work on every
call. If the image format is known, then more direct procedures (like
grabbing the Java array) are available, but you have to pack your own
pixels if you do so.
The fact that using setRGB() for individual pixels costs so much memory, could
suggest that the internal raster is not int[]. If it would be that way, this
would mean that setRGB() needs to do do a lot of casting and create temporaray
objects, which would be a good explanation for the noticed memory consumption.
Since I am no expert here, I can only guess.
setRGB() consumes memory because it makes no assumptions about any
internal storage because it has to work even on a custom constructed
BufferedImage with a 3rd party SampleModel and a 3rd party ColorModel
and a 3rd party DataBuffer (and a 3rd party ColorSpace as well). For
all it knows the colors are represented by calculating the Nth number in
the Fibonacci sequence, composing a pixel by distributing its bits using
a reversible scrambling algorithm, and finally storing them into an SQL
database on another continent.
(Perhaps if it took the time to examine the data structures actually
being used it might be able to discern a more direct route than using
the general APIs on ColorModel, SampleModel and DataBuffer, but it is
only available for convenience, not performance.)
The primary consumption of memory for setRGB() has nothing to do with
whether or not the internal raster is int[], but the fact that many of
the general APIs on ColorModel, SampleModel and DataBuffer take small
arrays of size 3 or 4 containing one color component per entry in the
array - so each call to setRGB() involves the creation of at least one,
possibly 2 of these tiny arrays. With the modern garbage collectors in
Hotspot, they are geared to be forgiving of a lot of small objects that
are used quickly and discarded.
MfG;
ChaosE
[Message sent by forum member 'chaose71' (chaose71)]
I think one of the problems is that we never really documented the
internal representation of the standard BufferedImage types very well.
On one hand, this is for a good reason which I'll get into further
below, and on the other hand, this lack of documentation causes them to
be scary for the casual user even though they are quite simple.
Basically, if you create a TYPE_INT_RGB, or TYPE_INT_ARGB, then it will
have 1 Raster with 1 DataBuffer with 1 array of int[] that is large
enough for every pixel in the image. You can verify this by examining
the SampleModel that it uses and the number of banks in the DataBuffer,
etc., but that is the way it will (appear?) to store the internal data.
Thus, if you create a BufferedImage of one of those types then you can
grab its int[] array once using a code snippet similar to what has
already been posted here and keep using it for the life of the image for
any pixel in the image - one grab of the array and one cast and then you
are done for the life of the image.
Now, the "good reason" why we wanted to be a bit vague on this (even
though it is information that is implied by all of the data structures
that are composed into the BufferedImage) is that, for example, we
wanted the flexibility to not use a Java array for a BufferedImage and
put the data into the C heap memory, or into VRAM. Apple has done such
an optimization for performance on some of their older runtimes (before
we created the managed image facilities which give most of the benefit
of that technique without ditching the Java arrays), but that
optimization was not a problem for the Java developer because their
runtime would automagically promote the image to use a real Java array
if you ever called the getData() method on the DataBuffer. In other
words, the shift in the underlying storage was transparent to the
developer. Thus, optimized storage until you needed then Java array and
then first class Java array convenience when you needed it. Also, any
benefit of using cached copies or an alternate storage methodology is
lost if you are modifying every pixel on every frame (which is what
these animation situations tend to do) anyway since one way or another
the pixels have to cross the RAM/VRAM boundary and the performance of
moving data across that boundary swamps most other performance concerns.
If anything, batching up all of your modifications into the Java array
of a BufferedImage lets the system batch up the data movement and do it
for an entire image in one operation instead of pixel by pixel.
So, if you want a real Java array that owns some pixels, a BufferedImage
of TYPE_INT_[A]RGB is a perfectly good container for doing so. It is
faster than MemoryImageSource because MIS has to "send" the pixels into
the Image after you are done modifying them whereas the BufferedImage
approach lets you modify the real live pixels themselves. Grabbing the
data array, while it ties our hands wrt making accelerated cached copies
of the BufferedImage, is much faster than setRGB() because of its use of
the general APIs on the underlying objects...
...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".