I just tried it out with this sketch and it seems very much like @kll’s assumptions were on point.
If the image has to be rescaled and the rescaled version is fairly large, covering a good amount of pixels, it becomes very costly it seems like.
If I swap to the pre-scaled images and use the method without the width and height parameters, or pass the rescaled images exact width and height as arguments, it doesn’t cause high frame rate drops.
If I change the width or height parameter though, e.g. by adding 1 to width, the frame rate plummets once again as long as the image is large.
The rescaling method seems to cast the float values for width & height to int and then compare them to the image’s actual width & height to determine if rescaling is necessary.
Without looking at the source of g.image( img, x, y, w, h ), it probably iterates over all the pixels of the target size of the scaling calculation ( z = w * h, z pixels ).
I wrote a game in plain java before using java’s awt library and rescaling on every frame, I didn’t recall having lags there, but perhaps I was running on a lower frame rate there as well ( I think it was 30 or 24, I brought it down because it was turn-based ).
And it was everything on a fairly small scale as well and when I zoomed in a lot it seemed to get a little slower as well.
Since the rescaling method seems to “optimize” when the source wh matches the target wh, I’ll try g.image( img, x, y, w, h, sx, sy, sx2, sy2 ) with the exact wh parameters.
Of course it would be optimal if there was the same method without the w, h parameters so maybe I’ll write a custom one, but it’s probably not worth my time for optimizing away two comparisons.
EDIT:
I just realized that it is even more suboptimal than I expected.
The frameRate also drops if you just extract a part of the image or draw an image in reverse even if the width and height still match and no rescaling in that sense would be necessary.