Here's my understanding of the concept:
managed image: this is a
BufferedImagethat is optimized to run efficiently in memory.
Of course by default your images are managed. But there are 2 seemingly innocent ways to unmanage them. Once an image becomes unmanaged: there is no way to bring it back to its managed state. They are blacklisted. They are on the terrorist watchlist of your JVM. Rendering to an unmanaged image can be a factor of over 100x slower than rendering to a managed image.
The two ways I know to unmanage an image are:
- Access the raster's
DataBuffer. For example:
- Add an
ImageProducer. For example:
Now that I've scared you into listening, here's the great news: this problem has been mostly taken care of in recent years. Based on my own experience and the comments in this article: this only appears to be a problem if you're using a Mac with Quartz rendering.
To study this further yourself, I recommend running this sample program.
Here is sample output for that program from a few years ago, running Mac 10.4.9 PPC and Java 1.4:
Regular Test Time (1): 6
Unmanaged Test Time (1): 11494
Regular Test Time (2): 5
Unmanaged Test Time (2): 11384
Unmanaged Test time (2): 10129
So regardless of how I unmanaged my image, the results are about the same: my performance change to about 2000 times slower than it should be.
Also note that if you remove the
ImageConsumer it doesn't matter: the damage has already been done.
In a way this makes sense: if I have the
DataBuffer in hand, then I may be hijacking the image contents. So Java has to constantly check to make sure that the
DataBuffer and the
Graphics2D match up. Also if I have an
ImageConsumer listening to the
ImageProducer: this adds a level of complexity to how the image data is manipulated.
Here are tips for avoiding any problems. Even though the threat is largely passed, I still follow these practices out of habit/safety:
- If you never need to interact with the
Graphics2Dof an image, then you shouldn't see a performance problem. That is: suppose you just wanted to define an image pixel-by-pixel, but you never wanted to use a
Graphics2Dto manipulate that image.
- Suppose you do want to control the pixels in an image? Not a problem: use
bi.getRaster().setDataElements(). Just don't ask for the
As a footnote, Jerry recently pointed out that calling
myBufferedImage.setRGB()used to unmanage an image. This does not appear to be the case in Java 1.4 or later.