Note that to make the transparent image a "managed image" (sometimes called "automatic image", but "managed" is a more correct and descriptive term...) you currently need to use other API than creating a BufferedImage explicitly.

That is: new BufferedImage(...)will give you just a palin-old BufferedImage, no possibility of acceleration under the hood. But: GraphicsConfiguration.createCompatibleImage(...)will give you a BufferedImage that we may, depending on various constraints, cache in VRAM and accelerate using the graphics hardware.

Of course, this currently only works for transparent (vs. translucent) images, unless you are using the not-quite-ready-for-prime-time translucency acceleration described by trembovetski in one of these forums.

In some future release, we hope to "manage" all images, no matter how they are created. But currently, we just hook into specific API calls, such as: Component.createImage() GraphicsConfig.createCompatibleImage() Toolkit.getImage() new ImageIcon().getImage()

I would think that you would get this same error whether you were creating the BufferedImages explicitly (new BufferedImage) or as managed images (createCompatibleImage()); we are essentially doing the same type of thing underneath. In the managed image case, we may also create a VRAM-cached version of the image, but these cached images do not affect the size of the Java heap.

In any case, if you are having heap-size problems, you might want to increase your heap size when you run Java. It runs with a default heap size of 64 M on Windows (I believe); maybe try something like: java -Xmx128m <class>or try other values until you get one that works for you.Also, if you know your heap will grow to that size, then you probably also want to increase the initial heap size to eliminate the performance penalty of the VM growing the heap incrementally: java -Xms128m <class>would start off Java with a heap of 128 megs (I think it starts at 16M by default, but I'm hazy on that detail).

public GraphicsConfiguration getGraphicsConfiguration()Gets the GraphicsConfiguration associated with this Component. If the Component has not been assigned a specific GraphicsConfiguration, the GraphicsConfiguration of the Component object's top-level container is returned. If the Component has been created, but not yet added to a Container, this method returns null.

Returns:the GraphicsConfiguration used by this Component or nullSince: 1.3

where as Window does this...

Quote

public GraphicsConfiguration getGraphicsConfiguration()This method returns the GraphicsConfiguration used by this Window.

Overrides:getGraphicsConfiguration in class ComponentReturns:the GraphicsConfiguration used by this Component or null

from what i've found, I don't think a Window has to be visible for it to have a GraphicsConfiguration object associated with it.

having steps 2) & 3) is wasteful, and hopefully will be combined in 1.4.2 or 1.5.

p.s. I know frame.createImage() returns an acceleratable image, but I prefer not to use this method, as it is asynchronous, messy, and the images returned have an underlying ImageProducer that misbehaves with some of the image manipulation classes.

Just wanted to clarify something about Component.createImage(). When I said earlier that calls to this method will create managed (acceleratable) images, the method I was actually referring to was Component.createImage(w, h), not createImage(ImageProducer). This latter method will not produce a managed image and has the asynchronous problems you pointed out. But the createImage(w,h) version is completely synchronous (we create the image at the time that you call the method) and it creates a managed image. Note that this method does not support the transparency that you would need in a sprite; for that, you have to call GraphicsConfiguration.createCompatibleImage(w, h, Transparency.BITMASK), as mentioned in various posts above.

Sorry for the confusion; there's just too many ways to create images and it's easy to get them all confused, especially with our current managed image approach of only hooking into some of these methods for acceleration (just a quick hack while we work on the long term solution of being able to accelerate any image, no matter how it is created).

Just wanted to clarify something about Component.createImage(). When I said earlier that calls to this method will create managed (acceleratable) images, the method I was actually referring to was Component.createImage(w, h), not createImage(ImageProducer). This latter method will not produce a managed image and has the asynchronous problems you pointed out. But the createImage(w,h) version is completely synchronous (we create the image at the time that you call the method) and it creates a managed image. Note that this method does not support the transparency that you would need in a sprite; for that, you have to call GraphicsConfiguration.createCompatibleImage(w, h, Transparency.BITMASK), as mentioned in various posts above.

Sorry for the confusion; there's just too many ways to create images and it's easy to get them all confused, especially with our current managed image approach of only hooking into some of these methods for acceleration (just a quick hack while we work on the long term solution of being able to accelerate any image, no matter how it is created).

Chet.Java2D

hehe, my mistake,

The line you seem to have picked up on

1

frame.createImage()

was meant to read

1

toolkit.createImage()

(which makes what I said immediately after, make alot more sense )

as for component.createImage(<any of them>)

I'v already stopped using them in favor of the equivalent GraphicsConfiguration methods.

and actually, the Toolkit class recommends that developers don't use the toolkit.getImage() either, and instead use the createImage version. (and implement their own caching system)so, I would say this is most correct :-

you are assuming the default screen device, and default GraphicsConfiguration for that device. (hence the 'compatible' Image returned may not infact be 'compatible' for the Frame on which you intend to render the image!

ofcourse for that line to work, you'd also have to change the definition of the method, so 'con' was actually a Frame rather than just a Container.(but it would make more sense passing in a Frame anyway :-What You want to load (String, would be better as an URL)Where you intend to render it (The Frame)How you intend to render it (The transparency type))

P.S.

I was just thinking about the implications of using toolkit.getImage() on a system with multiple display devices (with regard to how the 'managed image' version of image would be handled

heres abit of code explaining what I mean :-

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

Imagefred = getTookit().getImage("fred.png");Imagefred2 = getTookit().getImage("fred.png");//at this point both fred and fred2 (although different objects) may have the same ImageProducer

f1.getGraphics().drawImage(fred);f2.getGraphics().drawImage(fred2);// ^ ok, you would need more than 1 draw for the image to be cached in VRAM,// but, heres my question...// how would they be cached :S

in that example, how would the automatic images be managed?2 images sharing the same ImageProducer, while being rendered to 2 different display devices (and hence requiring 2 different VRam copies [potencially in different pixel formats?]) could cause an awful mess, could it not??

You reacted pretty strongly to the ImageIcon.getImage() above, calling it lazy and evil.

I'd like to know why, and I'd like to know what your suggestion for a non-lazy version would be.

cos its horribly inefficient, if you go through the sourcecode, you'll find that the little line...

1

newImageIcon(String).getImage();

hides a huge amount of unnecessary code.

1) you create an ImageIcon,

If its your first ImageIcon, then the following static stuff is created...

A) a MediaTracker

1

protectedfinalstaticMediaTrackertracker = newMediaTracker(component);

B) and, because a MediaTracker needs an ImageObserver to monitor the loading, a Component is also created to pass into the MediaTrackers constructor.

1

protectedfinalstaticComponentcomponent = newComponent() {};

neither of those objects will ever become disposable (until the Class Loader is destroyed...),so by simply creating an ImageIcon, you add an extra overhead to your mem. requirements.

2) ImageIcon uses the toolkit.getImage() variants of the image loading methods rather than createImage(). I don't know if that is good/bad/indifferent, but, it could potencially introduce some problems.

3) MediaTracker itself contains all sorts of rubbish.For instance, each image added has a 'MediaEntry' object created, which as far as i can gather is simply a node for a linkedlist.(actually, 'cos its an image, it uses the subclass 'ImageMediaEntry'!!)

there are 2 alternatives,

1) the quick and ez path, use ImageIO

2) use toolkit.createImage, toolkit.prepareImage, and an ImageObserver of your own.

Quote

(Please don't take offense at my question, I'm REALLY REALLY tired and perhaps not phrasing it correctly, but also really interested in the answer. Why is it evil???)

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org