博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一个非常好用的图片切割工具(c# winform开发)
阅读量:5924 次
发布时间:2019-06-19

本文共 15235 字,大约阅读时间需要 50 分钟。

本人业余时间开发了一个图片切割工具,非常好用,也很灵活!

特别对大型图片切割,更能体现出该软件的优势!

功能说明

可以设定切割的高度和宽度。切割线可以上下拖动,可以增加一个切割区域,可设定某个区域不参与切割。

主要技术点分析

切割区域确定

  每个切割区域是一个长方形。用一个结构标识该属性。

1 class SpliteMoveIndex 2     { 3         public enum EN_DIR 4         { 5             NON, 6             HORIZONTAL, 7             VERTICAL 8         }; 9         public EN_DIR direct = EN_DIR.NON;//0 无;1 水平;2垂直10         public int rectIndex; //第几个rect11         public int lineIndex; //第几个线 1:上或左;2 下或右12         public int mouseX;13         public int mouseY;14 15 16         public static SpliteMoveIndex CreateNon(int x, int y)17         {18             SpliteMoveIndex _nonIndex = new SpliteMoveIndex();19             _nonIndex.direct = EN_DIR.NON;20             _nonIndex.SetMouse(x, y);21             return _nonIndex;22         }23 24         public SpliteMoveIndex()25         {26 27         }28         public SpliteMoveIndex(int x, int y)29         {30             SetMouse(x, y);31         }32 33         public bool IsSameLine(SpliteMoveIndex another)34         {35             return this.direct == another.direct36                 && this.rectIndex == another.rectIndex37                 && this.lineIndex == another.lineIndex;38         }39 40         public bool IsIn()41         {42             return direct != EN_DIR.NON;43         }44         public bool IsHorIn()45         {46             return direct == EN_DIR.HORIZONTAL;47         }48         public bool IsVertIn()49         {50             return direct == EN_DIR.VERTICAL;51         }52 53         public void SetMouse(int x, int y)54         {55             mouseX = x;56             mouseY = y;57         }58     }
View Code

SpliteRectGroup 负责组合这些长方形。当有鼠标移动时,动态调整这些长方形大小,再重画!

1  class SpliteRectGroup  2     {  3         List
_listSplitRect = new List
(); 4 int _widthSrc; 5 int _heightSrc; 6 7 SpliteMoveIndex _lastMoveIndex = new SpliteMoveIndex(); 8 9 public int _defaultHitSpace = 5; 10 11 int _moveAllFlagR = 10; 12 bool _isMoveAll = false; 13 14 //不参加切割的区域 15 List
_listSplitRectNotUsed = new List
(); 16 17 public void SetRect(int widthSrc, int heightSrc, int startX, int startY, 18 int widthDest, int heightDest) 19 { 20 _widthSrc = widthSrc; 21 _heightSrc = heightSrc; 22 _listSplitRect.Clear(); 23 24 GetSplitSize(_widthSrc, _heightSrc, startX, startY, 25 widthDest, heightDest, ref _listSplitRect); 26 } 27 28 public List
GetRects() 29 { 30 return _listSplitRect; 31 } 32 33 public List
GetRectsSplit() 34 { 35 List
listShow = new List
(); 36 37 int i = 0; 38 foreach(Rectangle rect in _listSplitRect) 39 { 40 if(IsRectUsed(i)) 41 { 42 listShow.Add(rect); 43 } 44 i++; 45 } 46 return listShow; 47 } 48 49 50 public int GetStartX() 51 { 52 if (_listSplitRect.Count == 0) 53 return 0; 54 Rectangle first = _listSplitRect.First(); 55 return first.X; 56 } 57 58 public int GetSpliteWidth() 59 { 60 if (_listSplitRect.Count == 0) 61 return 0; 62 Rectangle first = _listSplitRect.First(); 63 return first.Width; 64 } 65 66 public int GetSpliteTotalHeight() 67 { 68 if (_listSplitRect.Count == 0) 69 return 0; 70 int i = 0; 71 foreach (Rectangle r in _listSplitRect) 72 { 73 i += r.Height; 74 } 75 return i; 76 } 77 78 public void SetMoveAllFlag(bool flag) 79 { 80 _isMoveAll = flag; 81 } 82 83 public bool GetMoveAllFlag() 84 { 85 return _isMoveAll; 86 } 87 88 public int GetStartY() 89 { 90 if (_listSplitRect.Count == 0) 91 return 0; 92 Rectangle first = _listSplitRect.First(); 93 return first.Y; 94 } 95 public void Draw(Graphics g) 96 { 97 SolidBrush brushRect = new SolidBrush(Color.FromArgb(200, 255, 0, 0)); 98 Font strfont = new Font("Verdana", 20); 99 Brush strBrush = Brushes.Blue;100 Brush strBrushBack = Brushes.White;101 102 //起点圆103 int x = GetStartX();104 int y = GetStartY();105 g.FillEllipse(brushRect, x - _moveAllFlagR, y - _moveAllFlagR, 2 * _moveAllFlagR, 2 * _moveAllFlagR);106 brushRect.Dispose();107 //起点信息108 string startInfo = string.Format("({0}:{1})",x,y);109 SizeF sizeF = g.MeasureString(startInfo, strfont);110 Point ptStart = new Point((int)(x-sizeF.Width/2), (int)(y -sizeF.Height- _defaultHitSpace*2) );111 g.FillRectangle(strBrushBack, new RectangleF(ptStart, sizeF));112 g.DrawString(startInfo, strfont, strBrush, ptStart);113 114 115 //画方框116 Color backColor = Color.FromArgb(0, Color.PowderBlue);117 HatchBrush hat1 = new HatchBrush(HatchStyle.OutlinedDiamond, Color.DarkBlue, backColor);118 HatchBrush hat2 = new HatchBrush(HatchStyle.OutlinedDiamond, Color.Red, backColor);119 120 //输出提示信息121 Pen rectPen = Pens.Red; 122 int i = 0;123 int showIndex = 0;124 string info;125 foreach (Rectangle rect in _listSplitRect)126 {127 i++;128 bool used = IsRectUsed(rect);129 if (used)130 {131 showIndex++;132 info = string.Format("{0}-({1}:{2})", showIndex, rect.Width, rect.Height);133 }134 else135 {136 info = string.Format("({0}:{1})--不参与切割", rect.Width, rect.Height);137 }138 139 g.DrawRectangle(rectPen, rect);140 if (!used)141 {142 g.FillRectangle(hat1, rect);143 }144 145 Point strStart = new Point(rect.X + 5, rect.Y + 5); 146 sizeF = g.MeasureString(info, strfont);147 g.FillRectangle(strBrushBack, new RectangleF(strStart, sizeF));148 149 g.DrawString(info, strfont, strBrush, strStart); 150 }151 strfont.Dispose();152 hat1.Dispose();153 hat2.Dispose();154 }155 public bool StartPointMoveTo(int x, int y)156 {157 if (_listSplitRect.Count == 0)158 return false;159 160 Rectangle first = _listSplitRect.First();161 int moveX = x - first.X;162 int moveY = y - first.Y;163 164 List
listSplitRectNew = new List
();165 foreach (Rectangle r in _listSplitRect)166 {167 Rectangle tmp = r;168 tmp.Offset(moveX, moveY);169 listSplitRectNew.Add(tmp);170 }171 172 _listSplitRect.Clear();173 _listSplitRect = listSplitRectNew;174 return true;175 }176 177 public bool IsAllMove(int mouseX, int mouseY)178 {179 GraphicsPath myGraphicsPath = new GraphicsPath();180 myGraphicsPath.Reset();181 Region myRegion = new Region();182 183 int x = GetStartX();184 int y = GetStartY();185 myGraphicsPath.AddEllipse(x - _moveAllFlagR, y - _moveAllFlagR, 2 * _moveAllFlagR, 2 * _moveAllFlagR);//points);186 myRegion.MakeEmpty();187 myRegion.Union(myGraphicsPath);188 //返回判断点是否在多边形里189 bool myPoint = myRegion.IsVisible(mouseX, mouseY);190 return myPoint;191 }192 193 public void ResetMoveFlag()194 {195 _lastMoveIndex.direct = SpliteMoveIndex.EN_DIR.NON;196 }197 198 public bool SetMove(SpliteMoveIndex index)199 {200 //移动到区域外201 if (!index.IsIn())202 {203 _lastMoveIndex = index;204 return false;205 }206 207 //不是同一条线208 if (!_lastMoveIndex.IsSameLine(index))209 {210 _lastMoveIndex = index;211 return false;212 }213 214 //移动到新的区域215 MoveRect(_lastMoveIndex, index);216 _lastMoveIndex = index;217 return true;218 }219 220 public bool IsInSplite()221 {222 if (_lastMoveIndex == null)223 return false;224 return _lastMoveIndex.IsIn();225 }226 227 void MoveRect(SpliteMoveIndex last, SpliteMoveIndex now)228 {229 if (last.IsHorIn())230 {231 MoveRectHor(last, now);232 }233 else if (last.IsVertIn())234 {235 MoveRectVert(last, now);236 }237 }238 239 void MoveRectHor(SpliteMoveIndex last, SpliteMoveIndex now)240 {241 int moveY = now.mouseY - last.mouseY;242 List
listSplitRectNew = new List
();243 int i = 0;244 int find = 0;245 foreach (Rectangle r in _listSplitRect)246 {247 Rectangle tmp = r;248 i++;249 if (find == 2)250 {251 listSplitRectNew.Add(tmp);252 continue;253 }254 if (find == 1)255 {256 tmp.Y += moveY;257 tmp.Height -= moveY;258 find = 2;259 listSplitRectNew.Add(tmp);260 continue;261 }262 263 if (i == last.rectIndex)264 {265 if (last.lineIndex == 1)266 {267 tmp.Y += moveY;268 tmp.Height -= moveY;269 find = 2;270 listSplitRectNew.Add(tmp);271 }272 else if (last.lineIndex == 2)273 {274 tmp.Height += moveY;275 find = 1;276 listSplitRectNew.Add(tmp);277 }278 }279 else280 {281 listSplitRectNew.Add(tmp);282 }283 }284 285 _listSplitRect.Clear();286 _listSplitRect = listSplitRectNew;287 }288 289 290 void MoveRectVert(SpliteMoveIndex last, SpliteMoveIndex now)291 {292 int moveX = now.mouseX - last.mouseX;293 List
listSplitRectNew = new List
();294 int i = 0;295 foreach (Rectangle r in _listSplitRect)296 {297 Rectangle tmp = r;298 i++;299 if (last.lineIndex == 1)300 {301 tmp.X += moveX;302 tmp.Width -= moveX;303 listSplitRectNew.Add(tmp);304 }305 else if (last.lineIndex == 2)306 {307 tmp.Width += moveX;308 listSplitRectNew.Add(tmp);309 }310 }311 312 _listSplitRect.Clear();313 _listSplitRect = listSplitRectNew;314 }315 316 SpliteMoveIndex GetHorizontal(int x, int y, int hitSpace)317 {318 int startX = GetStartX();319 int width = GetSpliteWidth();320 if (x < startX || x > (startX + width))321 return SpliteMoveIndex.CreateNon(x, y);322 323 int i = 0;324 foreach (Rectangle rect in _listSplitRect)325 {326 i++;327 int y1 = rect.Y;328 //是否落在水平线 一定范围内329 if (y >= y1 - hitSpace && y <= (y1 + hitSpace))330 {331 SpliteMoveIndex moveIndex = new SpliteMoveIndex(x, y);332 moveIndex.direct = SpliteMoveIndex.EN_DIR.HORIZONTAL;333 moveIndex.rectIndex = i;334 moveIndex.lineIndex = 1;335 return moveIndex;336 }337 338 int y2 = rect.Y + rect.Height;339 if (y >= (y2 - hitSpace) && y <= (y2 + hitSpace))340 {341 SpliteMoveIndex moveIndex = new SpliteMoveIndex(x, y);342 moveIndex.direct = SpliteMoveIndex.EN_DIR.HORIZONTAL;343 moveIndex.rectIndex = i;344 moveIndex.lineIndex = 2;345 return moveIndex;346 }347 }348 349 return SpliteMoveIndex.CreateNon(x, y);350 }351 352 SpliteMoveIndex GetVectical(int x, int y, int hitSpace)353 {354 int startY = GetStartY();355 if (y < startY || y > (startY + _heightSrc))356 return SpliteMoveIndex.CreateNon(x, y);357 358 int i = 0;359 foreach (Rectangle rect in _listSplitRect)360 {361 i++;362 //是否落在垂直线 一定范围内363 if (y >= rect.Y && y <= (rect.Y + rect.Height))364 {365 int x1 = rect.X;366 if (x >= (x1 - hitSpace) && x <= (x1 + hitSpace))367 {368 SpliteMoveIndex moveIndex = new SpliteMoveIndex(x, y);369 moveIndex.direct = SpliteMoveIndex.EN_DIR.VERTICAL;370 moveIndex.rectIndex = i;371 moveIndex.lineIndex = 1;372 return moveIndex;373 }374 375 int x2 = rect.X + rect.Width;376 if (x >= (x2 - hitSpace) && x <= (x2 + hitSpace))377 {378 SpliteMoveIndex moveIndex = new SpliteMoveIndex(x, y);379 moveIndex.direct = SpliteMoveIndex.EN_DIR.VERTICAL;380 moveIndex.rectIndex = i;381 moveIndex.lineIndex = 2;382 return moveIndex;383 }384 }385 }386 387 return SpliteMoveIndex.CreateNon(x, y);388 }389 390 public SpliteMoveIndex PointHit(int x, int y, int hitSpace)391 {392 //判断是否在水平线393 SpliteMoveIndex hRect = GetHorizontal(x, y, hitSpace);394 if (hRect.IsIn())395 return hRect;396 397 //判断是否在垂直线398 SpliteMoveIndex vRect = GetVectical(x, y, hitSpace);399 if (vRect.IsIn())400 return vRect;401 402 return SpliteMoveIndex.CreateNon(x, y);403 }404 405 public bool PointInRect(int x,int y)406 {407 int startX = GetStartX();408 int width = GetSpliteWidth();409 if (x < startX || x > (startX + width))410 return false;411 412 int startY = GetStartY();413 int heght = GetSpliteTotalHeight();414 if (y < startY || y > (startY + heght))415 return false;416 return true;417 }418 419 public void ClearNotUsedRect()420 {421 _listSplitRectNotUsed.Clear();422 }423 424 public bool GetRectIndex(int index,ref Rectangle outRect)425 {426 int i = 0;427 foreach (Rectangle rect in _listSplitRect)428 {429 if (i == index)430 {431 outRect = rect;432 return true;433 }434 i++;435 }436 return false;437 }438 439 public bool IsNotUsed(int x, int y)440 {441 Rectangle rect = new Rectangle(); 442 foreach (int n in _listSplitRectNotUsed)443 {444 if (GetRectIndex(n, ref rect) && rect.Contains(x, y))445 { 446 return true;447 }448 }449 return false;450 }451 452 public bool IsRectUsed(Rectangle rect)453 {454 Rectangle rectNot = new Rectangle();455 foreach (int n in _listSplitRectNotUsed)456 {457 if (GetRectIndex(n, ref rectNot) && rectNot == rect)458 {459 return false;460 }461 }462 return true;463 }464 465 public bool IsRectUsed(int index)466 {467 foreach (int n in _listSplitRectNotUsed)468 {469 if (n == index)470 return false;471 }472 return true;473 }474 475 //区块加入切割476 public bool AddRectUsed(int x,int y)477 {478 int i = 0;479 Rectangle rectNot = new Rectangle();480 foreach (int n in _listSplitRectNotUsed)481 {482 if (GetRectIndex(n, ref rectNot) && rectNot.Contains(x,y))483 {484 _listSplitRectNotUsed.RemoveAt(i);485 return true;486 }487 i++;488 }489 return false;490 }491 492 //区块不加入切割493 public bool DelRectUsed(int x, int y)494 {495 int i = 0;496 foreach (Rectangle rect in _listSplitRect)497 {498 if (rect.Contains(x, y))499 {500 _listSplitRectNotUsed.Add(i);501 return true; 502 }503 i++;504 }505 return false;506 }507 508 public bool AddHorLine(int x, int y)509 {510 List
listSplitRectNew = new List
();511 foreach (Rectangle rect in _listSplitRect)512 {513 if (y > rect.Y && y < rect.Y + rect.Height)514 {515 Rectangle r1 = new Rectangle(rect.Location, rect.Size);516 r1.Height = y - rect.Y;517 listSplitRectNew.Add(r1);518 519 r1.Y = y ;520 r1.Height = (rect.Y + rect.Height - y);521 listSplitRectNew.Add(r1);522 }523 else524 {525 listSplitRectNew.Add(rect);526 }527 }528 _listSplitRect = listSplitRectNew;529 return true;530 }531 532 //删除水平线533 public bool DeleteHorSplite(SpliteMoveIndex index)534 {535 List
listSplitRectNew = new List
();536 int i = 0;537 bool del = false;538 Rectangle lastRect = new Rectangle();539 bool haveLast = false;540 541 foreach (Rectangle rect in _listSplitRect)542 {543 i++;544 if(haveLast)545 {546 haveLast = false;547 lastRect.Height += rect.Height;548 listSplitRectNew.Add(lastRect);549 continue;550 }551 552 if(index.rectIndex == i)553 {554 del = true;555 if (index.lineIndex == 1)556 {557 if(listSplitRectNew.Count == 0)558 {559 continue;560 }561 else562 {563 Rectangle r = listSplitRectNew.Last();564 r.Height += rect.Height;565 listSplitRectNew.RemoveAt(listSplitRectNew.Count-1);566 listSplitRectNew.Add(r);567 }568 }569 else if (index.lineIndex == 2)570 {571 if(i == _listSplitRect.Count)572 {573 continue;574 }575 else576 {577 lastRect = rect;578 haveLast = true;579 }580 }581 else { Debug.Assert(false); }582 }583 else584 {585 listSplitRectNew.Add(rect);586 }587 }588 589 _listSplitRect = listSplitRectNew;590 return del;591 }592 593 public static int GetSplitSize(int widthSrc, int heightSrc, int startX, int startY,594 int widthDest, int heightDest, ref List
listOut)595 {596 listOut = new List
();597 598 int width = Math.Min(widthSrc - startX, widthDest);599 600 int i = 0;601 bool stop = false;602 while (!stop)603 {604 Rectangle rect = new Rectangle();605 606 rect.X = startX;607 rect.Y = startY + (i * heightDest);608 rect.Width = width;609 rect.Height = heightDest;610 if (rect.Y + rect.Height >= heightSrc)611 {612 stop = true;613 rect.Height = heightSrc - rect.Y;614 }615 listOut.Add(rect);616 i++;617 }618 return 0;619 }620 }
View Code

图像快速切割

 图像切割其实就是在一个内存中重新绘制,再将内存中的数据保存到文件。切割代码如下:

。。。

技术交流联系qq 13712486

转载于:https://www.cnblogs.com/yuanchenhui/p/pic_splite.html

你可能感兴趣的文章
【干货】界面控件DevExtreme视频教程大汇总!
查看>>
闭包 !if(){}.call()
查看>>
python MySQLdb安装和使用
查看>>
Java小细节
查看>>
poj - 1860 Currency Exchange
查看>>
chgrp命令
查看>>
Java集合框架GS Collections具体解释
查看>>
洛谷 P2486 BZOJ 2243 [SDOI2011]染色
查看>>
linux 笔记本的温度提示
查看>>
(转)DOTA新版地图6.78发布:大幅改动 增两位新英雄
查看>>
数值积分中的辛普森方法及其误差估计
查看>>
Web service (一) 原理和项目开发实战
查看>>
跑带宽度多少合适_跑步机选购跑带要多宽,你的身体早就告诉你了
查看>>
广平县北方计算机第一届PS设计大赛
查看>>
深入理解Java的接口和抽象类
查看>>
java与xml
查看>>
Javascript异步数据的同步处理方法
查看>>
快速排序——Java
查看>>
unity游戏与我
查看>>
187. Repeated DNA Sequences
查看>>