[iOS] 圖像處理 - 一種高效裁剪圖片圓角的算法

場(chǎng)景

經(jīng)??吹礁鞣N高效裁剪圓角的文章,正好之前做過(guò)一點(diǎn)數(shù)字圖像處理,就打算用空域處理的辦法,寫(xiě)個(gè)裁剪圓角的算法,一定要盡可能的快的,不然界面容易卡頓。

裁圓角很簡(jiǎn)單,對(duì)于圖像上的一個(gè)點(diǎn)(x, y),判斷其在不在圓角矩形內(nèi),在的話 alpha 是原值,不在的話 alpha 設(shè)為 0 即可。如下圖

15F6A143-2704-402D-88EA-DB80B0266F80.png

我遍歷所有像素,判斷每個(gè)像素在不在4個(gè)圓的圓內(nèi)就行了,4個(gè)角,每個(gè)角有一個(gè)四分之一的圓。

一個(gè)優(yōu)化就是,我不需要遍歷全部的像素就能裁出圓角,只需要考慮類似左下角三角形的區(qū)域就行了,左下,左上,右上,右下,一共4個(gè)三角形區(qū)域(另外3個(gè)圖中沒(méi)畫(huà)出),for循環(huán)的時(shí)候,就循環(huán)這個(gè)4個(gè)三角形區(qū)域就行了。

所以對(duì)于一幅 w * h 的圖像,設(shè)圓角大小為 n,n <= min(w, h) / 2,其復(fù)雜度為 O(n) = 2(n^2),最壞的情況計(jì)算量也不會(huì)超過(guò) wh / 2

對(duì)于一個(gè)像素點(diǎn)(x, y),判斷其在不在圓內(nèi)的公式

如果  (x-cx)^2 + (y-cy)^2 <= r^2  就表示點(diǎn) (x, y) 在圓內(nèi),反之不在。

理論說(shuō)完了,下面看實(shí)際的測(cè)試數(shù)據(jù)。

測(cè)試結(jié)果與分析

根據(jù)上面的分析,我寫(xiě)了一個(gè)裁剪圓角的程序,叫為 my裁剪。
還用了蘋(píng)果 CoreGraphics 庫(kù)的 CGContext 裁剪圓角,叫為 CGContext 裁剪。
還用了 UIKit 的 UIBezierPath 裁剪圓角,叫為 貝塞爾裁剪。

下面來(lái)對(duì)比三種方法,哪種最快,分別是
1. my裁剪
2. CGContext裁剪
3. 貝塞爾裁剪


實(shí)驗(yàn)數(shù)據(jù):
一張 png 格式 512 * 512 的 lena 女神的標(biāo)準(zhǔn)實(shí)驗(yàn)圖像。
圓角大小分別取 10,50,100,250,這4個(gè)值。
每次實(shí)驗(yàn)裁剪 10000 張圖片數(shù)據(jù),獲得總耗時(shí)。

因?yàn)閳D片是 512 * 512 的,最大的圓角為 512 / 2 = 256,所以超過(guò) 256 的會(huì)被強(qiáng)制設(shè)在 256,所以實(shí)驗(yàn)中用了個(gè)近似 256 的 250 做為最大的測(cè)試數(shù)據(jù)。

實(shí)驗(yàn)前關(guān)閉所有比較耗CPU的軟件。實(shí)驗(yàn)中不操作電腦,避免影響實(shí)驗(yàn)結(jié)果準(zhǔn)確性,最好真機(jī)測(cè)試,關(guān)掉后臺(tái)所有APP。最后得到了以下實(shí)驗(yàn)數(shù)據(jù),并繪制成表格。

表格.jpeg

根據(jù)上圖可以看出 my 裁剪運(yùn)行時(shí)間看起來(lái)像指數(shù)上升的,是不是會(huì)更慢?
答:不是的,看 x 軸的坐標(biāo)間距,10 到 50 到 100,然后直接跳到 250 了,不是均等分的!要是畫(huà)均等分的話,圖會(huì)非常非常長(zhǎng)。
如果要 x, y 軸刻度均等分的話,畫(huà)出來(lái)的圖大概是這樣的,如下圖:

表格2.jpeg

my 裁剪時(shí)間隨著圓角大小線性上升,到達(dá) 256 的時(shí)候,是最大值了。

實(shí)驗(yàn)過(guò)程中的具體數(shù)據(jù)。

  • 圓角為 10 的情況
裁剪方法 用時(shí) ms
my裁剪 2085
CGContext裁剪 15270
貝塞爾裁剪 14317
圓角為 10
  • 圓角為 50 的情況
裁剪方法 用時(shí) ms
my裁剪 2419
CGContext裁剪 14676
貝塞爾裁剪 14612
圓角為 50
  • 圓角為 100 的情況
裁剪方法 用時(shí) ms
my裁剪 3662
CGContext裁剪 14646
貝塞爾裁剪 14597
圓角為 100
  • 圓角為 250 的情況
裁剪方法 用時(shí) ms
my裁剪 12399
CGContext裁剪 14692
貝塞爾裁剪 14313
圓角為 250

結(jié)論與分析

從上面數(shù)據(jù)可以看出:
時(shí)間上:不管圓角大小 n 是多少,CGContext 和 UIBezierPath,耗時(shí)都在 14.6 秒左右。而 my裁剪在圓角小的時(shí)候,性能較好,耗時(shí)在 3 秒左右,隨著圓角增到250,耗時(shí)也去到了 12 秒,但最壞不會(huì)超過(guò) w * h / 2,在 n < min(w, h) / 2 時(shí),具有較高的性能,比CGContext, UIBezierPath要快。

空間上:內(nèi)存使用上,沒(méi)精確測(cè)量,大致看了一下,裁剪1萬(wàn)張 512 * 512的圖片,3種算法的內(nèi)存使用都在 10MB 左右,還可以接受,但 UIBezierPath 裁剪時(shí)居然會(huì)寫(xiě)磁盤(pán)。

另外,在圖像編碼/解碼中,用了 CGDataProviderRef,CGImageRef,這兩個(gè)對(duì)象,它們的速度應(yīng)該是很快的了,如果自己寫(xiě)的話,預(yù)測(cè)可以更快。

最后口說(shuō)無(wú)憑,我發(fā)個(gè)代碼可以自己下載運(yùn)行看看結(jié)果(下載地址
使用方法都在代碼的 ViewController.m 文件里,就這么一個(gè)文件,很好找,沒(méi)有其他了。請(qǐng)?jiān)?iphone6,6 plus 的屏幕下運(yùn)行。本實(shí)驗(yàn)重點(diǎn)在于3個(gè)算法,無(wú)關(guān)緊要的東西沒(méi)做太多處理。

最后編輯于
?著作權(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)容

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