Как сжать/изменить размер изображения на iOS перед загрузкой на сервер?

В настоящее время я загружаю изображение на сервер с помощью Imgur на iOS со следующим кодом:

NSData* imageData = UIImagePNGRepresentation(image);
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString* fullPathToFile = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"SBTempImage.png"];
[imageData writeToFile:fullPathToFile atomically:NO];

[uploadRequest setFile:fullPathToFile forKey:@"image"];

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

Это наводит меня на мысль, что большие изображения, сделанные iPhone, выходят из-под контроля относительно медленной сети 3G. Есть ли способ сжать/изменить размер изображения с iPhone перед его отправкой?


person joshholat    schedule 09.12.2010    source источник


Ответы (12)


Вы должны иметь возможность сделать изображение меньшего размера, выполнив что-то вроде

UIImage *small = [UIImage imageWithCGImage:original.CGImage scale:0.25 orientation:original.imageOrientation];

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

person TerryH    schedule 09.12.2010
comment
Это изменяет сообщаемый размер масштабированного изображения, но фактически не изменяет данные изображения. Длина данных NSData, сгенерированных на исходном и масштабированном изображении, практически одинакова. - person Joshua Sullivan; 15.03.2012
comment
Это не работает! Это не должен быть принятый ответ! Я только что реализовал это в своем приложении только для того, чтобы узнать, что изображение, сжатое до 25% от исходного размера изображения, по-прежнему имеет тот же размер в байтах, что и оригинал. Я понятия не имею, почему так много голосов или этот нерабочий ответ! - person Michael; 18.02.2013
comment
не работает. масштабирует изображение, но оставляет данные в полном размере. - person nont; 20.09.2013
comment
Опять не работает. Пожалуйста, удалите/обновите этот ответ, чтобы не тратить больше времени. - person Zorayr; 27.12.2013
comment
Это не изменяет размер файла, потому что глубокая копия UIImage является CGImage, и изменение размера не меняет изображение. См. Apple docs, чтобы изменить размер файла, вы создаете новое изображение с масштабированной версией. Узнайте, что такое указатель. Дайте также знать, что уменьшение, а затем увеличение приведет к потере изображения, и если вы используете его для чего-то важного, позже оно будет выглядеть нечетким. Сожмите его и с помощью JPegCompress или любой другой функции, которая вызывается, и отправьте это. - person Nick Turner; 16.04.2015
comment
@FahimParkar +38 -70 ЛОЛ - person Ver Nick; 18.01.2019

Этот фрагмент изменит размер изображения:

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

Переменная newSize является CGSize и может быть определена следующим образом:

CGSize newSize = CGSizeMake(100.0f, 100.0f);
person Tuan Nguyen    schedule 17.12.2010
comment
Это решение, которое действительно работает (размер данных изображения увеличился с 145 до 30 КБ). - person Joshua Sullivan; 15.03.2012
comment
newSize - это CGSize, например. CGSize newSize = CGSizeMake(100.0f, 100.0f); - person Dexter; 10.05.2012
comment
Здорово! Не торопитесь с методами сжатия, самое простое и хорошее решение :) - person DivineDesert; 09.07.2013
comment
Но это изменит размер изображения, если мне нужно загрузить изображение на сервер с исходной спецификацией, то это не сработает, верно? - person Nuzhat Zari; 23.07.2013
comment
Является ли размер newSize размером изображения в пикселях? - person Stephan Boner; 14.07.2016

Автономное решение:

- (UIImage *)compressForUpload:(UIImage *)original scale:(CGFloat)scale
{
    // Calculate new size given scale factor.
    CGSize originalSize = original.size;
    CGSize newSize = CGSizeMake(originalSize.width * scale, originalSize.height * scale);

    // Scale the original image to match the new size.
    UIGraphicsBeginImageContext(newSize);
    [original drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
    UIImage *compressedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return compressedImage;
}

Спасибо @Tuan Nguyen.

person Zorayr    schedule 26.12.2013

В дополнение к @Tuan Nguyen, это, пожалуй, самый быстрый и элегантный способ сделать это.

Ссылка на сообщение Джона Мухова на iphonedevelopertips.com , добавление категории в UIImage — очень удобный способ очень быстрого масштабирования. Просто звоню

    UIImage *_image = [[[UIImage alloc] initWithData:SOME_NSDATA] scaleToSize:CGSizeMake(640.0,480.0)];

возвращает вам изображение вашего NSDATA размером 640x480 (это может быть онлайн-изображение) без дополнительной строки кода.

person nembleton    schedule 24.02.2012
comment
Он фактически уменьшает пиксели. Таким образом, это также уменьшает размер изображения. Но это не делает рекомпрессию как таковую. Если это то, что вы упоминаете здесь. - person nembleton; 07.06.2013

MGImageUtilities Мэтта Геммелла очень хороши, они эффективно изменяют размер и используют некоторые методы, облегчающие работу.

person Matthew Frederick    schedule 09.12.2010

В этом коде 0,5 означает 50%...

UIImage *original = image;
UIImage *compressedImage = UIImageJPEGRepresentation(original, 0.5f);
person Jagandeep Singh    schedule 13.07.2015
comment
Это было именно то, что мне было нужно. - person scott; 28.10.2015

используйте этот простой метод NSData *data = UIImageJPEGRepresentation(chosenImage, 0.2f);

person Community    schedule 10.06.2014

Быстрая реализация функции Зорайра (с небольшим изменением, чтобы включить ограничения по высоте или ширине в фактических единицах измерения, а не в масштабе):

class func compressForUpload(original:UIImage, withHeightLimit heightLimit:CGFloat, andWidthLimit widthLimit:CGFloat)->UIImage{

    let originalSize = original.size
    var newSize = originalSize

    if originalSize.width > widthLimit && originalSize.width > originalSize.height {

        newSize.width = widthLimit
        newSize.height = originalSize.height*(widthLimit/originalSize.width)
    }else if originalSize.height > heightLimit && originalSize.height > originalSize.width {

        newSize.height = heightLimit
        newSize.width = originalSize.width*(heightLimit/originalSize.height)
    }

    // Scale the original image to match the new size.
    UIGraphicsBeginImageContext(newSize)
    original.drawInRect(CGRectMake(0, 0, newSize.width, newSize.height))
    let compressedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return compressedImage
}
person PJeremyMalouf    schedule 11.05.2015
comment
это решение хорошее, но оно не работает для квадратных изображений. из-за originalSize.width › originalSize.height и originalSize.height › originalSize.width, поэтому лучше изменить один на ›= :-) - person rcpfuchs; 25.04.2016

Версия Swift 2.0 метода Джагандипа Сингха, но вам нужно преобразовать данные в изображение, потому что NSData? не конвертируется UIImage автоматически.

let orginalImage:UIImage = image

let compressedData = UIImageJPEGRepresentation(orginalImage, 0.5)
let compressedImage = UIImage(data: compressedData!)
person CodeOverRide    schedule 29.03.2016

UIImage *image = [UIImage imageNamed:@"image.png"];
NSData *imgData1 = UIImageJPEGRepresentation(image, 1);
NSLog(@"Original --- Size of Image(bytes):%d",[imgData1 length]);

NSData *imgData2 = UIImageJPEGRepresentation(image, 0.5);
NSLog(@"After --- Size of Image(bytes):%d",[imgData2 length]);
image = [UIImage imageWithData:imgData2];
imgTest.image = image;

попробуйте конвертировать JPG по коэффициенту масштабирования. Здесь я использую 0,5. В моем случае: Оригинал --- Размер изображения (в байтах): 85 КБ и после --- Размер изображения (в байтах): 23 КБ

person Swatee Salunkhe    schedule 01.06.2016

-(UIImage *) resizeImage:(UIImage *)orginalImage resizeSize:(CGSize)size
{
CGFloat actualHeight = orginalImage.size.height;
CGFloat actualWidth = orginalImage.size.width;
//  if(actualWidth <= size.width && actualHeight<=size.height)
//  {
//      return orginalImage;
//  }
float oldRatio = actualWidth/actualHeight;
float newRatio = size.width/size.height;
if(oldRatio < newRatio)
{
    oldRatio = size.height/actualHeight;
    actualWidth = oldRatio * actualWidth;
    actualHeight = size.height;
}
else
{
    oldRatio = size.width/actualWidth;
    actualHeight = oldRatio * actualHeight;
    actualWidth = size.width;
}

CGRect rect = CGRectMake(0.0,0.0,actualWidth,actualHeight);
UIGraphicsBeginImageContext(rect.size);
[orginalImage drawInRect:rect];
orginalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return orginalImage;
 }

Это вызов метода

 UIImage *compimage=[appdel resizeImage:imagemain resizeSize:CGSizeMake(40,40)];      

он возвращает изображение, это изображение, которое вы можете отображать где угодно...........

person mahesh chowdary    schedule 28.11.2013

person    schedule
comment
Обычно бывает полезно уточнить такие ответы. Предоставление ссылок на документацию, цитаты из этой документации, а также объяснение того, почему ваш код отвечает на вопрос. - person Chad; 03.04.2016