如何在iOS上传到服务器之前压缩/调整图像大小?

76

我目前正在使用以下代码,在iOS上通过Imgur将图像上传到服务器:

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"];

当我在模拟器中运行代码并从模拟器的照片库上传文件时,代码可以正常工作,因为我所在的以太网连接速度很快。然而,当我在iPhone上选择一个拍摄的图像时,同样的代码会超时。因此,我尝试保存从网络上获取的小图片并尝试上传,这是成功的。

这导致我相信,由于有些缓慢的3G网络,iPhone拍摄的大型图像会超时。是否有办法在发送之前从iPhone压缩/调整图片大小?

13个回答

203

这段代码将会改变图片的尺寸:

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

变量newSize是一个CGSize,可以这样定义:

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

1
这是实际上似乎起作用的解决方案(图像数据大小从145k减少到30k)。 - Joshua Sullivan
9
"newSize" 是一个 CGSize 类型的变量。 例如:CGSize newSize = CGSizeMake(100.0f, 100.0f); - Dexter
太好了!不要急于使用压缩技术,最简单和好的解决方案 :) - DivineDesert
但是这将改变图像的大小,如果我需要按原始规格上传图像到服务器,那么这不起作用,对吗? - Nuzhat Zari
这个“newSize”大小是以像素为单位的图像大小吗? - 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所说的,这可能是最快、最优雅的方法。

要链接到John Muchow 在 iphonedevelopertips.com 的文章,为UIImage添加一个类别是非常方便、非常快速地缩放图片的一种方式。只需调用:

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

这将为您返回一个640x480的图像,表示您的NSData(可能是在线图像),无需编写任何其他代码。


1
它实际上是缩小像素。因此,它还减小了图片所占用的尺寸。但它并没有进行“重新压缩”。如果您在这里提到的就是那个。 - nembleton

7

Matt Gemmell的MGImageUtilities非常好,能够高效地调整大小并具有一些减少工作量的方法。


6
在这段代码中,0.5表示50%…
UIImage *original = image;
UIImage *compressedImage = UIImageJPEGRepresentation(original, 0.5f);

这正是我所需要的。 - scott

5

使用这种简单的方法 NSData *data = UIImageJPEGRepresentation(chosenImage, 0.2f);


3

这是Zorayr的函数的Swift实现(稍作修改,以包括实际单位而不是比例的高度或宽度约束):

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
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。 在我的情况下: 原始 --- 图像大小(字节):85KB & 转换后 --- 图像大小(字节):23KB


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

1
通常来说,像这样详细阐述答案会很有帮助。提供文档链接、引用该文档中的内容以及解释代码如何回答问题。 - Chad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接