日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

iOS 下的圖片處理與性能優(yōu)化詳解

瀏覽:103日期:2022-09-16 16:33:43
圖片在計(jì)算機(jī)世界中怎樣被存儲和表示?

圖片和其他所有資源一樣,在內(nèi)存中本質(zhì)上都是0和1的二進(jìn)制數(shù)據(jù),計(jì)算機(jī)需要將這些原始內(nèi)容渲染成人眼能觀察的圖片,反過來,也需要將圖片以合適的形式保存在存儲器或者在網(wǎng)絡(luò)上傳送。

這種將圖片以某種規(guī)則進(jìn)行二進(jìn)制編碼的方式,就是圖片的格式。

常見的圖片格式

圖片的格式有很多種,除了我們熟知的 JPG、PNG、GIF,還有Webp,BMP,TIFF,CDR 等等幾十種,用于不同的場景或平臺。

這些格式可以分為兩大類:有損壓縮和無損壓縮。

有損壓縮:相較于顏色,人眼對光線亮度信息更為敏感,基于此,通過合并圖片中的顏色信息,保留亮度信息,可以在盡量不影響圖片觀感的前提下減少存儲體積。顧名思義,這樣壓縮后的圖片將會永久損失一些細(xì)節(jié)。最典型的有損壓縮格式是 jpg。

無損壓縮:和有損壓縮不同,無損壓縮不會損失圖片細(xì)節(jié)。它降低圖片體積的方式是通過索引,對圖片中不同的顏色特征建立索引表,減少了重復(fù)的顏色數(shù)據(jù),從而達(dá)到壓縮的效果。常見的無損壓縮格式是 png,gif。

除了上述提到的格式,有必要再簡單介紹下 webp 和 bitmap這兩種格式:

Webp:jpg 作為主流的網(wǎng)絡(luò)圖片標(biāo)準(zhǔn)可以向上追溯到九十年代初期,已經(jīng)十分古老了。所以谷歌公司推出了Webp標(biāo)準(zhǔn)意圖替代陳舊的jpg,以加快網(wǎng)絡(luò)圖片的加載速度,提高圖片壓縮質(zhì)量。

webp 同時(shí)支持有損和無損兩種壓縮方式,壓縮率也很高,無損壓縮后的 webp 比 png 少了45%的體積,相同質(zhì)量的 webp 和 jpg,前者也能節(jié)省一半的流量。同時(shí) webp 還支持動圖,可謂圖片壓縮格式的集大成者。

webp 的缺點(diǎn)是瀏覽器和移動端支持還不是很完善,我們需要引入谷歌的 libwebp 框架,編解碼也會消耗相對更多的資源。

bitmap:bitmap 又叫位圖文件,它是一種*非壓縮*的圖片格式,所以體積非常大。所謂的非壓縮,就是圖片每個(gè)像素的原始信息在存儲器中依次排列,一張典型的1920*1080像素的 bitmap 圖片,每個(gè)像素由 RGBA 四個(gè)字節(jié)表示顏色,那么它的體積就是 1920 * 1080 * 4 = 1012.5kb。

由于 bitmap 簡單順序存儲圖片的像素信息,它可以不經(jīng)過解碼就直接被渲染到 UI 上。實(shí)際上,其它格式的圖片一般都需要先被首先解碼為 bitmap,然后才能渲染到界面上。

如何判斷圖片的格式?

在一些場景中,我們需要手動去判斷圖片數(shù)據(jù)的格式,以進(jìn)行不同的處理。一般來說,只要拿到原始的二進(jìn)制數(shù)據(jù),根據(jù)不同壓縮格式的編碼特征,就可以進(jìn)行簡單的分類了。以下是一些圖片框架的常用實(shí)現(xiàn),可以復(fù)制使用:

+ (XRImageFormat)imageFormatForImageData:(nullable NSData *)data { if (!data) {return XRImageFormatUndefined; }uint8_t c; [data getBytes:&c length:1]; switch (c) {case 0xFF: return XRImageFormatJPEG;case 0x89: return XRImageFormatPNG;case 0x47: return XRImageFormatGIF;case 0x49:case 0x4D: return XRImageFormatTIFF;case 0x52: if (data.length < 12) {return XRImageFormatUndefined; }NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding]; if ([testString hasPrefix:@'RIFF'] && [testString hasSuffix:@'WEBP']) {return XRImageFormatWebP; } } return XRImageFormatUndefined;}UIImageView 的性能瓶頸

如上文所說,大部分格式的圖片,都需要被首先解碼為bitmap,然后才能渲染到UI上。

UIImageView 顯示圖片,也有類似的過程。實(shí)際上,一張圖片從在文件系統(tǒng)中,到被顯示到 UIImageView,會經(jīng)歷以下幾個(gè)步驟:

分配內(nèi)存緩沖區(qū)和其它資源。 從磁盤拷貝數(shù)據(jù)到內(nèi)核緩沖區(qū) 從內(nèi)核緩沖區(qū)復(fù)制數(shù)據(jù)到用戶空間 生成UIImageView,把圖像數(shù)據(jù)賦值給UIImageView 將壓縮的圖片數(shù)據(jù),解碼為位圖數(shù)據(jù)(bitmap),如果數(shù)據(jù)沒有字節(jié)對齊,Core Animation會再拷貝一份數(shù)據(jù),進(jìn)行字節(jié)對齊。 CATransaction捕獲到UIImageView layer樹的變化,主線程Runloop提交CATransaction,開始進(jìn)行圖像渲染 GPU處理位圖數(shù)據(jù),進(jìn)行渲染。

由于 UIKit 的封裝性,這些細(xì)節(jié)不會直接對開發(fā)者展示。實(shí)際上,當(dāng)我們調(diào)用[UIImage imageNamed:@'xxx']后,UIImage 中存儲的是未解碼的圖片,而調(diào)用 [UIImageView setImage:image]后,會在主線程進(jìn)行圖片的解碼工作并且將圖片顯示到 UI 上,這時(shí)候,UIImage 中存儲的是解碼后的 bitmap 數(shù)據(jù)。

而圖片的解壓縮是一個(gè)非常消耗 CPU 資源的工作,如果我們有大量的圖片需要展示到列表中,將會大大拖慢系統(tǒng)的響應(yīng)速度,降低運(yùn)行幀率。這就是 UIImageView 的一個(gè)性能瓶頸。

解決性能瓶頸:強(qiáng)制解碼

如果 UIImage 中存儲的是已經(jīng)解碼后的數(shù)據(jù),速度就會快很多,所以優(yōu)化的思路就是:在子線程中對圖片原始數(shù)據(jù)進(jìn)行強(qiáng)制解碼,再將解碼后的圖片拋回主線程繼續(xù)使用,從而提高主線程的響應(yīng)速度。

我們需要使用的工具是 Core Graphics 框架的 CGBitmapContextCreate 方法和相關(guān)的繪制函數(shù)。總體的步驟是:

A. 創(chuàng)建一個(gè)指定大小和格式的 bitmap context。

B. 將未解碼圖片寫入到這個(gè) context 中,這個(gè)過程包含了*強(qiáng)制解碼*。

C. 從這個(gè) context 中創(chuàng)建新的 UIImage 對象,返回。

下面是 SDWebImage 實(shí)現(xiàn)的核心代碼,編號對應(yīng)的解析在下文中:

// 1.CGImageRef imageRef = image.CGImage;// 2.CGColorSpaceRef colorspaceRef = [UIImage colorSpaceForImageRef:imageRef];size_t width = CGImageGetWidth(imageRef);size_t height = CGImageGetHeight(imageRef);// 3.size_t bytesPerRow = 4 * width;// 4.CGContextRef context = CGBitmapContextCreate(NULL, width, height, kBitsPerComponent, bytesPerRow, colorspaceRef, kCGBitmapByteOrderDefault|kCGImageAlphaNoneSkipLast);if (context == NULL) { return image;}// 5.CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);// 6.CGImageRef newImageRef = CGBitmapContextCreateImage(context);// 7.UIImage *newImage = [UIImage imageWithCGImage:newImageRefscale:image.scale orientation:image.imageOrientation];CGContextRelease(context);CGImageRelease(newImageRef);return newImage;

對上述代碼的解析:

1、從 UIImage 對象中獲取 CGImageRef 的引用。這兩個(gè)結(jié)構(gòu)是蘋果在不同層級上對圖片的表示方式,UIImage 屬于 UIKit,是 UI 層級圖片的抽象,用于圖片的展示;CGImageRef 是 QuartzCore 中的一個(gè)結(jié)構(gòu)體指針,用C語言編寫,用來創(chuàng)建像素位圖,可以通過操作存儲的像素位來編輯圖片。這兩種結(jié)構(gòu)可以方便的互轉(zhuǎn):

// CGImageRef 轉(zhuǎn)換成 UIImageCGImageRef imageRef = CGBitmapContextCreateImage(context);UIImage *image = [UIImage imageWithCGImage:imageRef]; // UIImage 轉(zhuǎn)換成 CGImageRefUIImage *image=[UIImage imageNamed:@'xxx'];CGImageRef imageRef=loadImage.CGImage;

2、調(diào)用 UIImage 的 +colorSpaceForImageRef: 方法來獲取原始圖片的顏色空間參數(shù)。

什么叫顏色空間呢,就是對相同顏色數(shù)值的解釋方式,比如說一個(gè)像素的數(shù)據(jù)是(FF0000FF),在 RGBA 顏色空間中,會被解釋為紅色,而在 BGRA 顏色空間中,則會被解釋為藍(lán)色。所以我們需要提取出這個(gè)參數(shù),保證解碼前后的圖片顏色空間一致。

3、計(jì)算圖片解碼后每行需要的比特?cái)?shù),由兩個(gè)參數(shù)相乘得到:每行的像素?cái)?shù) width,和存儲一個(gè)像素需要的比特?cái)?shù)4。

這里的4,其實(shí)是由每張圖片的像素格式和像素組合來決定的,下表是蘋果平臺支持的像素組合方式。

我們解碼后的圖片,默認(rèn)采用 kCGImageAlphaNoneSkipLast RGB 的像素組合,沒有 alpha 通道,每個(gè)像素32位4個(gè)字節(jié),前三個(gè)字節(jié)代表紅綠藍(lán)三個(gè)通道,最后一個(gè)字節(jié)廢棄不被解釋。

4、最關(guān)鍵的函數(shù):調(diào)用 CGBitmapContextCreate() 方法,生成一個(gè)空白的圖片繪制上下文,我們傳入了上述的一些參數(shù),指定了圖片的大小、顏色空間、像素排列等等屬性。

5、調(diào)用 CGContextDrawImage() 方法,將未解碼的 imageRef 指針內(nèi)容,寫入到我們創(chuàng)建的上下文中,這個(gè)步驟,完成了隱式的解碼工作。

6、從 context 上下文中創(chuàng)建一個(gè)新的 imageRef,這是解碼后的圖片了。

7、從 imageRef 生成供UI層使用的 UIImage 對象,同時(shí)指定圖片的 scale 和orientation 兩個(gè)參數(shù)。

scale 指的是圖片被渲染時(shí)需要被壓縮的倍數(shù),為什么會存在這個(gè)參數(shù)呢,因?yàn)樘O果為了節(jié)省安裝包體積,允許開發(fā)者為同一張圖片上傳不同分辨率的版本,也就是我們熟悉的@2x,@3x后綴圖片。不同屏幕素質(zhì)的設(shè)備,會獲取到對應(yīng)的資源。為了繪制圖片時(shí)統(tǒng)一,這些圖片會被set自己的scale屬性,比如@2x圖片,scale 值就是2,雖然和1x圖片的繪制寬高一樣,但是實(shí)際的長是width * scale。

orientation 很好理解,就是圖片的旋轉(zhuǎn)屬性,告訴設(shè)備,以哪個(gè)方向作為圖片的默認(rèn)方向來渲染。

通過以上的步驟,我們成功在子線程中對圖片進(jìn)行了強(qiáng)制轉(zhuǎn)碼,回調(diào)給主線程使用,從而大大提高了圖片的渲染效率。這也是現(xiàn)在主流 App 和大量三方庫的最佳實(shí)踐。

總結(jié)

總結(jié)一下本文內(nèi)容:

圖片在計(jì)算機(jī)世界中被按照不同的封裝格式進(jìn)行壓縮,以便存儲和傳輸。 手機(jī)會在主線程中將壓縮的圖片解壓為可以進(jìn)行渲染的位圖格式,這個(gè)過程會消耗大量資源,影響App性能。 我們使用 Core Graphics 的繪制方法,強(qiáng)制在子線程中先對 UIImage 進(jìn)行轉(zhuǎn)碼工作,減少主線程的負(fù)擔(dān),從而提升App的響應(yīng)速度。

和 UIImageView 類似,UIKit 隱藏了很多技術(shù)細(xì)節(jié),降低開發(fā)者的學(xué)習(xí)門檻,但另一方面,卻也限制了我們對一些底層技術(shù)的探究。文中提到的強(qiáng)制解碼方法,其實(shí)也是CGBitmapContextCreate 方法的一個(gè)『副作用』,屬于比較hack方式,這也是iOS平臺的一個(gè)局限:蘋果過于封閉了。

用戶對軟件性能(幀率、響應(yīng)速度、閃退率等等)其實(shí)非常敏感,作為開發(fā)者,必須不斷探究性能瓶頸背后的原理,并且嘗試解決,移動端開發(fā)的性能優(yōu)化永無止境。

以上就是iOS 下的圖片處理與性能優(yōu)化詳解的詳細(xì)內(nèi)容,更多關(guān)于ios 圖片處理與性能優(yōu)化的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: IOS
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
免费久久精品| 国产精品伦一区二区| av免费不卡国产观看| 日本欧美久久久久免费播放网| 美女久久久久| 三级欧美在线一区| 亚久久调教视频| 日韩av一区二区在线影视| 美女久久一区| 国产超碰精品| 亚洲黄色网址| 色爱av综合网| 91精品二区| 在线观看一区| 久久狠狠亚洲综合| 激情久久99| 中文字幕在线视频久| 久久精品国产68国产精品亚洲| 欧美成人高清| 中文无码日韩欧| 国产欧美一区二区三区国产幕精品| 精品午夜视频| 免费观看久久av| 日韩欧美四区| 国产一区二区精品久| 精品在线播放| 无码日韩精品一区二区免费| 久久精品999| 国产h片在线观看| 91久久黄色| 欧美一区精品| 伊人久久高清| av不卡在线| 国产欧美自拍| 99久久99视频只有精品| 一二三区精品| 麻豆高清免费国产一区| 92国产精品| 先锋影音国产一区| 欧美黑人巨大videos精品| 日韩中文在线播放| 热久久久久久久| 国产精品xxx| 欧美在线资源| 7777精品| 久久天堂av| 日本在线不卡视频| 激情不卡一区二区三区视频在线| 成人免费电影网址| 日韩精品福利一区二区三区| 精品国产欧美日韩| 国产视频亚洲| 红杏一区二区三区| 亚洲欧美视频| 日本久久综合| 日韩精品a在线观看91| 91精品韩国| 7m精品国产导航在线| 亚洲婷婷在线| 免费一区二区三区在线视频| 女人天堂亚洲aⅴ在线观看| 国产精品igao视频网网址不卡日韩 | 日韩欧乱色一区二区三区在线| 国产成年精品| 色狠狠一区二区三区| 久久精品青草| 国产伦理久久久久久妇女| 欧洲毛片在线视频免费观看| 国产精品777777在线播放| 欧美日韩精品一本二本三本 | 免费一级欧美片在线观看网站 | 国产精品中文字幕制服诱惑| 欧美日韩国产亚洲一区| 欧美aa在线视频| 一区二区三区网站| 亚洲a在线视频| 婷婷精品在线观看| 91精品电影| 成人小电影网站| 国产欧美一区二区三区米奇| 亚洲一区二区毛片| 日韩国产专区| 久久不见久久见中文字幕免费| 免费在线观看不卡| 激情黄产视频在线免费观看| 国产精品一卡| 亚洲另类黄色| 欧美日韩国产高清| 日韩欧美一区二区三区在线观看| 国产精品任我爽爆在线播放| 中文一区一区三区免费在线观 | 在线精品一区| 2023国产精品久久久精品双| 中文在线а√天堂 | 国产精品videossex久久发布| 伊人久久一区| 夜久久久久久| 成人羞羞视频播放网站| 精品三级在线| 免费在线欧美黄色| 国产欧美日韩在线观看视频| 日韩精品视频网站| 日本一区二区中文字幕| 综合在线一区| 日韩中文字幕区一区有砖一区 | 国产精品美女午夜爽爽| 午夜电影一区| 亚洲人妖在线| 爽爽淫人综合网网站| 亚洲午夜久久久久久尤物| 精品视频自拍| 久久精品一区二区三区中文字幕| 久久99精品久久久久久园产越南 | 日韩精品1区2区3区| 亚洲精品动态| 综合激情五月婷婷| 亚洲欧美日本国产| 四虎精品永久免费| 日本一区二区三区中文字幕| 亚洲精品激情| 日韩av在线播放中文字幕| 日韩国产一区二| 欧美日韩一区二区高清| 日韩二区三区四区| 97精品国产99久久久久久免费| 日韩va亚洲va欧美va久久| 日韩不卡免费视频| 国产精品久久久久久久免费软件| 久久爱www成人| 日本激情一区| 欧美日韩在线网站| 夜久久久久久| 日韩一区精品字幕| 亚洲日本三级| 国产精品一区二区三区四区在线观看 | 青草久久视频| 国产精品久久久久9999高清| 麻豆视频一区二区| 9999国产精品| 久久国产亚洲精品| 午夜视频精品| 中文字幕免费一区二区| 日韩三级视频| 久久精品国产99国产| 日韩免费看片| 亚洲资源av| 日韩视频一二区| 国产日韩欧美中文在线| 黄色网一区二区| 久久伦理在线| 蜜臀av性久久久久蜜臀aⅴ流畅| 欧美日韩伊人| 欧美aa一级| 蜜桃视频第一区免费观看| 国产亚洲高清在线观看| 国产h片在线观看| 香蕉久久久久久久av网站| 97久久超碰| 亚洲性色av| 亚洲另类黄色| 精品美女视频| 午夜免费一区| 日韩福利视频一区| 色爱综合网欧美| 亚洲专区欧美专区| 国产精品草草| 美女网站一区| 欧美日一区二区在线观看| 欧产日产国产精品视频| 一区二区三区四区在线观看国产日韩| 国产乱人伦精品一区| 999精品一区| 日韩av在线免费观看不卡| 老牛影视精品| 丝袜美腿亚洲色图| 精品国产三区在线| 久久最新视频| 国产精品大片| 国产精品7m凸凹视频分类| 日韩国产在线不卡视频| 日韩国产欧美| 亚洲免费福利一区| 岛国av免费在线观看| 亚洲一二三区视频| 欧美久久天堂| 日韩精品亚洲专区| 久久久久国产| 国产精品对白| 午夜久久免费观看| 精品国产三区在线| 亚洲精品无吗| 麻豆视频在线看| 视频一区在线视频| 四虎8848精品成人免费网站| 亚洲色图网站| 欧美成人基地| 久久av资源| 亚洲另类av| 五月天久久久| 福利视频一区|