如何在iOS中压缩图像?

时间:2016-08-12 17:09:18

标签: ios objective-c amazon-s3 uiimage image-compression

我一直在浏览每个堆栈溢出帖子和视频在线,我找不到正常工作的解决方案。现在,用户在上传到AWS S3存储桶之前选择要压缩的照片。上传工作完美,但由于某种原因,压缩图像比原始图像大!例如,如果用户选择9KB照片,当我上传到S3时,照片为28.5KB。我尝试了另一张照片,它是48KB,在S3上“压缩”后它的378.9KB! (我正在使用所有内容的最新软件版本并使用模拟器进行编译)

我想在上传之前尽可能地压缩原始图片。

这是我到目前为止所做的:

我如何“压缩”图像:

UIImage *compressedProductImage;
NSData *NSproductImage;
NSUInteger productImageSize;

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info{
    self.productImage = info[UIImagePickerControllerOriginalImage];
    [self.productImageImageView setImage:self.productImage];
    [self dismissViewControllerAnimated:YES completion:nil];

    NSproductImage = UIImageJPEGRepresentation(self.productImage, 0.5f);
    productImageSize = [NSproductImage length];

    compressedProductImage = [UIImage imageWithData: NSproductImage];

我如何上传照片:

//Convert product UIImage
NSArray *productImagePaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *productImageFilePath = [[productImagePaths objectAtIndex:0] stringByAppendingPathComponent:[NSString stringWithFormat:@".png"]];
[UIImagePNGRepresentation(compressedProductImage) writeToFile:productImageFilePath atomically:YES];
NSURL *productImageFileUrl = [NSURL fileURLWithPath:productImageFilePath];

uploadRequest.body = productImageFileUrl;//Needs to be a NSURL
uploadRequest.bucket = AWS_BUCKET_NAME;
uploadRequest.key = productImageKey;
uploadRequest.contentType = @"image/png";
uploadRequest.ACL = AWSS3BucketCannedACLPublicRead;

[[transferManager upload:uploadRequest] continueWithExecutor:[AWSExecutor mainThreadExecutor] withBlock:^id(AWSTask *task) {
    if (task.error != nil) {
        NSLog(@"%s %@","Error uploading (product image):", uploadRequest.key);
    }else{
        NSLog(@"Product image upload completed");
    }
    return nil;
}];

2 个答案:

答案 0 :(得分:4)

正如rmaddy指出的那样,您正在拍摄所选图像,将其转换为JPEG,转换回UIImage(失去JPEG压缩的任何好处),然后将其转换为PNG,它提供适度的压缩,通常比用户照片库中的原始JPEG压缩得多。

您有几个选择。

  1. 您可以从照片库中的资源中检索原始imageData,如https://stackoverflow.com/a/32845656/1271826所示,从而避免通过UIImage进行往返。因此,您可以保留原始图像的质量,保留与此图像关联的元数据,并享受原始资产的适当压缩。

  2. 您可以将选中的图像作为UIImage并执行以下组合:

    • 在调用UIImageJPEGRepresentation之前缩小图片的尺寸(有关示例算法,请参阅https://stackoverflow.com/a/10491692/1271826);和/或

    • 使用质量低于1.0的UIImageJPEGRepresentation,其中数字越小,压缩越多,但图像质量损失越多。

答案 1 :(得分:3)

你实际上没有压缩任何东西。您从UIImage开始。这是一个完整的逐像素表示,通常采用宽度x高度x 4个字节。

然后将其转换为具有一些压缩的JPG。所以NSproductImage在图像的JPG版本的内存中的表示要小得多。这是您认为现在压缩的地方所假设的较小尺寸。

然后您将该JPG数据转换回UIImage作为compressedProductImage。这个新的UIImage仍然具有原始UIImage的相同宽度和高度。结果,它仍然采用与原始相同的宽度x高度×4字节。由于JPG压缩,它的质量低于原始质量。

现在您将更新的UIImage转换为PNG。由于PNG是无损的,因此它的压缩程度几乎与JPG尝试的压缩程度不同。然后,您将此更大的PNG版本的图像发送到亚马逊。

首先应删除首先转换为JPG的无意义代码,然后再移回UIImage

此时你应该使用PNG的大小,或者使用JPG,然后将较小的JPG发送给亚马逊。

另一个选择是在将图像发送到亚马逊之前缩放图像。