SDWebImageDecoder引發(fā)的思考

關(guān)于SDWebImage中的SDWebImageDecoder這個類,看完以后有下面幾個思考

0.為什么圖片要解碼

1.這么解碼的好處

2.這么解碼有壞處嗎

圖片的格式(png, jpg, gif ,webp,bitMap等等)

jpeg :

(1)有損壓縮格式, 將像素信息用jpeg保存成文件再讀取出來,其中某些像素值會有少許變化。

(2)沒有透明信息

(3)jpeg比較適合用來存儲相機(jī)拍攝出來的圖片

png :

(1) png是一種無損壓縮格式

(2) png可以有透明效果

(3)png比較適合矢量圖,幾何圖.

(矢量格式的一大優(yōu)點(diǎn)就是縮放.矢量格式的圖像其實是一組繪圖命令.這些指令通常是獨(dú)立于尺寸的.如果你想要擴(kuò)大一個圓形,只需在繪制之前擴(kuò)大他的半徑就可以了)

bitMap(位圖):

(1)bmp格式?jīng)]有壓縮像素格式

(2)存儲在文件中時先有文件頭、再圖像頭、后面就都是像素數(shù)據(jù)了,上下顛倒存儲

最早接觸到bitMap是在imageView的layer.shouldRasterize,你是否也用過這個屬性

CALayer的shouldRasterize和離屏渲染(offscreen rendering):

開啟shouldRasterize后,CALayer會被光柵化為bitmap,layer的陰影等效果也會被保存到bitmap中.

更新已光柵化的layer,會造成大量的offscreen渲染.

offscreen rendring: 指的是在圖像在繪制到當(dāng)前屏幕前,需要先進(jìn)行一次渲染,之后才繪制到當(dāng)前屏幕。

離屏渲染有兩種:

1 .GPU的離屏渲染(shouldRasterize,mask等layer相關(guān)的 )

2 ,CPU的離屏渲染(使用drawRect,和CoreGraphic(線程安全,SDWebImage的解壓圖片))

?離屏渲染消耗性能:(看了好多文章都是這么寫的):

原因是顯卡需要另外alloc一塊內(nèi)存來進(jìn)行渲染,渲染完畢后在繪制到當(dāng)前屏幕,而且對于顯卡來說,onscreen到offscreen的上下文環(huán)境切換是非常昂貴的(涉及到OpenGL的pipelines和barrier等).

開啟柵格化,相當(dāng)于把部分GPU的工作轉(zhuǎn)到CPU來做了,由CPU生成bitMap,供GPU下次使用.

總結(jié): 開起柵格化的圖片的內(nèi)容不應(yīng)該經(jīng)常變化,否則造成大量的離屏渲染.它使用的范圍應(yīng)該是當(dāng)前l(fā)ayer的顯示比較復(fù)雜,但卻不怎么變化.

就可以開啟柵格化,在內(nèi)存中保留一份,以方便使用.

Advanced Graphics and Animations for iOS Apps

這篇文章比較詳細(xì),也介紹了Instruments對性能的測試,對上面有興趣的可以深看一下.

圖片的在內(nèi)存中的大小

圖片在內(nèi)存中占用的大小 跟圖片自身的大小沒有關(guān)系

內(nèi)存中占用的大小 = 圖片的寬度 * 圖片的高度*每個像素占用的字節(jié)數(shù)

在SDWebImage中衡量大圖的標(biāo)準(zhǔn):

圖片的像素總數(shù) > 60M內(nèi)存所存儲的像素數(shù) ? 壓縮 : 不壓縮.

蘋果官方的加載大圖demo

這個里面的大圖處理邏輯個SDWebImage 是完全一樣的,介紹更詳細(xì),效果看起來也更好,建議看蘋果官方的.

基本原理:也就是原圖按照定好的大小(像素).來對原圖進(jìn)行切塊,然后再一塊塊的繪制到destContext.

(這里網(wǎng)上Google了好多文章,對這個介紹很少,還是不怎么明白

static const CGFloat ?kDestSeemOverlap =2.0f;// the numbers of pixels to overlap(重疊) the seems where tiles(切片) meet.

為什么要定義這個,這個為什么會有重合的像素,以及它在后面的代碼里面的操作.還望有大神明白指導(dǎo)一下,不勝感激).

這些都是經(jīng)過壓縮編碼后的圖片格式,是不能直接使用的,其基本原理

圖片為什么要解碼

png,jpeg格式的數(shù)據(jù)是不能直接使用的,需要將其轉(zhuǎn)化為位圖.

當(dāng)我們使用imageView顯示圖片的時候:

1.讀取圖片

2.解壓圖片為位圖(消耗CPU)

3.如果位圖數(shù)據(jù)不是字節(jié)對齊的,CoreAnimation會copy一份位圖數(shù)據(jù)并進(jìn)行字節(jié)對齊

4 CoreAnimation渲染解壓縮過的位圖

這一切在IOS中都是默認(rèn)發(fā)生在主線程成的并且是在UIImageView執(zhí)行setImage方法的時候完成的(在UIImage imageNamed的時候不會發(fā)生,具體參考下文).

當(dāng)你使用[UIImage ImageNamed: @"xxx.jpg"]的時候,內(nèi)存不會有明顯變化,只有當(dāng)調(diào)用

UIImageView的setImage的時候,這時候內(nèi)存才會增加.并且這時候你將imageView移除,內(nèi)存也不會有減少. 這也是為什么

+ (nullableUIImage*)imageNamed:(NSString*)name;

不適合加載大的 不常用的圖片.因為它會默認(rèn)在程序里保存這張圖片數(shù)據(jù)(不會隨ImageView的移除而移除).只有經(jīng)常使用圖片適合這種方式加載.

+ (nullableUIImage*)imageWithContentsOfFile:(NSString*)path;

這個方法跟上面的略有不同,他不會在內(nèi)存中保留一份數(shù)據(jù).只要imageView移除,內(nèi)存中的數(shù)據(jù)就會直接移除.這也就是這個方法為什么適合加載大的圖片,但卻不常用的圖片.


這樣解碼的好處:

把圖片解碼這個默認(rèn)在主線程執(zhí)行,耗損CPU的行為,放在了后臺線程.

只需要在使用的時候,直接setImage,不會有太大的CPU消耗

這只是對圖片優(yōu)化的其中一種方式.在圖片從下載到顯示的過程中有很多個步驟可以優(yōu)化:

有興趣的可以參考這篇文章:

IOS異步圖片加載與常用的優(yōu)化

Instruments的測試

由于數(shù)據(jù)比較多,直接做成了gif動畫. 細(xì)細(xì)觀察吧

PS:

下面的前兩幅圖是執(zhí)行下面這段代碼:(圖1,圖2,內(nèi)存和CPU的消耗):?

(1) 解壓是代碼執(zhí)行SDWebImage的:

NSString*path = [[NSBundlemainBundle]pathForResource:@"xxx.jpg"ofType:nil];

UIImage *image = [UIImage imageWithContentsOfFile:path];

_decodeImage = [UIImage decodedImageWithImage :image];(SDWebImage的decodedImageWithImage)方法

(2) 點(diǎn)擊灰色區(qū)域:

_showImageView.image = _decodeImage;

(3)點(diǎn)擊移除

[_showImageView removeFromSuperView];

_decodeImage = nil;

下面的后兩幅圖是執(zhí)行下面這段代碼:(圖3,圖4,內(nèi)存和CPU的消耗):

(1) 點(diǎn)擊 使用UIImage imageName加載的按鈕 是代碼執(zhí)行的:

_image = [UIImage imageNamed:@"xxx.jpg"];

(2) 點(diǎn)擊灰色區(qū)域:

_showImageView.image = _image;

(3)點(diǎn)擊移除

[_showImageView removeFromSuperView];

_image = nil;

使用SDWebImage的decodedImageWithImage方法解碼的時候,內(nèi)存的占用情況


1

使用SDWebImage的decodedImageWithImage方法解碼的時候,CPU的占用情況


2

使用[UIImage imageNamed:@"xxx.jpg"]的內(nèi)存占用情況


3 這里可以清楚地看到,移除ImageView和指針后,圖片沒有被銷毀,還存在內(nèi)存中

使用[UIImage imageNamed:@"xxx.jpg"]的CPU占用情況


4

這樣解碼的弊端:

這樣解碼就是以空間換時間的方法,提前解壓好,用的時候直接從內(nèi)存讀取.

如果下載的圖片比較大,然后直接解碼的話 這個是內(nèi)存所不能承受,需要對圖片進(jìn)行壓縮.

不過SDWebImage里面也提供了對大圖的壓縮API.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 誰吃掉我們的CPU: 方法CA::Render::create_image_from_provider 圖片預(yù)解碼...
    神采飛揚(yáng)_2015閱讀 3,456評論 2 6
  • 導(dǎo)語:這是SDWebImage源碼理解的第一篇,本篇先介紹圖片解碼相關(guān)的背景知識,然后介紹SDWebImage中解...
    南華coder閱讀 7,771評論 12 48
  • 繪制像素到屏幕上 answer-huang22 Mar 2014 分享文章 一個像素是如何繪制到屏幕上去的?有很多...
    阿貍旅途T恤閱讀 1,766評論 0 7
  • 卷首語 歡迎來到 objc.io 的第三期! 這一期都是關(guān)于視圖層的。當(dāng)然視圖層有很多方面,我們需要把它們縮小到幾...
    評評分分閱讀 1,932評論 0 18
  • 在聊這一話題之前,我們先看看屏幕是如何顯示圖像的。 屏幕顯示圖像的原理 在最簡單的情況下,幀緩沖區(qū)只有一個,這時幀...
    muice閱讀 3,362評論 4 19

友情鏈接更多精彩內(nèi)容