Як стиснути / змінити розмір зображення на iOS перед завантаженням на сервер?


75

Зараз я завантажую зображення на сервер за допомогою 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 перед відправкою?

Відповіді:


-36

Ви повинні мати можливість зробити менший малюнок, роблячи щось подібне

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

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


52
Це змінює повідомлений розмір масштабованого зображення, але фактично не змінює дані зображення. Довжина даних NSData, що генеруються на оригіналі та масштабованому зображенні, практично однакова.
— Джошуа Салліван

13
Це не працює! Це не повинна бути прийнятою відповіддю! Я щойно застосував його у своєму додатку, щоб з’ясувати, що зображення, стиснене до 25% від початкового розміру, все ще має той самий розмір у байтах, що й оригінал. Я поняття не маю, чому так багато голосів "за" чи ця неробоча відповідь!
— Майкл

не працює. масштабує зображення, але залишає дані в повному розмірі.
— не

Знову ж таки, не працює. Вилучіть / оновіть цю відповідь, щоб не витрачати більше часу.
— Zorayr

Це не змінює розмір файлу, оскільки Глибока копія UIImage є CGImage, а зміна розміру не змінює зображення. Дивіться яблучні документи, щоб змінити розмір файлу, ви створюєте нове зображення в масштабованій версії. Дізнайтеся, що таке вказівник. Нехай також буде відомо, що зменшення, а потім збільшення призведе до втрати зображення, і якщо ви використовуєте його для чогось важливого, воно згодом буде виглядати нечітко. Стисніть його за допомогою JPegCompress або будь-якої іншої функції, що називається, і надішліть це.
— Нік Тернер

202

Цей фрагмент змінить розмір зображення:

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

Змінна newSizeє a CGSizeі може бути визначена так:

CGSize newSize = CGSizeMake(100.0f, 100.0f);

1
Це рішення, яке насправді працює (розмір даних зображення змінився з 145 тис. До 30 тис.).
— Джошуа Салліван

9
"newSize" - це CGSize, наприклад. CGSize newSize = CGSizeMake (100.0f, 100.0f);
— Декстер

Чудово! Не поспішайте з прийомами стиснення, найпростішим і хорошим рішенням :)
— DivineDesert

Але це змінить розмір зображення, якщо мені потрібно завантажити зображення на сервер з оригінальною специфікацією, це не буде працювати, так?
— Nuzhat Zari

Це розмір "newSize" ImageSize у пікселях?
— Stephan Boner

38

Автономне рішення:

- (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.


16

Щоб доповнити @Tuan Nguyen, це, мабуть, найшвидший та найелегантніший спосіб зробити це.

Щоб зробити посилання на допис Джона Мухова на iphonedevelopertips.com , додавання категорії до UIImage - це дуже зручний спосіб масштабування дуже швидко. Просто телефонує

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

повертає вам зображення представлення 640x480 вашого NSDATA (це може бути зображення в Інтернеті) без жодного рядка коду.


1
Це фактично зменшує пікселі. Таким чином, це також зменшує розмір, який робить знімок. Але це не робить "рекомпресії" як такої. Якщо це те, про що ви тут згадуєте.
— nembleton



4

скористайтеся цим простим методом NSData *data = UIImageJPEGRepresentation(chosenImage, 0.2f);


3

Швидка реалізація функції Zorayr (з невеликою зміною, щоб включити обмеження висоти або ширини за фактичними одиницями, а не за масштабом):

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
}

2
це рішення приємне, але для квадратних зображень воно не працює. через originalSize.width> originalSize.height та originalSize.height> originalSize.width, тому краще змінити один на> = :-)
— rcpfuchs

0
#import <ImageIO/ImageIO.h>
#import <MobileCoreServices/MobileCoreServices.h>

+ (UIImage *)resizeImage:(UIImage *)image toResolution:(int)resolution {
NSData *imageData = UIImagePNGRepresentation(image);
CGImageSourceRef src = CGImageSourceCreateWithData((__bridge CFDataRef)imageData, NULL);
CFDictionaryRef options = (__bridge CFDictionaryRef) @{
                                                       (id) kCGImageSourceCreateThumbnailWithTransform : @YES,
                                                       (id) kCGImageSourceCreateThumbnailFromImageAlways : @YES,
                                                       (id) kCGImageSourceThumbnailMaxPixelSize : @(resolution)
                                                       };
CGImageRef thumbnail = CGImageSourceCreateThumbnailAtIndex(src, 0, options);
CFRelease(src);
UIImage *img = [[UIImage alloc]initWithCGImage:thumbnail];
return img;
}

0

Версія Swift 2.0 методу Jagandeep Singh, але потрібно перетворити дані на зображення, оскільки NSData? не перетворюється UIImage автоматично.

let orginalImage:UIImage = image

let compressedData = UIImageJPEGRepresentation(orginalImage, 0.5)
let compressedImage = UIImage(data: compressedData!)

0
NsData *data=UiImageJPEGRepresentation(Img.image,0.2f);

1
Зазвичай корисно детальніше обговорити такі відповіді. Надаючи посилання на документацію, цитати з цієї документації, а також пояснення, чому ваш код відповідає на запитання.
— Чад,

0
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 КБ


-1
-(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)];      

воно повертає зображення, це зображення u може відображати де завгодно ...........

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.