Home > other >  Disable anti-aliasing in UIKit
Disable anti-aliasing in UIKit

Time:07-02

I've got a pixel art game app that uses UIKit for its menus and SpriteKit for the gameplay scene. The pixels are getting blurred due to anti-aliasing.

With the sprites I can turn off the anti-aliasing using...

node.texture?.filteringMode = .nearest

but in UIKit I can't find a way to turn off the anti-aliasing in the UIImageView's.

I saw this post but there's no example and the answer wasn't accepted. Not sure how to turn it off using CGContextSetShouldAntialias, or where to call it.

Based on the example I found here, tried using this subclass but it didn't seem to make a difference; according to my breakpoints the method is never called:

class NonAliasingView: UIImageView {
    
    override func draw(_ rect: CGRect) {
        guard let ctx = UIGraphicsGetCurrentContext() else { return }
        
        // fill background with black color
        ctx.addRect(bounds)
        ctx.setFillColor(UIColor.black.cgColor)
        ctx.fillPath()
       
        if let img = image {
            let pixelSize = CGSize(width: img.size.width * layer.contentsScale, height: img.size.height * layer.contentsScale)
            UIGraphicsBeginImageContextWithOptions(pixelSize, true, 1)

            guard let imgCtx = UIGraphicsGetCurrentContext() else { return  }
            imgCtx.setShouldAntialias(false)
            img.draw(in: CGRect(x: 0, y: 0, width: pixelSize.width, height: pixelSize.height))

            guard let cgImg = imgCtx.makeImage() else { return }
            ctx.scaleBy(x: 1, y: -1)
            ctx.translateBy(x: 0, y: -bounds.height)
 
            ctx.draw(cgImg, in: CGRect(x: (bounds.width - img.size.width) / 2, y: (bounds.height - img.size.height) / 2, width: img.size.width, height: img.size.height))
        }
    }
}

Here's the code from my view controller where I tried to implement the subclass (modeImage is an IBOutlet to a UIImageView):

//    modeImage.image = gameMode.displayImage

let modeImg = NonAliasingView()
modeImg.image = gameMode.displayImage
modeImage = modeImg

If I try to use UIGraphicsGetCurrentContext in the view controller it is nil and never passes the guard statement.

I've confirmed view.layer.allowsEdgeAntialiasing defaults to false. I don't need anti-aliasing at all, so if there's a way to turn off anti-aliasing app wide, or in the whole view controller, I'd be happy to use it.

How do you disable anti-aliasing with a UIImageView in UIKit?

UPDATE

Added imgCtx.setShouldAntialias(false) to method but still not working.

CodePudding user response:

To remove all antialiasing on your image view and just use nearest-neighbor filtering, set the magnificationFilter and minificationFilter of the image view's layer to CALayerContentsFilter.nearest, as in:

yourImageView.layer.magnificationFilter = .nearest
yourImageView.layer.minificationFilter = .nearest
  • Related