UI blur on non-retina displays

I’m running into an issue with rendering png based graphics on OSX.
Everything looks tack sharp on retina displays but once you connect an external display that is 1080p (or even something like 3440x1440 (I tried a bunch) and scale down the window size, things get blurry.

It’s a bit hard to capture in screenshots, as it looks a lot worse in person.

Some of the things I have tried so far:

  • Software renderer - aliased
  • OpenGL render - aliased
  • CoreGraphics render - blurred (almost as if bilinear filtering is enabled)
  • g.setImageResamplingQuality(juce::Graphics::highResamplingQuality); makes no difference, and low looks even worse.

The issue is also happening on windows but it’s less noticeable since the blur is not applied. It basically looks like software renderer on OSX. That makes sense since the ‘filtering’ is only happening under CoreGraphics.

What could be going on here? I don’t think I am doing anything unusual in my plugin, so I would expect JUCE to handle scaling well out of the box.

I had the same issue.

With the software renderer (which is used by default on Windows AFAIK), bitmap downsampling is OK down to half the original size. If you downsample more than that it looks aliased and is practically unusable.

With CoreGraphics, it indeed looks blurry I’m not exactly sure why. But something is up with AffineTransforms.

Say your image is 1000x1000:

g.drawImage(image, Rectangle<int>(800, 800)); // not blurry

g.drawImage(image, Rectangle<int>(1000, 1000)); // blurry

I’m not sure but I think this has to do with CoreGraphics transformation matrix using doubles and JUCE using floats.
g.addTransform() applies a float transformation matrix to the CG context, then g.drawImage() applies another float transform to fit in the specified rectangle. Both matrix are multiplied which carries error from floating point. At the end, CG will draw your image transformed by a ratio like 0.800015479. With the antialiasing from CG perhaps it can explain the blur, but that’s just my guess.

A solution could be to use the software or OpenGL renderer on Mac, and make sure that your bitmaps won’t be downsampled more than half…
I ended up handling the scaling of my editor without using transforms, and wrapped Lanczos resizing functions from IPP and Accelerate to resample my bitmaps at any size.

I’ve has some good improvement using the gin module applyResize() function, although without reading this whole thread carefully I’m not sure if it applies to your issue: