drawImage performance on retina ipad with non-retina images

If I create an Animated Application template in the projucer, and set it to display a fullscreen image that scrolls continuously, when I run it on an ipad air 2, I get approximately 27fps. The image is ARGB , fullscreen (but not retina), and I draw it with

drawImageAt(img, 0,0);

Now, if I go into juce_mac_CoreGraphicsContext.mm and in the CoreGraphicsContext::drawImage method add :

CGContextSetInterpolationQuality (context, kCGInterpolationNone);

just before the call to CGContextDrawImage (context, imageRect, image);

Then suddenly I get 60 fps !

The problem does not occur if I draw a retina image (if I double the size of the image and draw it with drawImageTransformed(img, AffineTranform::scale(0.5f)) )

What’s the performance like if you do

g.setImageResamplingQuality (Graphics::ResamplingQuality::lowResamplingQuality)


With lowResamplingQuality (which sets kCGInterpolationLow) , it is back to 27fps, it’s is really the kCGInterpolationNone flag that seems to make a difference. I can’t test on a retina mac but I would not be too surprised if it behaves the same way.

I’ve added a new Graphics::ResamplingQuality to the develop branch: Graphics::ResamplingQuality::noResampling.


g.setImageResamplingQuality (Graphics::noResampling)

should do what you want.

I’ll use that, thanks t0m !

What’s the difference between lowResamplingQuality (which is described as nearest-neighbor in the comments), and the new noResampling ?

Actually, in the CoreGraphicsContext it seems like lowResamplingQuality is not at all mapped to nearest neighbor resampling, but rather to kCGInterpolationLow, which I suppose does some cheap filtering. So maybe the comments are wrong?

Also, how is mediumResamplingQuality handled in CoreGraphicsContext::setInterpolationQuality? Relying on default resampling mode?

I think you’re right (that lowResamplingQuality should have been kCGInterpolationNone), and it seems that CoreGraphicsContext::setInterpolationQuality is missing an entry for the mediumResamplingQuality (which would be kCGInterpolationLow ) ?

1 Like

Yes exactly, this must be the case. Unless the other GraphicContext implementations also apply some sort of filtering even with the lowResamplingQuality, in which case the comments should be corrected accordingly and the new noResampling quality actually make sense. But otherwise it doesn’t =)

I think it’s very valuable to have a nearest-neighbor image resizing alternative available in a well-defined way on all platforms. Not just for performance reasons, but when dealing with such things as monochromatic graphics or strictly rectangular “perfect shapes”-GUI elements, it’s really handy to be able to resize without applying filters and introducing anti aliasing artifacts.

Yes, you’re correct - lowResamplingQuality should actually map to kCGInterpolationNone.

However, the risk here is that people’s existing JUCE apps may suddenly look worse…

What is the behavior in other GraphicsContext implementations? Does lowResamplingQuality disable resampling (i.e. use nearest-neighbor policy) correctly there?

In some places, yes. It’s hard to get this working completely consistently across all platforms.

If it is not realistic to completely harmonize the behavior across platform, at least try to document the different behaviors. I know i’ve been struggling trying to disable resampling also with the software renderer on windows platform in the past, without really knowing whether it’s supposed to work.

OK, I’ve just changed things again.

Graphics::noResampling no longer exists - please use Graphics::lowResamplingQuality.