Cách đơn giản nhất để thay đổi kích thước một UIImage?


397

Trong ứng dụng iPhone của tôi, tôi chụp ảnh bằng máy ảnh, sau đó tôi muốn thay đổi kích thước của nó thành 290 * 390 pixel. Tôi đã sử dụng phương pháp này để thay đổi kích thước hình ảnh:

UIImage *newImage = [image _imageScaledToSize:CGSizeMake(290, 390)
                         interpolationQuality:1];    

Nó hoạt động hoàn hảo, nhưng đó là một chức năng không có giấy tờ, vì vậy tôi không thể sử dụng nó nữa với iPhone OS4.

Vậy ... cách đơn giản nhất để thay đổi kích thước một UIImage là gì?


Cách thực hiện vào năm 2019, nshipster.com/image-resizing
dengST30

Câu trả lời:


772

Cách đơn giản nhất là đặt khung của bạn UIImageViewvà đặt thành contentModemột trong các tùy chọn thay đổi kích thước.

Hoặc bạn có thể sử dụng phương pháp tiện ích này, nếu bạn thực sự cần thay đổi kích thước hình ảnh:

+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
    //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.
    UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    
    UIGraphicsEndImageContext();
    return newImage;
}

Ví dụ sử dụng:

#import "MYUtil.h"

UIImage *myIcon = [MYUtil imageWithImage:myUIImageInstance scaledToSize:CGSizeMake(20, 20)];

11
Tôi sẽ KHÔNG giữ lại kết quả ở đây. newImagesẽ được tự động phát hành và nó sẽ tùy thuộc vào phương thức được gọi là này để giữ lại hay không. Cách tiếp cận này chỉ là cầu xin một lỗi bộ nhớ vì initkhông phải là một phần của tên phương thức. Tôi mong đợi một phương thức có tên như thế này sẽ trả về một đối tượng tự động.
Alex Wayne

Điểm hợp lệ, và chỉnh sửa. Tôi sẽ cảnh báo rằng mã của tôi sử dụng mã này tạo ra lỗi malloc ở nơi khác mà không cần giữ lại thêm, đó rõ ràng là lỗi của tôi bằng cách nào đó :-).
Paul Lynch

26
Kể từ iOS 4.0 , các chức năng UIGraphics * đều an toàn cho chuỗi.
BJ Homer

3
@Paul Lynch: Hãy nhớ rằng thay đổi này phá vỡ nhiệm vụ của bài đăng gốc: Cách thay đổi kích thước hình ảnh thành một số kích thước pixel chính xác (trái ngược với kích thước điểm ).
Nikolai Ruhe

8
Đối với những người gặp khó khăn do giới hạn @NikolaiRuhe đã chỉ ra, bạn có thể buộc nó tới kích thước pixel chính xác bằng cách chuyển 1.0 thay vì 0.0 trong cuộc gọi đếnUIGraphicsBeginImageContextWithOptions
Danny

84

Đây là phiên bản Swift của câu trả lời của Paul Lynch

func imageWithImage(image:UIImage, scaledToSize newSize:CGSize) -> UIImage{
    UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0);
    image.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height))
    let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage
}

Và như một phần mở rộng:

public extension UIImage {
    func copy(newSize: CGSize, retina: Bool = true) -> UIImage? {
        // In next line, pass 0 to use the current device's pixel scaling factor (and thus account for Retina resolution).
        // Pass 1 to force exact pixel size.
        UIGraphicsBeginImageContextWithOptions(
            /* size: */ newSize,
            /* opaque: */ false,
            /* scale: */ retina ? 0 : 1
        )
        defer { UIGraphicsEndImageContext() }

        self.draw(in: CGRect(origin: .zero, size: newSize))
        return UIGraphicsGetImageFromCurrentImageContext()
    }
}

2
chỉ lưu ý rằng, trong iOS, kích thước mới của bạn sẽ nhân lên gấp 2, 3 lần dựa trên thiết bị
Sbean A.Suk

6
UIGraphicsBeginImageContextWithOptions (newSize, false, image.scale); cho tất cả các thiết bị
phnmnn

Lưu ý rằng điều này không thay đổi kích thước CGImage cơ bản (ít nhất là trong iOS 12.1). Dựa trên câu hỏi là ổn, nhưng nếu bạn viết ra hình ảnh, bạn sẽ phải sử dụng cgImage và bạn sẽ có được hình ảnh gốc.
prewett

72

Giải pháp Swift 3.0 phù hợp cho iOS 10+ : Sử dụng ImageRenderervà đóng cú pháp:

func imageWith(newSize: CGSize) -> UIImage {
    let renderer = UIGraphicsImageRenderer(size: newSize)
    let image = renderer.image { _ in
        self.draw(in: CGRect.init(origin: CGPoint.zero, size: newSize))
    }

    return image.withRenderingMode(self.renderingMode)
}

Và đây là phiên bản Objective-C:

@implementation UIImage (ResizeCategory)
- (UIImage *)imageWithSize:(CGSize)newSize
{
    UIGraphicsImageRenderer *renderer = [[UIGraphicsImageRenderer alloc] initWithSize:newSize];
    UIImage *image = [renderer imageWithActions:^(UIGraphicsImageRendererContext*_Nonnull myContext) {
        [self drawInRect:(CGRect) {.origin = CGPointZero, .size = newSize}];
    }];
    return [image imageWithRenderingMode:self.renderingMode];
}
@end

1
Giải pháp rất thanh lịch, đây sẽ là câu trả lời được chấp nhận!
ứng dụng vào

2
Điều này tốt hơn thanh lịch, nó chính xác. Các tài liệu api của Apple khuyên mã mới sử dụng UIGraphicsRenderer như mã này. Cảm ơn bạn
Paul Bruneau

1
@appsunited Câu hỏi đã gần 8 tuổi. Và phương pháp này chỉ hoạt động cho iOS10 + như đã nêu.

Khi sao chép đối tượng hình ảnh mới vào bảng tạm, nó tạo ra một khối màu trắng cho tôi. Nó không thực sự thay đổi kích thước xem hình ảnh?
Oliver Dixon

1
Hàm này trả về hình ảnh có chiều cao 0 và chiều rộng 0, chiều cao dự kiến ​​là 9000 chiều cao và chiều rộng 9000.
krishan kumar

31

Trevor Howard có một số loại UIImage xử lý thay đổi kích thước khá độc đáo. Nếu không có gì khác, bạn có thể sử dụng mã làm ví dụ.

Lưu ý: Kể từ iOS 5.1, câu trả lời này có thể không hợp lệ. Xem bình luận dưới đây.


2
Tôi cũng cần thay đổi kích thước một số hình ảnh và lần đầu tiên tôi đã thử các bổ sung của Trevor cho UIImage, nhưng đã gặp một số lỗi kỳ lạ trên PNG (một cái gì đó về kênh alpha). Các câu trả lời được chấp nhận cho câu hỏi này làm việc độc đáo mặc dù.
Sorig

1
Điều này không còn hợp lệ (ít nhất là với iOS5.1
Jann

@Jann, hãy xem các cam kết bên dưới bài viết.
vikingosegundo

@Jann Nếu bạn làm theo các bản sửa lỗi được đề xuất trong các nhận xét, hãy đi với "Matt nói: ngày 22 tháng 11 năm 2011 lúc 5:39 chiều" bởi vì anh ta phát hành các màu sắc (không giống như giải pháp tương tự của horseshoe7).
Ben Flynn

1
@sanmai sử dụng bất kỳ phương pháp thay đổi kích thước nào, hình ảnh sẽ mất đi tính sắc nét của nó. Có cách nào để đạt được độ sắc nét
vamsi575kg

31

Phiên bản nhỏ gọn hơn cho Swift 4 và iOS 10+:

extension UIImage {
    func resized(to size: CGSize) -> UIImage {
        return UIGraphicsImageRenderer(size: size).image { _ in
            draw(in: CGRect(origin: .zero, size: size))
        }
    }
}

Sử dụng:

let resizedImage = image.resized(to: CGSize(width: 50, height: 50))

26

Tôi cũng đã thấy điều này được thực hiện tốt (mà tôi sử dụng UIButtonscho trạng thái Bình thường và được chọn do các nút không resizephù hợp). Tín dụng cho bất cứ ai là tác giả ban đầu.

Đầu tiên tạo một tệp .h và .m trống được gọi UIImageResizing.hUIImageResizing.m

// Put this in UIImageResizing.h
@interface UIImage (Resize)
- (UIImage*)scaleToSize:(CGSize)size;
@end

// Put this in UIImageResizing.m
@implementation UIImage (Resize)

- (UIImage*)scaleToSize:(CGSize)size {
UIGraphicsBeginImageContext(size);

CGContextRef context = UIGraphicsGetCurrentContext();
CGContextTranslateCTM(context, 0.0, size.height);
CGContextScaleCTM(context, 1.0, -1.0);

CGContextDrawImage(context, CGRectMake(0.0f, 0.0f, size.width, size.height), self.CGImage);

UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

return scaledImage;
}

@end

Bao gồm tệp .h đó trong bất kỳ tệp .m nào bạn sẽ sử dụng hàm trong và sau đó gọi nó như thế này:

UIImage* image = [UIImage imageNamed:@"largeImage.png"];
UIImage* smallImage = [image scaleToSize:CGSizeMake(100.0f,100.0f)];

Điều này không sao chép theo định hướng hình ảnh.
Kevin

20

Cải tiến mã này của Paul sẽ cung cấp cho bạn hình ảnh độ phân giải cao sắc nét trên iPhone có màn hình retina. Nếu không, khi giảm xuống, nó mờ.

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

13
Chỉ cần FYI, những thay đổi bạn đã thực hiện là không cần thiết, vì việc cung cấp giá trị 0,0 cho tỷ lệ trong UIGraphicsBeginImageContextWithOptionssẽ tự động sử dụng tỷ lệ của màn hình chính (kể từ iOS 3.2).
Andrew R.

16

Đây là một cách đơn giản:

    UIImage * image = [UIImage imageNamed:@"image"];
    CGSize sacleSize = CGSizeMake(10, 10);
    UIGraphicsBeginImageContextWithOptions(sacleSize, NO, 0.0);
    [image drawInRect:CGRectMake(0, 0, sacleSize.width, sacleSize.height)];
    UIImage * resizedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

resizedImage là một hình ảnh mới.


16

Giải pháp Swift cho Stretch Fill, Aspect Fill và Aspect Fit

extension UIImage {
    enum ContentMode {
        case contentFill
        case contentAspectFill
        case contentAspectFit
    }

    func resize(withSize size: CGSize, contentMode: ContentMode = .contentAspectFill) -> UIImage? {
        let aspectWidth = size.width / self.size.width
        let aspectHeight = size.height / self.size.height

        switch contentMode {
        case .contentFill:
            return resize(withSize: size)
        case .contentAspectFit:
            let aspectRatio = min(aspectWidth, aspectHeight)
            return resize(withSize: CGSize(width: self.size.width * aspectRatio, height: self.size.height * aspectRatio))
        case .contentAspectFill:
            let aspectRatio = max(aspectWidth, aspectHeight)
            return resize(withSize: CGSize(width: self.size.width * aspectRatio, height: self.size.height * aspectRatio))
        }
    }

    private func resize(withSize size: CGSize) -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(size, false, self.scale)
        defer { UIGraphicsEndImageContext() }
        draw(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))
        return UIGraphicsGetImageFromCurrentImageContext()
    }
}

và để sử dụng, bạn có thể làm như sau:

let image = UIImage(named: "image.png")!
let newImage = image.resize(withSize: CGSize(width: 200, height: 150), contentMode: .contentAspectFill)

Cảm ơn abdullahselek cho giải pháp ban đầu của mình.


15

Đây là một sửa đổi của thể loại được viết bởi iWasRobbed ở trên. Nó giữ tỷ lệ khung hình của ảnh gốc thay vì làm biến dạng nó.

- (UIImage*)scaleToSizeKeepAspect:(CGSize)size {
    UIGraphicsBeginImageContext(size);

    CGFloat ws = size.width/self.size.width;
    CGFloat hs = size.height/self.size.height;

    if (ws > hs) {
        ws = hs/ws;
        hs = 1.0;
    } else {
        hs = ws/hs;
        ws = 1.0;
    }

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(context, 0.0, size.height);
    CGContextScaleCTM(context, 1.0, -1.0);

    CGContextDrawImage(context, CGRectMake(size.width/2-(size.width*ws)/2,
        size.height/2-(size.height*hs)/2, size.width*ws,
        size.height*hs), self.CGImage);

    UIImage* scaledImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return scaledImage;
}

11

Nếu bạn chỉ muốn một hình ảnh nhỏ hơn và không quan tâm đến kích thước chính xác:

+ (UIImage *)imageWithImage:(UIImage *)image scaledToScale:(CGFloat)scale
{
    UIGraphicsBeginImageContextWithOptions(self.size, YES, scale);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextSetInterpolationQuality(context, kCGInterpolationHigh);
    [self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return newImage;
}

Đặt tỷ lệ thành 0.25f sẽ cung cấp cho bạn hình ảnh 816 x 612 từ camera 8MP.

Đây là danh mục UIImage + Scale cho những ai cần.


10

Sao lại phức tạp thế? Tôi nghĩ rằng sử dụng API hệ thống có thể đạt được kết quả tương tự:

UIImage *largeImage;
CGFloat ratio = 0.4; // you want to get a new image that is 40% the size of large image.
UIImage *newImage = [UIImage imageWithCGImage:largeImage.CGImage
                                        scale:1/ratio
                                  orientation:largeImage.imageOrientation];
// notice the second argument, it is 1/ratio, not ratio.

Gotcha duy nhất là bạn nên chuyển tỷ lệ nghịch của tỷ lệ đích làm đối số thứ hai, vì theo tài liệu, tham số thứ hai chỉ định tỷ lệ của ảnh gốc so với tỷ lệ mới.


Bởi vì tỷ lệ (%) không giống với pixel (w / h).

Tỷ lệ nên là LargeImage.scale / ratio chứ không phải 1 / ratio.
Marián Černý

9

Đây là tiện ích mở rộng UIImage tương thích với Swift 3Swift 4 , tỷ lệ hình ảnh theo kích thước đã cho với tỷ lệ khung hình

extension UIImage {

    func scaledImage(withSize size: CGSize) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
        defer { UIGraphicsEndImageContext() }
        draw(in: CGRect(x: 0.0, y: 0.0, width: size.width, height: size.height))
        return UIGraphicsGetImageFromCurrentImageContext()!
    }

    func scaleImageToFitSize(size: CGSize) -> UIImage {
        let aspect = self.size.width / self.size.height
        if size.width / aspect <= size.height {
            return scaledImage(withSize: CGSize(width: size.width, height: size.width / aspect))
        } else {
            return scaledImage(withSize: CGSize(width: size.height * aspect, height: size.height))
        }
    }

}

Ví dụ sử dụng

let image = UIImage(named: "apple")
let scaledImage = image.scaleImageToFitSize(size: CGSize(width: 45.0, height: 45.0))

Tôi muốn giới thiệu để đặt tên cho chức năng scaledImage(with size:)hoặc scaledWithSize(_:). Cũng UIGraphicsGetImageFromCurrentImageContextkhông thể thực sự trở lại nil, do đó !cũng sẽ làm việc. Bạn cũng có thể đơn giản hóa việc tạo trực tràng để CGRect(origin: .zero, size: size).
Sulthan

8

Tôi đã tìm thấy một danh mục cho UIImage trong các ví dụ của chính Apple cũng thực hiện thủ thuật tương tự. Đây là liên kết: https://developer.apple.com/l Library / ios / samplecode / sc2273 / Listings / IrDropSample_UIImage_Resize_m.html .

Bạn sẽ phải thay đổi cuộc gọi:

UIGraphicsBeginImageContextWithOptions(newSize, YES, 2.0);

trong imageWithImage:scaledToSize:inRect:với:

UIGraphicsBeginImageContextWithOptions(newSize, NO, 2.0);

Để xem xét các kênh alpha trong hình ảnh.


6
 func resizeImage(image: UIImage, newWidth: CGFloat) -> UIImage 
{
        let scale = newWidth / image.size.width
        let newHeight = image.size.height * scale
        UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight))
        image.drawInRect(CGRectMake(0, 0, newWidth, newHeight))
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage
}

Đó là một ý tưởng tốt để thêm một số văn bản mô tả đi kèm với mã của bạn.
GMchris

6

Đối với đồng nghiệp Xamarians của tôi, đây là phiên bản Xamarin.iOS C # của câu trả lời @Paul Lynch.

private UIImage ResizeImage(UIImage image, CGSize newSize) 
{
    UIGraphics.BeginImageContextWithOptions(newSize, false, 0.0f);
    image.Draw(new CGRect(0, 0, newSize.Width, newSize.Height));
    UIImage newImage = UIGraphics.GetImageFromCurrentImageContext();
    UIGraphics.EndImageContext();
    return newImage;
}

5

Nếu bạn muốn tạo hình thu nhỏ của UIImage (với thay đổi kích thước theo tỷ lệ hoặc có thể có một số cắt xén liên quan), hãy xem danh mục UIImage + Thay đổi kích thước cho phép bạn sử dụng cú pháp giống như ImageMagick:

UIImage* squareImage       = [image resizedImageByMagick: @"320x320#"];

5

[cf Chris] Để thay đổi kích thước thành kích thước mong muốn:

UIImage *after = [UIImage imageWithCGImage:before.CGImage
                                     scale:CGImageGetHeight(before.CGImage)/DESIREDHEIGHT
                               orientation:UIImageOrientationUp];

hoặc, tương đương, thay thế CGImageGetWidth(...)/DESIREDWIDTH


Lưu ý rằng bản thân dữ liệu hình ảnh không được thay đổi kích thước nhưng hệ số tỷ lệ được áp dụng có nghĩa là hình ảnh có cùng kích thước trong bộ nhớ.
inkredibl

5

Rogerio Chaves trả lời như một phần mở rộng nhanh chóng

func scaledTo(size: CGSize) -> UIImage{
    UIGraphicsBeginImageContextWithOptions(size, false, 0.0);
    self.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
    let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
    UIGraphicsEndImageContext()
    return newImage
}

Và cũng là tiền thưởng

func scaledTo(height: CGFloat) -> UIImage{
    let width = height*self.size.width/self.size.height
    return scaledTo(size: CGSize(width: width, height: height))
}

5

Swift 3.0 với tùy chọn failafe (trả về ảnh gốc trong trường hợp có lỗi):

func resize(image: UIImage, toSize size: CGSize) -> UIImage{
    UIGraphicsBeginImageContextWithOptions(size,false,1.0)
    image.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
    if let resizedImage = UIGraphicsGetImageFromCurrentImageContext() {
        UIGraphicsEndImageContext()
        return resizedImage
    }
    UIGraphicsEndImageContext()
    return image
}

5

(Tương thích Swift 4) Giải pháp iOS 10+ và iOS <10 (sử dụng UIGraphicsImageRenderernếu có thể, UIGraphicsGetImageFromCurrentImageContextnếu không)

/// Resizes an image
///
/// - Parameter newSize: New size
/// - Returns: Resized image
func scaled(to newSize: CGSize) -> UIImage {
    let rect = CGRect(origin: .zero, size: newSize)

    if #available(iOS 10, *) {
        let renderer = UIGraphicsImageRenderer(size: newSize)
        return renderer.image { _ in
            self.draw(in: rect)
        }
    } else {
        UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
        self.draw(in: rect)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return newImage!
    }
}

5

Cách tiếp cận hiệu quả mà không cần kéo dài hình ảnh Swift 4

// Method to resize image
func resize(image: UIImage, toScaleSize:CGSize) -> UIImage {
                UIGraphicsBeginImageContextWithOptions(toScaleSize, true, image.scale)
                        image.draw(in: CGRect(x: 0, y: 0, width: toScaleSize.width, height: toScaleSize.height))
                        let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
                        UIGraphicsEndImageContext()
                        return scaledImage!
                }

// Phương thức gọi

    let resizedImage = self.resize(image: UIImage(named: "YourImageName")!, toScaleSize: CGSize(width: 290, height: 390))

3

Câu trả lời của @Paul Lynch rất hay, nhưng nó sẽ thay đổi tỷ lệ hình ảnh. Nếu bạn không muốn thay đổi tỷ lệ hình ảnh và vẫn muốn hình ảnh mới phù hợp với kích thước mới, hãy thử điều này.

+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {

// calculate a new size which ratio is same to original image
CGFloat ratioW = image.size.width / newSize.width;
CGFloat ratioH = image.size.height / newSize.height;

CGFloat ratio = image.size.width / image.size.height;

CGSize showSize = CGSizeZero;
if (ratioW > 1 && ratioH > 1) { 

    if (ratioW > ratioH) { 
        showSize.width = newSize.width;
        showSize.height = showSize.width / ratio;
    } else {
        showSize.height = newSize.height;
        showSize.width = showSize.height * ratio;
    }

} else if (ratioW > 1) {

    showSize.width = showSize.width;
    showSize.height = showSize.width / ratio;

} else if (ratioH > 1) {

    showSize.height = showSize.height;
    showSize.width = showSize.height * ratio;

}

//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.
UIGraphicsBeginImageContextWithOptions(showSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, showSize.width, showSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;}

3

sử dụng phần mở rộng này

extension UIImage {
    public func resize(size:CGSize, completionHandler:(resizedImage:UIImage, data:NSData?)->()) {
        dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), { () -> Void in
            let newSize:CGSize = size
            let rect = CGRectMake(0, 0, newSize.width, newSize.height)
            UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
            self.drawInRect(rect)
            let newImage = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            let imageData = UIImageJPEGRepresentation(newImage, 0.5)
            dispatch_async(dispatch_get_main_queue(), { () -> Void in
                completionHandler(resizedImage: newImage, data:imageData)
            })
        })
    }
}

2

Swift 2.0:

let image = UIImage(named: "imageName")
let newSize = CGSize(width: 10, height: 10)

UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
image?.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height))
let imageResized = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()

2

Đây là mã Swift hơi dài dòng của tôi

func scaleImage(image:UIImage,  toSize:CGSize) -> UIImage {
    UIGraphicsBeginImageContextWithOptions(toSize, false, 0.0);

    let aspectRatioAwareSize = self.aspectRatioAwareSize(image.size, boxSize: toSize, useLetterBox: false)


    let leftMargin = (toSize.width - aspectRatioAwareSize.width) * 0.5
    let topMargin = (toSize.height - aspectRatioAwareSize.height) * 0.5


    image.drawInRect(CGRectMake(leftMargin, topMargin, aspectRatioAwareSize.width , aspectRatioAwareSize.height))
    let retVal = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return retVal
}

func aspectRatioAwareSize(imageSize: CGSize, boxSize: CGSize, useLetterBox: Bool) -> CGSize {
    // aspect ratio aware size
    // http://stackoverflow.com/a/6565988/8047
    let imageWidth = imageSize.width
    let imageHeight = imageSize.height
    let containerWidth = boxSize.width
    let containerHeight = boxSize.height

    let imageAspectRatio = imageWidth/imageHeight
    let containerAspectRatio = containerWidth/containerHeight

    let retVal : CGSize
    // use the else at your own risk: it seems to work, but I don't know 
    // the math
    if (useLetterBox) {
        retVal = containerAspectRatio > imageAspectRatio ? CGSizeMake(imageWidth * containerHeight / imageHeight, containerHeight) : CGSizeMake(containerWidth, imageHeight * containerWidth / imageWidth)
    } else {
        retVal = containerAspectRatio < imageAspectRatio ? CGSizeMake(imageWidth * containerHeight / imageHeight, containerHeight) : CGSizeMake(containerWidth, imageHeight * containerWidth / imageWidth)
    }

    return retVal
}

1
Điều này tiết kiệm thời gian của tôi. Cảm ơn!
Quý Nguyễn

hữu ích, nhưng hành động kỳ lạ sau các hoạt động khác biệt và quay trở lại, xem tại đây plz: stackoverflow.com/questions/30978685/ory
He Yifei 何 一

Xin lưu ý: Bạn có thể muốn thêm một điều kiện tiên quyết ( guard) vào aspectRatioAwareSizehàm sao cho nó sẽ không tạo ra một phép chia cho ngoại lệ bằng 0 nếu các tham số đầu vào cho imageSize hoặc boxSize làCGSize.zero
pkluz

@pkluz đây là một gợi ý hay, nhưng bạn cần chúng trên tất cả các chức năng, tôi nghĩ, vì mỗi biến là ước số của một dòng khác ... Tôi sẽ để lại điều này cho rõ ràng. Đối với sản xuất hoặc thư viện cho github, bạn có thể muốn tăng cường điều này ... Hơn cả một người bảo vệ, tôi lo ngại rằng hàm sử dụng các tên biến ngắn không nói nhiều. Tôi có thể sửa nó trước, sau đó thêm vệ sĩ cho những thứ khác, rồi thêm kiểm tra đơn vị.
Dan Rosenstark

2

Swift 4 câu trả lời:

func scaleDown(image: UIImage, withSize: CGSize) -> UIImage {
    let scale = UIScreen.main.scale
    UIGraphicsBeginImageContextWithOptions(withSize, false, scale)
    image.draw(in: CGRect(x: 0, y: 0, width: withSize.width, height: withSize.height))
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage!
}

Không cần thiết lập tỷ lệ thực:The scale factor to apply to the bitmap. If you specify a value of 0.0, the scale factor is set to the scale factor of the device’s main screen.
nathan

1

Tôi đã phát hiện ra rằng thật khó để tìm ra câu trả lời mà bạn có thể sử dụng ngoài hộp trong dự án Swift 3 của mình . Vấn đề chính của các câu trả lời khác là họ không tôn trọng kênh alpha của hình ảnh. Đây là kỹ thuật mà tôi đang sử dụng trong các dự án của mình.

extension UIImage {

    func scaledToFit(toSize newSize: CGSize) -> UIImage {
        if (size.width < newSize.width && size.height < newSize.height) {
            return copy() as! UIImage
        }

        let widthScale = newSize.width / size.width
        let heightScale = newSize.height / size.height

        let scaleFactor = widthScale < heightScale ? widthScale : heightScale
        let scaledSize = CGSize(width: size.width * scaleFactor, height: size.height * scaleFactor)

        return self.scaled(toSize: scaledSize, in: CGRect(x: 0.0, y: 0.0, width: scaledSize.width, height: scaledSize.height))
    }

    func scaled(toSize newSize: CGSize, in rect: CGRect) -> UIImage {
        if UIScreen.main.scale == 2.0 {
            UIGraphicsBeginImageContextWithOptions(newSize, !hasAlphaChannel, 2.0)
        }
        else {
            UIGraphicsBeginImageContext(newSize)
        }

        draw(in: rect)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage ?? UIImage()
    }

    var hasAlphaChannel: Bool {
        guard let alpha = cgImage?.alphaInfo else {
            return false
        }
        return alpha == CGImageAlphaInfo.first ||
            alpha == CGImageAlphaInfo.last ||
            alpha == CGImageAlphaInfo.premultipliedFirst ||
            alpha == CGImageAlphaInfo.premultipliedLast
    }
}

Ví dụ về cách sử dụng:

override func viewDidLoad() {
    super.viewDidLoad()

    let size = CGSize(width: 14.0, height: 14.0)
    if let image = UIImage(named: "barbell")?.scaledToFit(toSize: size) {
        let imageView = UIImageView(image: image)
        imageView.center = CGPoint(x: 100, y: 100)
        view.addSubview(imageView)
    }
}

Mã này là một bản viết lại của tiện ích mở rộng của Apple có thêm hỗ trợ cho hình ảnh có và không có kênh alpha.

Để đọc thêm, tôi khuyên bạn nên kiểm tra bài viết này để biết các kỹ thuật thay đổi kích thước hình ảnh khác nhau. Cách tiếp cận hiện tại cung cấp hiệu suất tốt, nó vận hành API cấp cao và dễ hiểu. Tôi khuyên bạn nên giữ nó trừ khi bạn thấy rằng thay đổi kích thước hình ảnh là một nút cổ chai trong hiệu suất của bạn.


1

Sử dụng tiện ích mở rộng này, trong trường hợp bạn chỉ cần thay đổi kích thước chiều rộng / chiều cao với tỷ lệ khung hình.

extension UIImage {
    func resize(to size: CGSize) -> UIImage {
        return UIGraphicsImageRenderer(size: size).image { _ in
            draw(in: CGRect(origin: .zero, size: size))
        }
    }
    func resize(width: CGFloat) -> UIImage {
        return resize(to: CGSize(width: width, height: width / (size.width / size.height)))
    }
    func resize(height: CGFloat) -> UIImage {
        return resize(to: CGSize(width: height * (size.width / size.height), height: height))
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.