Image and Graphics Best Practices

目錄:

一、UIImage and UIImageView
二、Image Scource
三、Custom drawing with UIKit
四、Advanced CPU and GPU techniques
五、總結(jié)

一、UIImage and UIImageView

問題1:UIImageVIew顯示圖片,會(huì)有哪此過程?(加載——解碼——渲染)
顯示圖片的過程
  • 1.加載一個(gè)圖片,產(chǎn)生一個(gè)的DataBuffer(存儲(chǔ)了二進(jìn)制的元數(shù)據(jù))
    2.將圖片解碼,解碼過程中會(huì)產(chǎn)生一個(gè)ImageBuffer(記錄每一個(gè)象素的色彩信息)
    3.渲染一個(gè)圖片,渲染的過程中會(huì)產(chǎn)生一個(gè)FrameBuffer(存儲(chǔ)了App的每幀的實(shí)際渲染輸出)

問題2 :內(nèi)存,cpu,電池壽命,響應(yīng)速度的關(guān)系?
各資源間的關(guān)系
  • 內(nèi)存占用高,引起CPU占用高,導(dǎo)致耗電快,響應(yīng)速度慢

問題3:我們?cè)陲@示圖片時(shí),解碼操作會(huì)消耗較高的內(nèi)存,我們?cè)谶@個(gè)過程中,如何節(jié)約內(nèi)存?
  • 1.降低采樣:減少ImageBuffer的size,從而降低內(nèi)存的占用
func downsample(imageAt imageURL: URL, to pointSize: CGSize, scale: CGFloat) -> UIImage {
    let imageSourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary
    let imageSource = CGImageSourceCreateWithURL(imageURL as CFURL, imageSourceOptions)!
    let maxDimensionInPixels = max(pointSize.width, pointSize.height) * scale
    let downsampleOptions = 
       [kCGImageSourceCreateThumbnailFromImageAlways: true,
         kCGImageSourceShouldCacheImmediately: true,
         kCGImageSourceCreateThumbnailWithTransform: true,
         kCGImageSourceThumbnailMaxPixelSize: maxDimensionInPixels] as  CFDictionary
    let downsampledImage =
        CGImageSourceCreateThumbnailAtIndex(imageSource, 0, downsampleOptions)!
    return UIImage(cgImage: downsampledImage)
}

2.預(yù)取和異步解碼:由于當(dāng)用戶快速滑動(dòng)的時(shí)候,會(huì)頻繁在主線程中進(jìn)行圖片的解碼操作,會(huì)造成cpu某一時(shí)刻的占用率極高。為了使cpu資源的平滑分配,使用預(yù)?。╬refetchRowsAt:)和異步解碼(通過多線程,在子線程獲取解碼后的圖片,然后展示到主線程上,降低 CPU 的占用)。

let serialQueue = DispatchQueue(label: "Decode queue")
  func collectionView(_ collectionView: UICollectionView,
                     prefetchItemsAt indexPaths: [IndexPath]) {
     // Asynchronously decode and downsample every image we are about to show
    for indexPath in indexPaths {
         serialQueue.async {
           let downsampledImage = downsample(images[indexPath.row])
           DispatchQueue.main.async { self.update(at: indexPath, with: downsampledImage) }
         }
     }
 } 


二、Image Scource

問題1:圖片從哪里來?

1.在assetCatelog中的圖片資源
2.在應(yīng)用或框架中的bundle文件
3.在文件系統(tǒng)中的文件
4.從?網(wǎng)絡(luò)上下載的文件

問題2:為什么推薦ImageAssets

1.基于名稱和特征的優(yōu)化查找
2.智能緩沖緩存
3.應(yīng)用瘦身(應(yīng)用在安裝時(shí),根據(jù)設(shè)備選擇資源)
4.矢量化圖片(勾選Preserve Vector Data選項(xiàng))
注:如果有一個(gè)圖片有多張尺寸,最好用多個(gè)圖片資源代替,而不選擇矢量柵格化


三、Custom drawing with UIKit

問題1:繼承View的子類實(shí)現(xiàn)draw方法和使用UIImageView顯示一個(gè)圖片,會(huì)有哪些不同?
添加多個(gè)view和繼承view對(duì)比

1.繼承View的子類:繼承UIView重寫draw方法,CALayer會(huì)創(chuàng)建一個(gè)備用緩存,然后再將內(nèi)容傳給FrameBuffer。
2.UIImageView:ImageView創(chuàng)建圖片,并讓圖片創(chuàng)建一個(gè)解碼后的圖片緩存,而且將解碼后的圖片給CALayer,作為它的內(nèi)容

問題2:如何減少備用緩存

1.設(shè)置ContentsFormat屬性同時(shí)更新layerWillDraw的實(shí)現(xiàn),來隱式的開啟優(yōu)化(設(shè)置CALayer的屬性來提示是否需要更廣的色域)
2.通過屬性的方法,減少draw方法的重寫從而減少后備緩存的使用。比如UIView.backgroundColor渲染frameBuffer時(shí)不需要后備緩存(不推薦使用圖案色填充,可用UIImageView的tiling Image代替)
3.圓角時(shí),使用CALayer的cornerRadius或者修剪好的圖片(UIView的maskView和CALayer.maskLayer會(huì)有臨時(shí)圖片緩存,而CALayer的cornerRadius則沒有)
4.使用UIImageView和IULabel
注:屏幕之外,使用UIGraphicsImageRenderer更有效率。


四、Advanced CPU and GPU techniques

1.對(duì)圖片進(jìn)行實(shí)時(shí)處理時(shí)考慮使用CoreImage,它解放了CPU,在GPU上執(zhí)行。 `[[UIImage alloc] initWithCIImage:]
2.使用CVPixelBuffer在Metal,Vision,Accelerate框架之間傳遞數(shù)據(jù)


五、總結(jié):

1.預(yù)取和異步解碼的實(shí)現(xiàn)
2.使用UIImageView 和 UILabel來減少Backing Store
3.不要無意中關(guān)閉了自定義draw方法中系統(tǒng)嘗試做的優(yōu)化
4.推薦使用 Image Assets
5.避免過度依賴Preserve Vector Data

?著作權(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)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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