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

SARS_蔡 7年前發布 | 7K 次閱讀 算法 圖像處理 iOS開發 移動開發

場景

經常看到各種高效裁剪圓角的文章,正好之前做過一點數字圖像處理,就打算用空域處理的辦法,寫個裁剪圓角的算法,一定要盡可能的快的,不然界面容易卡頓。

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

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

一個 優化 就是,我不需要遍歷全部的像素就能裁出圓角,只需要考慮類似左下角三角形的區域就行了,左下,左上,右上,右下,一共4個三角形區域(另外3個圖中沒畫出),for循環的時候,就循環這個4個三角形區域就行了。

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

對于一個像素點(x, y),判斷其在不在圓內的公式

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

理論說完了,下面看實際的測試數據。

測試結果與分析

根據上面的分析,我寫了一個裁剪圓角的程序,叫為 my裁剪

還用了蘋果 CoreGraphics 庫的 CGContext 裁剪圓角,叫為 CGContext 裁剪

還用了 UIKit 的 UIBezierPath 裁剪圓角,叫為 貝塞爾裁剪

下面來對比三種方法,哪種最快,分別是

1.my裁剪

2.CGContext裁剪

3.貝塞爾裁剪

實驗數據:

一張 png 格式 512 * 512 的 lena 女神的標準實驗圖像。

圓角大小分別取 10,50,100,250,這4個值。

每次實驗裁剪 10000 張圖片數據,獲得總耗時。

因為圖片是 512 * 512 的,最大的圓角為 512 / 2 = 256,所以超過 256 的會被強制設在 256,所以實驗中用了個近似 256 的 250 做為最大的測試數據。

實驗前關閉所有比較耗CPU的軟件。實驗中不操作電腦,避免影響實驗結果準確性,最好真機測試,關掉后臺所有APP。最后得到了以下實驗數據,并繪制成表格。

表格.jpeg

根據上圖可以看出 my 裁剪運行時間看起來像指數上升的,是不是會更慢?

答:不是的,看 x 軸的坐標間距,10 到 50 到 100,然后直接跳到 250 了,不是均等分的!要是畫均等分的話,圖會非常非常長。

如果要 x, y 軸刻度均等分的話,畫出來的圖大概是這樣的,如下圖:

表格2.jpeg

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

實驗過程中的具體數據。

  • 圓角為 10 的情況

  • 圓角為 50 的情況

  • 圓角為 100 的情況

  • 圓角為 250 的情況

結論與分析

從上面數據可以看出:

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

空間上:內存使用上,沒精確測量,大致看了一下,裁剪1萬張 512 * 512的圖片,3種算法的內存使用都在 10MB 左右,還可以接受,但 UIBezierPath 裁剪時居然會寫磁盤。

另外,在圖像編碼/解碼中,用了 CGDataProviderRef,CGImageRef,這兩個對象,它們的速度應該是很快的了,如果自己寫的話,預測可以更快。

使用方法都在代碼的 ViewController.m 文件里,就這么一個文件,很好找,沒有其他了。請在 iphone6,6 plus 的屏幕下運行。本實驗重點在于3個算法,無關緊要的東西沒做太多處理。

 

 本文由用戶 SARS_蔡 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!