本文始發(fā)于我的博文App圖片壓縮裁剪原理和上傳方案侦啸,以及那些有趣的事兒...,現(xiàn)轉(zhuǎn)發(fā)至此丧枪。
目錄
- App怎么壓縮質(zhì)量光涂?
- iOS和Android壓縮接口
- 實驗一
- 如何計算圖片的大小拧烦?
- JPEG&JFIF壓縮做了什么忘闻?
- 色彩空間轉(zhuǎn)換
- 縮減取樣
- 離散余弦變換
- 量化
- 編碼
- App怎么裁剪分辨率?
- 圖片壓縮裁剪上傳方案
- 實驗一:上傳速度
- 實驗二:用戶設(shè)備主要分辨率
- 實驗三:上傳的照片的主要分辨率
- 實驗四:壓縮質(zhì)量的大致規(guī)律
- 實驗五:等比例裁剪后壓縮質(zhì)量的大致規(guī)律
- 實驗六:WebP壓縮
- 制定方案
- 總結(jié)
- 附錄
- 圖像的一些概念澄清
- 壓縮算法概念
- 微信圖片處理規(guī)律
- Base64編碼后大小
- iOS的pt與Android的sp
- Android圖片質(zhì)量會比iPhone的差恋博?
- iOS的UIImage保存圖片問題
- 壓縮再壓縮做了什么
最近有反饋說App上傳圖片偶爾會失敗齐佳,特別是在網(wǎng)速慢和iPhone 6s的機器上。有些提示是“413 Request Entity Too Large”债沮,Request大小1.15MB炼吴。之前只是簡單地壓到0.7,沒有做裁剪等其他處理疫衩。
所以這幾天整體研究下iOS和Android的圖片壓縮裁剪和JPEG壓縮原理缺厉,也稍微找了微信發(fā)圖片的規(guī)律,越深入發(fā)現(xiàn)越多有趣的東西隧土,問題一環(huán)扣一環(huán)。
App怎么壓縮質(zhì)量命爬?
最先接觸的是壓縮質(zhì)量曹傀,所以看下壓縮質(zhì)量做了什么。
iOS和Android壓縮接口
iOS:
UIImageJPEGRepresentation(UIImage * __nonnull image, CGFloat compressionQuality);
// return image as JPEG. May return nil if image has no CGImageRef or invalid bitmap format. compression is 0(most)..1(least)
Android:
/**
* Write a compressed version of the bitmap to the specified outputstream.
* If this returns true, the bitmap can be reconstructed by passing a
* corresponding inputstream to BitmapFactory.decodeStream(). Note: not
* all Formats support all bitmap configs directly, so it is possible that
* the returned bitmap from BitmapFactory could be in a different bitdepth,
* and/or may have lost per-pixel alpha (e.g. JPEG only supports opaque
* pixels).
*
* @param format The format of the compressed image
* @param quality Hint to the compressor, 0-100. 0 meaning compress for
* small size, 100 meaning compress for max quality. Some
* formats, like PNG which is lossless, will ignore the
* quality setting
* @param stream The outputstream to write the compressed data.
* @return true if successfully compressed to the specified stream.
*/
compress(CompressFormat format, int quality, OutputStream stream)
從官方注釋看饲宛,iOS的compressionQuality取值從0-1皆愉,且“1”注明是least,也就是說“1”不是不壓縮艇抠,而是壓縮強度最弱幕庐;Android的quality取值0-100,也是100代表最大質(zhì)量家淤,不是不壓縮异剥。最后面測試也驗證了這個問題,而不是網(wǎng)上很多文檔說的不壓縮絮重。我們先統(tǒng)稱compressionQuality和quality為質(zhì)量系數(shù)冤寿,下文也是歹苦。
實驗一
于是拍了一張照片A,然后Android和iOS都壓縮得到照片B督怜。
對比了A殴瘦、B兩張圖,想看看到底影響了什么:
寬度:2448像素
高度:3264像素
分辨率:72像素/英寸
文檔:22.9MB
通道:3(RGB)
注:需弄明白附錄的關(guān)于圖像的一些概念澄清号杠。
兩張照片看到的參數(shù)都一樣蚪腋,那為什么它們的文件大小會不一樣呢?(過程中發(fā)現(xiàn)iOS的UIImage會做多一些工作姨蟋,使得實驗結(jié)果有誤屉凯,原因后面會提到。)(用Picasa看圖軟件可以查看質(zhì)量芬探,數(shù)值上看到等于我們的質(zhì)量系數(shù))所以就想到第二個問題神得,文件大小怎么計算的?由什么決定偷仿?
如何計算圖片的大辛ú尽?
總分辨率 * 像素表示的位數(shù)酝静。
像素表示的位數(shù):這就涉及到色彩模式节榜,比較常見有RGB、CMYK别智、YUV等宗苍。RGB一般用RGB24(還有RGB555、RGB565薄榛、RGB32)讳窟,即紅綠藍都分別用8位表示,所以用了24位表示一個像素敞恋,可以組合出2^24種顏色丽啡。
上面兩張圖水平有2448個像素,垂直有3264個像素硬猫,每個像素用24b表示补箍,按這公式大小應(yīng)該都是:2448x3264x24b=23970816B=22.86MB。為什么呢啸蜜?
后來明白坑雅,原來這公式是算位圖的占用空間大小,而JPEG&JFIF是將位圖壓縮衬横,不僅壓縮圖像質(zhì)量還壓縮圖像占用空間(后面會講到)裹粤。也就是說圖像壓縮不等于壓縮質(zhì)量和分辨率,還有壓縮占用空間蜂林。
網(wǎng)上查到JFIF文件沒有計算大小的公式蛹尝,因為壓縮質(zhì)量和壓縮后大小沒有特定關(guān)系后豫,如線性關(guān)系。那么JPEG&JFIF壓縮做了什么突那?這個質(zhì)量到底代表了什么挫酿?
JPEG&JFIF壓縮做了什么?
其實JPEG&JFIF做了兩件事情:
- 去掉視覺上的冗余信息
- 去掉數(shù)據(jù)本身結(jié)構(gòu)的冗余
第一步實現(xiàn)通過色彩空間轉(zhuǎn)換愕难、縮減取樣早龟、離散余弦變換、量化猫缭,第二步實現(xiàn)通過編碼葱弟。
其實這部分可以選擇跳過,只是我為了理解壓縮質(zhì)量是怎么體現(xiàn)的而去看的猜丹,后面也發(fā)現(xiàn)理解后很多問題都很清晰明白芝加。
色彩空間轉(zhuǎn)換
JPEG需要YUV色彩模式,所以需要將RGB轉(zhuǎn)成YUV:
- Y=0.299R'+0.587G'+0.114B'
- U=-0.147R'-0.289G'+0.436B'
- V=0.615R'-0.515G'-0.100B'
縮減取樣
YUV分別代表亮度射窒、色度藏杖、飽和度,因為人類的眼睛對于亮度差異的敏感度高于色彩變化脉顿,所以一般會對U蝌麸、V進行縮減采樣。在JPEG上這種縮減取樣的比例可以是4:4:4(無縮減取樣)艾疟、4:2:2来吩、4:2:0。所以經(jīng)常會看到Y(jié)UV444蔽莱,YUV422和YUV420等弟疆。
離散余弦變換
將每個8x8的子區(qū)域轉(zhuǎn)換到頻率空間,這部分是無損的盗冷。
-415 -30 -61 27 56 -20 -2 0
4 -22 -61 10 13 -7 -9 5
-47 7 77 -25 -29 10 5 -6
-49 12 34 -15 -10 6 2 2
12 -7 -13 -4 -2 2 -3 3
-8 3 2 -6 -2 1 4 2
-1 0 0 -2 -1 -3 4 -1
0 0 -1 -4 -1 0 1 2
量化
量化是有損的過程兽间,也是失真的主要原因。上面矩陣中每個值都是幅度正塌,量化是利用人眼特點在高頻率上降低信息的數(shù)量(簡單地把頻率領(lǐng)域上每個成分,除以一個對于該成分的常數(shù)就可完成恤溶,且接著舍位取最接近的整數(shù))乓诽,與一個基本矩陣運算然后得到一個新的矩陣,該新矩陣數(shù)據(jù)基本集中在左上角咒程。
其實量化做的就是減少非0系數(shù)幅度和增加0值系數(shù)的個數(shù)。
我們接口中的質(zhì)量系數(shù)就是和這里的基本矩陣有關(guān)。
編碼
Z掃描0值行程長度編碼牺蹄、哈夫曼編碼。
Z掃描0值行程長度編碼利用了量化后矩陣的特點奶段,使得0值的都能串在最后面,對于過早結(jié)束的最后用EOB表示剥纷。
這一步就是壓縮文件的占用空間痹籍。
App怎么裁剪分辨率?
弄清楚壓縮質(zhì)量問題后晦鞋,我們知道蹲缠,影響位圖的大小有分辨率,那么減少分辨率也就能使壓縮得更小了悠垛。注意這里裁剪分辨率不等于裁剪圖片线定,不會丟失圖片的某一部分。
iOS:
UIGraphicsBeginImageContext(newSize);
[imageFixed drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Android:
Bitmap image = BitmapFactory.decodeStream(file);
int bitmapWidth = image.getWidth();
int bitmapHeight = image.getHeight();
Matrix matrix = new Matrix();
matrix.postScale(scaleRatio, scaleRatio);
Bitmap scaledBitmap = Bitmap.createBitmap(image, 0, 0, bitmapWidth, bitmapHeight, matrix, false);
我們是等比例裁剪确买,比例和裁剪后占用空間大小并不一定成線性關(guān)系斤讥,這個裁剪具體怎么實現(xiàn)的和每個像素的質(zhì)量有關(guān)系。
圖片壓縮裁剪上傳方案
明白一個圖片的清晰度等受什么影響之后湾趾,可以來定下方案了芭商,但是還得做些測試獲取數(shù)據(jù),依據(jù)數(shù)據(jù)結(jié)果來定方案撑帖。
實驗一:上傳速度
我們用Charles模擬了各種網(wǎng)絡(luò)環(huán)境下上傳相同照片的網(wǎng)速:
| 環(huán)境 | wifi | 8M | 16M | 32M |
| :----: | :----: | :---: | :----: |
| 速度KB/s | 754.78 | 115.4 | 115.78 | 116.25 |
| 環(huán)境 | 32M光纖 | 100M光纖 | 3G | 4G |
| :----: | :----: | :---: | :----: |
| 速度KB/s | 174.65 | 167.33 | 114.18 | 174.73 |
這些不等價于我們用戶的網(wǎng)速平均值蓉坎,而且只取一次樣本,所以只是作為參考胡嘿。
實驗二:用戶設(shè)備主要分辨率
因為照片都是在用戶設(shè)備上看的蛉艾,所以了解下用戶的主流分辨率,將分辨率裁剪到趨近或稍大于該主流分辨率會比較適合衷敌。iOS和Android都取接近的值勿侯。
在友盟查看了我們的應(yīng)用的相關(guān)數(shù)據(jù):
- Android,較大占比的是寬度1080像素和720像素的設(shè)備缴罗。寬度1080像素的助琐,新增用戶占比49.69%,啟動次數(shù)占比44.29%面氓;寬度720像素的兵钮,新增用戶占比32.47%,啟動次數(shù)占比37.76%舌界。
- iOS掘譬,較大占比的是寬度1242像素、750像素和640像素的設(shè)備呻拌。寬度1242像素的葱轩,新增用戶占比31.84%,啟動次數(shù)占比26.91%;寬度750像素的靴拱,新增用戶占比36.20%垃喊,啟動次數(shù)占比31.59%;寬度640像素的袜炕,新增用戶占比20.36%本谜,啟動次數(shù)占比20.84%。
實驗三:上傳的照片的主要分辨率
找下上傳的照片的主要分辨率妇蛀,可以針對這些分辨率去確定和衡量方案耕突。
也是在友盟上看我們的應(yīng)用的數(shù)據(jù):
- iOS主流機型是iPhone6、iPhone6s评架、iPhone6 Plus眷茁、iPhone6s Plus,占到70%左右纵诞。它們的拍照分辨率分別是2448x3264上祈,3024x4032。
- Android相對較碎片化浙芙,只能是針對最大的分辨率去衡量登刺。
實驗四:壓縮質(zhì)量的大致規(guī)律
2448x3264照片壓縮后的數(shù)據(jù)大小(單位B):
壓縮強度 | 圖片1 | 圖片2 | 圖片3 | 圖片4 |
---|---|---|---|---|
0.1 | 197777 | 174464 | 152897 | 195214 |
0.2 | 212779 | 183532 | 163225 | 209426 |
0.3 | 253658 | 205512 | 196188 | 248320 |
0.4 | 360091 | 256013 | 283607 | 349968 |
0.5 | 498199 | 336823 | 390525 | 485286 |
0.6 | 724491 | 488737 | 548437 | 698421 |
0.7 | 1209508 | 883664 | 936968 | 1161342 |
0.8 | 1475669 | 1063724 | 1130241 | 1415084 |
0.9 | 1700461 | 1247600 | 1334143 | 1636293 |
1.0 | 4568157 | 3629379 | 4139209 | 4433556 |
原圖占用 | 1714688 | 1257647 | 1353635 | 1647936 |
3024x4032照片壓縮后的數(shù)據(jù)大形撕簟(單位B):
壓縮強度 | 圖片5 | 圖片6 | 圖片7 | 圖片8 |
---|---|---|---|---|
0.1 | 551527 | 325434 | 296792 | 492494 |
0.2 | 619307 | 352608 | 328183 | 547533 |
0.3 | 785915 | 422342 | 416459 | 683265 |
0.4 | 1061504 | 537826 | 589206 | 931686 |
0.5 | 1408297 | 891288 | 839938 | 1290788 |
0.6 | 2071014 | 973894 | 1108102 | 1607344 |
0.7 | 2547536 | 1228021 | 1756824 | 2479774 |
0.8 | 2652258 | 1320258 | 1831889 | 2617015 |
0.9 | 3336839 | 1603754 | 2212214 | 3079872 |
1.0 | 7282230 | 4337074 | 5787540 | 7962849 |
原圖占用 | 2635183 | 1511290 | 1860418 | 2641699 |
- 會出現(xiàn)壓縮出來反而比原圖大的問題纸俭,后面會討論
- 在沒有裁剪的情況下,壓到0.6依舊不是太理想南窗,特別是分辨率更高的照片揍很。
- 在excel表格中將數(shù)據(jù)組成折線圖,可以看出在0.9万伤、0.8的時候下降幅度較大窒悔,后面相對平緩一點。
實驗五:等比例裁剪后壓縮質(zhì)量的大致規(guī)律
2448x3264照片等比例壓縮到寬度1224像素時的數(shù)據(jù)大械新颉(單位B):
壓縮強度 | 圖片1 | 圖片2 | 圖片3 | 圖片4 |
---|---|---|---|---|
0.1 | 58975 | 52025 | 43301 | 60029 |
0.2 | 64446 | 55583 | 46529 | 65347 |
0.3 | 76982 | 63805 | 55494 | 77891 |
0.4 | 99499 | 77605 | 76695 | 100042 |
0.5 | 129826 | 95116 | 103949 | 129597 |
0.6 | 173036 | 120654 | 144188 | 173569 |
0.7 | 246847 | 174977 | 209876 | 249223 |
0.8 | 303546 | 208392 | 261322 | 308841 |
0.9 | 411181 | 294795 | 358003 | 420013 |
1.0 | 1574657 | 1280563 | 1536779 | 1566585 |
原圖占用 | 1714688 | 1257647 | 1353635 | 1647936 |
3024x4032照片等比例壓縮到寬度1224像素時的數(shù)據(jù)大屑蛑椤(單位B):
壓縮強度 | 圖片5 | 圖片6 | 圖片7 | 圖片8 |
---|---|---|---|---|
0.1 | 111697 | 70802 | 54321 | 121994 |
0.2 | 127179 | 77524 | 61810 | 136869 |
0.3 | 163959 | 94048 | 79713 | 172194 |
0.4 | 225870 | 122258 | 113295 | 230197 |
0.5 | 302097 | 157160 | 155152 | 300772 |
0.6 | 395440 | 202312 | 210836 | 385183 |
0.7 | 524345 | 273895 | 295530 | 505417 |
0.8 | 623839 | 323884 | 363596 | 593923 |
0.9 | 777293 | 420943 | 481205 | 745946 |
1.0 | 2184791 | 1530139 | 1774130 | 2291622 |
原圖占用 | 2635183 | 1511290 | 1860418 | 2641699 |
- 可以看到裁剪這個分辨率后壓縮質(zhì)量0.6的大小相對可接受,而且圖片質(zhì)量影響也較小虹钮。
- 在這個分辨率下聋庵,壓縮質(zhì)量0.8時基本壓縮到1/4至1/5。
實驗六:WebP壓縮
WebP據(jù)稱在同等質(zhì)量下大小可以壓縮至JPEG的2/3芙粱。在iOS和Android都做了WebP的壓縮測試祭玉,發(fā)現(xiàn)壓縮速度非常慢,需要20s-35s宅倒,這是很不可接受的。上網(wǎng)查到WebP的壓縮效率的確較慢,是JPEG的8倍左右拐迁,而且相比JPEG需要耗費更多的系統(tǒng)性能蹭劈。所以本來想用WebP做兜底的方案暫時落空。
制定方案
方案的目的是:
- 上傳圖片不超時
- 處理后質(zhì)量清晰度可接受
- 縮短上傳耗時
結(jié)合實驗結(jié)論:
- 根據(jù)實驗一线召,平均上傳速度100KB/s铺韧,另外我們測試很差情況下有15KB/s的情況。我們的接口超時30s缓淹,所以可接受的圖片大小最大為450KB哈打。
- 根據(jù)實驗二,等比例寬度取750-1242像素比較合適讯壶。
- 根據(jù)實驗三料仗、四、五伏蚊,等比例裁剪到寬度1224像素后壓縮至0.6立轧、0.7大小相對可接受。質(zhì)量相對可接受(主觀感受)躏吊。
- JPG氛改、PNG和GIF圖片的基本原理及優(yōu)化方法講到,通常建議JPG質(zhì)量最好是在60左右的原因比伏。當(dāng)在Photoshop中把質(zhì)量設(shè)置低于51的時候胜卤,它就會執(zhí)行另一個叫做“降色采樣”的優(yōu)化算法,它會在8個像素周圍平均采樣赁项,這樣會在邊緣產(chǎn)生雜色葛躏。
定下方案:
- 照片寬度大于1224像素(因為iPhone6照片寬度2448所以想取個可以整除的)時等比例裁剪寬度成1224。因為分辨率太大甚至兩倍于手機分辨率實際沒有任何用處肤舞。
- 壓縮質(zhì)量系數(shù)至0.8(80)看下大小是否小于300KB紫新,排除一些小分辨率的照片。小于則上傳李剖,大于則繼續(xù)壓縮芒率,取0.7(70),排除一些中等的篙顺,如果還大于則取0.6(60)后不判斷直接上傳偶芍。根據(jù)上面的實驗可以看到在寬度1224像素下基本都會小于300KB,大于的則處于450KB內(nèi)德玫,且450KB是網(wǎng)速最差的情況匪蟀,因此基本可以保證上傳。
總結(jié)
方案目前看壓縮的質(zhì)量和時間控制都相對較好宰僧,但是還要繼續(xù)觀察一段時間看需不需要再調(diào)整參數(shù)材彪。在這過程中理清了很多概念,了解了圖片壓縮過程中發(fā)生了什么事情,挺有趣的段化,根本停不下來嘁捷。
附錄
文中涉及到的一些概念以及發(fā)現(xiàn)的一些其他相關(guān)事情。
圖像的一些概念澄清
其實圖像真正的信息是它的總分辨率(圖像寬度x圖像高度)和分辨率(水平分辨率&垂直分辨率)显熏,而涉及到英寸雄嚣、厘米等長度單位時的大小,其實不是圖像的信息喘蟆,只是在涉及到外部缓升,比如打印、設(shè)備屏幕顯示等等時蕴轨,換算出來的港谊。
- 水平分辨率&垂直分辨率
分辨率一般單位ppi(也有dpi),即每英寸上多少個像素尺棋。水平分辨率即水平方向上像素個數(shù)/水平長度封锉,垂直分辨率同理。一般水平分辨率和垂直分辨率是相等的膘螟,所以日常也簡稱為分辨率成福。dpi即每英寸上多少點。這兩個單位根據(jù)不同顯示設(shè)備有換算關(guān)系荆残。
- 圖像寬度&圖像高度
其實標(biāo)準(zhǔn)些奴艾,講寬度&高度時一般是講圖像水平/垂直上有多少個像素。如一張2448x3264的照片内斯,則寬度是2448像素蕴潦,高度是3264像素。也有講寬度是86.36厘米俘闯,高度是115.15厘米潭苞,一般在打印照片等情況下。
- 分辨率
日常講分辨率時其實可以指很多情況真朗,一般指圖像寬度x高度此疹,如2448x3264,指水平上有2448個像素遮婶,垂直上有3264個像素蝗碎。
壓縮算法概念
- JPEG
一個名稱為Joint Photographic Experts Group的組織,也是一種壓縮算法旗扑。JPEG本身只有描述如何將一個視頻轉(zhuǎn)換為字節(jié)的數(shù)據(jù)流(streaming)蹦骑,但并沒有說明這些字節(jié)如何在任何特定的存儲媒體上被封存起來。JPEG有有損壓縮和無損壓縮臀防,無損壓縮的沒有得到什么支持眠菇,所以一般講JPEG指它的有損壓縮边败。
- JFIF
JPEG File Interchange Format,JPEG文件交換格式捎废,詳細(xì)說明如何從一個JPEG流放闺,產(chǎn)出一個適合于電腦存儲和傳輸?shù)奈募?/strong>。一般后綴有.jpeg缕坎、.jpg、.jfif以及.jif篡悟。
- Bitmap
又稱柵格圖谜叹,是使用像素陣列來表示的圖像。非壓縮格式搬葬,從左往右從上往下掃描荷腊,占用較大存儲空間。
https://zh.wikipedia.org/wiki/JPEG
https://zh.wikipedia.org/wiki/%E4%BD%8D%E5%9B%BE
微信圖片處理規(guī)律
經(jīng)過簡單測試發(fā)現(xiàn)急凰,在微信女仰,A發(fā)一張原圖給B時,B直接保存縮略圖:
- iOS版的微信保存下來是等比例壓縮高度為800抡锈,質(zhì)量80疾忍。
- Android版的微信保存下來是等比例壓縮高度為1280,質(zhì)量80床三。
朋友圈的圖片保存下來一罩,都是等比例到高1280像素,質(zhì)量和大小還沒找到規(guī)律撇簿。
為什么微信是取高固定而不是寬呢聂渊?可以思考下。
Base64編碼后大小
我們現(xiàn)在還用著Base64編碼圖像數(shù)據(jù)四瘫,后面需改成提交表單方式汉嗽。
Base64要求把每三個8Bit的字節(jié)轉(zhuǎn)換為四個6Bit的字節(jié)(38 = 46 = 24),然后把6Bit再添兩位高位0找蜜,組成四個8Bit的字節(jié)饼暑,也就是說,轉(zhuǎn)換后的字符串理論上將要比原來的長1/3锹杈。
iOS的pt與Android的sp
我在iOS所有設(shè)備的分辨率撵孤、尺寸和縮放因子,放大模式區(qū)別和6P實際分辨率文章里講了iOS設(shè)備的pt和px關(guān)系竭望。
iOS的pt是開發(fā)單位邪码,一個邏輯point對應(yīng)一個點dot。@1x設(shè)備上一個pt上顯示1個px(像素)咬清,@2x上一個pt顯示2個px闭专,@3x上顯示3個px奴潘。平時在storyboard上設(shè)置時指的都是pt。
Android的sp一種基于屏幕密度的抽象單位影钉。
Android圖片質(zhì)量會比iPhone的差画髓?
在為什么Android的圖片質(zhì)量會比iPhone的差?平委、[Android算法] 【04/28 bug修改】android圖片壓縮終極解決方案奈虾、Android圖片編碼機制深度解析(Bitmap,Skia廉赔,libJpeg)三篇文章中講了Android系統(tǒng)在壓縮上的一些不為人知的問題肉微。
大致是,Android編碼保存圖片就是通過Java層函數(shù)——Native層函數(shù)——Skia庫函數(shù)——對應(yīng)第三方庫函數(shù)(例如libjpeg)蜡塌,這一層層調(diào)用做到的碉纳。 libjpeg在壓縮圖像時,有一個參數(shù)叫optimize_coding馏艾,如果設(shè)置optimize_coding為TRUE劳曹,將會使得壓縮圖像過程中基于圖像數(shù)據(jù)計算哈弗曼表,由于這個計算會顯著消耗空間和時間琅摩,默認(rèn)值被設(shè)置為FALSE铁孵。對于當(dāng)時的計算設(shè)備來說,空間和時間的消耗可能是顯著的房资,但到今天库菲,這似乎不應(yīng)再是問題。但谷歌的Skia項目工程師們對optimize_coding在Skia中默認(rèn)的等于了FALSE志膀,這就意味著更差的圖片質(zhì)量和更大的圖片文件熙宇。還有其他和iOS的比較可以看下。
也講到了Android可以替換libjpeg庫達到設(shè)置為TRUE的目的溉浙。
iOS的UIImage保存圖片問題
起初發(fā)現(xiàn)壓縮后保存圖片烫止,不同壓縮質(zhì)量系數(shù),得出來的文件大小趨勢和計算出的大小趨勢不同戳稽,所以懷疑使用NSData初始化UIImage時多做了什么馆蠕。
NSData *imageData06 = UIImageJPEGRepresentation(scaledImage, 0.6);
UIImage *image06 = [UIImage imageWithData:imageData06];
UIImageWriteToSavedPhotosAlbum(image06, nil, nil, nil);
通過軟件發(fā)現(xiàn),不同壓縮質(zhì)量系數(shù)惊奇,得出來的NSData保存成UIImage圖片互躬,看到的質(zhì)量都是92,按道理應(yīng)該是對應(yīng)的質(zhì)量系數(shù)才對颂郎。于是想將NSData保存成文件到目錄吼渡,讀取出文件大小。
NSString *documents = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *filePath = [documents stringByAppendingPathComponent:@"image.jpg"];
NSData *imageData = UIImageJPEGRepresentation(image, 0.7);
NSError *error = nil;
[imageData writeToFile:filePath options:NSDataWritingAtomic error:&error];
if (error != nil) {
NSLog(@"error = %@", error);
}else {
NSLog(@"success");
}
NSLog(@"imageData = %u", (unsigned)imageData.length);
NSFileManager* manager = [NSFileManager defaultManager];
if ([manager fileExistsAtPath:filePath]){
unsigned long long size = [[manager attributesOfItemAtPath:filePath error:nil] fileSize];
NSLog(@"0.7后文件大小 %llu", size);
}
UIImage *imageFromData = [UIImage imageWithData:imageData];
UIImageWriteToSavedPhotosAlbum(imageFromData, nil, nil, nil);
UIImage *imageRead = [[UIImage alloc] initWithContentsOfFile:filePath];
UIImageWriteToSavedPhotosAlbum(imageRead, nil, nil, nil);
讀取文件大小size和NSData大小imageData.length打印一致乓序,而與imageRead寺酪、imageFromData的大小不一樣坎背,因此可以證明UIImage這個對象本身還做了其他事情。
在AFNetworking2.0源碼解析這篇文章的截圖顯示寄雀,UIImage的imageWithData方法堆棧顯示還調(diào)用了哈夫曼解碼得滤。
壓縮再壓縮做了什么
- 首先談下看圖軟件怎么展示圖片。打開.jpg圖片時盒犹,看圖軟件將文件轉(zhuǎn)換成位圖才顯示出來懂更,即把量化表矩陣與基本轉(zhuǎn)化矩陣運算得出圖片當(dāng)前的位圖(因為經(jīng)過了壓縮,所以該位圖與原位圖不同)急膀。
- 壓縮后再壓縮也是膜蛔,先將圖片變回位圖,再將位圖按現(xiàn)在的壓縮質(zhì)量系數(shù)壓縮脖阵。
- 所以壓縮后的圖片有可能變大,我猜測原因是墅茉,壓縮前的占用空間壓縮率較大命黔,而再壓縮時選的質(zhì)量系數(shù)較大,導(dǎo)致壓縮占用空間率(即壓縮的第二步)較小就斤,所以導(dǎo)致質(zhì)量其實是變差了悍募,但是占用空間反而可能變大。
變大的例子如:本來圖片A大小500KB洋机,壓縮質(zhì)量系數(shù)選擇0.7坠宴,得到B圖片90KB,再拿這張B圖片去壓绷旗,壓縮質(zhì)量系數(shù)1.0喜鼓,得出C圖片。前面我們說壓縮不僅壓縮質(zhì)量衔肢,還壓縮占用空間庄岖。如果第一次壓縮的壓縮質(zhì)量比例跟第二次壓縮的比例的差值,比第一次壓縮的壓縮占用空間比例跟第二次的壓縮占用空間比例的差值小角骤,那么C圖片就會比B圖片大隅忿。因為雖然C圖片質(zhì)量比B圖片質(zhì)量差點,但是B圖片的空間壓縮得比C圖片大比較多邦尊。
-END-
歡迎到我的博客交流:http://zackzheng.info