C#自定義畫刷原理解析
windows系統(tǒng)中的畫板工具,有好幾種畫刷,C#中并沒有直接對(duì)應(yīng)可使用的類,只能自己研究。
1.畫刷原理
根據(jù)本人對(duì)PS的相關(guān)功能細(xì)心分析,發(fā)現(xiàn)各種畫刷其實(shí)就是一幅圖片的移位重疊顯示。通常這幅畫刷圖是半透明的,只有其中一些區(qū)域有顏色。
上圖中的畫刷,把間隔設(shè)大之后可以明顯看到原圖的模樣。
這是基于位移的畫刷,另外有基于時(shí)間的,比如噴槍工具。
2.代碼實(shí)現(xiàn)
1). 直線算法
為什么要直線算法?因?yàn)槲覀円苿?dòng)鼠標(biāo),觸發(fā)MouseMove事件,記錄鼠標(biāo)前一坐標(biāo)點(diǎn)與當(dāng)前點(diǎn),如果兩點(diǎn)是是相鄰的,當(dāng)然不需要再做多余的算法,當(dāng)如果兩點(diǎn)是不相鄰的,我們就需要計(jì)算兩點(diǎn)之間所有的點(diǎn)。否則無法有效地進(jìn)行固定間隔繪制畫刷圖。
/// <summary> /// 順序獲取兩點(diǎn)間直線上的所有點(diǎn) /// </summary> /// <param name="pStart">開始點(diǎn)</param> /// <param name="pEnd">結(jié)束點(diǎn)</param> /// <returns>兩點(diǎn)間直線上的所有點(diǎn)</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).鼠標(biāo)事件
分別為鼠標(biāo)按下、移動(dòng)、放開事件
bool bIsDraw = false; //主圖畫線 Point startPoint_Draw = new Point();//劃線點(diǎn)變量 List<Point> pts = new List<Point>();//畫點(diǎn)保存
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(); ?? ? ? ? ? ? ? } ? ? ? ? }
如果根據(jù)位移方向加上圖片的角度旋轉(zhuǎn)效果,應(yīng)該會(huì)更加接近PS的效果。
3.效果
我使用的畫刷圖就是來源于本文上圖的PS畫刷。
圖中5條畫刷線分別使用間隔1,10,20,40,80。使用不同的原圖,就能得到各種各樣的畫刷。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C#中系統(tǒng)時(shí)間和UNIX時(shí)間戳互相轉(zhuǎn)換
本文主要介紹C#中系統(tǒng)時(shí)間和UNIX時(shí)間戳相互轉(zhuǎn)換的方法,大家可以直接拿去用,希望有用。2016-05-05Unity UGUI的LayoutElement布局元素組件介紹使用示例
這篇文章主要為大家介紹了Unity UGUI的LayoutElement布局元素組件介紹使用示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07C#實(shí)現(xiàn)Zip壓縮目錄中所有文件的方法
這篇文章主要介紹了C#實(shí)現(xiàn)Zip壓縮目錄中所有文件的方法,涉及C#針對(duì)文件的讀寫與zip壓縮相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-07-07