UIImage: Ubah ukuran, lalu Potong

187

Saya telah membenturkan wajah saya ke wajah ini selama berhari-hari sekarang dan meskipun saya merasa terus-menerus bahwa saya benar di ujung wahyu, saya benar-benar tidak dapat mencapai tujuan saya.

Saya pikir, sebelumnya dalam fase konseptual desain saya, bahwa akan menjadi masalah sepele untuk mengambil gambar dari kamera atau perpustakaan iPhone, menurunkannya ke ketinggian yang ditentukan, menggunakan fungsi yang setara dengan opsi Isi Aspek dari UIImageView (seluruhnya dalam kode), dan kemudian memotong apa pun yang tidak cocok dengan CGRect yang disahkan.

Mendapatkan gambar asli dari kamera atau perpustakaan, itu sepele. Saya terkejut melihat betapa sulitnya dua langkah lainnya terbukti.

Gambar terlampir menunjukkan apa yang saya coba capai. Apakah seseorang tolong berbaik hati untuk memegang tangan saya? Setiap contoh kode yang saya temukan sejauh ini tampaknya menghancurkan gambar, terbalik, terlihat seperti omong kosong, menarik keluar batas, atau tidak berfungsi dengan benar.

Carson C.
sumber
7
Tautan rusak ke gambar Anda.
1
Satu hal yang tidak ada jika kita kaget adalah mengapa Apple belum menambahkannya ke UIImagePickerController - terlalu sulit ;-)
Tim

Jawaban:

246

Saya membutuhkan hal yang sama - dalam kasus saya, untuk memilih dimensi yang cocok setelah diskalakan, dan kemudian memotong setiap ujung agar sesuai dengan lebar. (Saya bekerja di lanskap, jadi mungkin tidak memperhatikan kekurangan dalam mode potret.) Ini kode saya - ini adalah bagian dari kategorisasi pada UIImage. Ukuran target dalam kode saya selalu diatur ke ukuran layar penuh perangkat.

@implementation UIImage (Extras)

#pragma mark -
#pragma mark Scale and crop image

- (UIImage*)imageByScalingAndCroppingForSize:(CGSize)targetSize
{
    UIImage *sourceImage = self;
    UIImage *newImage = nil;    
    CGSize imageSize = sourceImage.size;
    CGFloat width = imageSize.width;
    CGFloat height = imageSize.height;
    CGFloat targetWidth = targetSize.width;
    CGFloat targetHeight = targetSize.height;
    CGFloat scaleFactor = 0.0;
    CGFloat scaledWidth = targetWidth;
    CGFloat scaledHeight = targetHeight;
    CGPoint thumbnailPoint = CGPointMake(0.0,0.0);

    if (CGSizeEqualToSize(imageSize, targetSize) == NO) 
    {
        CGFloat widthFactor = targetWidth / width;
        CGFloat heightFactor = targetHeight / height;

        if (widthFactor > heightFactor) 
        {
            scaleFactor = widthFactor; // scale to fit height
        }
        else
        {
            scaleFactor = heightFactor; // scale to fit width
        }

        scaledWidth  = width * scaleFactor;
        scaledHeight = height * scaleFactor;

        // center the image
        if (widthFactor > heightFactor)
        {
            thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5; 
        }
        else
        {
            if (widthFactor < heightFactor)
            {
                thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
            }
        }
    }   

    UIGraphicsBeginImageContext(targetSize); // this will crop

    CGRect thumbnailRect = CGRectZero;
    thumbnailRect.origin = thumbnailPoint;
    thumbnailRect.size.width  = scaledWidth;
    thumbnailRect.size.height = scaledHeight;

    [sourceImage drawInRect:thumbnailRect];

    newImage = UIGraphicsGetImageFromCurrentImageContext();

    if(newImage == nil)
    {
        NSLog(@"could not scale image");
    }

    //pop the context to get back to the default
    UIGraphicsEndImageContext();

    return newImage;
}
Jane Sales
sumber
1
anehnya ia bekerja di simulator tetapi pada perangkat saya menerima ExecBadAccess ..
Sorin Antohi
5
Masalah dengan exec buruk terjadi, karena fungsi UIImage tidak aman thread. Itulah mengapa kadang-kadang crash, kadang-kadang tidak
Erik
1
Kode ini sangat bagus untuk saya, tetapi itu kabur pada retina. Menggabungkan kode ini dengan komentar di bawah ini menjadikan semuanya sempurna: stackoverflow.com/questions/603907/…
MaxGabriel
23
Gunakan UIGraphicsBeginImageContextWithOptions (targetSize, YES, 0,0); untuk membuat gambar bagus di retina juga.
Borut Tomazin
1
Ini berfungsi untuk saya dalam mode Potret, tetapi tidak lansekap. Tingginya membentang di lanskap. Ada yang tahu kenapa?
Darren
77

Posting yang lebih lama berisi kode untuk metode untuk mengubah ukuran UIImage Anda. Bagian yang relevan adalah sebagai berikut:

+ (UIImage*)imageWithImage:(UIImage*)image 
               scaledToSize:(CGSize)newSize;
{
   UIGraphicsBeginImageContext( newSize );
   [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
   UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
   UIGraphicsEndImageContext();

   return newImage;
}

Sejauh pemangkasan berlangsung, saya percaya bahwa jika Anda mengubah metode untuk menggunakan ukuran yang berbeda untuk penskalaan daripada untuk konteks, gambar yang dihasilkan Anda harus dipotong ke batas-batas konteks.

Brad Larson
sumber
3
Tidak membuat SENSE mengapa hal ini memperbaiki orientasi gambar, tetapi hal itu terjadi dan dengan demikian memperbaiki masalah saya dengan kamera yang tidak mengembalikan orientasi yang benar dalam originalImage. Terima kasih.
Brenden
10
Saya menemukan bahwa mengubah ukuran gambar pada perangkat retina tampak buram. Untuk menjaga kejelasan, saya diubah baris pertama dengan berikut ini: UIGraphicsBeginImageContextWithOptions(newSize, 1.0f, 0.0f);. (dijelaskan di sini: stackoverflow.com/questions/4334233/... )
johngraham
Ini memutar gambar - tetapi tidak memotongnya dengan benar! Mengapa ada begitu banyak suara?
Dejell
18
+ (UIImage *)scaleImage:(UIImage *)image toSize:(CGSize)targetSize {
    //If scaleFactor is not touched, no scaling will occur      
    CGFloat scaleFactor = 1.0;

    //Deciding which factor to use to scale the image (factor = targetSize / imageSize)
    if (image.size.width > targetSize.width || image.size.height > targetSize.height)
        if (!((scaleFactor = (targetSize.width / image.size.width)) > (targetSize.height / image.size.height))) //scale to fit width, or
            scaleFactor = targetSize.height / image.size.height; // scale to fit heigth.

    UIGraphicsBeginImageContext(targetSize); 

    //Creating the rect where the scaled image is drawn in
    CGRect rect = CGRectMake((targetSize.width - image.size.width * scaleFactor) / 2,
                             (targetSize.height -  image.size.height * scaleFactor) / 2,
                             image.size.width * scaleFactor, image.size.height * scaleFactor);

    //Draw the image into the rect
    [image drawInRect:rect];

    //Saving the image, ending image context
    UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return scaledImage;
}

Saya usulkan yang ini. Bukankah dia cantik? ;)

Siapa saja
sumber
1
Ini bagus, jika Anda menghapus terlebih dahulu jika pernyataan itu bertindak sebagai AspectFill.
RaffAl
7

Ini dia Yang ini sempurna ;-)

EDIT: lihat di bawah komentar - "Tidak bekerja dengan gambar tertentu, gagal dengan: CGContextSetInterpolationQuality: konteks yang tidak valid kesalahan 0x0"

// Resizes the image according to the given content mode, taking into account the image's orientation
- (UIImage *)resizedImageWithContentMode:(UIViewContentMode)contentMode imageToScale:(UIImage*)imageToScale bounds:(CGSize)bounds interpolationQuality:(CGInterpolationQuality)quality {
    //Get the size we want to scale it to
    CGFloat horizontalRatio = bounds.width / imageToScale.size.width;
    CGFloat verticalRatio = bounds.height / imageToScale.size.height;
    CGFloat ratio;

    switch (contentMode) {
        case UIViewContentModeScaleAspectFill:
            ratio = MAX(horizontalRatio, verticalRatio);
            break;

        case UIViewContentModeScaleAspectFit:
            ratio = MIN(horizontalRatio, verticalRatio);
            break;

        default:
            [NSException raise:NSInvalidArgumentException format:@"Unsupported content mode: %d", contentMode];
    }

    //...and here it is
    CGSize newSize = CGSizeMake(imageToScale.size.width * ratio, imageToScale.size.height * ratio);


    //start scaling it
    CGRect newRect = CGRectIntegral(CGRectMake(0, 0, newSize.width, newSize.height));
    CGImageRef imageRef = imageToScale.CGImage;
    CGContextRef bitmap = CGBitmapContextCreate(NULL,
                                                newRect.size.width,
                                                newRect.size.height,
                                                CGImageGetBitsPerComponent(imageRef),
                                                0,
                                                CGImageGetColorSpace(imageRef),
                                                CGImageGetBitmapInfo(imageRef));

    CGContextSetInterpolationQuality(bitmap, quality);

    // Draw into the context; this scales the image
    CGContextDrawImage(bitmap, newRect, imageRef);

    // Get the resized image from the context and a UIImage
    CGImageRef newImageRef = CGBitmapContextCreateImage(bitmap);
    UIImage *newImage = [UIImage imageWithCGImage:newImageRef];

    // Clean up
    CGContextRelease(bitmap);
    CGImageRelease(newImageRef);

    return newImage;
}
cdstamper
sumber
1
Terlihat sangat cantik :) Saya suka InterpolationQuality di sini
Kostiantyn Sokolinskyi
Tidak berfungsi dengan gambar tertentu, gagal dengan: CGContextSetInterpolationQuality: konteks yang tidak valid 0x0 kesalahan
RaffAl
6

Ini adalah versi jawaban Jane Sales di Swift. Bersulang!

public func resizeImage(image: UIImage, size: CGSize) -> UIImage? {
    var returnImage: UIImage?

    var scaleFactor: CGFloat = 1.0
    var scaledWidth = size.width
    var scaledHeight = size.height
    var thumbnailPoint = CGPointMake(0, 0)

    if !CGSizeEqualToSize(image.size, size) {
        let widthFactor = size.width / image.size.width
        let heightFactor = size.height / image.size.height

        if widthFactor > heightFactor {
            scaleFactor = widthFactor
        } else {
            scaleFactor = heightFactor
        }

        scaledWidth = image.size.width * scaleFactor
        scaledHeight = image.size.height * scaleFactor

        if widthFactor > heightFactor {
            thumbnailPoint.y = (size.height - scaledHeight) * 0.5
        } else if widthFactor < heightFactor {
            thumbnailPoint.x = (size.width - scaledWidth) * 0.5
        }
    }

    UIGraphicsBeginImageContextWithOptions(size, true, 0)

    var thumbnailRect = CGRectZero
    thumbnailRect.origin = thumbnailPoint
    thumbnailRect.size.width = scaledWidth
    thumbnailRect.size.height = scaledHeight

    image.drawInRect(thumbnailRect)
    returnImage = UIGraphicsGetImageFromCurrentImageContext()

    UIGraphicsEndImageContext()

    return returnImage
}
Ishan Handa
sumber
2

Saya memodifikasi Kode Brad Larson. Itu akan aspek mengisi gambar dalam kotak yang diberikan.

-(UIImage*) scaleAndCropToSize:(CGSize)newSize;
{
    float ratio = self.size.width / self.size.height;

    UIGraphicsBeginImageContext(newSize);

    if (ratio > 1) {
        CGFloat newWidth = ratio * newSize.width;
        CGFloat newHeight = newSize.height;
        CGFloat leftMargin = (newWidth - newHeight) / 2;
        [self drawInRect:CGRectMake(-leftMargin, 0, newWidth, newHeight)];
    }
    else {
        CGFloat newWidth = newSize.width;
        CGFloat newHeight = newSize.height / ratio;
        CGFloat topMargin = (newHeight - newWidth) / 2;
        [self drawInRect:CGRectMake(0, -topMargin, newSize.width, newSize.height/ratio)];
    }

    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return newImage;
}
Seunghoon
sumber
1
Diuji dengan dua gambar lain, potret dan lansekap. Ini BUKAN melakukan Isi Aspek.
RaffAl
2

Versi Xamarin.iOS untuk jawaban yang diterima tentang cara mengubah ukuran dan kemudian memotong UIImage (Isi Aspek) di bawah

    public static UIImage ScaleAndCropImage(UIImage sourceImage, SizeF targetSize)
    {
        var imageSize = sourceImage.Size;
        UIImage newImage = null;
        var width = imageSize.Width;
        var height = imageSize.Height;
        var targetWidth = targetSize.Width;
        var targetHeight = targetSize.Height;
        var scaleFactor = 0.0f;
        var scaledWidth = targetWidth;
        var scaledHeight = targetHeight;
        var thumbnailPoint = PointF.Empty;
        if (imageSize != targetSize)
        {
            var widthFactor = targetWidth / width;
            var heightFactor = targetHeight / height;
            if (widthFactor > heightFactor)
            {
                scaleFactor = widthFactor;// scale to fit height
            }
            else
            {
                scaleFactor = heightFactor;// scale to fit width
            }
            scaledWidth = width * scaleFactor;
            scaledHeight = height * scaleFactor;
            // center the image
            if (widthFactor > heightFactor)
            {
                thumbnailPoint.Y = (targetHeight - scaledHeight) * 0.5f;
            }
            else
            {
                if (widthFactor < heightFactor)
                {
                    thumbnailPoint.X = (targetWidth - scaledWidth) * 0.5f;
                }
            }
        }
        UIGraphics.BeginImageContextWithOptions(targetSize, false, 0.0f);
        var thumbnailRect = new RectangleF(thumbnailPoint, new SizeF(scaledWidth, scaledHeight));
        sourceImage.Draw(thumbnailRect);
        newImage = UIGraphics.GetImageFromCurrentImageContext();
        if (newImage == null)
        {
            Console.WriteLine("could not scale image");
        }
        //pop the context to get back to the default
        UIGraphics.EndImageContext();

        return newImage;
    }
Alex Sorokoletov
sumber
2

Saya mengubah panduan Sam Wirch menjadi cepat dan itu bekerja dengan baik bagi saya, meskipun ada sedikit "pengekangan" pada gambar akhir yang tidak bisa saya selesaikan.

func resizedCroppedImage(image: UIImage, newSize:CGSize) -> UIImage {
    var ratio: CGFloat = 0
    var delta: CGFloat = 0
    var offset = CGPointZero
    if image.size.width > image.size.height {
        ratio = newSize.width / image.size.width
        delta = (ratio * image.size.width) - (ratio * image.size.height)
        offset = CGPointMake(delta / 2, 0)
    } else {
        ratio = newSize.width / image.size.height
        delta = (ratio * image.size.height) - (ratio * image.size.width)
        offset = CGPointMake(0, delta / 2)
    }
    let clipRect = CGRectMake(-offset.x, -offset.y, (ratio * image.size.width) + delta, (ratio * image.size.height) + delta)
    UIGraphicsBeginImageContextWithOptions(newSize, true, 0.0)
    UIRectClip(clipRect)
    image.drawInRect(clipRect)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage
}

Jika ada yang menginginkan versi c yang objektif, itu ada di situs webnya.

William T.
sumber
2

Saya menemukan bahwa Swift 3 yang diposting oleh Evgenii Kanvets tidak secara seragam mengukur gambar.

Ini adalah versi fungsi Swift 4 saya yang tidak merusak gambar:

static func resizedCroppedImage(image: UIImage, newSize:CGSize) -> UIImage? {

    // This function returns a newImage, based on image
    // - image is scaled uniformaly to fit into a rect of size newSize
    // - if the newSize rect is of a different aspect ratio from the source image
    //     the new image is cropped to be in the center of the source image
    //     (the excess source image is removed)

    var ratio: CGFloat = 0
    var delta: CGFloat = 0
    var drawRect = CGRect()

    if newSize.width > newSize.height {

        ratio = newSize.width / image.size.width
        delta = (ratio * image.size.height) - newSize.height
        drawRect = CGRect(x: 0, y: -delta / 2, width: newSize.width, height: newSize.height + delta)

    } else {

        ratio = newSize.height / image.size.height
        delta = (ratio * image.size.width) - newSize.width
        drawRect = CGRect(x: -delta / 2, y: 0, width: newSize.width + delta, height: newSize.height)

    }

    UIGraphicsBeginImageContextWithOptions(newSize, true, 0.0)
    image.draw(in: drawRect)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage
} 
Chris Capener
sumber
Saya harus mengatur penskalaan ke 1.0 UIGraphicsBeginImageContextWithOptionstetapi yang lain bekerja dengan sempurna. Terima kasih!
maksmzd
1

Kode sederhana berikut ini berfungsi untuk saya.

[imageView setContentMode:UIViewContentModeScaleAspectFill];
[imageView setClipsToBounds:YES];
William Li
sumber
Kode Anda berfungsi dengan baik untuk UIImageViewobjek. Namun, pertanyaan ini adalah tentang penskalaan UIImageobjek itu sendiri.
Rickster
1
scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0,0.0,ScreenWidth,ScreenHeigth)];
    [scrollView setBackgroundColor:[UIColor blackColor]];
    [scrollView setDelegate:self];
    [scrollView setShowsHorizontalScrollIndicator:NO];
    [scrollView setShowsVerticalScrollIndicator:NO];
    [scrollView setMaximumZoomScale:2.0];
    image=[image scaleToSize:CGSizeMake(ScreenWidth, ScreenHeigth)];
    imageView = [[UIImageView alloc] initWithImage:image];
    UIImageView* imageViewBk = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background.png"]];
    [self.view addSubview:imageViewBk];
    CGRect rect;
    rect.origin.x=0;
    rect.origin.y=0;
    rect.size.width = image.size.width;
    rect.size.height = image.size.height;

    [imageView setFrame:rect];

    [scrollView setContentSize:[imageView frame].size];
    [scrollView setMinimumZoomScale:[scrollView frame].size.width / [imageView frame].size.width];
    [scrollView setZoomScale:[scrollView minimumZoomScale]];
    [scrollView addSubview:imageView];

    [[self view] addSubview:scrollView];

maka Anda dapat mengambil tangkapan layar ke gambar Anda dengan ini

float zoomScale = 1.0 / [scrollView zoomScale];
CGRect rect;
rect.origin.x = [scrollView contentOffset].x * zoomScale;
rect.origin.y = [scrollView contentOffset].y * zoomScale;
rect.size.width = [scrollView bounds].size.width * zoomScale;
rect.size.height = [scrollView bounds].size.height * zoomScale;

CGImageRef cr = CGImageCreateWithImageInRect([[imageView image] CGImage], rect);

UIImage *cropped = [UIImage imageWithCGImage:cr];

CGImageRelease(cr);
khaled
sumber
0
- (UIImage*)imageScale:(CGFloat)scaleFactor cropForSize:(CGSize)targetSize
{
    targetSize = !targetSize.width?self.size:targetSize;
    UIGraphicsBeginImageContext(targetSize); // this will crop

    CGRect thumbnailRect = CGRectZero;

    thumbnailRect.size.width  = targetSize.width*scaleFactor;
    thumbnailRect.size.height = targetSize.height*scaleFactor;
    CGFloat xOffset = (targetSize.width- thumbnailRect.size.width)/2;
    CGFloat yOffset = (targetSize.height- thumbnailRect.size.height)/2;
    thumbnailRect.origin = CGPointMake(xOffset,yOffset);

    [self drawInRect:thumbnailRect];

    UIImage *newImage  = UIGraphicsGetImageFromCurrentImageContext();

    if(newImage == nil)
    {
        NSLog(@"could not scale image");
    }

    UIGraphicsEndImageContext();

    return newImage;
}

Di bawah contoh pekerjaan: Gambar kiri - (gambar asal); Gambar kanan dengan skala x2

masukkan deskripsi gambar di sini

Jika Anda ingin skala gambar tetapi mempertahankan frame (proporsinya), panggil metode ini dengan cara:

[yourImage imageScale:2.0f cropForSize:CGSizeZero];
David
sumber
0

Pertanyaan ini tampaknya telah dikesampingkan, tetapi dalam pencarian saya untuk solusi yang saya bisa lebih mudah mengerti (dan ditulis dalam Swift), saya sampai pada ini (juga diposting ke: Bagaimana cara memotong UIImage? )


Saya ingin dapat memotong dari suatu wilayah berdasarkan rasio aspek, dan skala ke ukuran berdasarkan batas luar. Berikut variasi saya:

import AVFoundation
import ImageIO

class Image {

    class func crop(image:UIImage, crop source:CGRect, aspect:CGSize, outputExtent:CGSize) -> UIImage {

        let sourceRect = AVMakeRectWithAspectRatioInsideRect(aspect, source)
        let targetRect = AVMakeRectWithAspectRatioInsideRect(aspect, CGRect(origin: CGPointZero, size: outputExtent))

        let opaque = true, deviceScale:CGFloat = 0.0 // use scale of device's main screen
        UIGraphicsBeginImageContextWithOptions(targetRect.size, opaque, deviceScale)

        let scale = max(
            targetRect.size.width / sourceRect.size.width,
            targetRect.size.height / sourceRect.size.height)

        let drawRect = CGRect(origin: -sourceRect.origin * scale, size: image.size * scale)
        image.drawInRect(drawRect)

        let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return scaledImage
    }
}

Ada beberapa hal yang saya anggap membingungkan, masalah terpisah dari penanaman dan ukuran. Pemotongan ditangani dengan asal kotak yang Anda lewati untuk menggambarInRect, dan penskalaan ditangani oleh bagian ukuran. Dalam kasus saya, saya perlu menghubungkan ukuran kotak tanam pada sumber, dengan kotak keluaran saya dari rasio aspek yang sama. Faktor skala kemudian adalah output / input, dan ini perlu diterapkan ke drawRect (diteruskan ke drawInRect).

Satu peringatan adalah bahwa pendekatan ini secara efektif mengasumsikan bahwa gambar yang Anda gambar lebih besar dari konteks gambar. Saya belum menguji ini, tetapi saya pikir Anda dapat menggunakan kode ini untuk menangani pemotongan / pembesaran, tetapi secara eksplisit mendefinisikan parameter skala sebagai parameter skala yang disebutkan di atas. Secara default, UIKit menerapkan pengganda berdasarkan resolusi layar.

Akhirnya, perlu dicatat bahwa pendekatan UIKit ini lebih tinggi daripada pendekatan CoreGraphics / Quartz dan Core Image, dan tampaknya menangani masalah orientasi gambar. Perlu juga disebutkan bahwa itu cukup cepat, kedua dari ImageIO, menurut posting ini di sini: http://nshipster.com/image-resizing/

Chris Conover
sumber
0

Versi cepat:

    static func imageWithImage(image:UIImage, newSize:CGSize) ->UIImage {
    UIGraphicsBeginImageContextWithOptions(newSize, true, UIScreen.mainScreen().scale);
    image.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height))

    let newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();
    return newImage
}
Roman Barzyczak
sumber
1
Fungsi kecil yang bagus tapi saya cukup yakin ini hanya memperbesar gambar ke ukuran tertentu, tidak menjaga rasio aspek dan memotong ...
William T.
Ya Anda benar, ini hanya untuk memotong gambar ke ukuran paritcular.
Roman Barzyczak
0

Ini adalah versi Swift 3 dari panduan Sam Wirch untuk swift yang diposting oleh William T.

extension UIImage {

    static func resizedCroppedImage(image: UIImage, newSize:CGSize) -> UIImage? {
        var ratio: CGFloat = 0
        var delta: CGFloat = 0
        var offset = CGPoint.zero

        if image.size.width > image.size.height {
            ratio = newSize.width / image.size.width
            delta = (ratio * image.size.width) - (ratio * image.size.height)
            offset = CGPoint(x: delta / 2, y: 0)
        } else {
            ratio = newSize.width / image.size.height
            delta = (ratio * image.size.height) - (ratio * image.size.width)
            offset = CGPoint(x: 0, y: delta / 2)
        }

        let clipRect = CGRect(x: -offset.x, y: -offset.y, width: (ratio * image.size.width) + delta, height: (ratio * image.size.height) + delta)
        UIGraphicsBeginImageContextWithOptions(newSize, true, 0.0)
        UIRectClip(clipRect)
        image.draw(in: clipRect)
        let newImage = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return newImage
    }

}
Yevhenii Kanivets
sumber