Изменение размера UIImage, сохраняя соотношение сторон и ширину - PullRequest
130 голосов
/ 04 октября 2011

Я видел во многих постах изменение размера изображения с сохранением соотношения сторон. Эти функции используют фиксированные точки (ширина и высота) для RECT при изменении размера. Но в моем проекте мне нужно изменить размер представления, основываясь только на ширине, высота должна быть взята автоматически на основе соотношения сторон. кто-нибудь, помогите мне достичь этого.

Ответы [ 17 ]

226 голосов
/ 22 ноября 2011

Метод Срикара работает очень хорошо, если вы знаете, как высота и ширина вашего нового размера. Если вы, например, знаете только ширину, на которую хотите масштабировать, и не заботитесь о высоте, сначала вы должны вычислить масштабный коэффициент высоты.

+(UIImage*)imageWithImage: (UIImage*) sourceImage scaledToWidth: (float) i_width
{
    float oldWidth = sourceImage.size.width;
    float scaleFactor = i_width / oldWidth;

    float newHeight = sourceImage.size.height * scaleFactor;
    float newWidth = oldWidth * scaleFactor;

    UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight));
    [sourceImage drawInRect:CGRectMake(0, 0, newWidth, newHeight)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    
    UIGraphicsEndImageContext();
    return newImage;
}
56 голосов
/ 06 марта 2012

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

Допустим, у вас есть UIImage *myLargeImage, что составляет 4: 3.

UIImage *myResizedImage = [ImageUtilities imageWithImage:myLargeImage 
                                        scaledToMaxWidth:1024 
                                               maxHeight:1024];

Измененный размер UIImage будет 1024x768, если ландшафт; 768x1024, если портрет. Этот метод также генерирует изображения с высоким разрешением для отображения сетчатки.

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

    return newImage;
}

+ (UIImage *)imageWithImage:(UIImage *)image scaledToMaxWidth:(CGFloat)width maxHeight:(CGFloat)height {
    CGFloat oldWidth = image.size.width;
    CGFloat oldHeight = image.size.height;

    CGFloat scaleFactor = (oldWidth > oldHeight) ? width / oldWidth : height / oldHeight;

    CGFloat newHeight = oldHeight * scaleFactor;
    CGFloat newWidth = oldWidth * scaleFactor;
    CGSize newSize = CGSizeMake(newWidth, newHeight);

    return [ImageUtilities imageWithImage:image scaledToSize:newSize];
}
38 голосов
/ 05 декабря 2015

Лучший ответ Maverick 1st's правильно переведен на Swift (работает с последними swift 3 ):

func imageWithImage (sourceImage:UIImage, scaledToWidth: CGFloat) -> UIImage {
    let oldWidth = sourceImage.size.width
    let scaleFactor = scaledToWidth / oldWidth

    let newHeight = sourceImage.size.height * scaleFactor
    let newWidth = oldWidth * scaleFactor

    UIGraphicsBeginImageContext(CGSize(width:newWidth, height:newHeight))
    sourceImage.draw(in: CGRect(x:0, y:0, width:newWidth, height:newHeight))
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage!
}
36 голосов
/ 09 апреля 2015

благодаря @ Maverick1st алгоритму, я реализовал его для Swift, в моем случае высота является входным параметром

class func resizeImage(image: UIImage, newHeight: CGFloat) -> UIImage {

    let scale = newHeight / image.size.height
    let newWidth = image.size.width * scale
    UIGraphicsBeginImageContext(CGSizeMake(newWidth, newHeight))
    image.drawInRect(CGRectMake(0, 0, newWidth, newHeight))
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()

    return newImage
}
18 голосов
/ 28 мая 2015

Этот метод относится к категории на UIImage. Масштабируется, чтобы поместиться в несколько строк кода, используя AVFoundation. Не забудьте импортировать #import <AVFoundation/AVFoundation.h>.

@implementation UIImage (Helper)

- (UIImage *)imageScaledToFitToSize:(CGSize)size
{
    CGRect scaledRect = AVMakeRectWithAspectRatioInsideRect(self.size, CGRectMake(0, 0, size.width, size.height));
    UIGraphicsBeginImageContextWithOptions(size, NO, 0);
    [self drawInRect:scaledRect];
    UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return scaledImage;
}

@end
7 голосов
/ 21 ноября 2011

Самый простой способ - установить фрейм UIImageView и установить для contentMode один из вариантов изменения размера.

Код выглядит так - Это можно использовать как служебный метод -

+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize
{
    UIGraphicsBeginImageContext(newSize);
    [image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();    
    UIGraphicsEndImageContext();
    return newImage;
}
5 голосов
/ 10 августа 2015

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

Мои требования были

  1. Если ширина изображения превышает 1920, измените его размер на 1920 и сохраните высоту с исходным соотношением сторон.
  2. Если высота изображения превышает 1080, измените его размер на 1080 и сохраните ширину с исходным соотношением сторон.

 if (originalImage.size.width > 1920)
 {
        CGSize newSize;
        newSize.width = 1920;
        newSize.height = (1920 * originalImage.size.height) / originalImage.size.width;
        originalImage = [ProfileEditExperienceViewController imageWithImage:originalImage scaledToSize:newSize];        
 }

 if (originalImage.size.height > 1080)
 {
            CGSize newSize;
            newSize.width = (1080 * originalImage.size.width) / originalImage.size.height;
            newSize.height = 1080;
            originalImage = [ProfileEditExperienceViewController imageWithImage:originalImage scaledToSize:newSize];

 }

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

Спасибо @ Srikar Appal , за изменение размера я использовал его метод.

Вы также можете проверить этот , а также для расчета изменения размера.

5 голосов
/ 11 марта 2017

Программный:

imageView.contentMode = UIViewContentModeScaleAspectFit;

Раскадровка:

enter image description here

4 голосов
/ 30 апреля 2014

Просто импортируйте AVFoundation и используйте AVMakeRectWithAspectRatioInsideRect(CGRectCurrentSize, CGRectMake(0, 0, YOUR_WIDTH, CGFLOAT_MAX)

2 голосов
/ 16 июля 2014

Чтобы улучшить ответ Райана:

   + (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)size {
CGFloat oldWidth = image.size.width;
        CGFloat oldHeight = image.size.height;

//You may need to take some retina adjustments into consideration here
        CGFloat scaleFactor = (oldWidth > oldHeight) ? width / oldWidth : height / oldHeight;

return [UIImage imageWithCGImage:image.CGImage scale:scaleFactor orientation:UIImageOrientationUp];
    }
...