[聚合文章] 一个非常好用的图片切割工具(c# winform开发) 附源码

.Net 2017-12-06 12 阅读

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

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

开发工具为winform,源码下载地址:http://download.csdn.net/download/qq_29939347/10147808

功能说明

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

主要技术点分析

切割区域确定

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

 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<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                 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<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                 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<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                 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<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                         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<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

图像快速切割

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

 1  public static bool SplitPic(Image initImage, 2           int startX, int startY, int width, int height, ref Image destImage,int destWidth = 0) 3         { 4             if (startX >= initImage.Width || startY >= initImage.Height) 5                 return false; 6  7             //计算最大宽度 长度 8            int width2 = Math.Min(width, initImage.Width - startX); 9            int height2 = Math.Min(height, initImage.Height - startY);10 11             int destHeight;12             if (destWidth == 0)13             {14                 destWidth = width2;15                 destHeight = height2;16             }17             else18             {19                 destHeight = (height2 * destWidth) / width2;20             }21 22 23             width = width2;24             height = height2;25 26             //裁剪对象27             System.Drawing.Image pickedImage = null;28             System.Drawing.Graphics pickedG = null;29 30             //定位31             Rectangle fromR = new Rectangle(0, 0, 0, 0);//原图裁剪定位32             Rectangle toR = new Rectangle(0, 0, 0, 0);//目标定位33 34             //裁剪对象实例化35             pickedImage = new System.Drawing.Bitmap(destWidth, destHeight);36             pickedG = System.Drawing.Graphics.FromImage(pickedImage);37 38             //裁剪源定位39             fromR.X = startX;40             fromR.Y = startY;41             fromR.Width = width;42             fromR.Height = height;43 44             //裁剪目标定位45             toR.X = 0;46             toR.Y = 0;47             toR.Width = destWidth;48             toR.Height = destHeight;49 50             //设置质量51             pickedG.InterpolationMode = InterpolationMode.HighQualityBicubic;52             pickedG.SmoothingMode =  SmoothingMode.HighQuality;53             //裁剪54             pickedG.DrawImage(initImage, toR, fromR, System.Drawing.GraphicsUnit.Pixel);55 56             destImage = pickedImage;57             return true;58         }

 

技术交流联系qq 13712486

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。