iOS 圖片按比例壓縮,指定大小壓縮


使用系統方法UIImageJPEGRepresentation(UIimage *image,CGFloat quality)進行圖片質量壓縮,暫且叫參數quality為壓縮比吧,取值范圍為0~1。

此壓縮並非線性,當quality為0.99時,大致壓縮到原圖片大小的1/3以內,也就是說你無法通過此方法來把一個圖片壓縮到原大小的一半。

弄明白這這一點剩下的就好辦了,至於實現,根據自己的需去要DIY就行了~

首先聲明,以下方法無法實現對圖片大小的精確壓縮。

 

1 //以40K大小為例,誤差1K為例 
2   UIImage * image = [UIImage imageWithData:[self compressImageWithImage:image aimWidth:200 aimLength:40*1024 accuracyOfLength:1024]];

1、質量壓縮方法實現:

 1 /**
 2  *  壓縮圖片質量,返回值為可直接轉化成UIImage對象的NSData對象
 3  *  aimLength: 目標大小,單位:字節(b)
 4  *  accuracyOfLength: 壓縮控制誤差范圍(+ / -),本方法雖然給出了誤差范圍,但實際上很難確定一張圖片是否能壓縮到誤差范圍內,無法實現精確壓縮。
 5  */
 6 - (NSData *)compressImageWithImage:(UIImage *)image aimWidth:(CGFloat)width aimLength:(NSInteger)length accuracyOfLength:(NSInteger)accuracy{
 7     UIImage * newImage = [self imageWithImage:image scaledToSize:CGSizeMake(width, width * image.size.height / image.size.width)];
 8    
 9     NSData  * data = UIImageJPEGRepresentation(newImage, 1);
10     NSInteger imageDataLen = [data length];
11     
12     if (imageDataLen <= length + accuracy) {
13         return data;
14     }else{
15         NSData * imageData = UIImageJPEGRepresentation( newImage, 0.99);
16         if (imageData.length < length + accuracy) {
17             return imageData;
18         }
19         
20         CGFloat maxQuality = 1.0;
21         CGFloat minQuality = 0.0;
22         int flag = 0;
23         
24         while (1) {
25             CGFloat midQuality = (maxQuality + minQuality)/2;
26             
27             if (flag == 6) {
28                 NSLog(@"************* %ld ******** %f *************",UIImageJPEGRepresentation(newImage, minQuality).length,minQuality);
29                 return UIImageJPEGRepresentation(newImage, minQuality);
30             }
31             flag ++;
32             
33             NSData * imageData = UIImageJPEGRepresentation(newImage, midQuality);
34             NSInteger len = imageData.length;
35             
36             if (len > length+accuracy) {
37                 NSLog(@"-----%d------%f------%ld-----",flag,midQuality,len);
38                 maxQuality = midQuality;
39                 continue;
40             }else if (len < length-accuracy){
41                  NSLog(@"-----%d------%f------%ld-----",flag,midQuality,len);
42                 minQuality = midQuality;
43                 continue;
44             }else{
45                  NSLog(@"-----%d------%f------%ld--end",flag,midQuality,len);
46                 return imageData;
47                 break;
48             }
49         }
50     }
51 }
52 

 

2、壓縮尺寸,傳入帶壓縮圖片對象以及目標大小即可實現。

 1  //對圖片尺寸進行壓縮--
 2 -(UIImage*)imageWithImage:(UIImage*)image scaledToSize:(CGSize)newSize
 3 {
 4     UIGraphicsBeginImageContext(newSize);
 5     [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
 6     UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
 7     UIGraphicsEndImageContext();
 8     return newImage;
 9 }

 

update[2016-2-29]:

  今天安卓組的同事提了個bug,說壓縮到40K的圖片,下載到本地卻需要五六百K,拿到這個問題之后想了一下,壓縮到40K的數據沒有問題,上傳之后卻五六百K,在壓縮和上傳的過程中肯定出了什么問題,由於上傳操作是另一個同事做的,檢查了一下代碼才發現上傳的PNG格式的圖片,問題很可能就在這里了。

  因為壓縮過后把NSData使用imageWithData:轉成了UIImage對象,這一下就把40K左右的圖片轉成了一兩百K的UIImage對象,上傳之前需要把UIImage對象轉成NSData,他使用UIImagePNGRepresentation這個方法,於是data的大小又上升到五六百K。

  於是更改方法,把壓縮好的NSData對象直接用於上傳,上傳的圖片格式使用JPEG,通過瀏覽器打開圖片驗證之后問題得以解決。這也說明了一個問題,NSData的大小不等於UIImage的大小,而png格式的圖片比同質量同分辨率的jpg和jpeg格式圖片大了數倍。

  下面分享一下項目中用於從zip中讀取圖片和壓縮切割圖片的分類,實現從zip中直接讀取文件而不解壓zip的是第三方類庫ZipZap,需要的話可以通過pod search zipzap命令在Github上搜索,分類請點此下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM