App圖片壓縮裁剪原理和上傳方案,以及那些有趣的事兒...

本文始發(fā)于我的博文App圖片壓縮裁剪原理和上傳方案,以及那些有趣的事兒...,現(xiàn)轉(zhuǎn)發(fā)至此。

目錄

  • App怎么壓縮質(zhì)量?
    • iOS和Android壓縮接口
    • 實(shí)驗(yàn)一
  • 如何計(jì)算圖片的大小?
  • JPEG&JFIF壓縮做了什么?
    • 色彩空間轉(zhuǎn)換
    • 縮減取樣
    • 離散余弦變換
    • 量化
    • 編碼
  • App怎么裁剪分辨率?
  • 圖片壓縮裁剪上傳方案
    • 實(shí)驗(yàn)一:上傳速度
    • 實(shí)驗(yàn)二:用戶設(shè)備主要分辨率
    • 實(shí)驗(yàn)三:上傳的照片的主要分辨率
    • 實(shí)驗(yàn)四:壓縮質(zhì)量的大致規(guī)律
    • 實(shí)驗(yàn)五:等比例裁剪后壓縮質(zhì)量的大致規(guī)律
    • 實(shí)驗(yàn)六:WebP壓縮
    • 制定方案
  • 總結(jié)
  • 附錄
    • 圖像的一些概念澄清
    • 壓縮算法概念
    • 微信圖片處理規(guī)律
    • Base64編碼后大小
    • iOS的pt與Android的sp
    • Android圖片質(zhì)量會(huì)比iPhone的差?
    • iOS的UIImage保存圖片問題
    • 壓縮再壓縮做了什么

最近有反饋說App上傳圖片偶爾會(huì)失敗,特別是在網(wǎng)速慢和iPhone 6s的機(jī)器上。有些提示是“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”不是不壓縮,而是壓縮強(qiáng)度最弱;Android的quality取值0-100,也是100代表最大質(zhì)量,不是不壓縮。最后面測(cè)試也驗(yàn)證了這個(gè)問題,而不是網(wǎng)上很多文檔說的不壓縮。我們先統(tǒng)稱compressionQuality和quality為質(zhì)量系數(shù),下文也是。

實(shí)驗(yàn)一

于是拍了一張照片A,然后Android和iOS都?jí)嚎s得到照片B。

對(duì)比了A、B兩張圖,想看看到底影響了什么:

寬度:2448像素
高度:3264像素
分辨率:72像素/英寸
文檔:22.9MB
通道:3(RGB)

注:需弄明白附錄的關(guān)于圖像的一些概念澄清

兩張照片看到的參數(shù)都一樣,那為什么它們的文件大小會(huì)不一樣呢?(過程中發(fā)現(xiàn)iOS的UIImage會(huì)做多一些工作,使得實(shí)驗(yàn)結(jié)果有誤,原因后面會(huì)提到。)(用Picasa看圖軟件可以查看質(zhì)量,數(shù)值上看到等于我們的質(zhì)量系數(shù))所以就想到第二個(gè)問題,文件大小怎么計(jì)算的?由什么決定?

如何計(jì)算圖片的大小?

總分辨率 * 像素表示的位數(shù)。

像素表示的位數(shù):這就涉及到色彩模式,比較常見有RGB、CMYK、YUV等。RGB一般用RGB24(還有RGB555、RGB565、RGB32),即紅綠藍(lán)都分別用8位表示,所以用了24位表示一個(gè)像素,可以組合出2^24種顏色。

上面兩張圖水平有2448個(gè)像素,垂直有3264個(gè)像素,每個(gè)像素用24b表示,按這公式大小應(yīng)該都是:2448x3264x24b=23970816B=22.86MB。為什么呢?

后來明白,原來這公式是算位圖的占用空間大小,而JPEG&JFIF是將位圖壓縮,不僅壓縮圖像質(zhì)量還壓縮圖像占用空間(后面會(huì)講到)。也就是說圖像壓縮不等于壓縮質(zhì)量和分辨率,還有壓縮占用空間

網(wǎng)上查到JFIF文件沒有計(jì)算大小的公式,因?yàn)閴嚎s質(zhì)量和壓縮后大小沒有特定關(guān)系,如線性關(guān)系。那么JPEG&JFIF壓縮做了什么?這個(gè)質(zhì)量到底代表了什么?

JPEG&JFIF壓縮做了什么?

其實(shí)JPEG&JFIF做了兩件事情:

  1. 去掉視覺上的冗余信息
  2. 去掉數(shù)據(jù)本身結(jié)構(gòu)的冗余

第一步實(shí)現(xiàn)通過色彩空間轉(zhuǎn)換、縮減取樣、離散余弦變換、量化,第二步實(shí)現(xiàn)通過編碼。

其實(shí)這部分可以選擇跳過,只是我為了理解壓縮質(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分別代表亮度、色度、飽和度,因?yàn)槿祟惖难劬?duì)于亮度差異的敏感度高于色彩變化,所以一般會(huì)對(duì)U、V進(jìn)行縮減采樣。在JPEG上這種縮減取樣的比例可以是4:4:4(無縮減取樣)、4:2:2、4:2:0。所以經(jīng)常會(huì)看到Y(jié)UV444,YUV422和YUV420等。

離散余弦變換

將每個(gè)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

量化

量化是有損的過程,也是失真的主要原因。上面矩陣中每個(gè)值都是幅度,量化是利用人眼特點(diǎn)在高頻率上降低信息的數(shù)量(簡單地把頻率領(lǐng)域上每個(gè)成分,除以一個(gè)對(duì)于該成分的常數(shù)就可完成,且接著舍位取最接近的整數(shù)),與一個(gè)基本矩陣運(yùn)算然后得到一個(gè)新的矩陣,該新矩陣數(shù)據(jù)基本集中在左上角

其實(shí)量化做的就是減少非0系數(shù)幅度和增加0值系數(shù)的個(gè)數(shù)
我們接口中的質(zhì)量系數(shù)就是和這里的基本矩陣有關(guān)。

編碼

Z掃描0值行程長度編碼、哈夫曼編碼。
Z掃描0值行程長度編碼利用了量化后矩陣的特點(diǎn),使得0值的都能串在最后面,對(duì)于過早結(jié)束的最后用EOB表示。
這一步就是壓縮文件的占用空間

App怎么裁剪分辨率?

弄清楚壓縮質(zhì)量問題后,我們知道,影響位圖的大小有分辨率,那么減少分辨率也就能使壓縮得更小了。注意這里裁剪分辨率不等于裁剪圖片,不會(huì)丟失圖片的某一部分。

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)系,這個(gè)裁剪具體怎么實(shí)現(xiàn)的和每個(gè)像素的質(zhì)量有關(guān)系。

圖片壓縮裁剪上傳方案

明白一個(gè)圖片的清晰度等受什么影響之后,可以來定下方案了,但是還得做些測(cè)試獲取數(shù)據(jù),依據(jù)數(shù)據(jù)結(jié)果來定方案。

實(shí)驗(yàn)一:上傳速度

我們用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 |

這些不等價(jià)于我們用戶的網(wǎng)速平均值,而且只取一次樣本,所以只是作為參考。

實(shí)驗(yàn)二:用戶設(shè)備主要分辨率

因?yàn)檎掌际窃谟脩粼O(shè)備上看的,所以了解下用戶的主流分辨率,將分辨率裁剪到趨近或稍大于該主流分辨率會(huì)比較適合。iOS和Android都取接近的值。

在友盟查看了我們的應(yīng)用的相關(guān)數(shù)據(jù):

  • Android,較大占比的是寬度1080像素和720像素的設(shè)備。寬度1080像素的,新增用戶占比49.69%,啟動(dòng)次數(shù)占比44.29%;寬度720像素的,新增用戶占比32.47%,啟動(dòng)次數(shù)占比37.76%。
  • iOS,較大占比的是寬度1242像素、750像素和640像素的設(shè)備。寬度1242像素的,新增用戶占比31.84%,啟動(dòng)次數(shù)占比26.91%;寬度750像素的,新增用戶占比36.20%,啟動(dòng)次數(shù)占比31.59%;寬度640像素的,新增用戶占比20.36%,啟動(dòng)次數(shù)占比20.84%。

實(shí)驗(yàn)三:上傳的照片的主要分辨率

找下上傳的照片的主要分辨率,可以針對(duì)這些分辨率去確定和衡量方案。
也是在友盟上看我們的應(yīng)用的數(shù)據(jù):

  • iOS主流機(jī)型是iPhone6、iPhone6s、iPhone6 Plus、iPhone6s Plus,占到70%左右。它們的拍照分辨率分別是2448x3264,3024x4032。
  • Android相對(duì)較碎片化,只能是針對(duì)最大的分辨率去衡量。

實(shí)驗(yàn)四:壓縮質(zhì)量的大致規(guī)律

2448x3264照片壓縮后的數(shù)據(jù)大小(單位B):

壓縮強(qiáng)度 圖片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):

壓縮強(qiáng)度 圖片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
  • 會(huì)出現(xiàn)壓縮出來反而比原圖大的問題,后面會(huì)討論
  • 在沒有裁剪的情況下,壓到0.6依舊不是太理想,特別是分辨率更高的照片。
  • 在excel表格中將數(shù)據(jù)組成折線圖,可以看出在0.9、0.8的時(shí)候下降幅度較大,后面相對(duì)平緩一點(diǎn)。

實(shí)驗(yàn)五:等比例裁剪后壓縮質(zhì)量的大致規(guī)律

2448x3264照片等比例壓縮到寬度1224像素時(shí)的數(shù)據(jù)大小(單位B):

壓縮強(qiáng)度 圖片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í)的數(shù)據(jù)大小(單位B):

壓縮強(qiáng)度 圖片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
  • 可以看到裁剪這個(gè)分辨率后壓縮質(zhì)量0.6的大小相對(duì)可接受,而且圖片質(zhì)量影響也較小。
  • 在這個(gè)分辨率下,壓縮質(zhì)量0.8時(shí)基本壓縮到1/4至1/5。

實(shí)驗(yàn)六:WebP壓縮

WebP據(jù)稱在同等質(zhì)量下大小可以壓縮至JPEG的2/3。在iOS和Android都做了WebP的壓縮測(cè)試,發(fā)現(xiàn)壓縮速度非常慢,需要20s-35s,這是很不可接受的。上網(wǎng)查到WebP的壓縮效率的確較慢,是JPEG的8倍左右,而且相比JPEG需要耗費(fèi)更多的系統(tǒng)性能。所以本來想用WebP做兜底的方案暫時(shí)落空。

制定方案

方案的目的是:

  1. 上傳圖片不超時(shí)
  2. 處理后質(zhì)量清晰度可接受
  3. 縮短上傳耗時(shí)

結(jié)合實(shí)驗(yàn)結(jié)論:

  • 根據(jù)實(shí)驗(yàn)一,平均上傳速度100KB/s,另外我們測(cè)試很差情況下有15KB/s的情況。我們的接口超時(shí)30s,所以可接受的圖片大小最大為450KB。
  • 根據(jù)實(shí)驗(yàn)二,等比例寬度取750-1242像素比較合適。
  • 根據(jù)實(shí)驗(yàn)三、四、五,等比例裁剪到寬度1224像素后壓縮至0.6、0.7大小相對(duì)可接受。質(zhì)量相對(duì)可接受(主觀感受)。
  • JPG、PNG和GIF圖片的基本原理及優(yōu)化方法講到,通常建議JPG質(zhì)量最好是在60左右的原因。當(dāng)在Photoshop中把質(zhì)量設(shè)置低于51的時(shí)候,它就會(huì)執(zhí)行另一個(gè)叫做“降色采樣”的優(yōu)化算法,它會(huì)在8個(gè)像素周圍平均采樣,這樣會(huì)在邊緣產(chǎn)生雜色。

定下方案:

  1. 照片寬度大于1224像素(因?yàn)閕Phone6照片寬度2448所以想取個(gè)可以整除的)時(shí)等比例裁剪寬度成1224。因?yàn)榉直媛侍笊踔羶杀队谑謾C(jī)分辨率實(shí)際沒有任何用處。
  2. 壓縮質(zhì)量系數(shù)至0.8(80)看下大小是否小于300KB,排除一些小分辨率的照片。小于則上傳,大于則繼續(xù)壓縮,取0.7(70),排除一些中等的,如果還大于則取0.6(60)后不判斷直接上傳。根據(jù)上面的實(shí)驗(yàn)可以看到在寬度1224像素下基本都會(huì)小于300KB,大于的則處于450KB內(nèi),且450KB是網(wǎng)速最差的情況,因此基本可以保證上傳。

總結(jié)

方案目前看壓縮的質(zhì)量和時(shí)間控制都相對(duì)較好,但是還要繼續(xù)觀察一段時(shí)間看需不需要再調(diào)整參數(shù)。在這過程中理清了很多概念,了解了圖片壓縮過程中發(fā)生了什么事情,挺有趣的,根本停不下來。

附錄

文中涉及到的一些概念以及發(fā)現(xiàn)的一些其他相關(guān)事情。

圖像的一些概念澄清

其實(shí)圖像真正的信息是它的總分辨率(圖像寬度x圖像高度)和分辨率(水平分辨率&垂直分辨率),而涉及到英寸、厘米等長度單位時(shí)的大小,其實(shí)不是圖像的信息,只是在涉及到外部,比如打印、設(shè)備屏幕顯示等等時(shí),換算出來的。

  • 水平分辨率&垂直分辨率

分辨率一般單位ppi(也有dpi),即每英寸上多少個(gè)像素。水平分辨率即水平方向上像素個(gè)數(shù)/水平長度,垂直分辨率同理。一般水平分辨率和垂直分辨率是相等的,所以日常也簡稱為分辨率。dpi即每英寸上多少點(diǎn)。這兩個(gè)單位根據(jù)不同顯示設(shè)備有換算關(guān)系。

  • 圖像寬度&圖像高度

其實(shí)標(biāo)準(zhǔn)些,講寬度&高度時(shí)一般是講圖像水平/垂直上有多少個(gè)像素。如一張2448x3264的照片,則寬度是2448像素,高度是3264像素。也有講寬度是86.36厘米,高度是115.15厘米,一般在打印照片等情況下。

  • 分辨率

日常講分辨率時(shí)其實(shí)可以指很多情況,一般指圖像寬度x高度,如2448x3264,指水平上有2448個(gè)像素,垂直上有3264個(gè)像素。

壓縮算法概念

  • JPEG

一個(gè)名稱為Joint Photographic Experts Group的組織,也是一種壓縮算法。JPEG本身只有描述如何將一個(gè)視頻轉(zhuǎn)換為字節(jié)的數(shù)據(jù)流(streaming),但并沒有說明這些字節(jié)如何在任何特定的存儲(chǔ)媒體上被封存起來。JPEG有有損壓縮和無損壓縮,無損壓縮的沒有得到什么支持,所以一般講JPEG指它的有損壓縮。

  • JFIF

JPEG File Interchange Format,JPEG文件交換格式,詳細(xì)說明如何從一個(gè)JPEG流,產(chǎn)出一個(gè)適合于電腦存儲(chǔ)和傳輸?shù)奈募?/strong>。一般后綴有.jpeg、.jpg、.jfif以及.jif。

  • Bitmap

又稱柵格圖,是使用像素陣列來表示的圖像。非壓縮格式,從左往右從上往下掃描,占用較大存儲(chǔ)空間。

https://zh.wikipedia.org/wiki/JPEG
https://zh.wikipedia.org/wiki/%E4%BD%8D%E5%9B%BE

微信圖片處理規(guī)律

經(jīng)過簡單測(cè)試發(fā)現(xiàn),在微信,A發(fā)一張?jiān)瓐D給B時(shí),B直接保存縮略圖:

  • iOS版的微信保存下來是等比例壓縮高度為800,質(zhì)量80。
  • Android版的微信保存下來是等比例壓縮高度為1280,質(zhì)量80。

朋友圈的圖片保存下來,都是等比例到高1280像素,質(zhì)量和大小還沒找到規(guī)律。
為什么微信是取高固定而不是寬呢?可以思考下。

Base64編碼后大小

我們現(xiàn)在還用著Base64編碼圖像數(shù)據(jù),后面需改成提交表單方式。

Base64要求把每三個(gè)8Bit的字節(jié)轉(zhuǎn)換為四個(gè)6Bit的字節(jié)(38 = 46 = 24),然后把6Bit再添兩位高位0,組成四個(gè)8Bit的字節(jié),也就是說,轉(zhuǎn)換后的字符串理論上將要比原來的長1/3

iOS的pt與Android的sp

我在iOS所有設(shè)備的分辨率、尺寸和縮放因子,放大模式區(qū)別和6P實(shí)際分辨率文章里講了iOS設(shè)備的pt和px關(guān)系。
iOS的pt是開發(fā)單位,一個(gè)邏輯point對(duì)應(yīng)一個(gè)點(diǎn)dot。@1x設(shè)備上一個(gè)pt上顯示1個(gè)px(像素),@2x上一個(gè)pt顯示2個(gè)px,@3x上顯示3個(gè)px。平時(shí)在storyboard上設(shè)置時(shí)指的都是pt。

Android的sp一種基于屏幕密度的抽象單位。

Android圖片質(zhì)量會(huì)比iPhone的差?

為什么Android的圖片質(zhì)量會(huì)比iPhone的差?[Android算法] 【04/28 bug修改】android圖片壓縮終極解決方案Android圖片編碼機(jī)制深度解析(Bitmap,Skia,libJpeg)三篇文章中講了Android系統(tǒng)在壓縮上的一些不為人知的問題。

大致是,Android編碼保存圖片就是通過Java層函數(shù)——Native層函數(shù)——Skia庫函數(shù)——對(duì)應(yīng)第三方庫函數(shù)(例如libjpeg),這一層層調(diào)用做到的。 libjpeg在壓縮圖像時(shí),有一個(gè)參數(shù)叫optimize_coding,如果設(shè)置optimize_coding為TRUE,將會(huì)使得壓縮圖像過程中基于圖像數(shù)據(jù)計(jì)算哈弗曼表,由于這個(gè)計(jì)算會(huì)顯著消耗空間和時(shí)間,默認(rèn)值被設(shè)置為FALSE。對(duì)于當(dāng)時(shí)的計(jì)算設(shè)備來說,空間和時(shí)間的消耗可能是顯著的,但到今天,這似乎不應(yīng)再是問題。但谷歌的Skia項(xiàng)目工程師們對(duì)optimize_coding在Skia中默認(rèn)的等于了FALSE,這就意味著更差的圖片質(zhì)量和更大的圖片文件。還有其他和iOS的比較可以看下。

也講到了Android可以替換libjpeg庫達(dá)到設(shè)置為TRUE的目的。

iOS的UIImage保存圖片問題

起初發(fā)現(xiàn)壓縮后保存圖片,不同壓縮質(zhì)量系數(shù),得出來的文件大小趨勢(shì)和計(jì)算出的大小趨勢(shì)不同,所以懷疑使用NSData初始化UIImage時(shí)多做了什么。

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)該是對(duì)應(yīng)的質(zhì)量系數(shù)才對(duì)。于是想將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這個(gè)對(duì)象本身還做了其他事情。

AFNetworking2.0源碼解析這篇文章的截圖顯示,UIImage的imageWithData方法堆棧顯示還調(diào)用了哈夫曼解碼。

壓縮再壓縮做了什么

  1. 首先談下看圖軟件怎么展示圖片。打開.jpg圖片時(shí),看圖軟件將文件轉(zhuǎn)換成位圖才顯示出來,即把量化表矩陣與基本轉(zhuǎn)化矩陣運(yùn)算得出圖片當(dāng)前的位圖(因?yàn)榻?jīng)過了壓縮,所以該位圖與原位圖不同)。
  2. 壓縮后再壓縮也是,先將圖片變回位圖,再將位圖按現(xiàn)在的壓縮質(zhì)量系數(shù)壓縮。
  3. 所以壓縮后的圖片有可能變大,我猜測(cè)原因是,壓縮前的占用空間壓縮率較大,而再壓縮時(shí)選的質(zhì)量系數(shù)較大,導(dǎo)致壓縮占用空間率(即壓縮的第二步)較小,所以導(dǎo)致質(zhì)量其實(shí)是變差了,但是占用空間反而可能變大。

變大的例子如:本來圖片A大小500KB,壓縮質(zhì)量系數(shù)選擇0.7,得到B圖片90KB,再拿這張B圖片去壓,壓縮質(zhì)量系數(shù)1.0,得出C圖片。前面我們說壓縮不僅壓縮質(zhì)量,還壓縮占用空間。如果第一次壓縮的壓縮質(zhì)量比例跟第二次壓縮的比例的差值,比第一次壓縮的壓縮占用空間比例跟第二次的壓縮占用空間比例的差值小,那么C圖片就會(huì)比B圖片大。因?yàn)殡m然C圖片質(zhì)量比B圖片質(zhì)量差點(diǎn),但是B圖片的空間壓縮得比C圖片大比較多。

-END-
歡迎到我的博客交流:http://zackzheng.info

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,967評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,273評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,870評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,742評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,527評(píng)論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,010評(píng)論 1 322
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,108評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,250評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,769評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,656評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,853評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,371評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,103評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,472評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,717評(píng)論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,487評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,815評(píng)論 2 372

推薦閱讀更多精彩內(nèi)容

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標(biāo)簽?zāi)J(rèn)的外補(bǔ)...
    _Yfling閱讀 13,774評(píng)論 1 92
  • 版本記錄 前言 只要是做圖片的或者與圖片相關(guān)的,那么圖片的格式就是一個(gè)不可以繞過的問題,我們見過很多的圖片格式,但...
    刀客傳奇閱讀 14,381評(píng)論 0 5
  • 非原創(chuàng),只是整理,如果里面發(fā)現(xiàn)引用的內(nèi)容沒有標(biāo)識(shí)出來,歡迎指出。 一、基本知識(shí) (1)兩種圖片: 1)矢量圖: 矢...
    風(fēng)再起時(shí)ME閱讀 2,462評(píng)論 0 19
  • LZ-Says:小沈陽版程序員~~~程序員其實(shí)可痛苦的了......需求一做一改,一個(gè)月就過去了;嚎~需求再一改一...
    靜心Study閱讀 3,853評(píng)論 1 14
  • 好久沒寫了,主要是人懶了,一有時(shí)間就玩手機(jī)~過去幾天,經(jīng)歷了低谷,各種面試的失敗,讓我已經(jīng)有了無力感。想找各種人說...
    哈啦呢閱讀 290評(píng)論 0 1