如何實現photoshop的套索功能

 


最近沒事在研究PS中一些我比較感興趣的功能的實現方法,上一次實現了套索的螞蟻線功能,效果還行。此次就來看看套索自己是如何實現的。算法

整體來講要實現這個功能主要包括如下幾個方面:一、套索也即複雜多邊形的內外部識別;二、生成bitmap(相似於GDI中的region(區域));三、根據bitmap轉換成套索;四、bitmap布爾操做。dom


---原理、實現---spa

一、套索也即複雜多邊形的內外部識別3d

如何識別一個複雜多邊形的內部區域,有兩種經常使用的方法:一、奇偶規則(odd-even rule) 二、非零環繞數規則(nonzero winding-number rule)。blog

PS中使用的是非零環繞數規則,這個網上資料不少,在這簡單說一下規則:首先假定多邊形的邊是有方向的:好比規定順時針是正方向,逆時針是負方向。這時判斷一個點是否在多邊形內,能夠從這一點向多邊形外發射一條直線,直線每通過一條邊根據此邊是正方向仍是負方向分別+1和-1,最後統計若是非零則此點在多邊形內,不然在外。爲了方便計算通常引一條與X軸平行的線進行計算,這個方法主要的麻煩就在射線與邊線以及邊線與邊線之間的交點計算,由於求交點是判斷線段方向的前提,從圖形學上來講計算線段的相交性及交點都是比較麻煩的事。ip

有沒有辦法能夠簡化這些計算呢?上面的計算之因此麻煩是由於是從通常圖形學角度來看的——線段是無限連續的,只能經過線段總體判斷方向;若是隻從計算機圖形學的角度看——線段被光柵化、再也不是連續的、最小單位是像素、線段能夠用連續的像素點表示——這個線段能夠被離散化的特性就是簡化計算的關鍵——判斷方向不須要計算線段交點,只經過相鄰點的座標值比較便可判斷。it

具體方法就是以像素爲單位,沿着繪製多邊形邊的順序,對每一個通過的座標點維護一個值,順時針移動時(比較Y值便可,比上一個點Y值大的表示順時針)+1,逆時針移動-1,與X軸平行的點設爲0,而後經過掃描這個結構(在此是一個二維表),就能夠肯定多邊形的內外部區域,生成bitmap。io


二、生成bitmap(相似於GDI中的region(區域))asm

相似邊界標誌算法,用平行於X軸的掃描線自左向右掃描上面生成的二維表結構,累加掃描通過的像素對應的值,不爲0的即爲內部點,填充到bitmap(位圖)。原理


三、根據bitmap轉換成套索

自上向下、從左到右兩個方向掃描bitmap,記錄輪廓線。


四、bitmap布爾操做

與、或、非、異或、減 (相似GDI裏ROP碼(光柵操做))

具體看dome和代碼

 

效果圖: 圖1 原始線段

           圖2 邊線賦值、區份內外

           圖3 新邊緣

                                               

                        圖1                                                                         圖2                                                                        圖3


---存在問題---

前面說了線段能夠被離散化的特性是簡化計算的關鍵,但代價是引入了交點計算偏差,從理論上說兩方向相反非平衡的線段相交必有一個交點(見圖4),根據非零環繞規則這個點的環繞數爲0(1+-1=0),是一個外部的不該該顯示的點。在用像素模擬線段交點時,根據的是像素是否重疊來判斷交點的,但在有的狀況下兩條線段會出現相交而沒有像素重疊的狀況(見圖5),這樣簡化方法沒法斷定交點,對此只能看成相鄰的方向相反的像素來處理,本應環繞數爲0而斷開的位置,會有1個或幾個(根據斜率)像素繼續存在,會形成本不應聯通的位置聯通,同時用戶使用此功能時也可能產生混亂。

                     

                   圖4                                                               圖5

---解決辦法---

解決辦法很簡單就是不理它、無視它、塞到桌子下面看成這個世界依然完美,由於photoshop就是這麼幹的(有沒有"說的如此有道理我居然無言以對"的感受)?嗯~試着猜一下PS容許這樣乾的理由:一、偏差影響範圍有限,只在交點出現而且隻影響周圍有限幾個像素;二、這個功能自己不須要那麼精確。


---一點感想---

想了不少辦法也作不到與ps的bitmap輪廓線徹底相同,不過各有優劣,ps大法雖好,這個細節作的也並不是完美^^,不同就不同吧。

相關算法找準關鍵字——「非零環繞數規則「、「多邊形填充中的邊界標誌算法」——網上搜一搜都有。

 

---代碼及程序(masm32)---

http://files.cnblogs.com/hhh2000/nonzero.zip

相關文章
相關標籤/搜索