resizableImageWithCapInsets 方法的探析

SketchK發表於2016-03-08

1. 故事背景

蘋果公司為iOS開發者提供了以下的方法用於處理圖片的拉伸問題

但在實際使用過程中,我發現自己對該方法的理解不夠深入,所以今天特地編寫了一些程式碼來探析該方法!
好了,廢話不多說,下面我們就開始探析該方法的奧妙吧!

2. 方法介紹和說明

 


圖2.1 capInsets 引數示意圖.png

3. 設計實驗方法

實驗物件

Image物件尺寸為60*128(為行文方便,之後簡稱為原始影像,圖3.1)
ImageView物件尺寸為180*384(為行文方便,之後簡稱為相框)


圖3.1 原始影像.png

實驗方法

  1. 對原始影像使用拉伸方法並輸入不同的引數
  2. 將拉伸後的影像放入相框,觀察其拉伸效果

測試軟體的介面設計

介面設計如圖3.2
正上方為原始影像視窗,用於顯示原始影像的效果
左下方為測試影像視窗,用於顯示測試狀況的效果
右下方為對比影像視窗,用於顯示預設狀況的效果


圖3.2 測試軟體的介面設計.png

4.實驗分析

4.1 拉伸模式

resizingMode引數為UIImageResizingModeStretch

4.1.1.capInsets引數為UIEdgeInsetsMake(0, 0, 0, 0)時

當我們向拉伸方法傳入該組引數時,代表我們未對原始影像的任何區域進行保護.其拉伸效果如圖4.1.1
在該種情況下,我們發現原始影像按比例放大了3倍,因此我們將該情況當做拉伸模式下的預設狀況
在之後的實驗中,我們將該種狀況當做參考物件,顯示在介面的右下角


圖4.1.1 測試結果1.png

4.1.2.capInsets引數為UIEdgeInsetsMake(42, 0, 0, 0)時

當我們向拉伸方法傳入該組引數時,代表我們對原始影像上部的三分之一進行保護(即紅色方塊區域).其拉伸效果如圖4.1.2
在該種情況下,我們可以發現拉伸後的影像中:

  • 原始影像中受保護的區域(即紅色方塊區域)在Y軸方向保持了原比例,但在X軸方向進行了拉伸
  • 原始影像中未受保護的區域,直接按比例進行了拉伸

 


圖4.1.2 測試結果2.png

4.1.3.capInsets引數為UIEdgeInsetsMake(0,20, 0, 0)時

當我們向拉伸方法傳入該組引數時,代表我們對原始影像左部的三分之一進行保護(即紅色方塊區域).其拉伸效果如圖4.1.3
在該種情況下,我們可以發現拉伸後的影像中:

  • 原始影像中受保護的區域(即紅色方塊區域)在X軸方向保持了原比例,但在Y軸方向進行了拉伸
  • 原始影像中未受保護的區域,直接按比例進行了拉伸

 


圖4.1.3 測試結果3.png

4.1.4.capInsets引數為UIEdgeInsetsMake(42, 20, 42, 20)時

當我們向拉伸方法傳入該組引數時,代表我們對原始影像除數字5以外的區域進行保護(即兩個紅色方塊圍起來的區域).其拉伸效果如圖4.1.4
在該種情況下,我們可以發現拉伸後的影像中:

  • 在X軸上,由於1被左邊和上邊的設定保護,3被右邊和上邊的設定保護,所以只能用中間的2來拉伸,同理最底下的7,8,9
  • 在Y軸上,由於1被左邊和上邊的設定保護,7被左邊和下邊的設定保護,所以只能用中間的4來拉伸,同理最底下的3,6,9
  • 由於5沒有被保護,所以在整個剩餘的空間中,用5進行拉伸填充

 


圖4.1.4 測試結果4.png

4.2選擇平鋪模式

resizingMode引數為UIImageResizingModeTile

4.2.1.capInsets引數為UIEdgeInsetsMake(0, 0, 0, 0)時

當我們向拉伸方法傳入該組引數時,代表我們未對原始影像的任何區域進行保護.其平鋪效果如圖4.2.1
在該種情況下,我們發現原始影像按比例填充了相框,因此我們將該情況當做拉伸模式下的預設狀況
在之後的實驗中,我們將該種狀況當做參考物件,顯示在介面的右下角


圖4.2.1 測試結果1.png

4.2.2.capInsets引數為UIEdgeInsetsMake(42, 0, 0, 0)時

當我們向拉伸方法傳入該組引數時,代表我們對原始影像上部的三分之一進行保護(即紅色方塊區域).其平鋪效果如圖4.2.2
在該種情況下,我們可以發現拉伸後的影像中:

  • 原始影像中受保護的區域(即紅色方塊區域)在Y軸方向保持了原比例,但在X軸方向進行了平鋪填充
  • 原始影像中未受保護的區域,直接按比例進行了平鋪,但不包含被保護的區域(注意觀察藍色箭頭所指的區域)

 


Paste_Image.png

4.2.3.capInsets引數為UIEdgeInsetsMake(0,20, 0, 0)時

當我們向拉伸方法傳入該組引數時,代表我們對原始影像左部的三分之一進行保護(即紅色方塊區域).其平鋪效果如圖4.2.3
在該種情況下,我們可以發現拉伸後的影像中:

  • 原始影像中受保護的區域(即紅色方塊區域)在X軸方向保持了原比例,但在Y軸方向進行了平鋪填充
  • 原始影像中未受保護的區域,直接按比例進行了平鋪,但不包含被保護的區域(注意觀察藍色箭頭所指的區域)

 


圖4.2.3 測試結果3.png

4.2.4.capInsets引數為UIEdgeInsetsMake(42, 20, 42, 20)時

當我們向拉伸方法傳入該組引數時,代表我們對原始影像除數字5以外的區域進行保護(即兩個紅色方塊圍起來的區域).其拉伸效果如圖4.2.4
在該種情況下,我們可以發現拉伸後的影像中:

  • 在X軸上,由於1被左邊和上邊的設定保護,3被右邊和上邊的設定保護,所以只能用中間的2來平鋪,同理最底下的7,8,9
  • 在Y軸上,由於1被左邊和上邊的設定保護,7被左邊和下邊的設定保護,所以只能用中間的4來平鋪,同理最底下的3,6,9
  • 由於5沒有被保護,所以在整個剩餘的空間中,用5進行平鋪填充

 


圖4.2.4 測試結果4.png

5. 結論和建議

通過8組實驗資料可以觀察出拉伸方法在平鋪模式和拉伸模式下的變化過程和主要區別,由此我們可知:

  • 對原始圖形使用拉伸方法且在四周增加保護區域後,能保證原始圖形的四個角不失真,但其餘部分的變化細節則有不同
  • 如果原始影像的外輪廓不平整的話,使用拉伸方式會讓外輪廓的不平整度放大,使用平鋪方式應該能減小這種情況

6. 附錄-程式碼

為了縮短程式碼的長度,我使用了Storyboard搭建軟體介面,想重現實驗的朋友可以自行構建介面,具體的引數我在文章和附錄中進行了簡要說明,我相信聰明的你一定可以搞定!

相關文章