C#自定义画刷原理解析

 更新时间:2022年08月19日 11:18:49   作者:林子xxx  
这篇文章主要为大家详细介绍了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。使用不同的原图,就能得到各种各样的画刷。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • 基于C#实现乱码视频效果

    基于C#实现乱码视频效果

    乱码视频效果可能很多人都在抖音看到过,即把一个短视频,转成数字、字母等乱码组成的形式进行播放。本文将用C#实现一下这一效果,感兴趣的可以了解一下
    2023-01-01
  • 深入了解c# 匿名类型

    深入了解c# 匿名类型

    这篇文章主要介绍了c# 匿名类型的相关资料,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • C#生成sitemap站点地图的方法

    C#生成sitemap站点地图的方法

    C#生成sitemap站点地图的方法,需要的朋友可以参考一下
    2013-04-04
  • UGUI实现图片拖拽功能

    UGUI实现图片拖拽功能

    这篇文章主要为大家详细介绍了UGUI实现图片拖拽功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-02-02
  • C#使用for循环移除HTML标记

    C#使用for循环移除HTML标记

    大家在项目开发阶段移除文字中的html标记最常用的方法就是使用正则表达式,但是正则表达式不能处理所有的html文档,所以采用迭代方式会更好,下面小编给大家解答下
    2016-08-08
  • C#中增加SQLite事务操作支持与使用方法

    C#中增加SQLite事务操作支持与使用方法

    这篇文章主要介绍了C#中增加SQLite事务操作支持与使用方法,结合实例形式分析了C#中针对SQLite事务操作的添加及使用技巧,需要的朋友可以参考下
    2017-07-07
  • WPF实现动画效果(六)之路径动画

    WPF实现动画效果(六)之路径动画

    这篇文章介绍了WPF实现动画效果之路径动画,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06
  • C#多线程传递参数及任务用法示例

    C#多线程传递参数及任务用法示例

    这篇文章主要介绍了C#多线程传递参数及任务用法,结合简单实例形式分析了C#多线程的使用及相关的参数传递与任务创建等使用技巧,需要的朋友可以参考下
    2016-06-06
  • C#实现QQ邮箱发送邮件

    C#实现QQ邮箱发送邮件

    今天小编就为大家分享一篇关于C#实现QQ邮箱发送邮件,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • C#中子类调用父类的实现方法

    C#中子类调用父类的实现方法

    这篇文章主要介绍了C#中子类调用父类的实现方法,通过实例逐步分析了类中初始化构造函数的执行顺序问题,有助于加深对C#面向对象程序设计的理解,需要的朋友可以参考下
    2014-09-09

最新评论