面試-iOS圖片渲染

渲染圖片到屏幕上

每一個(gè)像素點(diǎn)均由三個(gè)顏色組件構(gòu)成:紅,藍(lán),綠外加一個(gè)透明度。在每個(gè)蘋果產(chǎn)品上都有上百萬(wàn)個(gè)像素點(diǎn)需要繪制,并且需要一個(gè)穩(wěn)定的FPS支撐頁(yè)面的流暢度,這是一個(gè)很龐大的工作量。這是怎樣一個(gè)流程?
  iOS設(shè)備給用戶視覺(jué)反饋其實(shí)都是通過(guò)QuartzCore框架來(lái)進(jìn)行的,說(shuō)白了,所有用戶最終看到的顯示界面都是圖層合成的結(jié)果,而圖層即是QuartzCore中的CALayer。
 通常我們所說(shuō)的視圖即UIView,并不是直接顯示在屏幕上,而是在創(chuàng)建視圖對(duì)象的時(shí)候視圖對(duì)象會(huì)自動(dòng)創(chuàng)建一個(gè)層,而視圖對(duì)象把要顯示的東西繪制在層上,待到需要顯示時(shí)硬件將所有的層拷貝,然后按Z軸的高低合成最終的合成效果。

軟件對(duì)圖形處理的流程

對(duì)于這塊詳細(xì)的介紹請(qǐng)看:繪制像素到屏幕上

GPU在相識(shí)像素方面起核心作用(在浮點(diǎn)運(yùn)算方面做的很好)。它連接到CPU,在兩者間有OpenGL,Core Animation 和 Core Graphics來(lái)做數(shù)據(jù)傳輸。上圖的流程確保了圖形的繪制。其次,在透明和不透明方面,當(dāng)源紋理是完全不透明的情況下R = S + D * ( 1 – ?alpha )這個(gè)繪制公式,就不需要合成像素值,大大提高了性能通過(guò)CALayer的opaque來(lái)設(shè)置。ps:Quartz是iPhone OS的窗口服務(wù)器和描畫技術(shù)的一般叫法。Core Graphics框架是Quartz的核心,也是內(nèi)容描畫的基本接口。Core Graphics就是調(diào)用drawRect()方法繪制上下文時(shí)候的一系列函數(shù)

離屏渲染

這個(gè)知識(shí)點(diǎn)需要知道當(dāng)前屏幕渲染的概念,當(dāng)前屏幕渲染是指GPU在的渲染操作是在當(dāng)前的屏幕緩沖區(qū)中進(jìn)行渲染的。
離屏渲染相比當(dāng)前屏幕渲染,所有不在當(dāng)前屏幕緩沖區(qū)進(jìn)行渲染的過(guò)程都是離屏渲染,即GPU在當(dāng)前屏幕緩沖區(qū)以外新開(kāi)辟一個(gè)緩沖區(qū)進(jìn)行渲染操作。這其中有一種特殊的渲染方式就是CPU渲染。這種情況發(fā)生在當(dāng)我們對(duì)UIView的DrawRect方法進(jìn)行重寫的情況下并在代碼中用到了Core Graphics技術(shù)進(jìn)行了操作,這就是CPU渲染。整個(gè)CPU在App內(nèi)同步完成,渲染得到的bitmap最后在提交給GPU進(jìn)行顯示。但是由于所有的Core Graphics都是線程安全的所以可以異步完成CPU渲染。

性能

1.由于離屏渲染需要多次的上下文切換:先從當(dāng)前屏幕切換到離屏進(jìn)行渲染操作;渲染結(jié)束后,切換回當(dāng)前屏幕將渲染完成之后的結(jié)果放到屏幕上。上下文切換的代價(jià)相當(dāng)大?。?!
2.離屏渲染需要新建一個(gè)緩沖區(qū)!

設(shè)置了下面的CALayer屬性都會(huì)觸發(fā)離屏繪制:
shouldRasterize(光柵化)
masks(遮罩)
shadows(陰影)
edge antialiasing(抗鋸齒)
group opacity(不透明)

看到了這個(gè)masks很容易就讓我想到了我們經(jīng)常用的設(shè)置圓角的makeToMasks屬性。嘿嘿,性能低下吧,那接下來(lái)就來(lái)高效的設(shè)置一個(gè)圓角圖形。

高效設(shè)置圓角圖形

在UIImage中添加一個(gè)類別


-(UIImage *)jg_drawRadius:(CGFloat)radius size:(CGSize) sizetoFit{
    CGRect rect = CGRectMake(0, 0, sizetoFit.width, sizetoFit.height);//圖形大小
    UIGraphicsBeginImageContextWithOptions(rect.size,false,[UIScreen mainScreen].scale);//繪制圖形按尺寸,透明,比例
    
    CGContextAddPath(UIGraphicsGetCurrentContext(),[UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)].CGPath);//添加路徑
    
    CGContextClip(UIGraphicsGetCurrentContext());//裁剪內(nèi)容
    
    [self drawInRect:rect];
    
    CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathFillStroke);
    UIImage *output = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return output;
}

針對(duì)于這種方法就是一定要注意這個(gè)圖片的背景色不能隨意設(shè)置因?yàn)樵谶@種方法中我們刻意的避免的masks的使用,就是避免了離屏渲染,所以如果有背景色還是會(huì)影響視覺(jué)效果!core animation也不會(huì)變黃哦!

FPS

查看自己應(yīng)用程序是否卡頓--FPS
1.自帶工具Profile的Core Animation。查看FPS
2.通過(guò)CADisplayLink

聲明:frameInterval的固定值為1,表示是一秒鐘刷新60幀。duration是一幀維持的時(shí)間。CADisplayLink相比NSTimer的區(qū)別是,前者調(diào)用方法時(shí)間一定,而且相當(dāng)精準(zhǔn)。后者調(diào)用會(huì)受到runtime的繁忙程度影響。

CADisplayLink

首先它是一個(gè)定時(shí)器,需要我們手動(dòng)加入到runloop。本質(zhì)上和NSTimer是一樣的。但是他不同的是每次頻率刷新的時(shí)候會(huì)調(diào)用方法。the selector on the target is called when the screen’s contents need to be updated.調(diào)用方法target中可以使用timestamp(時(shí)間戳)來(lái)計(jì)算FPS。可以通過(guò)時(shí)間戳的插值這樣計(jì)算1/(timestamp1-timestamp2)計(jì)算但是由于timestamp1-timestamp2差值很小不易計(jì)算一般通過(guò)count多計(jì)算幾次這樣計(jì)算count/(timestamp1-timestamp(n))--相當(dāng)精準(zhǔn)。
可以參考一個(gè)很好的源碼:Github

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

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

  • 繪制像素到屏幕上 answer-huang22 Mar 2014 分享文章 一個(gè)像素是如何繪制到屏幕上去的?有很多...
    阿貍旅途T恤閱讀 1,756評(píng)論 0 7
  • 卷首語(yǔ) 歡迎來(lái)到 objc.io 的第三期! 這一期都是關(guān)于視圖層的。當(dāng)然視圖層有很多方面,我們需要把它們縮小到幾...
    評(píng)評(píng)分分閱讀 1,926評(píng)論 0 18
  • 圓角是一種很常見(jiàn)的視圖效果,相比于直角,它更加柔和優(yōu)美,易于接受。設(shè)置圓角會(huì)帶來(lái)一定的性能損耗,如何提高性能是一個(gè)...
    Chars閱讀 634評(píng)論 0 8
  • 在本系列上一篇《iOS 2D Graphic(1)—— Concept 基本概念和原理》中,我們已經(jīng)了解了關(guān)于iO...
    ac3閱讀 2,378評(píng)論 2 11
  • 李朝鳳像往常一樣在信紙上寫上“敬候坤祺”四個(gè)字落款。翻來(lái)覆去地把信看了幾遍,確定沒(méi)有寫上比較敏感會(huì)被截留的內(nèi)容后,...
    瀟湘楚裔閱讀 359評(píng)論 0 0

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