Last active
February 1, 2024 19:04
-
-
Save tomasbasham/10533743 to your computer and use it in GitHub Desktop.
Scale a UIImage to any given rect keeping the aspect ratio
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@implementation UIImage (scale) | |
/** | |
* Scales an image to fit within a bounds with a size governed by | |
* the passed size. Also keeps the aspect ratio. | |
* | |
* Switch MIN to MAX for aspect fill instead of fit. | |
* | |
* @param newSize the size of the bounds the image must fit within. | |
* @return a new scaled image. | |
*/ | |
- (UIImage *)scaleImageToSize:(CGSize)newSize { | |
CGRect scaledImageRect = CGRectZero; | |
CGFloat aspectWidth = newSize.width / self.size.width; | |
CGFloat aspectHeight = newSize.height / self.size.height; | |
CGFloat aspectRatio = MIN ( aspectWidth, aspectHeight ); | |
scaledImageRect.size.width = self.size.width * aspectRatio; | |
scaledImageRect.size.height = self.size.height * aspectRatio; | |
scaledImageRect.origin.x = (newSize.width - scaledImageRect.size.width) / 2.0f; | |
scaledImageRect.origin.y = (newSize.height - scaledImageRect.size.height) / 2.0f; | |
UIGraphicsBeginImageContextWithOptions( newSize, NO, 0 ); | |
[self drawInRect:scaledImageRect]; | |
UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext(); | |
UIGraphicsEndImageContext(); | |
return scaledImage; | |
} | |
@end |
@lee-ho, perhaps you can replace this line
UIGraphicsBeginImageContext(newSize)
with this
UIGraphicsBeginImageContextWithOptions(newSize, false, UIScreen.main.scale)
and try?
Does anyone have the version of this to work in NSImage (for MacOS)?
Swift 5 (Mac Os)
This working for me but I'm sure if is the best approach
extension NSImage {
/// Represents a scaling mode
enum ScalingMode {
case aspectFill
case aspectFit
/// Calculates the aspect ratio between two sizes
///
/// - parameters:
/// - size: the first size used to calculate the ratio
/// - otherSize: the second size used to calculate the ratio
///
/// - return: the aspect ratio between the two sizes
func aspectRatio(between size: CGSize, and otherSize: CGSize) -> CGFloat {
let aspectWidth = size.width/otherSize.width
let aspectHeight = size.height/otherSize.height
switch self {
case .aspectFill:
return max(aspectWidth, aspectHeight)
case .aspectFit:
return min(aspectWidth, aspectHeight)
}
}
}
/// Scales an image to fit within a bounds with a size governed by the passed size. Also keeps the aspect ratio.
///
/// - parameter:
/// - newSize: the size of the bounds the image must fit within.
/// - scalingMode: the desired scaling mode
///
/// - returns: a new scaled image.
func scaled(to newSize: CGSize, scalingMode: ScalingMode = .aspectFill) -> NSImage {
let aspectRatio = scalingMode.aspectRatio(between: newSize, and: size)
/* Build the rectangle representing the area to be drawn */
var scaledImageRect = CGRect.zero
scaledImageRect.size.width = size.width * aspectRatio
scaledImageRect.size.height = size.height * aspectRatio
scaledImageRect.origin.x = (newSize.width - size.width * aspectRatio) / 2.0
scaledImageRect.origin.y = (newSize.height - size.height * aspectRatio) / 2.0
let scaledImage = NSImage(size: newSize)
scaledImage.lockFocus()
draw(in: scaledImageRect)
scaledImage.unlockFocus()
return scaledImage
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
@shinrikiken - your code is not giving me the perfect image which should fits to the image size.