2016-08-12 55 views
1

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

我要压缩的原始图像,就像我可以在上传之前。

这是我到目前为止有:

如何我 “压缩” 的形象:

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

回答

3

你不实际上并不压缩任何东西。你从UIImage开始。这是一个完整的逐像素表示法,通常采用width x height x 4字节。

然后,您将其转换为具有某种压缩的JPG格式。因此,NSproductImage在图像的JPG版本中是一个小得多的内存代表。这是你认为它现在被压缩的地方所看到的更小的尺寸。

但是当你转换的是JPG数据备份到一个UIImagecompressedProductImage。这个新的UIImage仍然具有相同的宽度和高度的原始UIImage。因此,它仍然采用与原始宽度相同的x高度x 4字节。由于JPG压缩,它的质量比原来低。

现在您将更新UIImage成PNG。由于PNG是无损的,它不会像JPG尝试那样压缩。然后,您将这个更大的PNG版本的图像发送给亚马逊。

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

此时您应该与PNG的大小居住或使用JPG,而不是发送较小的JPG亚马逊。

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

+0

所以它看起来像它无论是复杂或不值得在所有上传前将图像压缩。我想我会处理更大的图像,然后在更好的缓存系统上工作,谢谢你的深刻反应! –

3

正如rmaddy指出的那样,您将拍摄的图像转换为JPEG格式,转换回UIImage(失去JPEG压缩的任何好处),然后将其转换为PNG,该PNG提供适度的压缩,通常远小于用户照片库中原始JPEG的压缩率。

您有几种选择。

  1. 你可从资产原始imageData在你的照片库,如图https://stackoverflow.com/a/32845656/1271826,从而避免了往返它通过UIImage可言。因此,您可以保留原始图像的质量,保留与此图像关联的元数据,并享受原始资产的体面压缩。

  2. 你可以把摄取的图像作为UIImage和做的组合:

    • 减少图像的尺寸调用UIImageJPEGRepresentation之前(见https://stackoverflow.com/a/10491692/1271826样品算法);和/或

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

+0

因此,它看起来要么复杂或不值得它在上传之前压缩图像。我想我会处理更大的图像,然后在更好的缓存系统上工作,谢谢你的深刻反应! –

+0

我不确定你的意思是太复杂。当调用didFinishPickingMediaWithInfo时,只需抓住'UIImagePickerControllerReferenceURL',从PHImageManager获取原始资源,然后发送它。这非常简单。您可以获得原始资产,它很好,很小,没有图像质量或元数据丢失,并且可以避免将所有复杂的转换转换为JPEG以及转换为PNG。但每一个他自己。 – Rob