C#自定義畫刷原理解析
windows系統中的畫板工具,有好幾種畫刷,C#中並沒有直接對應可使用的類,隻能自己研究。
1.畫刷原理
根據本人對PS的相關功能細心分析,發現各種畫刷其實就是一幅圖片的移位重疊顯示。通常這幅畫刷圖是半透明的,隻有其中一些區域有顏色。
上圖中的畫刷,把間隔設大之後可以明顯看到原圖的模樣。
這是基於位移的畫刷,另外有基於時間的,比如噴槍工具。
2.代碼實現
1). 直線算法
為什麼要直線算法?因為我們移動鼠標,觸發MouseMove事件,記錄鼠標前一坐標點與當前點,如果兩點是是相鄰的,當然不需要再做多餘的算法,當如果兩點是不相鄰的,我們就需要計算兩點之間所有的點。否則無法有效地進行固定間隔繪制畫刷圖。
/// <summary> /// 順序獲取兩點間直線上的所有點 /// </summary> /// <param name="pStart">開始點</param> /// <param name="pEnd">結束點</param> /// <returns>兩點間直線上的所有點</returns> private List<Point> getPoint2Point(Point pStart, Point pEnd) { List<Point> linePoint = new List<Point>(); if (pStart.X == pEnd.X && pStart.Y == pEnd.Y) { linePoint.Add(pStart); return linePoint; } DDALine(pStart.X, pStart.Y, pEnd.X, pEnd.Y, ref linePoint); return linePoint; } //DDA直線畫法 private void DDALine(int x0, int y0, int x1, int y1, ref List<Point> ptl) { int dx,dy,eps1,k; float x,y,xIncre,yIncre; dx=x1-x0; dy=y1-y0; x=x0; y=y0; if(Math.Abs(dx)>Math.Abs(dy)) eps1=Math.Abs(dx); else eps1=Math.Abs(dy); xIncre=(float)dx/(float)eps1; yIncre=(float)dy/(float)eps1; for(k=0;k<=eps1;k++) { ptl.Add( new Point((int)(x + 0.5), (int)(y + 0.5)) ); x+=xIncre; y+=yIncre; } }
2).鼠標事件
分別為鼠標按下、移動、放開事件
bool bIsDraw = false; //主圖畫線 Point startPoint_Draw = new Point();//劃線點變量 List<Point> pts = new List<Point>();//畫點保存
private void pictureBox_main_MouseMove(object sender, MouseEventArgs e) { PictureBox pb = sender as PictureBox; ssl_point.Text = e.Location.ToString(); pb.Refresh(); if (bIsDraw) { Point p = limitPoint(e.Location, pictureBox_main.ClientSize); if (p == startPoint_Draw) return; Graphics gs = Graphics.FromImage(pb.Image); if (pictureBox_main.Image != null ) { List<Point> pl = getPoint2Point(startPoint_Draw, p); pl.RemoveAt(0); pts.AddRange(pl); if (pts.Count >= peninv) { for (int i = penmod; i < pts.Count; i += peninv) { gs.DrawImage(blushbmp_curr, pts[i].X - pensize , pts[i].Y - pensize , pensize*2, pensize*2); } penmod = pts.Count % peninv; pts.RemoveRange(0, pts.Count - penmod); } } gs.Dispose(); startPoint_Draw = p; } } private void pictureBox_main_MouseDown(object sender, MouseEventArgs e) { if(e.Button == System.Windows.Forms.MouseButtons.Left) if (bIsDraw == false) { startPoint_Draw = e.Location; pts.Clear(); pts.Add(startPoint_Draw); bIsDraw = true; } } private void pictureBox_main_MouseUp(object sender, MouseEventArgs e) { if (bIsDraw == true) { bIsDraw = false; if (pictureBox_main.Image != null ) { pts.Clear(); } pictureBox_main.Refresh(); } }
如果根據位移方向加上圖片的角度旋轉效果,應該會更加接近PS的效果。
3.效果
我使用的畫刷圖就是來源於本文上圖的PS畫刷。
圖中5條畫刷線分別使用間隔1,10,20,40,80。使用不同的原圖,就能得到各種各樣的畫刷。
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。