在不损失质量的情况下调整图像大小

Posted

技术标签:

【中文标题】在不损失质量的情况下调整图像大小【英文标题】:Resize Image without losing quality 【发布时间】:2015-09-16 15:24:09 【问题描述】:

我正在使用下面的函数来调整图像的宽度和高度,但我注意到它会破坏图像质量。

class 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;


class func resizeImageWithAspect(image: UIImage,scaledToMaxWidth width:CGFloat,maxHeight height :CGFloat)->UIImage



    let scaleFactor =  width / height;


    let newSize = CGSizeMake(width, height);

    return imageWithSize(image, size: newSize);

有没有其他方法可以在不影响质量的情况下调整图像大小?或者如何修复下面的函数,以免在调整大小后破坏图像质量?

【问题讨论】:

您获得哪种品质,您期望哪种品质? @Mats 它将图像大小正确调整为我传递给函数的任何宽度和高度。问题是图像变得模糊 仅供参考 - ios 4 中添加了 UIGraphicsBeginImageContextWithOptions 功能。检查在当今时代是否应该使用它是毫无意义的。 @rmaddy 知道我应该为 iOS 8 使用什么吗?我只想调整高度和宽度的大小而不让输出变得模糊 只要 newSize 保持原来的纵横比并且你正在缩小图像,你所做的看起来是正确的。 【参考方案1】:

这是我的 swift 代码。对于平方图像,它的效果非常好,而且没有任何质量损失!

extension UIImage 

    func resize(targetSize: CGSize) -> UIImage 
        return UIGraphicsImageRenderer(size:targetSize).image  _ in
            self.draw(in: CGRect(origin: .zero, size: targetSize))
        
    


【讨论】:

这应该是 iOS 10.0 及更高版本的公认答案。 令人难以置信的是,这并不是无处不在的答案。几乎所有的答案都是冗长的、令人费解的,并且扭曲了图像,但事实并非如此。 它适用于平方图像,但其他没有平方的图像呢? 谢谢,你很安全 完美!比其他人干净多了。当然,我只使用方形图片。但我希望如果纵横比相同,它也应该适用于矩形......【参考方案2】:

这是我的Objective-C 代码。这对我有用。

+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize isAspectRation:(BOOL)aspect 
    if (!image) 
        return nil;
    
    //UIGraphicsBeginImageContext(newSize);
    // In next line, pass 0.0 to use the current device's pixel scaling factor (and thus account for Retina resolution).
    // Pass 1.0 to force exact pixel size.
    CGFloat originRatio = image.size.width / image.size.height;
    CGFloat newRatio = newSize.width / newSize.height;

    CGSize sz;

    if (!aspect) 
        sz = newSize;
    else 
        if (originRatio < newRatio) 
            sz.height = newSize.height;
            sz.width = newSize.height * originRatio;
        else 
            sz.width = newSize.width;
            sz.height = newSize.width / originRatio;
        
    
    CGFloat scale = 1.0;
    //    if([[UIScreen mainScreen]respondsToSelector:@selector(scale)]) 
    //        CGFloat tmp = [[UIScreen mainScreen]scale];
    //        if (tmp > 1.5) 
    //            scale = 2.0;
    //        
    //    
    sz.width /= scale;
    sz.height /= scale;
    UIGraphicsBeginImageContextWithOptions(sz, NO, scale);
    [image drawInRect:CGRectMake(0, 0, sz.width, sz.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;

我在Swift 中看到了您的代码。我只是将我的Objective-C 转换为Swift 而不进行测试。你可以试试,让我知道。谢谢!

struct CommonUtils 
    static func imageWithImage(image: UIImage, scaleToSize newSize: CGSize, isAspectRation aspect: Bool) -> UIImage

        let originRatio = image.size.width / image.size.height;//CGFloat
        let newRatio = newSize.width / newSize.height;

        var sz: CGSize = CGSizeZero

        if (!aspect) 
            sz = newSize
        else 
            if (originRatio < newRatio) 
                sz.height = newSize.height
                sz.width = newSize.height * originRatio
            else 
                sz.width = newSize.width
                sz.height = newSize.width / originRatio
            
        
        let scale: CGFloat = 1.0

        sz.width /= scale
        sz.height /= scale
        UIGraphicsBeginImageContextWithOptions(sz, false, scale)
        image.drawInRect(CGRectMake(0, 0, sz.width, sz.height))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage
    

【讨论】:

【参考方案3】:
func image(image:UIImage,imageSize:CGSize)->UIImage

    UIGraphicsBeginImageContextWithOptions(imageSize, false, 0.0)
    [image .drawInRect(CGRectMake(0, 3, imageSize.width, imageSize.height))]
    let newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext()
    return newImage;

【讨论】:

考虑添加一些上下文/对要点的解释,以便您的回答更有帮助。 - 降低视频质量。亨利的回答很好。【参考方案4】:

我刚刚使用 swift 5 创建了这个有用的 UIImage 扩展。您可以使用它来调整 UIImage 的大小而不会降低质量。

我添加了几种方法,以便能够将图像调整为宽度或高度,同时保持纵横比。


extension UIImage 

    func resize(targetSize: CGSize) -> UIImage 
        return UIGraphicsImageRenderer(size:targetSize).image  _ in
            self.draw(in: CGRect(origin: .zero, size: targetSize))
        
    

    func resize(scaledToWidth desiredWidth: CGFloat) -> UIImage 
        let oldWidth = size.width
        let scaleFactor = desiredWidth / oldWidth

        let newHeight = size.height * scaleFactor
        let newWidth = oldWidth * scaleFactor
        let newSize = CGSize(width: newWidth, height: newHeight)

        return resize(targetSize: newSize)
    

    func resize(scaledToHeight desiredHeight: CGFloat) -> UIImage 
        let scaleFactor = desiredHeight / size.height
        let newWidth = size.width * scaleFactor
        let newSize = CGSize(width: newWidth, height: desiredHeight)

        return resize(targetSize: newSize)
    



【讨论】:

以上是关于在不损失质量的情况下调整图像大小的主要内容,如果未能解决你的问题,请参考以下文章

python如何在不损失质量的情况下调整(缩小)图像的大小

如何在不损失图像质量的情况下调整图像大小以适合小型 HTML5 画布? [复制]

是否可以在不损失质量的情况下调整 UIImage 的大小?

在 python 中放大 SVG 图像而不损失其质量

目标 C:如何在不损失边缘质量的情况下从 JPG 图像中去除白色背景

如何使用 PIL 减小图像文件大小