Bir UIImage'ı yeniden boyutlandırmanın en basit yolu?


397

İPhone uygulamamda kamerayla resim çekiyorum, ardından 290 * 390 piksel olarak yeniden boyutlandırmak istiyorum. Görüntüyü yeniden boyutlandırmak için bu yöntemi kullanıyordum:

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

Mükemmel çalışıyor, ancak belgesiz bir işlev, bu yüzden artık iPhone OS4 ile kullanamıyorum.

Öyleyse ... UIImage'ı yeniden boyutlandırmanın en basit yolu nedir?


2019'da bunu yapmanın yolu, nshipster.com/image-resizing
dengST30

Yanıtlar:


772

En basit yol, çerçevenizi UIImageViewayarlamak contentModeve yeniden boyutlandırma seçeneklerinden birine ayarlamaktır .

Ya da aslında bir görüntüyü yeniden boyutlandırmanız gerekiyorsa bu yardımcı programı kullanabilirsiniz:

+ (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;
}

Örnek kullanım:

#import "MYUtil.h"

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

11
Sonuç burada kalmaz. newImagezaten otomatik olarak yayınlanacak ve bunu saklamak ya da tutmamak için çağıran yönteme bağlı olmalıdır. initYöntem adının bir parçası olmadığı için bu yaklaşım sadece bir bellek hatası için yalvarıyor . Bu şekilde adlandırılan bir yöntemin otomatik olarak yayımlanan bir nesne döndürmesini beklerim.
Alex Wayne

Geçerli nokta ve düzenlenmiştir. Ben sadece bu benim kodu açıkça bir şekilde benim hatam :-) bir ek tutma olmadan, başka bir yerde malloc hataları üretir dikkat bırakacaktır.
Paul Lynch

26
İOS 4.0'dan itibaren , UIGraphics * işlevlerinin tümü iş parçacığı için güvenlidir.
BJ Homer

3
@Paul Lynch: Bu değişikliğin orijinal gönderinin görevini bozduğunu unutmayın: Bir görüntüyü tam piksel boyutuna nasıl yeniden boyutlandırabiliriz ( nokta boyutunun aksine ).
Nikolai Ruhe

8
Çağrısında 1.0 yerine 0.0 geçirerek sınırlama @NikolaiRuhe işaret etmek, tam olarak bir piksel boyutuna zorlayabilir nedeniyle mücadele edenler içinUIGraphicsBeginImageContextWithOptions
Danny

84

Paul Lynch'in cevabının bir Swift versiyonu

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
}

Ve bir uzantı olarak:

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
iOS'ta newSize'in cihaza göre 2x, 3x ile
çarpacağını belirttim

6
UIGraphicsBeginImageContextWithOptions (newSize, false, image.scale); tüm cihazlar için
phnmnn

Bunun altta yatan CGImage'ı yeniden boyutlandırmadığını unutmayın (en azından iOS 12.1'de). Bu soruya göre iyidir, ancak görüntüyü yazıyorsanız, cgImage'ı kullanmanız gerekir ve orijinal görüntüyü alırsınız.
Prewett

72

İOS 10+ için uygun Swift 3.0 çözümü: Kullanma ve kapatma sözdizimi:ImageRenderer

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

Ve işte Objective-C versiyonu:

@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
Çok zarif bir çözüm, bu kabul edilen cevap olmalı!
appsunited

2
Bu zariften daha iyidir, doğrudur. Apple'ın api dokümanları, bu kodda olduğu gibi UIGraphicsRenderer'ı kullanmak için yeni bir kod önerir. Teşekkür ederim
Paul Bruneau

1
@appsunited Soru neredeyse 8 yaşında. Ve bu yöntem yalnızca belirtildiği gibi iOS10 + için çalışır .

Yeni görüntü nesnesini panoya kopyalarken benim için beyaz bir blok oluşturur. Aslında görüntü görünümünü yeniden boyutlandırmıyor mu?
Oliver Dixon

1
0 yükseklik ve 0 genişlikli bir görüntü döndüren bu fonksiyon, yükseklik 9000 yükseklik ve 9000 genişliktir.
krishan kumar

31

Trevor Howard, yeniden boyutlandırmayı oldukça güzel bir şekilde ele alan bazı UIImage kategorilerine sahiptir. Başka bir şey yoksa kodu örnek olarak kullanabilirsiniz.

Not: iOS 5.1'den itibaren bu cevap geçersiz olabilir. Aşağıdaki açıklamaya bakınız.


2
Bazı görüntüleri de yeniden boyutlandırmam gerekiyordu ve ilk olarak Trevor'ın UIImage'a eklemelerini denedim, ancak PNG'lerde (alfa kanalı hakkında bir şey) bazı garip hatalar aldım. Bu soruya kabul edilen cevap güzel çalıştı.
Sorig

1
Bu artık geçerli değil (en azından iOS5.1
Jann

@Jann, gönderinin altındaki taahhütlere bir göz atın.
vikingosegundo

@Jann Yorumlarda önerilen düzeltmeleri takip ederseniz "Matt diyor: 22 Kasım 2011, 17:39" ile gidin çünkü o renk aralığını serbest bırakır (at nalı7 benzer çözüm aksine).
Ben Flynn

1
@sanmai, bu yeniden boyutlandırma yöntemlerinden herhangi birini kullanarak görüntüleri keskinliğini kaybeder. netlik elde etmek için herhangi bir yolu var mı
vamsi575kg

31

Swift 4 ve iOS 10+ için daha kompakt bir sürüm:

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

Kullanımı:

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

26

Ben de bunu gördüm ( UIButtonsdüğmeler resizesığmadığı için Normal ve Seçili durum için kullanıyorum ). Kredi, asıl yazarın olduğu kişiye gider.

İlk olarak adlandırılan boş .h ve .m dosyasını yapmak UIImageResizing.hveUIImageResizing.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

Bu .h dosyasını, işlevi kullanacağınız herhangi bir .m dosyasına ekleyin ve ardından şu şekilde çağırın:

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

Bu, görüntü yönlendirmesinin üzerine kopyalanmaz.
Kevin

20

Paul kodundaki bu iyileştirme, retina ekranlı bir iPhone'da keskin bir yüksek çözünürlüklü görüntü verecektir. Aksi takdirde ölçekleme yapılırken bulanık olur.

+ (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
Sadece FYI, yaptığınız değişiklikler gereksizdir, çünkü ölçek için 0.0 değeri sağlamak UIGraphicsBeginImageContextWithOptionsana ekranın ölçeğini otomatik olarak kullanacaktır (iOS 3.2'den itibaren).
Andrew R.

16

İşte basit bir yol:

    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 yeni bir resimdir.


16

Stretch Fill, Aspect Fill ve Aspect Fit için hızlı çözüm

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

ve kullanmak için aşağıdakileri yapabilirsiniz:

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

Abdullahselek'e orijinal çözümü için teşekkürler.


15

Yukarıda iWasRobbed tarafından yazılan kategorinin bir modifikasyonu. Orijinal görüntünün görüntü oranını bozmak yerine tutar.

- (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

Sadece daha küçük bir görüntü istiyorsanız ve tam boyut umurumda değilse:

+ (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;
}

Ölçeği ayarlamak 0.25f, 8MP kameradan 816 x 612 resim verecektir.

İşte ihtiyaç duyanlar için bir kategori UIImage + Ölçeği .


10

Neden bu kadar karmaşık? Ben sistem API kullanarak aynı sonucu elde düşünüyorum:

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.

Tek sorun, ikinci argüman olarak hedef oranın tersini geçmeniz gerektiğidir, belgeye göre ikinci parametre, orijinal görüntünün yeni ölçekli olana kıyasla oranını belirtir.


Çünkü ölçek (%) piksel (w / h) ile aynı şey değildir.

Ölçek büyük olmalıdır. Görüntü. Ölçek / oran 1 / oran değil.
Marián Černý

9

Bu, görüntüyü en boy oranıyla belirli bir boyuta ölçeklendiren Swift 3 ve Swift 4 ile uyumlu bir UIImage uzantısıdır

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

}

Örnek kullanım

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

İşlevi adlandırmanızı tavsiye ederim scaledImage(with size:)veya scaledWithSize(_:). Ayrıca UIGraphicsGetImageFromCurrentImageContextgerçekten geri dönemez nil, bu yüzden !de işe yarayacaktı. Ayrıca rect oluşturmayı da basitleştirebilirsiniz CGRect(origin: .zero, size: size).
Sulthan

8

Apple'ın kendi örneklerinde aynı numarayı yapan UIImage için bir kategori buldum. Bağlantı şu şekildedir: https://developer.apple.com/library/ios/samplecode/sc2273/Listings/AirDropSample_UIImage_Resize_m.html .

Sadece aramayı değiştirmeniz gerekir:

UIGraphicsBeginImageContextWithOptions(newSize, YES, 2.0);

içinde imageWithImage:scaledToSize:inRect:birlikte:

UIGraphicsBeginImageContextWithOptions(newSize, NO, 2.0);

Resimdeki alfa kanalını dikkate almak için.


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
}

Kodunuza uygun bazı açıklayıcı metinler eklemek iyi bir fikirdir.
GMchris

6

Arkadaşım Xamarians için, @Paul Lynch yanıtının bir Xamarin.iOS C # sürümü.

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

Bir UIImage'ın küçük resmini yapmak istiyorsanız (orantılı yeniden boyutlandırma veya belki biraz kırpma dahil), kısa, ImageMagick benzeri sözdizimini kullanmanıza izin veren UIImage + Resize kategorisine göz atın :

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

5

[cf Chris] İstenen boyuta yeniden boyutlandırmak için :

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

veya eşdeğer olarak, ikame CGImageGetWidth(...)/DESIREDWIDTH


Görüntü verilerinin kendisinin yeniden boyutlandırılmadığını, ancak görüntünün bellekte aynı boyutta olduğu anlamına gelen bir ölçek faktörü uygulandığını unutmayın.
inkredibl

5

Rogerio Chaves hızlı bir eklenti olarak cevap veriyor

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
}

Ve ayrıca bonus

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

5

Arıza korumalı Swift 3.0 (hata durumunda orijinal görüntüyü döndürür):

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

(Swift 4 uyumlu) iOS 10+ ve iOS <10 çözümü ( UIGraphicsImageRenderermümkünse kullanma UIGraphicsGetImageFromCurrentImageContext)

/// 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

Görüntü gerilmeden etkili yaklaşım 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!
                }

// Çağrı yöntemi

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

3

Paul Lynch'in cevabı harika, ancak görüntü oranını değiştirecekti. görüntü oranını değiştirmek istemiyorsanız ve yine de yeni görüntünün yeni boyuta uygun olmasını istiyorsanız bunu deneyin.

+ (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

bu uzantıyı kullan

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

İşte biraz ayrıntılı Swift kodum

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
Bu benim zamanımı kurtardı. Teşekkürler!
Quy Nguyen

yararlı, ancak segue ve geri gelme faaliyetlerinden sonra garip davranın, buraya bakın plz: stackoverflow.com/questions/30978685/…
He Yifei 何 一 非

Not edin: (a ön şartı eklemek isteyebilirsiniz guardkadar) aspectRatioAwareSizeimagesize veya boxSize biri için giriş parametreleri ise sıfır istisna bir bölünmeyi atmaz şekilde fonksiyonuCGSize.zero
pkluz

@pkluz bu iyi bir öneri, ama tüm fonksiyon boyunca onlara ihtiyacınız olacak, sanırım, her değişken başka bir hattın bölenidir ... Netlik için olduğu gibi bunu bırakacağım. Üretim veya github için bir kütüphane için, bu kadar sığır eti isteyebilirsiniz ... Bir muhafızdan daha fazlası, fonksiyonun çok fazla şey söylemeyen kısa değişken isimleri kullandığından endişeliyim. Muhtemelen önce bunu düzeltirim, sonra başka şeyler için korumalar ekler ve sonra birim testleri eklerdim.
Dan Rosenstark

2

Swift 4 cevabı:

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

Gerçek ölçeği ayarlamanıza gerek yok: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

Swift 3 projenizde kutudan çıkabileceğiniz bir cevap bulmanın zor olduğunu keşfettim . Diğer cevapların ana sorunu, görüntünün alfa kanalını onurlandırmadıklarıdır. İşte projelerimde kullandığım teknik.

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

Kullanım örneği:

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

Bu kod, Apple uzantısının yeniden yazılmasıdır alfa kanalı olan ve olmayan görüntüler için ek destek .

Daha fazla okuma için, bu makaleyi farklı görüntü boyutlandırma teknikleri için kontrol etmenizi öneririm . Mevcut yaklaşım iyi bir performans sunar, yüksek seviyeli API'ler çalıştırır ve anlaşılması kolaydır. Görüntü yeniden boyutlandırmanın performansınızda bir darboğaz olduğunu düşünmüyorsanız buna bağlı kalmanızı öneririz.


1

Genişliği / yüksekliği yalnızca en boy oranıyla yeniden boyutlandırmanız gerektiğinde bu uzantıyı kullanın.

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))
    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.