Reputation: 303
I load an image (NSImage) from the disk, and draw it to an NSImageView on MAC, No problem image looks fine and clear.
After drawing it to the NSImageView, I call the function below with the same image, then draw the returned value to the same NSImageView. The resulting image is extremly blurry, even if all I do is lockFocus and UnlockFocus without doing anything else.
-(NSImage*)addTarget:(NSImage*)image
{
[image lockFocus]; // this image is sharp and clear
[image unlockFocus];
return image; // this image is extremely blurry
}
Anybody knows why or how to fix that?
thanks rough
Upvotes: 3
Views: 1108
Reputation: 1203
So as doing some research I realized that this is related to Retina displays. I guess locking focus will always draw at bestRepresentation which if there is a retina display attached anywhere to the computer, it will render based on that scale factor. So in order to get this to maintain proper dimensions and DPI I created a method that iterates through all screens and returns the largest backingScaleFactor
func maximumScaleFactor(screen: NSScreen) -> CGFloat {
var max: CGFloat = 0
for s in NSScreen.screens()! {
if s.backingScaleFactor > max { max = s.backingScaleFactor }
}
return max / screen.backingScaleFactor
}
Then for the 'NSImage' I did the following
-(NSImage*)addTarget:(NSImage*)image
let scale = self.maximumScaleFactor(currentScreen)
let originalSize = image.size
//cut the image size in half
var size = image.size
size.x /= scale
size.y /= scale
image.lockFocus()
//do whatever drawing you need here
image.unlockFocus()
//set the image back to its original size
image.size = originalSize
return image
}
So far this has worked well for me and the image quality subjectively appears the same to me.
Upvotes: 1
Reputation: 1835
To fix your problem is difficult because you don't say what you want to achieve. Why did you write that method, why do you call it, what do you expect this method does? You said: all I do is lockFocus and UnlockFocus without doing anything else.
Indeed it looks like calling lockFocus
unlockFocus
(and nothing between) does nothing. But that is wrong. [image lockFocus]
alone changes image
dramatically. An NSImage
object contains zero, one (in most cases) or more (icon or some TIFFs) object of class NSImageRep
. A call of lockFocus
on this image selects an NSImageRep
, that is best suited for depicting on the screen. Then it computes how many pixels (but now for a screen) it needs to render the image with the given size but with a resolution of only 72 dpi (or 144 dpi for retina screens). And then removes the NSImageRep
from the list of representations and creates instead a new NSImageRep. In former OS-versions (before 10.6) an NSCachedImageRep
was created. But now an NSCGImageSnapshotRep
is created which under the hood is a CGImage. Make a
NSLog(@" image is:\n%@", image );
before lockFocus
and one after the call of unlockFocus
and the you will see what happens: for a high resolution image the number of pixels will go down, which is a nothing else than a reduction in quality. And that makes your image blurry.
Upvotes: 0