Cara paling sederhana untuk mengubah ukuran UIImage?

397

Di aplikasi iPhone saya, saya mengambil gambar dengan kamera, lalu saya ingin mengubah ukurannya menjadi 290 * 390 piksel. Saya menggunakan metode ini untuk mengubah ukuran gambar:

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

Ini berfungsi dengan baik, tetapi ini adalah fungsi tidak berdokumen, jadi saya tidak dapat menggunakannya lagi dengan iPhone OS4.

Jadi ... apa cara paling sederhana untuk mengubah ukuran UIImage?

pimpampoum
sumber
Cara melakukannya pada 2019, nshipster.com/image-resizing
dengST30

Jawaban:

772

Cara paling sederhana adalah mengatur bingkai Anda UIImageViewdan mengaturnya contentModeke salah satu opsi pengubahan ukuran.

Atau Anda dapat menggunakan metode utilitas ini, jika Anda benar-benar perlu mengubah ukuran gambar:

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

Contoh penggunaan:

#import "MYUtil.h"

UIImage *myIcon = [MYUtil imageWithImage:myUIImageInstance scaledToSize:CGSizeMake(20, 20)];
Paul Lynch
sumber
11
Saya TIDAK akan mempertahankan hasilnya di sini. newImageakan sudah autoreleased sudah, dan harus sampai metode yang memanggil ini untuk mempertahankannya atau tidak. Pendekatan ini hanya meminta bug memori karena initbukan bagian dari nama metode. Saya akan mengharapkan metode bernama ini untuk mengembalikan objek autoreleased.
Alex Wayne
Poin valid, dan diedit. Saya hanya akan meninggalkan peringatan bahwa kode saya yang menggunakan ini menghasilkan kesalahan malloc di tempat lain tanpa tambahan, yang jelas-jelas salah saya :-).
Paul Lynch
26
Pada iOS 4.0 , fungsi UIGraphics * semuanya aman.
BJ Homer
3
@ Paul Lynch: Perlu diingat bahwa perubahan ini memecah misi posting asli: Cara mengubah ukuran gambar ke beberapa ukuran piksel yang tepat (sebagai lawan ukuran titik ).
Nikolai Ruhe
8
Bagi mereka yang berjuang karena batasan yang ditunjukkan oleh @NikolaiRuhe, Anda dapat memaksanya ke ukuran piksel yang tepat dengan melewati 1.0 bukannya 0.0 dalam panggilan keUIGraphicsBeginImageContextWithOptions
Danny
84

Inilah versi Swift dari jawaban 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
}

Dan sebagai perpanjangan:

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()
    }
}
Rogerio Chaves
sumber
2
baru saja mencatat bahwa, di iOS, newSize Anda akan digandakan dengan 2x, 3x berdasarkan perangkat
Sruit A.Suk
6
UIGraphicsBeginImageContextWithOptions (newSize, false, image.scale); untuk semua perangkat
phnmnn
Perhatikan bahwa ini tidak mengubah ukuran CGImage yang mendasarinya (setidaknya di iOS 12.1). Yang tidak apa-apa berdasarkan pertanyaan, tetapi jika Anda menulis gambar, Anda harus menggunakan cgImage, dan Anda akan mendapatkan gambar aslinya.
prewett
72

Solusi Proper Swift 3.0 untuk iOS 10+ : Menggunakan ImageRendererdan menutup sintaksis:

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

Dan inilah versi 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
Jakub Průša
sumber
1
Solusi yang sangat elegan, ini harus menjadi jawaban yang diterima!
appsunited
2
Ini lebih baik daripada elegan, benar. Dokumen api Apple menyarankan kode baru untuk menggunakan UIGraphicsRenderer seperti kode ini. Terima kasih
Paul Bruneau
1
@appsunited Pertanyaannya hampir 8 tahun. Dan metode ini hanya berfungsi untuk iOS10 + seperti yang dinyatakan.
Saat menyalin objek gambar baru ke clipboard itu menghasilkan blok putih untuk saya. Ini sebenarnya tidak mengubah ukuran tampilan gambar?
Oliver Dixon
1
fungsi ini mengembalikan gambar dengan tinggi 0 dan lebar 0, tinggi harapan adalah tinggi 9000 dan lebar 9000.
Krishan Kumar
31

Trevor Howard memiliki beberapa kategori UIImage yang menangani pengubahan ukuran dengan cukup baik. Jika tidak ada yang lain, Anda dapat menggunakan kode sebagai contoh.

Catatan: Pada iOS 5.1, jawaban ini mungkin tidak valid. Lihat komentar di bawah.

TechZen
sumber
2
Saya perlu mengubah ukuran beberapa gambar juga, dan saya pertama kali mencoba penambahan Trevor untuk UIImage, tetapi mendapat beberapa bug aneh pada PNG (sesuatu tentang saluran alpha). Namun jawaban yang diterima untuk pertanyaan ini berhasil dengan baik.
Sorig
1
Ini tidak lagi berlaku (setidaknya dengan iOS5.1
Jann
@Jann, lihat komit di bawah posting.
vikingosegundo
@Jann Jika Anda mengikuti perbaikan yang disarankan dalam komentar, pergi dengan "Matt mengatakan: 22 November 2011 pukul 17:39" karena ia melepaskan colorspaceref (tidak seperti solusi serupa horseshoe7).
Ben Flynn
1
@sanmai menggunakan salah satu dari metode pengubahan ukuran ini, gambar kehilangan ketajamannya. apakah ada cara untuk mencapai ketajaman
vamsi575kg
31

Versi yang lebih ringkas untuk Swift 4 dan iOS 10+:

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

Pemakaian:

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

Saya juga melihat ini dilakukan (yang saya gunakan UIButtonsuntuk Normal dan Selected state karena tombol tidak resizecocok). Penghargaan diberikan kepada siapa pun penulis aslinya.

Pertama buat file .h dan .m yang kosong dipanggil UIImageResizing.hdanUIImageResizing.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

Sertakan file .h itu dalam file .m apa pun yang akan Anda gunakan fungsinya lalu panggil seperti ini:

UIImage* image = [UIImage imageNamed:@"largeImage.png"];
UIImage* smallImage = [image scaleToSize:CGSizeMake(100.0f,100.0f)];
aku telah dirampok
sumber
Ini tidak menyalin orientasi gambar.
Kevin
20

Peningkatan pada kode Paul ini akan memberi Anda gambar beresolusi tinggi yang tajam pada iPhone dengan tampilan retina. Kalau tidak, saat menurunkannya buram.

+ (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;
}
jahat
sumber
13
Hanya FYI, perubahan yang Anda buat tidak perlu, karena memberikan nilai 0,0 untuk skala di UIGraphicsBeginImageContextWithOptionsakan secara otomatis menggunakan skala layar utama (pada iOS 3.2).
Andrew R.
16

Ini cara sederhana:

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

gambar resized adalah gambar baru.

asmad
sumber
16

Solusi Swift untuk Stretch Fill, Fill Aspect, dan 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()
    }
}

dan untuk menggunakan Anda dapat melakukan hal berikut:

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

Terima kasih kepada abdullahselek untuk solusi aslinya.

Josh Bernfeld
sumber
15

Berikut ini adalah modifikasi dari kategori yang ditulis oleh iWasRobbed di atas. Itu menjaga rasio aspek gambar asli daripada mendistorsi itu.

- (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;
}
Scott Means
sumber
11

Jika Anda hanya ingin gambar lebih kecil dan tidak peduli tentang ukuran pastinya:

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

Mengatur skala untuk 0.25fakan memberi Anda gambar 816 x 612 dari kamera 8MP.

Berikut adalah kategori UIImage + Scale untuk mereka yang membutuhkannya.

sanmai
sumber
10

Kenapa begitu rumit? Saya pikir menggunakan sistem API dapat mencapai hasil yang sama:

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.

Satu-satunya gotcha adalah Anda harus melewati kebalikan dari rasio target sebagai argumen kedua, karena menurut dokumen parameter kedua menentukan rasio gambar asli dibandingkan dengan yang skala baru.

Chris
sumber
Karena skala (%) tidak sama dengan piksel (w / jam).
Skala harus largeImage.scale / rasio bukan 1 / rasio.
Marián Černý
9

Ini adalah ekstensi UIImage yang kompatibel dengan Swift 3 dan Swift 4 yang mengubah skala gambar ke ukuran tertentu dengan rasio aspek

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

}

Contoh penggunaan

let image = UIImage(named: "apple")
let scaledImage = image.scaleImageToFitSize(size: CGSize(width: 45.0, height: 45.0))
abdullahselek
sumber
Saya akan merekomendasikan untuk memberi nama fungsi scaledImage(with size:)atau scaledWithSize(_:). Juga UIGraphicsGetImageFromCurrentImageContexttidak dapat benar-benar kembali nil, oleh karena itu !akan berfungsi juga. Anda juga dapat menyederhanakan pembuatan rect CGRect(origin: .zero, size: size).
Sulthan
8

Saya menemukan kategori untuk UIImage dalam contoh Apple sendiri yang melakukan trik yang sama. Berikut tautannya: https://developer.apple.com/library/ios/samplecode/sc2273/Listings/AirDropSample_UIImage_Resize_m.html .

Anda hanya perlu mengubah panggilan:

UIGraphicsBeginImageContextWithOptions(newSize, YES, 2.0);

di imageWithImage:scaledToSize:inRect:dengan:

UIGraphicsBeginImageContextWithOptions(newSize, NO, 2.0);

Untuk mempertimbangkan saluran alfa dalam gambar.

aubykhan
sumber
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
}
ashwini
sumber
Merupakan ide bagus untuk menambahkan beberapa teks deskriptif agar sesuai dengan kode Anda.
GMchris
6

Untuk rekan Xamaria saya, berikut adalah versi Xamarin.iOS C # dari jawaban @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;
}
Martin Zikmund
sumber
5

Jika Anda ingin membuat thumbnail UIImage (dengan pengubahan ukuran proporsional atau mungkin beberapa pemangkasan), lihat UIImage + kategori Resize yang memungkinkan Anda menggunakan sintaks ringkas, seperti ImageMagick:

UIImage* squareImage       = [image resizedImageByMagick: @"320x320#"];
Vlad Andersen
sumber
5

[cf Chris] Untuk mengubah ukuran ke ukuran yang diinginkan:

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

atau, ekuivalen, gantikan CGImageGetWidth(...)/DESIREDWIDTH

tiritea
sumber
Perhatikan bahwa data gambar itu sendiri tidak diubah ukurannya tetapi faktor skala diterapkan yang berarti gambar dengan ukuran yang sama dalam memori.
inkredibl
5

Rogerio Chaves menjawab sebagai perpanjangan cepat

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
}

Dan juga bonus

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

Swift 3.0 dengan opsi failafe (mengembalikan gambar asli jika terjadi kesalahan):

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
}
rowel
sumber
5

(Swift 4 kompatibel) solusi iOS 10+ dan iOS <10 (menggunakan UIGraphicsImageRendererjika memungkinkan, UIGraphicsGetImageFromCurrentImageContextjika tidak)

/// 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!
    }
}
nathan
sumber
5

Pendekatan efektif tanpa peregangan gambar 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!
                }

// Metode panggilan

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

Jawaban @Paul Lynch bagus, tetapi itu akan mengubah rasio gambar. jika Anda tidak ingin mengubah rasio gambar, dan masih menginginkan gambar baru cocok untuk ukuran baru, coba ini.

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

gunakan ekstensi ini

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)
            })
        })
    }
}
Beslan Tularov
sumber
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()
Phil
sumber
2

Di sini kode Swift saya yang agak verbose

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
}
Dan Rosenstark
sumber
1
Ini menghemat waktu saya. Terima kasih!
Quy Nguyen
berguna, tetapi bertingkah aneh setelah segue dan kembali kegiatan, lihat di sini plz: stackoverflow.com/questions/30978685/…
He Yifei 何 一 非
Harap dicatat: Anda mungkin ingin menambahkan prasyarat ( guard) pada aspectRatioAwareSizefungsi sedemikian rupa sehingga tidak akan membagi pembagian dengan pengecualian nol jika parameter input untuk imageSize atau boxSize adalahCGSize.zero
pkluz
@ pkluz ini adalah saran yang bagus, tetapi Anda akan membutuhkan mereka di seluruh fungsinya, saya pikir, karena setiap variabel adalah pembagi dari baris lain ... Saya akan membiarkan ini sebagaimana adanya untuk kejelasan. Untuk produksi atau perpustakaan untuk github, Anda mungkin ingin menambahkan ini ... Lebih dari seorang penjaga, saya khawatir bahwa fungsinya menggunakan nama variabel pendek yang tidak banyak bicara. Saya mungkin akan memperbaikinya terlebih dahulu, dan kemudian menambahkan penjaga untuk hal-hal lain, dan kemudian menambahkan tes unit.
Dan Rosenstark
2

Swift 4 menjawab:

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!
}
DanielEdrisian
sumber
Tidak perlu mengatur skala nyata: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

Saya telah menemukan bahwa sulit untuk menemukan jawaban yang dapat Anda gunakan di luar kotak di proyek Swift 3 Anda . Masalah utama dari jawaban lain bahwa mereka tidak menghormati saluran alpha gambar. Berikut adalah teknik yang saya gunakan dalam proyek saya.

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

Contoh penggunaan:

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

Kode ini adalah penulisan ulang ekstensi Apple dengan dukungan tambahan untuk gambar dengan dan tanpa saluran alpha.

Sebagai bacaan lebih lanjut saya sarankan memeriksa artikel ini untuk berbagai teknik mengubah ukuran gambar. Pendekatan saat ini menawarkan kinerja yang layak, ia mengoperasikan API tingkat tinggi dan mudah dimengerti. Saya sarankan tetap melakukannya kecuali jika Anda menemukan bahwa mengubah ukuran gambar adalah hambatan dalam kinerja Anda.

Vadim Bulavin
sumber
1

Gunakan ekstensi ini, jika Anda perlu mengubah ukuran lebar / tinggi hanya dengan rasio aspek.

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))
    }
}
Jeffrey Neo
sumber