一个非常好用的图片切割工具(c# winform开发)

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

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

功能说明

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

主要技术点分析

切割区域确定

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

 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; //第几个rect
11         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.direct
36                 && this.rectIndex == another.rectIndex
37                 && 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<Rectangle> _listSplitRect = new List<Rectangle>();
  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<int> _listSplitRectNotUsed = new List<int>();
 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<Rectangle> GetRects()
 29         {
 30             return _listSplitRect;
 31         }
 32 
 33         public List<Rectangle> GetRectsSplit()
 34         {
 35             List<Rectangle> listShow = new List<Rectangle>();
 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                 else
135                 {
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<Rectangle> listSplitRectNew = new List<Rectangle>();
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<Rectangle> listSplitRectNew = new List<Rectangle>();
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                 else
280                 {
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<Rectangle> listSplitRectNew = new List<Rectangle>();
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<Rectangle> listSplitRectNew = new List<Rectangle>();
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                 else
524                 {
525                     listSplitRectNew.Add(rect);
526                 }
527             }
528             _listSplitRect = listSplitRectNew;
529             return true;
530         }
531 
532         //删除水平线
533         public bool DeleteHorSplite(SpliteMoveIndex index)
534         {
535             List<Rectangle> listSplitRectNew = new List<Rectangle>();
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                         else
562                         {
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                         else
576                         {
577                             lastRect = rect;
578                             haveLast = true;
579                         }
580                     }
581                     else { Debug.Assert(false); }
582                 }
583                 else
584                 {
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<Rectangle> listOut)
595         {
596             listOut = new List<Rectangle>();
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

posted @ 2017-12-06 13:20  源之缘-OFD解决方案  阅读(6070)  评论(3编辑  收藏  举报
关注我