UIImage: изменить размер, затем обрезать

Я бился об это буквально несколько дней, и хотя я постоянно чувствую, что нахожусь на грани откровения, я просто не могу достичь своей цели.

Я заранее подумал на концептуальных этапах своего дизайна, что было бы тривиально взять изображение с камеры или библиотеки iPhone, уменьшить его до указанной высоты, используя функцию, эквивалентную Aspect Заполнить параметр UIImageView (полностью в коде), а затем обрезать все, что не помещается в переданный CGRect.

Получить исходное изображение с камеры или библиотеки было тривиально. Я потрясен тем, насколько сложными оказались два других шага.

Прикрепленное изображение показывает, чего я пытаюсь достичь. Не мог бы кто-нибудь подержать меня за руку, пожалуйста? Кажется, что каждый пример кода, который я нашел до сих пор, разбивает изображение, переворачивается вверх ногами, выглядит как дерьмо, выходит за пределы или иначе просто не работает правильно.


person Carson C.    schedule 02.03.2009    source источник
comment
Ссылка на ваше изображение не работает.   -  person    schedule 12.09.2012
comment
Одно, если нас не шокирует, - это то, почему Apple не добавила его в UIImagePickerController - это чертовски сложно ;-)   -  person Tim    schedule 15.03.2015


Ответы (16)


Мне нужно было то же самое - в моем случае, выбрать размер, который подходит после масштабирования, а затем обрезать каждый конец, чтобы подогнать остальные по ширине. (Я работаю в альбомной ориентации, поэтому, возможно, не заметил каких-либо недостатков в портретном режиме.) Вот мой код - это часть категории UIImage. Целевой размер в моем коде всегда установлен на полный экран устройства.

@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;
}
person Jane Sales    schedule 03.03.2009
comment
как ни странно, он работает в симуляторе, но на устройстве я получаю ExecBadAccess .. - person Sorin Antohi; 02.09.2009
comment
То же самое. После переноса на устройство я получал периодические ошибки. приведенный ниже код, предоставленный Брэдом Лоусоном, работает аналогично, без ошибок. - person mmc; 19.09.2009
comment
Проблема с плохим exec возникает, потому что функции UIImage не являются потокобезопасными. Вот почему он иногда вылетает, иногда нет - person Erik; 16.03.2010
comment
@Chris Beeson, если я использую этот метод только в одном потоке, а не в каком-либо другом, будет ли это безопасно? - person Jack; 21.07.2011
comment
Этот код отлично работал у меня, но на сетчатке он был размытым. Объединение этого кода с комментарием ниже сделало все идеальным: stackoverflow .com / questions / 603907 / - person MaxGabriel; 20.10.2012
comment
Используйте UIGraphicsBeginImageContextWithOptions (targetSize, YES, 0.0); чтобы изображение было красивым и на сетчатке. - person Borut Tomazin; 31.12.2012
comment
У меня это работает в портретном режиме, но не в альбомном. Высота растянута по ландшафту. Есть идеи, почему? - person Darren; 12.01.2014
comment
Неважно. 2 дня пробовал всевозможные коды для обрезки, и у меня не было автоматического макета, установленного на моем UIImageview, отображающем окончательное изображение. Спасибо за это - person Darren; 12.01.2014
comment
Это можно запустить только в основном потоке. Если ваше приложение использует что-либо, кроме основного потока, вам следует избегать этого кода в пользу того, что не использует UIGraphicsBeginImageContext и UIGraphicsGetImageFromCurrentImageContext. - person kball; 18.03.2014
comment
О, проблема возникает, когда я работаю с портретным изображением. Я думал, что все будет хорошо, но это не так. - person pedrouan; 26.05.2014
comment
В документе Apple говорится о UIGraphicsBeginImageContext. Эта функция может быть вызвана из любого потока вашего приложения. разработчик. apple.com/library/ios/documentation/UIKit/Reference/ - person schmittsfn; 22.10.2015

Более старый пост содержит код метода изменения размера вашего UIImage. Соответствующая часть выглядит следующим образом:

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

   return newImage;
}

Что касается обрезки, я считаю, что если вы измените метод, чтобы использовать другой размер для масштабирования, чем для контекста, ваше результирующее изображение должно быть обрезано до границ контекста.

person Brad Larson    schedule 02.03.2009
comment
НЕТ СМЫСЛА относительно того, почему это исправляет ориентацию изображения, но это так, и, таким образом, это устранило мою проблему с камерой, не возвращающей правильную ориентацию в originalImage. Спасибо. - person Brenden; 14.08.2009
comment
Я обнаружил, что изменение размера изображения на устройстве Retina выглядело размытым. Для ясности я изменил первую строку на следующее: UIGraphicsBeginImageContextWithOptions(newSize, 1.0f, 0.0f);. (здесь объясняется: stackoverflow.com/questions/4334233/) - person johngraham; 25.01.2012
comment
Он поворачивает изображение, но не обрезает его должным образом! Почему у него так много голосов? - person Dejell; 21.01.2013

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

Предлагаю вот это. Разве она не красавица? ;)

person Anybody    schedule 22.11.2010
comment
Это хорошо, если вы сначала удалите оператор if, он действует как AspectFill. - person Rafa de King; 09.08.2012

Есть отличный код, связанный с изменением размера изображений и несколькими другими операциями. Я столкнулся с этим, когда пытался понять, как изменить размер изображений ... http://vocaro.com/trevor/blog/2009/10/12/resize-a-uiimage-the-right-способ/

person yonel    schedule 18.01.2010

Ну вот. Этот идеален ;-)

РЕДАКТИРОВАТЬ: см. Ниже комментарий - «Не работает с определенными изображениями, не работает с: CGContextSetInterpolationQuality: ошибка недопустимого контекста 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;
}
person chris stamper    schedule 28.06.2011
comment
Выглядят очень красиво :) Мне здесь нравится InterpolationQuality - person Kostiantyn Sokolinskyi; 08.12.2011
comment
Не работает с определенными изображениями, не работает с: CGContextSetInterpolationQuality: invalid context 0x0 error - person Rafa de King; 09.08.2012

Это версия ответа Джейн Сейлз на Swift. Ваше здоровье!

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
}
person Ishan Handa    schedule 24.12.2015

Я обнаружил, что Swift 3, опубликованный Евгением Канвцем, не масштабирует изображение равномерно.

Вот моя версия функции Swift 4, которая не сжимает изображение:

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
} 
person Chris Capener    schedule 19.06.2018
comment
Мне пришлось установить масштаб 1.0 в UIGraphicsBeginImageContextWithOptions, но другие работали отлично. Спасибо! - person maxmzd; 23.07.2018

Я модифицировал Код Брэда Ларсона. Это будет аспектное заполнение изображения в заданном прямоугольнике.

-(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;
}
person Seunghoon    schedule 09.01.2012
comment
Протестировано с двумя другими изображениями, портретным и пейзажным. Это НЕ выполнение Aspect Fill. - person Rafa de King; 09.08.2012

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];

затем вы можете делать снимки экрана с помощью этого

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);
person khaled    schedule 23.11.2012

Версия Xamarin.iOS для принятого ответа о том, как изменить размер и затем обрезать UIImage (Aspect Fill), приведена ниже.

    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;
    }
person Alex Sorokoletov    schedule 09.09.2014

Я преобразовал руководство Сэма Уирча в Swift, и у меня это сработало, хотя на финальном изображении есть некоторые очень легкие "сдавливания", которые я не смог разрешить.

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
}

Если кому-то нужна объективная версия c, она у него на сайте.

person William T.    schedule 16.08.2015

У меня сработал следующий простой код.

[imageView setContentMode:UIViewContentModeScaleAspectFill];
[imageView setClipsToBounds:YES];
person William Li    schedule 27.06.2012
comment
Ваш код хорошо работает с UIImageView объектами. Однако этот вопрос касается масштабирования самого объекта UIImage. - person Rickster; 12.12.2013

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

Ниже пример работы: Изображение слева - (исходное изображение); Правое изображение в масштабе x2

введите описание изображения здесь

Если вы хотите масштабировать изображение, но сохранить его рамку (пропорции), вызовите метод следующим образом:

[yourImage imageScale:2.0f cropForSize:CGSizeZero];
person David    schedule 12.02.2015

Этот вопрос, кажется, был решен, но в моем поиске решения, которое мне было бы легче понять (и написанного на Swift), я пришел к этому (также отправлено по адресу: Как обрезать UIImage?)


Я хотел иметь возможность обрезать область на основе соотношения сторон и масштабировать до размера на основе внешнего ограничивающего экстента. Вот мой вариант:

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

Есть пара вещей, которые меня сбивают с толку: отдельные проблемы обрезки и изменения размера. Обрезка обрабатывается с помощью источника прямоугольника, который вы передаете в drawInRect, а масштабирование обрабатывается с помощью части размера. В моем случае мне нужно было связать размер прямоугольника обрезки в источнике с моим выходным прямоугольником с таким же соотношением сторон. Затем масштабный коэффициент выводится / вводится, и его нужно применить к drawRect (передается в drawInRect).

Одно предостережение заключается в том, что этот подход фактически предполагает, что изображение, которое вы рисуете, больше, чем контекст изображения. Я не тестировал это, но думаю, вы можете использовать этот код для обработки обрезки / масштабирования, но явно определяя параметр масштаба как вышеупомянутый параметр масштаба. По умолчанию UIKit применяет множитель в зависимости от разрешения экрана.

Наконец, следует отметить, что этот подход UIKit является более высоким уровнем, чем подходы CoreGraphics / Quartz и Core Image, и, похоже, решает проблемы ориентации изображения. Также стоит отметить, что он довольно быстр, уступая ImageIO, согласно этому сообщению здесь: http://nshipster.com/image-resizing/

person Chris Conover    schedule 28.05.2015

Быстрая версия:

    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
}
person Roman Barzyczak    schedule 24.02.2015
comment
Маленькая приятная функция, но я почти уверен, что она просто растягивает изображение до определенного размера, не сохраняет пропорции и кадрирование ... - person William T.; 16.08.2015
comment
Да, вы правы, это только для растягивания изображения до определенного размера. - person Roman Barzyczak; 17.08.2015

Вот версия для Swift 3. Руководство Сэма Уирча по Swift, опубликованное Уильямом Т.

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
    }

}
person Yev Kanivets    schedule 04.09.2017