What is the proper Retina strategy?

I'm writing a cross platform plugin and of course I want images to look their best on Mac Retina displays and still work properly on Windows.  I can't seem to find what the best strategy is.

For instance, I'm creating a custom slider/rotary knob using images. Should I make the images 2x size and them draw them at half size with g.drawImage ?




1 Like

The best strategy is always to use vector graphics!

Come on, ALWAYS using vector graphics isn't feasible yet. Photo-realistic knobs still need to be rendered with a set of bitmap frames (and I'd LOVE to be proved wrong about this, so if Jules or anybody knows of a counter example, please let me know).

For now, I ended up having two sets of frames, one for 2x and one 1x, and then I use the appropriate one depending on the display


First, to answer the OP, you can try to draw the outline as a path, and then use an imagefill to fill the path using your bitmap. This combines the nice scalable outlines of vector drawing witht the ability to use non-trivial gradients on the inside of the button.

Next, jules, not this again. As the developer of a software library you should know better.

At least retina is easy to support with its exact 2× scale factor. In my experience, the 1.25× factor on Windows (aka 120dpi) is the worst.

Vector graphics are not going to magically solve that problem. Both vector graphics and bitmaps can have the problem of having their features, be it pixels or lines, misaligned with the physical pixels on the screen. Both will look shoddy if you don't provide versions for different resolutions.

If you have a 16×16 pixel icon at 1× scale, the only way to make it look acceptable on 1.25× scaling is to have a 20×20 icon. Vector graphics may be easier to scale, but you still must edit your 20×20 icon to align the features to that different pixel grid. And you must make sure that when rendering your icon, you exactly align the image with the physical pixels. There is a good reason why the Windows ICO format supports multiple layers of different sizes.

You also have to take into account details like if you draw that icon in the middle of a 25×25 area, you have to offset by half a pixel or it will look blurry.

Case in point, let's open the IntroJucer:


Note the ugly artefacts around the tabs in the larger version. Ironically this would look much better if it were using bitmaps for those tabs.

Now let's focus on the icons:

They look very pixellated, which is an artefact of poor downsampling (the resource images are 128×128). If we resize the resource images to 32×32, it looks significantly better, but blurry. This blurryness will not go away if you draw these icons using vector graphics.

And finally the only reason we can get away with using vector graphics a lot these days is this ongoing fad with “flat” user interfaces. This is slowly coming to an end, as more and more people are figuring out it is ruining usability.



As for the 125% issue on Windows, I ended up ignoring that completely by telling my JUCE application to ignore the DPI awareness on Windows.

The result is that, on Windows, every "logical" point will match every "physical" pixel. At least I only have to worry about 1x vs. 2x in Retina.