【问题标题】:How to compress images in iOS?如何在 iOS 中压缩图像?
【发布时间】:2016-12-19 18:40:35
【问题描述】:

我一直在查看每个堆栈溢出帖子和在线视频,但找不到可以正常工作的解决方案。现在,用户在上传到 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;
}];

【问题讨论】:

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


    【解决方案1】:

    正如 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,数字越小,压缩越多,但图像质量损失越大。

    【讨论】:

    • 因此在上传之前压缩图像看起来很复杂或根本不值得。我想我会处理更大的图像并在更好的缓存系统上工作,谢谢你有见地的回应!
    • 我不知道你说的太复杂是什么意思。当调用didFinishPickingMediaWithInfo 时,只需获取UIImagePickerControllerReferenceURL,从PHImageManager 获取原始资产,然后发送。超级简单。您将获得原始资产,它又好又小,没有图像质量或元数据丢失,并且您避免了所有复杂的 JPEG 转换和 PNG 转换。但对每个人来说都是他自己的。
    【解决方案2】:

    你实际上并没有压缩任何东西。您以UIImage 开头。这是一个完整的逐像素表示,通常占用(通常)宽 x 高 x 4 字节。

    然后您将其转换为经过一定压缩的 JPG。所以NSproductImage 在内存中是图像的 JPG 版本的一个小得多的表示。这是您认为现在压缩的地方所看到的假定较小的尺寸。

    但随后您将该 JPG 数据转换回 UIImagecompressedProductImage。这个新的UIImage 的宽度和高度仍与原来的UIImage 相同。结果,它仍然采用与原始相同的宽度 x 高度 x 4 字节。由于 JPG 压缩,它的质量比原版低。

    现在您将更新后的UIImage 转换为PNG。由于 PNG 是无损的,因此它的压缩率几乎没有 JPG 尝试的那么多。然后,您将这个较大的 PNG 版本的图像发送到亚马逊。

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

    此时,您应该接受 PNG 的大小,或者改用 JPG 并将较小的 JPG 发送到亚马逊。

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

    【讨论】:

    • 所以在上传之前压缩图像看起来很复杂或根本不值得。我想我会处理更大的图像并在更好的缓存系统上工作,谢谢你有见地的回应!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多