[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".

Reply via email to