通过保持纵横比和宽度来调整 UIImage 的大小

我在许多帖子中看到通过保持长宽比来调整图像的大小。这些函数在调整大小时使用 RECT 的固定点(Width 和 Height)。但是在我的项目中,我需要调整视图的宽度单独,高度应采取自动根据纵横比。 任何人帮助我实现这一点。

157744 次浏览

最简单的方法是设置 UIImageView的帧,并将 contentMode设置为调整大小选项之一。

代码是这样的-这可以作为一个实用的方法-

+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize
{
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}

Srikar 的方法非常好,如果你知道你的新尺寸的高度 还有宽度。 例如,如果您只知道要缩放到的宽度,而不关心高度,那么首先必须计算高度的缩放因子。

+(UIImage*)imageWithImage: (UIImage*) sourceImage scaledToWidth: (float) i_width
{
float oldWidth = sourceImage.size.width;
float scaleFactor = i_width / oldWidth;


float newHeight = sourceImage.size.height * scaleFactor;
float newWidth = oldWidth * scaleFactor;


UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
[sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}

如果你碰巧不知道图像是人像还是风景(例如用户用相机拍照) ,我创建了另一个方法,采用最大宽度和高度参数。

假设 UIImage *myLargeImage是4:3的比例。

UIImage *myResizedImage = [ImageUtilities imageWithImage:myLargeImage
scaledToMaxWidth:1024
maxHeight:1024];

大小调整后的 UIImage 将为1024x768(如果为横向) ; 768x1024(如果为纵向)。该方法还能生成较高分辨率的视网膜显示图像。

+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)size {
if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) {
UIGraphicsBeginImageContextWithOptions(size, NO, [[UIScreen mainScreen] scale]);
} else {
UIGraphicsBeginImageContext(size);
}
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();


return newImage;
}


+ (UIImage *)imageWithImage:(UIImage *)image scaledToMaxWidth:(CGFloat)width maxHeight:(CGFloat)height {
CGFloat oldWidth = image.size.width;
CGFloat oldHeight = image.size.height;


CGFloat scaleFactor = (oldWidth > oldHeight) ? width / oldWidth : height / oldHeight;


CGFloat newHeight = oldHeight * scaleFactor;
CGFloat newWidth = oldWidth * scaleFactor;
CGSize newSize = CGSizeMake(newWidth, newHeight);


return [ImageUtilities imageWithImage:image scaledToSize:newSize];
}

只需导入 AVFoundation 并使用 AVMakeRectWithAspectRatioInsideRect(CGRectCurrentSize, CGRectMake(0, 0, YOUR_WIDTH, CGFLOAT_MAX)

为了改进瑞安的回答:

   + (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)size {
CGFloat oldWidth = image.size.width;
CGFloat oldHeight = image.size.height;


//You may need to take some retina adjustments into consideration here
CGFloat scaleFactor = (oldWidth > oldHeight) ? width / oldWidth : height / oldHeight;


return [UIImage imageWithCGImage:image.CGImage scale:scaleFactor orientation:UIImageOrientationUp];
}

感谢@Maverick1的算法,我实现它到 Swift,在我的情况下高度是输入参数

class func resizeImage(image: UIImage, newHeight: CGFloat) -> UIImage {


let scale = newHeight / image.size.height
let newWidth = image.size.width * scale
UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight))
image.drawInRect(CGRectMake(0, 0, newWidth, newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()


return newImage
}

此方法是 UIImage 上的一个类别。使用 AVFoundation 进行缩放以适应几行代码。 别忘了导入 #import <AVFoundation/AVFoundation.h>

@implementation UIImage (Helper)


- (UIImage *)imageScaledToFitToSize:(CGSize)size
{
CGRect scaledRect = AVMakeRectWithAspectRatioInsideRect(self.size, CGRectMake(0, 0, size.width, size.height));
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
[self drawInRect:scaledRect];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return scaledImage;
}


@end

解决方案@Ryan 用迅捷的代码

用途:

 func imageWithSize(image: UIImage,size: CGSize)->UIImage{
if UIScreen.mainScreen().respondsToSelector("scale"){
UIGraphicsBeginImageContextWithOptions(size,false,UIScreen.mainScreen().scale);
}
else
{
UIGraphicsBeginImageContext(size);
}


image.drawInRect(CGRectMake(0, 0, size.width, size.height));
var newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();


return newImage;
}


//Summon this function VVV
func resizeImageWithAspect(image: UIImage,scaledToMaxWidth width:CGFloat,maxHeight height :CGFloat)->UIImage
{
let oldWidth = image.size.width;
let oldHeight = image.size.height;


let scaleFactor = (oldWidth > oldHeight) ? width / oldWidth : height / oldHeight;


let newHeight = oldHeight * scaleFactor;
let newWidth = oldWidth * scaleFactor;
let newSize = CGSizeMake(newWidth, newHeight);


return imageWithSize(image, size: newSize);
}

嗯,我们在这里有几个很好的答案调整图像,但我只是根据我的需要修改。希望这能帮到像我这样的人。

我的要求是

  1. 如果图像宽度大于1920,则用1920宽度调整大小,并用原始高宽比保持高度。
  2. 如果图像高度大于1080,则用1080的高度调整大小,并用原始长宽比维持宽度。

 if (originalImage.size.width > 1920)
{
CGSize newSize;
newSize.width = 1920;
newSize.height = (1920 * originalImage.size.height) / originalImage.size.width;
originalImage = [ProfileEditExperienceViewController imageWithImage:originalImage scaledToSize:newSize];
}


if (originalImage.size.height > 1080)
{
CGSize newSize;
newSize.width = (1080 * originalImage.size.width) / originalImage.size.height;
newSize.height = 1080;
originalImage = [ProfileEditExperienceViewController imageWithImage:originalImage scaledToSize:newSize];


}


+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize
{
UIGraphicsBeginImageContext(newSize);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}

感谢@Srikar Appal,为了调整大小,我使用了他的方法。

您也可以检查 这个以进行大小调整计算。

我已经用更简单的方法解决了

UIImage *placeholder = [UIImage imageNamed:@"OriginalImage.png"];
self.yourImageview.image = [UIImage imageWithCGImage:[placeholder CGImage] scale:(placeholder.scale * 1.5)
orientation:(placeholder.imageOrientation)];

尺度的乘法器将定义图像的尺度,越乘法器越小的图像。所以你可以检查什么适合你的屏幕。

或者你也可以通过除以图像宽度/屏幕宽度得到乘法。

最佳答案 Maverick 1的正确翻译为 斯威夫特(使用最新的 雨燕3) :

func imageWithImage (sourceImage:UIImage, scaledToWidth: CGFloat) -> UIImage {
let oldWidth = sourceImage.size.width
let scaleFactor = scaledToWidth / oldWidth


let newHeight = sourceImage.size.height * scaleFactor
let newWidth = oldWidth * scaleFactor


UIGraphicsBeginImageContext(CGSize(width:newWidth, height:newHeight))
sourceImage.draw(in: CGRect(x:0, y:0, width:newWidth, height:newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage!
}

程序设计:

imageView.contentMode = UIViewContentModeScaleAspectFit;

故事板:

enter image description here

Swift 3中有一些变化。 这是 UIImage 的一个扩展:

public extension UIImage {
public func resize(height: CGFloat) -> UIImage? {
let scale = height / self.size.height
let width = self.size.width * scale
UIGraphicsBeginImageContext(CGSize(width: width, height: height))
self.draw(in: CGRect(x:0, y:0, width:width, height:height))
let resultImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resultImage
}
}

这个对我来说太完美了。保持高宽比,采用 maxLength。宽度或高度不会超过 maxLength

-(UIImage*)imageWithImage: (UIImage*) sourceImage maxLength: (float) maxLength
{
CGFloat scaleFactor = maxLength / MAX(sourceImage.size.width, sourceImage.size.height);


float newHeight = sourceImage.size.height * scaleFactor;
float newWidth = sourceImage.size.width * scaleFactor;


UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
[sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}

根据可用宽度计算图像的最佳高度。

import Foundation


public extension UIImage {
public func height(forWidth width: CGFloat) -> CGFloat {
let boundingRect = CGRect(
x: 0,
y: 0,
width: width,
height: CGFloat(MAXFLOAT)
)
let rect = AVMakeRect(
aspectRatio: size,
insideRect: boundingRect
)
return rect.size.height
}
}
extension UIImage {


/// Returns a image that fills in newSize
func resizedImage(newSize: CGSize) -> UIImage? {
guard size != newSize else { return self }
        

let hasAlpha = false
let scale: CGFloat = 0.0
UIGraphicsBeginImageContextWithOptions(newSize, !hasAlpha, scale)
        

draw(in: CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height))
let newImage: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
    

/// Returns a resized image that fits in rectSize, keeping it's aspect ratio
/// Note that the new image size is not rectSize, but within it.
func resizedImageWithinRect(rectSize: CGSize) -> UIImage? {
let widthFactor = size.width / rectSize.width
let heightFactor = size.height / rectSize.height
        

var resizeFactor = widthFactor
if size.height > size.width {
resizeFactor = heightFactor
}
        

let newSize = CGSize(width: size.width / resizeFactor, height: size.height / resizeFactor)
let resized = resizedImage(newSize: newSize)
        

return resized
}
}

当比例设置为0.0时,使用主屏幕的比例因子,视网膜显示器的比例因子为2.0或更高(iPhone 6 Plus 的比例因子为3.0)。

Swift 5 版本的方面适合 身高,基于@J ános 的回答

使用现代的 UIGraphicsImageRenderer API,因此保证返回有效的 UIImage

extension UIImage
{
/// Given a required height, returns a (rasterised) copy
/// of the image, aspect-fitted to that height.


func aspectFittedToHeight(_ newHeight: CGFloat) -> UIImage
{
let scale = newHeight / self.size.height
let newWidth = self.size.width * scale
let newSize = CGSize(width: newWidth, height: newHeight)
let renderer = UIGraphicsImageRenderer(size: newSize)


return renderer.image { _ in
self.draw(in: CGRect(origin: .zero, size: newSize))
}
}
}

您可以结合使用这个(基于矢量的) PDF 图像资产,以保持任何渲染大小的质量。

Zeeshan Tufall 和 Womble 在 Swift 5中的回答有一些小的改进。 这里我们有两个扩展函数来缩放图像到任意维度的 maxLength和 jpeg 压缩。

extension UIImage {
func aspectFittedToMaxLengthData(maxLength: CGFloat, compressionQuality: CGFloat) -> Data {
let scale = maxLength / max(self.size.height, self.size.width)
let format = UIGraphicsImageRendererFormat()
format.scale = scale
let renderer = UIGraphicsImageRenderer(size: self.size, format: format)
return renderer.jpegData(withCompressionQuality: compressionQuality) { context in
self.draw(in: CGRect(origin: .zero, size: self.size))
}
}
func aspectFittedToMaxLengthImage(maxLength: CGFloat, compressionQuality: CGFloat) -> UIImage? {
let newImageData = aspectFittedToMaxLengthData(maxLength: maxLength, compressionQuality: compressionQuality)
return UIImage(data: newImageData)
}
}

如果有人在 Swift 5中需要这个解决方案:

private func resizeImage(image: UIImage, newHeight: CGFloat) -> UIImage {
    

let scale = newHeight / image.size.height
let newWidth = image.size.width * scale
UIGraphicsBeginImageContext(CGSize(width:newWidth, height:newHeight))
image.draw(in:CGRect(x:0, y:0, width:newWidth, height:newHeight))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()


return newImage
}