zoukankan      html  css  js  c++  java
  • 一个非常好用的图片切割工具(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

  • 相关阅读:
    Pycharm简单使用教程
    【Jenkins学习】【第二节】 jenkins构建触发器定时任务
    Docker之从零开始制作docker镜像
    手机APP自动化环境搭建
    格式字符详解
    Bash Shell之内建命令和保留字
    asp.net 实现后台异步处理的方式
    Spring3.2.0 之后各个版本完整包下载地址
    Oracle的rollup、cube、grouping sets函数
    C# 委托类型及使用
  • 原文地址:https://www.cnblogs.com/yuanchenhui/p/pic_splite.html
Copyright © 2011-2022 走看看