2016-08-12 77 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