C#自定义画刷原理解析
作者:林子xxx 发布时间:2021-06-19 19:17:32
标签: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。使用不同的原图,就能得到各种各样的画刷。
来源:https://blog.csdn.net/wangzibigan/article/details/78993975
0
投稿
猜你喜欢
- ListView显示大量相同格式数据常用属性:listSelector listView每项在选中、按下等不同状态时的Drawablediv
- JSR303介绍在Java中提供了一系列的校验方式这些校验方式在javax.validation.constraints包中引入依赖<
- Java操作redis设置第二天凌晨过期场景在做查询数据的时候,遇到了需要设置数据在redis中第二天过期的问题,但是redis又没有对应的
- C#中+=是什么意思在C#中, "+="有两种运用场合。第一种,用在数值后面作为逻辑运算符,自加变量,如:int i=0
- 本文将带领大家实现第一个用eclipse写的第一个Javaweb项目–简单购物车。文章会在问题分析、具体实现和常见问题这三块为大家详细解说。
- HttpClient模拟浏览器登录后发起请求浏览器实现这个效果需要如下几个步骤: 1请求一个需要登录的页
- 新版的IDEA为了防止 pom 更新时,MAVEN 自动导包时卡死的问题,取消了自动导包机制。但新增了导入按钮和快捷键。 问题id
- Spring注入方式可以分为三类,xml注入、注解注入、BeanDefinition注入;用法上可以分为三种,但是底层实现代码都是统一Bea
- 本文实例汇总了C#中@的用法,对C#程序设计来说有不错的借鉴价值。具体如下:一 字符串中的用法1.学过C#的人都知道C# 中字符串常量可以以
- 情况一:问题idea项目突然无法运行,提示找不到某个类。查看了编译输出目录out,发现没有class文件。尝试解决尝试删除out、重新导入项
- java实现数据加密问题,具体代码如下所示:package Array;import java.util.Scanner;/*某个公司采用电
- 问题由来一个简单的需求,要求把和当前用户相关的数据置顶展示。这里,我用了一个简单的用户表来复现这个需求。很简单,查询语句后面加上:order
- 在上篇文章给大家介绍了使用Java8 实现观察者模式的方法(上),本文继续给大家介绍java8观察者模式相关知识,具体内容如下所述:线程安全
- 目录1、Java Application 源程序的主类是指包含有( )方法的类。2、如果定义一种表达式结构:(+ 6 3)的值为9,(- 6
- 前言《模式策略的角色扮演游戏》游戏是自制的角色扮演游戏。选择两个角色,然后进行PK,可用来学习JAVA的接口,继承和多态。主要设计1.事先设
- 一、堆的概念堆的定义:n个元素的序列{k1 , k2 , … , kn}称之为堆,当且仅当满足以下条件时:(1)ki
- 在开发中经常使用到Set集合去重,那么去重的原理是怎样实现的呢?在此文章记录一下去重原理!!!下面是set集合类图下面我们来跟踪一下执行过程
- 什么是EJB?EJB 是 Java 企业Bean, 是JavaEE服务端 企业组件模型,它的设计目标与核心应用是部署分布式应用程序。话不多说
- 前言每种语言都会有字符串的操作,因为字符串是我们平常开发使用频率最高的一种类型。今天我们来聊一下Java的字符串操作及在某些具体方法中与C#
- 将DataGrid中上面这个表头变成下面的两行表头,你会怎么实现?很巧妙地截断和补充td tr来实现来源:http://www.cnsend