一个非常好用的图片切割工具(c# winform开发)
本人业余时间开发了一个图片切割工具,非常好用,也很灵活!
特别对大型图片切割,更能体现出该软件的优势!
功能说明
可以设定切割的高度和宽度。切割线可以上下拖动,可以增加一个切割区域,可设定某个区域不参与切割。
主要技术点分析
切割区域确定
每个切割区域是一个长方形。用一个结构标识该属性。
- class SpliteMoveIndex
- {
- public enum EN_DIR
- {
- NON,
- HORIZONTAL,
- VERTICAL
- };
- public EN_DIR direct = EN_DIR.NON;//0 无;1 水平;2垂直
- public int rectIndex; //第几个rect
- public int lineIndex; //第几个线 1:上或左;2 下或右
- public int mouseX;
- public int mouseY;
- public static SpliteMoveIndex CreateNon(int x, int y)
- {
- SpliteMoveIndex _nonIndex = new SpliteMoveIndex();
- _nonIndex.direct = EN_DIR.NON;
- _nonIndex.SetMouse(x, y);
- return _nonIndex;
- }
- public SpliteMoveIndex()
- {
- }
- public SpliteMoveIndex(int x, int y)
- {
- SetMouse(x, y);
- }
- public bool IsSameLine(SpliteMoveIndex another)
- {
- return this.direct == another.direct
- && this.rectIndex == another.rectIndex
- && this.lineIndex == another.lineIndex;
- }
- public bool IsIn()
- {
- return direct != EN_DIR.NON;
- }
- public bool IsHorIn()
- {
- return direct == EN_DIR.HORIZONTAL;
- }
- public bool IsVertIn()
- {
- return direct == EN_DIR.VERTICAL;
- }
- public void SetMouse(int x, int y)
- {
- mouseX = x;
- mouseY = y;
- }
- }
SpliteRectGroup 负责组合这些长方形。当有鼠标移动时,动态调整这些长方形大小,再重画!
- class SpliteRectGroup
- {
- List<Rectangle> _listSplitRect = new List<Rectangle>();
- int _widthSrc;
- int _heightSrc;
- SpliteMoveIndex _lastMoveIndex = new SpliteMoveIndex();
- public int _defaultHitSpace = ;
- int _moveAllFlagR = ;
- bool _isMoveAll = false;
- //不参加切割的区域
- List<int> _listSplitRectNotUsed = new List<int>();
- public void SetRect(int widthSrc, int heightSrc, int startX, int startY,
- int widthDest, int heightDest)
- {
- _widthSrc = widthSrc;
- _heightSrc = heightSrc;
- _listSplitRect.Clear();
- GetSplitSize(_widthSrc, _heightSrc, startX, startY,
- widthDest, heightDest, ref _listSplitRect);
- }
- public List<Rectangle> GetRects()
- {
- return _listSplitRect;
- }
- public List<Rectangle> GetRectsSplit()
- {
- List<Rectangle> listShow = new List<Rectangle>();
- int i = ;
- foreach(Rectangle rect in _listSplitRect)
- {
- if(IsRectUsed(i))
- {
- listShow.Add(rect);
- }
- i++;
- }
- return listShow;
- }
- public int GetStartX()
- {
- if (_listSplitRect.Count == )
- return ;
- Rectangle first = _listSplitRect.First();
- return first.X;
- }
- public int GetSpliteWidth()
- {
- if (_listSplitRect.Count == )
- return ;
- Rectangle first = _listSplitRect.First();
- return first.Width;
- }
- public int GetSpliteTotalHeight()
- {
- if (_listSplitRect.Count == )
- return ;
- int i = ;
- foreach (Rectangle r in _listSplitRect)
- {
- i += r.Height;
- }
- return i;
- }
- public void SetMoveAllFlag(bool flag)
- {
- _isMoveAll = flag;
- }
- public bool GetMoveAllFlag()
- {
- return _isMoveAll;
- }
- public int GetStartY()
- {
- if (_listSplitRect.Count == )
- return ;
- Rectangle first = _listSplitRect.First();
- return first.Y;
- }
- public void Draw(Graphics g)
- {
- SolidBrush brushRect = new SolidBrush(Color.FromArgb(, , , ));
- Font strfont = new Font("Verdana", );
- Brush strBrush = Brushes.Blue;
- Brush strBrushBack = Brushes.White;
- //起点圆
- int x = GetStartX();
- int y = GetStartY();
- g.FillEllipse(brushRect, x - _moveAllFlagR, y - _moveAllFlagR, * _moveAllFlagR, * _moveAllFlagR);
- brushRect.Dispose();
- //起点信息
- string startInfo = string.Format("({0}:{1})",x,y);
- SizeF sizeF = g.MeasureString(startInfo, strfont);
- Point ptStart = new Point((int)(x-sizeF.Width/), (int)(y -sizeF.Height- _defaultHitSpace*) );
- g.FillRectangle(strBrushBack, new RectangleF(ptStart, sizeF));
- g.DrawString(startInfo, strfont, strBrush, ptStart);
- //画方框
- Color backColor = Color.FromArgb(, Color.PowderBlue);
- HatchBrush hat1 = new HatchBrush(HatchStyle.OutlinedDiamond, Color.DarkBlue, backColor);
- HatchBrush hat2 = new HatchBrush(HatchStyle.OutlinedDiamond, Color.Red, backColor);
- //输出提示信息
- Pen rectPen = Pens.Red;
- int i = ;
- int showIndex = ;
- string info;
- foreach (Rectangle rect in _listSplitRect)
- {
- i++;
- bool used = IsRectUsed(rect);
- if (used)
- {
- showIndex++;
- info = string.Format("{0}-({1}:{2})", showIndex, rect.Width, rect.Height);
- }
- else
- {
- info = string.Format("({0}:{1})--不参与切割", rect.Width, rect.Height);
- }
- g.DrawRectangle(rectPen, rect);
- if (!used)
- {
- g.FillRectangle(hat1, rect);
- }
- Point strStart = new Point(rect.X + , rect.Y + );
- sizeF = g.MeasureString(info, strfont);
- g.FillRectangle(strBrushBack, new RectangleF(strStart, sizeF));
- g.DrawString(info, strfont, strBrush, strStart);
- }
- strfont.Dispose();
- hat1.Dispose();
- hat2.Dispose();
- }
- public bool StartPointMoveTo(int x, int y)
- {
- if (_listSplitRect.Count == )
- return false;
- Rectangle first = _listSplitRect.First();
- int moveX = x - first.X;
- int moveY = y - first.Y;
- List<Rectangle> listSplitRectNew = new List<Rectangle>();
- foreach (Rectangle r in _listSplitRect)
- {
- Rectangle tmp = r;
- tmp.Offset(moveX, moveY);
- listSplitRectNew.Add(tmp);
- }
- _listSplitRect.Clear();
- _listSplitRect = listSplitRectNew;
- return true;
- }
- public bool IsAllMove(int mouseX, int mouseY)
- {
- GraphicsPath myGraphicsPath = new GraphicsPath();
- myGraphicsPath.Reset();
- Region myRegion = new Region();
- int x = GetStartX();
- int y = GetStartY();
- myGraphicsPath.AddEllipse(x - _moveAllFlagR, y - _moveAllFlagR, * _moveAllFlagR, * _moveAllFlagR);//points);
- myRegion.MakeEmpty();
- myRegion.Union(myGraphicsPath);
- //返回判断点是否在多边形里
- bool myPoint = myRegion.IsVisible(mouseX, mouseY);
- return myPoint;
- }
- public void ResetMoveFlag()
- {
- _lastMoveIndex.direct = SpliteMoveIndex.EN_DIR.NON;
- }
- public bool SetMove(SpliteMoveIndex index)
- {
- //移动到区域外
- if (!index.IsIn())
- {
- _lastMoveIndex = index;
- return false;
- }
- //不是同一条线
- if (!_lastMoveIndex.IsSameLine(index))
- {
- _lastMoveIndex = index;
- return false;
- }
- //移动到新的区域
- MoveRect(_lastMoveIndex, index);
- _lastMoveIndex = index;
- return true;
- }
- public bool IsInSplite()
- {
- if (_lastMoveIndex == null)
- return false;
- return _lastMoveIndex.IsIn();
- }
- void MoveRect(SpliteMoveIndex last, SpliteMoveIndex now)
- {
- if (last.IsHorIn())
- {
- MoveRectHor(last, now);
- }
- else if (last.IsVertIn())
- {
- MoveRectVert(last, now);
- }
- }
- void MoveRectHor(SpliteMoveIndex last, SpliteMoveIndex now)
- {
- int moveY = now.mouseY - last.mouseY;
- List<Rectangle> listSplitRectNew = new List<Rectangle>();
- int i = ;
- int find = ;
- foreach (Rectangle r in _listSplitRect)
- {
- Rectangle tmp = r;
- i++;
- if (find == )
- {
- listSplitRectNew.Add(tmp);
- continue;
- }
- if (find == )
- {
- tmp.Y += moveY;
- tmp.Height -= moveY;
- find = ;
- listSplitRectNew.Add(tmp);
- continue;
- }
- if (i == last.rectIndex)
- {
- if (last.lineIndex == )
- {
- tmp.Y += moveY;
- tmp.Height -= moveY;
- find = ;
- listSplitRectNew.Add(tmp);
- }
- else if (last.lineIndex == )
- {
- tmp.Height += moveY;
- find = ;
- listSplitRectNew.Add(tmp);
- }
- }
- else
- {
- listSplitRectNew.Add(tmp);
- }
- }
- _listSplitRect.Clear();
- _listSplitRect = listSplitRectNew;
- }
- void MoveRectVert(SpliteMoveIndex last, SpliteMoveIndex now)
- {
- int moveX = now.mouseX - last.mouseX;
- List<Rectangle> listSplitRectNew = new List<Rectangle>();
- int i = ;
- foreach (Rectangle r in _listSplitRect)
- {
- Rectangle tmp = r;
- i++;
- if (last.lineIndex == )
- {
- tmp.X += moveX;
- tmp.Width -= moveX;
- listSplitRectNew.Add(tmp);
- }
- else if (last.lineIndex == )
- {
- tmp.Width += moveX;
- listSplitRectNew.Add(tmp);
- }
- }
- _listSplitRect.Clear();
- _listSplitRect = listSplitRectNew;
- }
- SpliteMoveIndex GetHorizontal(int x, int y, int hitSpace)
- {
- int startX = GetStartX();
- int width = GetSpliteWidth();
- if (x < startX || x > (startX + width))
- return SpliteMoveIndex.CreateNon(x, y);
- int i = ;
- foreach (Rectangle rect in _listSplitRect)
- {
- i++;
- int y1 = rect.Y;
- //是否落在水平线 一定范围内
- if (y >= y1 - hitSpace && y <= (y1 + hitSpace))
- {
- SpliteMoveIndex moveIndex = new SpliteMoveIndex(x, y);
- moveIndex.direct = SpliteMoveIndex.EN_DIR.HORIZONTAL;
- moveIndex.rectIndex = i;
- moveIndex.lineIndex = ;
- return moveIndex;
- }
- int y2 = rect.Y + rect.Height;
- if (y >= (y2 - hitSpace) && y <= (y2 + hitSpace))
- {
- SpliteMoveIndex moveIndex = new SpliteMoveIndex(x, y);
- moveIndex.direct = SpliteMoveIndex.EN_DIR.HORIZONTAL;
- moveIndex.rectIndex = i;
- moveIndex.lineIndex = ;
- return moveIndex;
- }
- }
- return SpliteMoveIndex.CreateNon(x, y);
- }
- SpliteMoveIndex GetVectical(int x, int y, int hitSpace)
- {
- int startY = GetStartY();
- if (y < startY || y > (startY + _heightSrc))
- return SpliteMoveIndex.CreateNon(x, y);
- int i = ;
- foreach (Rectangle rect in _listSplitRect)
- {
- i++;
- //是否落在垂直线 一定范围内
- if (y >= rect.Y && y <= (rect.Y + rect.Height))
- {
- int x1 = rect.X;
- if (x >= (x1 - hitSpace) && x <= (x1 + hitSpace))
- {
- SpliteMoveIndex moveIndex = new SpliteMoveIndex(x, y);
- moveIndex.direct = SpliteMoveIndex.EN_DIR.VERTICAL;
- moveIndex.rectIndex = i;
- moveIndex.lineIndex = ;
- return moveIndex;
- }
- int x2 = rect.X + rect.Width;
- if (x >= (x2 - hitSpace) && x <= (x2 + hitSpace))
- {
- SpliteMoveIndex moveIndex = new SpliteMoveIndex(x, y);
- moveIndex.direct = SpliteMoveIndex.EN_DIR.VERTICAL;
- moveIndex.rectIndex = i;
- moveIndex.lineIndex = ;
- return moveIndex;
- }
- }
- }
- return SpliteMoveIndex.CreateNon(x, y);
- }
- public SpliteMoveIndex PointHit(int x, int y, int hitSpace)
- {
- //判断是否在水平线
- SpliteMoveIndex hRect = GetHorizontal(x, y, hitSpace);
- if (hRect.IsIn())
- return hRect;
- //判断是否在垂直线
- SpliteMoveIndex vRect = GetVectical(x, y, hitSpace);
- if (vRect.IsIn())
- return vRect;
- return SpliteMoveIndex.CreateNon(x, y);
- }
- public bool PointInRect(int x,int y)
- {
- int startX = GetStartX();
- int width = GetSpliteWidth();
- if (x < startX || x > (startX + width))
- return false;
- int startY = GetStartY();
- int heght = GetSpliteTotalHeight();
- if (y < startY || y > (startY + heght))
- return false;
- return true;
- }
- public void ClearNotUsedRect()
- {
- _listSplitRectNotUsed.Clear();
- }
- public bool GetRectIndex(int index,ref Rectangle outRect)
- {
- int i = ;
- foreach (Rectangle rect in _listSplitRect)
- {
- if (i == index)
- {
- outRect = rect;
- return true;
- }
- i++;
- }
- return false;
- }
- public bool IsNotUsed(int x, int y)
- {
- Rectangle rect = new Rectangle();
- foreach (int n in _listSplitRectNotUsed)
- {
- if (GetRectIndex(n, ref rect) && rect.Contains(x, y))
- {
- return true;
- }
- }
- return false;
- }
- public bool IsRectUsed(Rectangle rect)
- {
- Rectangle rectNot = new Rectangle();
- foreach (int n in _listSplitRectNotUsed)
- {
- if (GetRectIndex(n, ref rectNot) && rectNot == rect)
- {
- return false;
- }
- }
- return true;
- }
- public bool IsRectUsed(int index)
- {
- foreach (int n in _listSplitRectNotUsed)
- {
- if (n == index)
- return false;
- }
- return true;
- }
- //区块加入切割
- public bool AddRectUsed(int x,int y)
- {
- int i = ;
- Rectangle rectNot = new Rectangle();
- foreach (int n in _listSplitRectNotUsed)
- {
- if (GetRectIndex(n, ref rectNot) && rectNot.Contains(x,y))
- {
- _listSplitRectNotUsed.RemoveAt(i);
- return true;
- }
- i++;
- }
- return false;
- }
- //区块不加入切割
- public bool DelRectUsed(int x, int y)
- {
- int i = ;
- foreach (Rectangle rect in _listSplitRect)
- {
- if (rect.Contains(x, y))
- {
- _listSplitRectNotUsed.Add(i);
- return true;
- }
- i++;
- }
- return false;
- }
- public bool AddHorLine(int x, int y)
- {
- List<Rectangle> listSplitRectNew = new List<Rectangle>();
- foreach (Rectangle rect in _listSplitRect)
- {
- if (y > rect.Y && y < rect.Y + rect.Height)
- {
- Rectangle r1 = new Rectangle(rect.Location, rect.Size);
- r1.Height = y - rect.Y;
- listSplitRectNew.Add(r1);
- r1.Y = y ;
- r1.Height = (rect.Y + rect.Height - y);
- listSplitRectNew.Add(r1);
- }
- else
- {
- listSplitRectNew.Add(rect);
- }
- }
- _listSplitRect = listSplitRectNew;
- return true;
- }
- //删除水平线
- public bool DeleteHorSplite(SpliteMoveIndex index)
- {
- List<Rectangle> listSplitRectNew = new List<Rectangle>();
- int i = ;
- bool del = false;
- Rectangle lastRect = new Rectangle();
- bool haveLast = false;
- foreach (Rectangle rect in _listSplitRect)
- {
- i++;
- if(haveLast)
- {
- haveLast = false;
- lastRect.Height += rect.Height;
- listSplitRectNew.Add(lastRect);
- continue;
- }
- if(index.rectIndex == i)
- {
- del = true;
- if (index.lineIndex == )
- {
- if(listSplitRectNew.Count == )
- {
- continue;
- }
- else
- {
- Rectangle r = listSplitRectNew.Last();
- r.Height += rect.Height;
- listSplitRectNew.RemoveAt(listSplitRectNew.Count-);
- listSplitRectNew.Add(r);
- }
- }
- else if (index.lineIndex == )
- {
- if(i == _listSplitRect.Count)
- {
- continue;
- }
- else
- {
- lastRect = rect;
- haveLast = true;
- }
- }
- else { Debug.Assert(false); }
- }
- else
- {
- listSplitRectNew.Add(rect);
- }
- }
- _listSplitRect = listSplitRectNew;
- return del;
- }
- public static int GetSplitSize(int widthSrc, int heightSrc, int startX, int startY,
- int widthDest, int heightDest, ref List<Rectangle> listOut)
- {
- listOut = new List<Rectangle>();
- int width = Math.Min(widthSrc - startX, widthDest);
- int i = ;
- bool stop = false;
- while (!stop)
- {
- Rectangle rect = new Rectangle();
- rect.X = startX;
- rect.Y = startY + (i * heightDest);
- rect.Width = width;
- rect.Height = heightDest;
- if (rect.Y + rect.Height >= heightSrc)
- {
- stop = true;
- rect.Height = heightSrc - rect.Y;
- }
- listOut.Add(rect);
- i++;
- }
- return ;
- }
- }
图像快速切割
图像切割其实就是在一个内存中重新绘制,再将内存中的数据保存到文件。切割代码如下:
- 。。。
技术交流联系qq 13712486
一个非常好用的图片切割工具(c# winform开发)的更多相关文章
- 一个非常好用的图片切割工具(c# winform开发) 附源码
本人业余时间开发了一个图片切割工具,非常好用,也很灵活! 特别对大型图片切割,更能体现出该软件的优势! 开发工具为winform,源码下载地址:http://download.csdn.net/dow ...
- ShoeBox一个超级好用的图片切割工具
下载地址:http://renderhjs.net/shoebox/ ShoeBox是一个图片处理软件,体积很小. 我主要用第三个功能拆开图片.根据大图上的小图空白间隙来处理的. 导出后变成很多小图
- 一个web图片热点生成工具(winform开发) 附源码
给图片加热点是web开发中经常用到的一个功能.这方面的工具也不少. 为了更好的满足自己的需求,写了一个winform程序. 可以方便的给图片加热点,更方便灵活! 源码下载 http://downloa ...
- 图片切割工具---产生多个div切割图片 采用for和一的二维阵列设置背景位置
照片库 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveGlhb21vZ2c=/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...
- 网络请求以及网络请求下载图片的工具类 android开发java工具类
package cc.jiusan.www.utils; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; ...
- Android中将一个图片切割成多个图片
有种场景,我们想将一个图片切割成多个图片.比如我们在开发一个拼图的游戏,就首先要对图片进行切割. 以下是封装好的两个类,可以实现图片的切割.仅供参考和学习. 一个是ImagePiece类,此类保存了一 ...
- Android中将一个图片切割成多个图片[转]
有种场景,我们想将一个图片切割成多个图片.比如我们在开发一个拼图的游戏,就首先要对图片进行切割. 以下是封装好的两个类,可以实现图片的切割.仅供参考和学习. 一个是ImagePiece类,此类保存了一 ...
- 转: ImageMagick 命令行的图片处理工具(客户端与服务器均可用)
http://www.imagemagick.com.cn/ 关于ImageMagick ImageMagick (TM) 是一个免费的创建.编辑.合成图片的软件.它可以读取.转换.写入多种格式的图片 ...
- Java操作图片的工具类
操作图片的工具类: import java.awt.AlphaComposite; import java.awt.Color; import java.awt.Font; import java.a ...
随机推荐
- (最小生成树)Jungle Roads -- HDU --1301
链接: http://acm.hdu.edu.cn/showproblem.php?pid=1301 http://acm.hust.edu.cn/vjudge/contest/view.action ...
- linux的客户端安装步骤配置
现有一个***.tar.gz的客户端软件,现在客户端安装步骤如下 说明:此软件是一个网络客户端认证软件,因为采用虚拟机中的linux主机,所以此主机的网路配置从只能使用Bridge模式,而不能使用NA ...
- word中添加引文操作
word中添加引文操作 转化为pdf的时候,可以通过引文处进行ctrl + 左键点击,挑战到相应的后文中的参考引文位置. 1.在文章末尾添加如下内容,并在他的下面添加一条被引文的格式
- hdu 4268 贪心+set lower_bound用法
http://acm.hdu.edu.cn/showproblem.php?pid=4268 A想用手里的牌尽量多地覆盖掉B手中的牌.. 牌有h和w 问A手中的牌最多能覆盖B多少张牌 iterator ...
- Android Sqlite 简单SQL语句
--- 创建表 create table student(_id integer primary key autoincrement, name text); --- 查询全部 select _id, ...
- bootstrap-table 中取主键字段的问题,主键名不叫id
问题 :取不到数据行的主键 要绑定的数据字段 RoleId rolename adddate RoleId 为主键是唯一的 bootstraptable的配置 uniqueId: "Role ...
- [ACM_水题] UVA 12502 Three Families [2人干3人的活后分钱,水]
Three Families Three families share a garden. They usually clean the garden together at the end o ...
- 安装docker ce版
可参考 菜鸟教程:http://www.runoob.com/docker/centos-docker-install.html 官网教程:https://docs.docker.com/instal ...
- wpf expender 展开动画
非原创,网上下载的,觉得还可以,记录一下以便以后查看学习 <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2 ...
- 编码CODING
摘自(复制)于海燕博客: http://www.cnblogs.com/haiyan123/p/7230533.html 1.内存和硬盘都是用来存储的. CPU:速度快 硬盘:永久保存 2.文本编辑器 ...