Як стиснути / змінити розмір зображення на 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.