├── .gitignore ├── KPCScaleToFillNSImageView.h ├── KPCScaleToFillNSImageView.m ├── LICENSE └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # CocoaPods 2 | # 3 | # We recommend against adding the Pods directory to your .gitignore. However 4 | # you should judge for yourself, the pros and cons are mentioned at: 5 | # http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control? 6 | # 7 | # Pods/ 8 | 9 | -------------------------------------------------------------------------------- /KPCScaleToFillNSImageView.h: -------------------------------------------------------------------------------- 1 | // 2 | // KPCScaleToFillNSImageView.h 3 | // 4 | // Created by onekiloparsec on 4/5/14. 5 | // MIT Licence 6 | // 7 | 8 | #import 9 | 10 | @interface KPCScaleToFillNSImageView : NSImageView 11 | @end 12 | -------------------------------------------------------------------------------- /KPCScaleToFillNSImageView.m: -------------------------------------------------------------------------------- 1 | // 2 | // KPCScaleToFillNSImageView.m 3 | // 4 | // Created by onekiloparsec on 4/5/14. 5 | // MIT Licence 6 | // 7 | 8 | #import "KPCScaleToFillNSImageView.h" 9 | 10 | @implementation KPCScaleToFillNSImageView 11 | 12 | - (id)init 13 | { 14 | self = [super init]; 15 | if (self) { 16 | [super setImageScaling:NSImageScaleAxesIndependently]; 17 | } 18 | return self; 19 | } 20 | 21 | - (id)initWithCoder:(NSCoder *)aDecoder 22 | { 23 | self = [super initWithCoder:aDecoder]; 24 | if (self) { 25 | [super setImageScaling:NSImageScaleAxesIndependently]; 26 | } 27 | return self; 28 | } 29 | 30 | - (id)initWithFrame:(NSRect)frameRect 31 | { 32 | self = [super initWithFrame:frameRect]; 33 | if (self) { 34 | [super setImageScaling:NSImageScaleAxesIndependently]; 35 | } 36 | return self; 37 | } 38 | 39 | - (void)setImageScaling:(NSImageScaling)newScaling 40 | { 41 | // That's necessary to use nothing but NSImageScaleAxesIndependently 42 | [super setImageScaling:NSImageScaleAxesIndependently]; 43 | } 44 | 45 | - (void)setImage:(NSImage *)image 46 | { 47 | if (image == nil) { 48 | [super setImage:image]; 49 | return; 50 | } 51 | 52 | __weak KPCScaleToFillNSImageView *weakSelf = self; 53 | NSImage *scaleToFillImage = [NSImage imageWithSize:self.bounds.size 54 | flipped:NO 55 | drawingHandler:^BOOL(NSRect dstRect) { 56 | 57 | NSSize imageSize = [image size]; 58 | NSSize imageViewSize = weakSelf.bounds.size; // Yes, do not use dstRect. 59 | 60 | NSSize newImageSize = imageSize; 61 | 62 | CGFloat imageAspectRatio = imageSize.height/imageSize.width; 63 | CGFloat imageViewAspectRatio = imageViewSize.height/imageViewSize.width; 64 | 65 | if (imageAspectRatio < imageViewAspectRatio) { 66 | // Image is more horizontal than the view. Image left and right borders need to be cropped. 67 | newImageSize.width = imageSize.height / imageViewAspectRatio; 68 | } 69 | else { 70 | // Image is more vertical than the view. Image top and bottom borders need to be cropped. 71 | newImageSize.height = imageSize.width * imageViewAspectRatio; 72 | } 73 | 74 | NSRect srcRect = NSMakeRect(imageSize.width/2.0-newImageSize.width/2.0, 75 | imageSize.height/2.0-newImageSize.height/2.0, 76 | newImageSize.width, 77 | newImageSize.height); 78 | 79 | [[NSGraphicsContext currentContext] setImageInterpolation:NSImageInterpolationHigh]; 80 | 81 | [image drawInRect:dstRect // Interestingly, here needs to be dstRect and not self.bounds 82 | fromRect:srcRect 83 | operation:NSCompositeCopy 84 | fraction:1.0 85 | respectFlipped:YES 86 | hints:@{NSImageHintInterpolation: @(NSImageInterpolationHigh)}]; 87 | 88 | return YES; 89 | }]; 90 | 91 | [scaleToFillImage setCacheMode:NSImageCacheNever]; // Hence it will automatically redraw with new frame size of the image view. 92 | 93 | [super setImage:scaleToFillImage]; 94 | } 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Cédric Foellmi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | KPCScaleToFillNSImageView 2 | ========================= 3 | 4 | A simple NSImageView subclass that does exactly one additional thing: the Cocoa/OSX equivalent of UIKit's UIImageScaleToFill mode. 5 | --------------------------------------------------------------------------------