Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confused about NSImageView scaling

I'm trying to display a simple NSImageView with it's image centered without scaling it like this:

Just like iOS does when you set an UIView's contentMode = **UIViewContentModeCenter**

Just like iOS does when you set an UIView's contentMode = UIViewContentModeCenter

So I tried all NSImageScaling values, this is what I get when I chose NSScaleNone

I really don't understand what's going on :-/

I really don't understand what's going on :-/

like image 581
betzerra Avatar asked Dec 06 '12 18:12

betzerra


4 Answers

Here's an awesome category for NSImage: NSImage+ContentMode

It allows content modes like in iOS, works great.

like image 126
Avishay Cohen Avatar answered Nov 17 '22 07:11

Avishay Cohen


You can manually generate the image of the correct size and content, and set it to be the image of the NSImageView so that NSImageView doesn't need to do anything.

NSImage *newImg = [self resizeImage:sourceImage size:newSize];
[aNSImageView setImage:newImg];

The following function resizes an image to fit the new size, keeping the aspect ratio intact. If the image is smaller than the new size, it is scaled up and filled with the new frame. If the image is larger than the new size, it is downsized, and filled with the new frame

- (NSImage*) resizeImage:(NSImage*)sourceImage size:(NSSize)size{

NSRect targetFrame = NSMakeRect(0, 0, size.width, size.height);
NSImage*  targetImage = [[NSImage alloc] initWithSize:size];

NSSize sourceSize = [sourceImage size];

float ratioH = size.height/ sourceSize.height;
float ratioW = size.width / sourceSize.width;

NSRect cropRect = NSZeroRect;
if (ratioH >= ratioW) {
    cropRect.size.width = floor (size.width / ratioH);
    cropRect.size.height = sourceSize.height;
} else {
    cropRect.size.width = sourceSize.width;
    cropRect.size.height = floor(size.height / ratioW);
}

cropRect.origin.x = floor( (sourceSize.width - cropRect.size.width)/2 );
cropRect.origin.y = floor( (sourceSize.height - cropRect.size.height)/2 );



[targetImage lockFocus];

[sourceImage drawInRect:targetFrame
               fromRect:cropRect       //portion of source image to draw
              operation:NSCompositeCopy  //compositing operation
               fraction:1.0              //alpha (transparency) value
         respectFlipped:YES              //coordinate system
                  hints:@{NSImageHintInterpolation:
 [NSNumber numberWithInt:NSImageInterpolationLow]}];

[targetImage unlockFocus];

return targetImage;}
like image 44
Shagru Avatar answered Nov 17 '22 06:11

Shagru


Set image scaling property to NSImageScaleAxesIndependently which will scale image to fill rectangle.This will not preserve aspect ratio.

like image 2
Ganesh Amrule Avatar answered Nov 17 '22 08:11

Ganesh Amrule


Swift version of @Shagru's answer (without the hints)

func resizeImage(_ sourceImage:NSImage, size:CGSize) -> NSImage
    {
        let targetFrame = CGRect(origin: CGPoint.zero, size: size);
        let targetImage = NSImage.init(size: size)
        let sourceSize = sourceImage.size
        let ratioH = size.height / sourceSize.height;
        let ratioW = size.width / sourceSize.width;

        var cropRect = CGRect.zero;
        if (ratioH >= ratioW) {
            cropRect.size.width = floor (size.width / ratioH);
            cropRect.size.height = sourceSize.height;
        } else {
            cropRect.size.width = sourceSize.width;
            cropRect.size.height = floor(size.height / ratioW);
        }

        cropRect.origin.x = floor( (sourceSize.width - cropRect.size.width)/2 );
        cropRect.origin.y = floor( (sourceSize.height - cropRect.size.height)/2 );
        targetImage.lockFocus()
        sourceImage.draw(in: targetFrame, from: cropRect, operation: .copy, fraction: 1.0, respectFlipped: true, hints: nil )


        targetImage.unlockFocus()
        return targetImage;
    }
like image 1
jvcleave Avatar answered Nov 17 '22 06:11

jvcleave