Search code examples
cocoahidpi

NSImageView 72dpi image blurry on HiDPI display


I'm loading a 72dpi image into an NSImageView and it looks very blurry on a HiDPI display. How can it get to render perfectly crisp?

I worked out I can improve by adding this entirely non-sensical override to NSImageView, but it doesn't fix it completely.

public class CustomImageView: NSImageView {
    public override func draw(_ dirtyRect: NSRect) {
        super.draw(dirtyRect)
    }
}

Here's how it looks by default:

default

With custom override:

improved

As rendered in Preview:

preview


Solution

  • I've found I can fix this by disabling image interpolation in the graphics context. This override will disable interpolation as long as the image is not larger than the draw rect, so it will look crisp if it fits in the view but retains the interpolation if it needs to scale down.

    public class CustomImageView: NSImageView {
        public override func draw(_ dirtyRect: NSRect) {
            if let image = self.image, image.size.width <= dirtyRect.size.width && image.size.height <= dirtyRect.size.height {
                NSGraphicsContext.current?.cgContext.interpolationQuality = .none
            }
            super.draw(dirtyRect)
            NSGraphicsContext.current?.cgContext.interpolationQuality = .default
        }
    }
    

    Still interested in any other answers or info about this. I'm surprised I can't find anything when searching, seems like it would be a common issue to me.


    UPDATE

    Setting the interpolation directly on the NSGraphicsContext isn't working on macOS 11 (possibly a bug in the system?). It only works if you target the cgContext.