调整图片大小而不失去质量

16

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

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
@Mats 它可以将图像正确地调整为我传递给函数的任何宽度和高度。问题在于图像变得模糊了。 - user5130344
1
FYI - UIGraphicsBeginImageContextWithOptions 函数是在 iOS 4 中添加的。在现今这个时代检查是否应该使用它已经没有意义了。 - rmaddy
@rmaddy,你有什么建议可以用在iOS 8上吗?我只想调整高度和宽度而不使输出变得模糊。 - user5130344
只要新的尺寸保持原始纵横比并且你正在缩小图像,那么你所做的看起来是正确的。 - rmaddy
4个回答

51

这是我的 Swift 代码。对于正方形的图像,它表现得非常好,而且没有任何质量损失!

extension UIImage {

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

}

6
这应该是适用于 iOS 10.0 及以上版本的被接受的答案。 - Josh O'Connor
3
这真令人难以置信,这不是到处都能找到的答案。 几乎所有的答案都很冗长、复杂,并且扭曲了形象,但是这个答案却没有这些问题。 - Gabriel Garrett
3
它适用于正方形图像,但对于其他非正方形的图像呢? - Birju
谢谢,你保护了我。 - IvanovDeveloper
所有以上的答案都降低了视频质量,只有这个答案保持了视频质量。 - AsifHabib
显示剩余2条评论

5

我使用Swift 5创建了这个有用的UIImage扩展。您可以使用它来调整UIImages的大小而不会失去质量。

我添加了一些方法,以便能够按比例调整图像的宽度或高度。


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)
    }

}


5

这是我的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;
}

3
考虑添加一些主要观点的背景/解释,以便您的答案更加有用。 - lfurini
降低视频质量。Henry的答案很好。 - AsifHabib

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接