other than the clipping methods you're using with setClip and the drawImage method, the only other way to achieve the same effect is to use the getSubimage method in BufferedImage, which just crops the image.

Ah ok I get it now. What im trying to do is draw a frame out of my sprite sheet. Not sure if the best approach is the drawImage or getSubImage. Which one is better? My images are buffered.

well, it depends. in both examples I gave you in my last post, the clips were pretty much always moving. in that case, the getSubimage method and the drawImage method are practically the same.

drawImage will crop the section of the image every time you call it, so if your clip object is always in movement, that's fine. but if you're setting a permanent clip, I would use getSubimage to save the clip to another BufferedImage object and then you can just draw than whenever you want (so java only has to "crop" the image one time).

so, in both scenarious, getSubimage turns out to be equal and/or better than the drawImage method, so I would just stick with getSubimage.

when it comes to NON rectangular clips, the best way to go is with the Graphics2D clipping methods with the Shape class.. but that's more computationally expensive and it is computed on each rendering call.

I get it now, but the thing is is that I will have a different clip range every other frame, so as to get the full animation (using a sprite sheet). So I guess i will stcik with the drawImage, since I need to reclip the image constantly, and getting the subImage sounds like it would create a new mage every time.

From a performance perspective, why are you even considering this issue?

The calculations necessary in the underlying pipeline are identical when comparing a clipped blit Vs a subrectangle blit.

The only issue you should be considering, is whether your blit will be hardware accelerated, as this will give you performance gains of between 100times, to 1000times the speed. (that is 10000% to 100000% the speed of an unaccelerated blit)

From the perspective of design, you should completely ignore the 'subrectangle' caabilities that BufferedImage offer.These api functions are not offered to give any kind of performance benefit, they are mearly convenience methods so that higher level programming need not concern itself with the complication of calculating the correct clip rectangle necessary to draw a particular sub-rectangle.Use the clipping capabilities offered by the Graphics[2D] classes - thats what it is there for.

caching the results of a subimage from a BufferedImage means you only have to perform the operation that one time - which will always be faster than clipping it over and over on each render ..

But if you are talking about painting part of a single image, then wouldn't sub-image & setting the clip be the same? Remember there is always a clip applied to drawing anything on the screen - the device (screen rectangle) clip.

If what you say is true, drawing an image that is bigger than the screen is quicker than drawing an image the same size... hmm shouldn't be too hard to make a bench-mark - I'll do it if I can find time. I bet there's no difference.

I think you guys are misreading me. I will definitely benchmark this later so you see what I mean.

picture a spritesheet, okay? you only want to draw a clip of that image. my theory is, caching each little sprite frame into an array of subImages would be faster than clipping the spritesheet at every render.

drawing a cached subimage is faster because there isn't any clipping done, java is just drawing a regular image, that happens to have been cropped beforehand from the spritesheet.

The operations performed to achieve the result are functionally identical in both cases - however I expect repeatedly clipping the single image will be everso-marginally faster.A simple blit such as :-

From a very superficial view, this approach will touch the same 2 areas of memory each time you do a blit.(writing to the clip fields in the Graphics object 'g', and reading from the member fields in BufferedImage 'img')But - however many part of the img you draw, you will only ever be touching the same 2 areas of memory.

The subrectangle approach will not touch the Graphics objects clipping members - however, each time a different subrectangle is drawn - you will be reading member variables from a different wrapper object - consequently you will be jumping all over memory.This IMO has a higher probability of causing cache misses.

I still very much doubt this difference will be detectable though, as there are far far larger overheads involved in the pipeline that will eclipse such a tiny speed difference.

However - for the comparison to be completely fair (and functionally equivalent in all cases), I suppose the setClip approach should realy be doing the followiing :-

Does that mean that painting a big, larger-than-the-screen image will forfeit hardware acceleration due to the screen clip?

hm... technically, ANY image that's drawn outside the boundaries of the screen is clipped, and therefore, should lose accleration. but if you notice, the sprites DO leave the screen a bit on the right/bottom sides.. with no obvious effect..

However, I would have expected this to cause no hardware acceleration for all versions - as getSubImage uses the same source pixel data as its parent image.Perhaps BufferedImage's created from getSubImage are cached in vram independantly of their parent image.

However, I would have expected this to cause no hardware acceleration for all versions - as getSubImage uses the same source pixel data as its parent image.Perhaps BufferedImage's created from getSubImage are cached in vram independantly of their parent image.

The reason you're seeing bad performance with non-subimage modes is that you use getSubImage() on the "sheet" image, which disables its acceleration.(it's easy to see if you run with -Dsun.java2d.trace=log to see what primitives arebeing used).

I made some simple mods to your test (which is pretty nicely done, btw):

Basically, I just do getSubImage on a different image instead of the one usedby "mode 0".

With this change I get _much_ better performance with drawImage method than getSubImage.

Especially with the new Direct3D pipeline in mustang, it costs a lot to change the texture to render from.In your case, if you have tons of images you'll change the source texture for every sprite,which costs a lot.

Also, with tons of smaller images you may be wasting more video memory.

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