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

Posted

技术标签:

【中文标题】如何在上传到服务器之前在 iOS 上压缩/调整图像大小?【英文标题】:How to compress/resize image on iOS before uploading to a server? 【发布时间】:2011-05-22 14:58:32 【问题描述】:

我目前正在使用 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拍摄的图像时,iPhone上的代码超时。因此,我通过从网络上保存一张小图片并尝试上传它进行了尝试,这很有效。

这让我相信 iPhone 拍摄的大图像在速度有点慢的 3G 网络上会超时。有什么方法可以在发送之前从 iPhone 压缩/调整图像大小?

【问题讨论】:

【参考方案1】:

这个 sn-p 将调整图像大小:

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

变量newSizeCGSize,可以这样定义:

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

【讨论】:

这个解决方案似乎确实有效(图像数据大小从 145k 变为 30k)。 "newSize" 是 CGSize 例如。 CGSize newSize = CGSizeMake(100.0f, 100.0f); 太棒了!不要急于压缩技术,最简单和好的解决方案:) 但是这会改变图片的大小,如果我需要将图片上传到原始规格的服务器,那么这将不起作用,对吧? 这是 Size "newSize" ImageSize 的像素吗?【参考方案2】:

一个独立的解决方案:

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

【讨论】:

【参考方案3】:

作为对@Tuan Nguyen 的补充,这可能是最快、最优雅的方式。

要链接到 John Muchow's post at iphonedevelopertips.com ,向 UIImage 添加类别是一种非常方便的快速缩放方式。 只是打电话

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

返回您的 NSDATA 的 640x480 表示图像(可能是在线图像),无需任何更多代码行。

【讨论】:

它实际上缩小了像素。所以它也减少了图片的大小。但它本身并没有进行“重新压缩”。如果这就是你在这里提到的。【参考方案4】:

Matt Gemmell 的 MGImageUtilities 非常好,可以有效地调整大小并采用一些省力的方法。

【讨论】:

【参考方案5】:

在此代码中,0.5 表示 50% ...

UIImage *original = image;
UIImage *compressedImage = UIImageJPEGRepresentation(original, 0.5f);

【讨论】:

这正是我所需要的。【参考方案6】:

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

【讨论】:

【参考方案7】:

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

【讨论】:

这个解决方案很好,但它不适用于方形图像。因为 originalSize.width > originalSize.height 和 originalSize.height > originalSize.width 所以最好改为 >= :-)【参考方案8】:
#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;

【讨论】:

【参考方案9】:

Swift 2.0 版本的 Jagandeep Singh 方法但需要将数据转换为图像,因为 NSData?不会自动转换 UIImage。

let orginalImage:UIImage = image

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

【讨论】:

【参考方案10】:
NsData *data=UiImageJPEGRepresentation(Img.image,0.2f);

【讨论】:

详细说明这样的答案通常会有所帮助。提供文档链接、该文档的引用以及您的代码回答问题的原因的解释。【参考方案11】:
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

【讨论】:

【参考方案12】:
-(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)];      

它返回图像这个图像你可以在任何地方显示............

【讨论】:

【参考方案13】:

您应该能够通过执行以下操作来制作更小的图像

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

(对于四分之一大小的图像)然后将较小的图像转换为 PNG 或您需要的任何格式。

【讨论】:

这改变了缩放图像的报告大小,但实际上并没有改变图像数据。在原始图像和缩放图像上生成的 NSData 的数据长度几乎相同。 这行不通!这不应该是公认的答案!我刚刚在我的应用程序中实现它只是发现压缩到原始图像大小的 25% 的图像仍然具有与原始图像相同的字节大小。我不知道为什么会有这么多的赞成票或这个无效的答案! 不起作用。缩放图像,但保留完整大小的数据。 再次,不起作用。请删除/更新此答案,以免浪费更多时间。 它不会改变文件大小,因为 UIImage 的深层副本是 CGImage 并且调整大小不会改变图像。请参阅苹果文档,以更改您使用缩放版本创建新图像的文件大小。了解什么是指针。还要知道缩小然后放大会导致图像丢失,如果您将它用于任何重要的事情,它稍后会看起来很模糊。压缩它并使用 JPegCompress 或任何调用函数并发送它。

以上是关于如何在上传到服务器之前在 iOS 上压缩/调整图像大小?的主要内容,如果未能解决你的问题,请参考以下文章

在上载到google cloud storage django之前调整图像大小

在上传到服务器之前使用 JavaScript 在客户端调整图像大小

在上传到服务器之前压缩视频和图像

如何在将图像上传到 Firebase 存储之前对其进行压缩?

如何在将图像上传到 Firebase 之前调整其大小?

可以在上传之前在 html 表单上调整图像(客户端)的大小吗?