UIImage resize (Масштабирование пропорции)

Возможный дубликат:
Изменить размер UIImage с соотношением сторон?

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

// Change image resolution (auto-resize to fit)
+ (UIImage *)scaleImage:(UIImage*)image toResolution:(int)resolution {
    CGImageRef imgRef = [image CGImage];
    CGFloat width = CGImageGetWidth(imgRef);
    CGFloat height = CGImageGetHeight(imgRef);
    CGRect bounds = CGRectMake(0, 0, width, height);

    //if already at the minimum resolution, return the orginal image, otherwise scale
    if (width <= resolution && height <= resolution) {
        return image;

    } else {
        CGFloat ratio = width/height;

        if (ratio > 1) {
            bounds.size.width = resolution;
            bounds.size.height = bounds.size.width / ratio;
        } else {
            bounds.size.height = resolution;
            bounds.size.width = bounds.size.height * ratio;
        }
    }

    UIGraphicsBeginImageContext(bounds.size);
    [image drawInRect:CGRectMake(0.0, 0.0, bounds.size.width, bounds.size.height)];
    UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return imageCopy;
}

person Mustafa    schedule 15.04.2010    source источник
comment
См. Этот вопрос (и мой ответ;): stackoverflow.com/questions/1703100/   -  person Frank Schmitt    schedule 17.04.2010
comment
Ссылки на другие вопросы SO на самом деле не считаются отличными ответами. Если это дубликат, его следует закрыть как таковой.   -  person joran    schedule 02.07.2012
comment
Это помогло мне решить проблему, когда мне нужно было масштабировать UIImage, спасибо :)   -  person RelativeGames    schedule 19.03.2013


Ответы (5)


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

    // grab the original image
    UIImage *originalImage = [UIImage imageNamed:@"myImage.png"];
    // scaling set to 2.0 makes the image 1/2 the size. 
    UIImage *scaledImage = 
                [UIImage imageWithCGImage:[originalImage CGImage] 
                              scale:(originalImage.scale * 2.0)
                                 orientation:(originalImage.imageOrientation)];
person Mark24x7    schedule 09.09.2010
comment
Это логичное изменение размера. Если вы хотите изменить размер изображения для повышения производительности, посмотрите voicearo.com/trevor/blog/2009/10/12/ или даже на eran.sandler.co.il/2011/11/07/, если вы столкнулись с неправильным поведением в iOS 5. - person Xavi Gil; 22.11.2011
comment
очевидно, что это Абдул, иначе не проголосовало бы 36 человек. Вы что-то делаете не так. - person Adam Waite; 06.11.2013
comment
масштабирование до 2,0 делает изображение 1/2 размера ... LOL! - person zonabi; 24.09.2015
comment
для быстрого: let img: UIImage = UIImage(named: "lena")! var scaledImage = UIImage(CGImage: img.CGImage!, scale: img.scale * 2, orientation: img.imageOrientation) - person vkalit; 25.11.2015
comment
@zonabi, это не так уж и смешно. А как насчет деления на 2,0 вместо умножения ... UIImage *scaledImage = [UIImage imageWithCGImage:[image CGImage] scale:image.scale/2.0 orientation:(image.imageOrientation)]; Таким образом, вы получите более логичное представление о своем желании масштабирования (также как и я хочу умножить масштаб на коэффициент n) - person Bejil; 04.12.2015

Это нормально, не большая проблема. Дело в том, что вам нужно найти пропорциональную ширину и высоту

например, если размер составляет 2048,0 x 1360,0, который необходимо изменить до разрешения 320 x 480, тогда размер результирующего изображения должен быть 722,0 x 480,0

here is the formulae to do that . if w,h is original and x,y are resulting image.
w/h=x/y 
=> 
x=(w/h)*y;  

submitting w=2048,h=1360,y=480 => x=722.0 ( here width>height. if height>width then consider x to be 320 and calculate y)

Вы можете представить на этой веб-странице. ARC

Смущенный ? Хорошо, вот категория для UIImage, которая сделает все за вас.

@interface UIImage (UIImageFunctions)
    - (UIImage *) scaleToSize: (CGSize)size;
    - (UIImage *) scaleProportionalToSize: (CGSize)size;
@end
@implementation UIImage (UIImageFunctions)

- (UIImage *) scaleToSize: (CGSize)size
{
    // Scalling selected image to targeted size
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(NULL, size.width, size.height, 8, 0, colorSpace, kCGImageAlphaPremultipliedLast);
    CGContextClearRect(context, CGRectMake(0, 0, size.width, size.height));

    if(self.imageOrientation == UIImageOrientationRight)
    {
        CGContextRotateCTM(context, -M_PI_2);
        CGContextTranslateCTM(context, -size.height, 0.0f);
        CGContextDrawImage(context, CGRectMake(0, 0, size.height, size.width), self.CGImage);
    }
    else
        CGContextDrawImage(context, CGRectMake(0, 0, size.width, size.height), self.CGImage);

    CGImageRef scaledImage=CGBitmapContextCreateImage(context);

    CGColorSpaceRelease(colorSpace);
    CGContextRelease(context);

    UIImage *image = [UIImage imageWithCGImage: scaledImage];

    CGImageRelease(scaledImage);

    return image;
}

- (UIImage *) scaleProportionalToSize: (CGSize)size1
{
    if(self.size.width>self.size.height)
    {
        NSLog(@"LandScape");
        size1=CGSizeMake((self.size.width/self.size.height)*size1.height,size1.height);
    }
    else
    {
        NSLog(@"Potrait");
        size1=CGSizeMake(size1.width,(self.size.height/self.size.width)*size1.width);
    }

    return [self scaleToSize:size1];
}

@end

- для этого подходит следующий вызов, если img является экземпляром UIImage.

img = [img scaleProportionalToSize: CGSizeMake (320, 480)];

person RamaKrishna Chunduri    schedule 14.12.2010
comment
Вы имеете в виду anImageView.contentMode = UIViewContentModeScaleAspectFit ;? - person Wayne Lo; 05.03.2011
comment
да, похоже на режим содержимого, но без использования каких-либо элементов пользовательского интерфейса, таким образом, масштабированное изображение может быть сохранено в файл или db ... - person RamaKrishna Chunduri; 25.09.2014

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

- (UIImage *) scaleProportionalToSize: (CGSize)size
{
    float widthRatio = size.width/self.size.width;
    float heightRatio = size.height/self.size.height;

    if(widthRatio > heightRatio)
    {
        size=CGSizeMake(self.size.width*heightRatio,self.size.height*heightRatio);
    } else {
        size=CGSizeMake(self.size.width*widthRatio,self.size.height*widthRatio);
    }

    return [self scaleToSize:size];
}
person Monte Goulding    schedule 29.02.2012

Это изменение сработало для меня:

// The size returned by CGImageGetWidth(imgRef) & CGImageGetHeight(imgRef) is incorrect as it doesn't respect the image orientation!
// CGImageRef imgRef = [image CGImage];
// CGFloat width = CGImageGetWidth(imgRef);
// CGFloat height = CGImageGetHeight(imgRef);
//
// This returns the actual width and height of the photo (and hence solves the problem
CGFloat width = image.size.width; 
CGFloat height = image.size.height;
CGRect bounds = CGRectMake(0, 0, width, height);
person Mustafa    schedule 16.04.2010

Попробуйте сделать размер bounds целым.

#include <math.h>
....

    if (ratio > 1) {
        bounds.size.width = resolution;
        bounds.size.height = round(bounds.size.width / ratio);
    } else {
        bounds.size.height = resolution;
        bounds.size.width = round(bounds.size.height * ratio);
    }
person kennytm    schedule 15.04.2010