1. 程式人生 > 其它 >C#實現自動切割圖片

C#實現自動切割圖片

由於做一個TD遊戲需要一些圖片素材,可是現有的從網上下載的<保衛蘿蔔>的圖片資源是多張圖片合在一起的,並且沒有什麼規則,雖然有 個xml檔案似乎用來描述此圖片內子圖片位置大小等資訊,但由於不想花太多時間在研究這個xml檔案內容上,所以轉變思路想寫一個根據透明的邊界自動分割 圖片的工具.

實現了,基本滿足需要.

主介面:

Qie()是開始切圖第一個函式,遍歷圖片每個畫素,找到不是透明的就開始切圖.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 void Qie()     {       
          for (int x = 0; x < bmp.Width; x++)         {             for (int y = 0; y < bmp.Height; y++)             {                 if (isT(x,y ))                 {                   }                 else                 {                     int maxY = 0, maxX = 0, minX = 9999, minY = 9999;
                    StartQie(x,y,ref minX,ref maxX,ref minY,ref maxY);                     if (maxY != 0)                     {                         JianQie(minX, maxX, minY, maxY);                     }                 }             }         }     }

 StartQie是一個遞迴函式,目的查詢與當前畫素相連並且非透明的畫素,判斷她的位置是否比當前的範圍要大,是則更新當前最大範圍.

最後切割圖片的大小就是最大範圍的大小.

    void StartQie(int x2, int y2 , ref int minX,ref int maxX, ref int minY,ref int maxY)
        {
            List<Point> ps = new List<Point>();
            Find(x2, y2,ref ps);

            foreach (var a in ps)
            {
                if (a.X < minX) minX = a.X;
                if (a.Y < minY) minY = a.Y;
                if (a.X > maxX) maxX = a.X;
                if (a.Y > maxY) maxY = a.Y;
            }
            //return;
            for (int x = minX; x <= maxX; x++)
            {
                for (int y = minY; y <=maxY; y++)
                {
                    if (Conten(ps, x, y)) continue;
                    if (isT(x, y) == false)
                    {
                        StartQie(x2, y2, ref minX, ref maxX, ref minY, ref maxY);
                    }
                }
            }

        }
  //這個函式用來切割圖片,根據給定範圍,從母圖上切出子圖並儲存本地.

void JianQie(int minX, int maxX,int minY, int maxY) { i++; var w = maxX - minX; var h = maxY - minY; var img = new Bitmap(w,h); Graphics g = Graphics.FromImage(img); g.PageUnit = GraphicsUnit.Pixel; g.DrawImage(bmp, new RectangleF(0, 0, w, h), new RectangleF(minX, minY, w, h), GraphicsUnit.Pixel); img.Save(bp+"/"+ i + ".png", System.Drawing.Imaging.ImageFormat.Png); for (int x = minX; x <= maxX; x++) { for (int y = minY; y <= maxY; y++) { bmp.SetPixel(x,y,Color.Transparent); } } }

這是最後一個比較重要的函式,定義8個方向,Find方法用於根據8個方向查詢相連且不透明的畫素,找到就加入List中.

  int[,] csz = new int[8, 2] { { 0, 1 }, { 0, -1 }, { -1, 0 }, { 1, 0 }, { 1, 1 }, { 1, -1 }, { -1, -1 }, { -1, 1 } };
      
        void Find(int x,int y ,ref List<Point> ps){

            for (int i = 0; i < 8; i++)
            {
                int zy = csz[i, 0];
                int sx = csz[i, 1];
                var nx=x+1*zy;
                var ny=y+1*sx;
                if (Conten(ps,nx,ny)==false && nx > -1 && nx < bmp.Width && ny > -1 && ny < bmp.Height && isT(nx, ny)==false)
                {
                    ps.Add(new Point(nx,ny));
                    Find(nx, ny ,ref ps);
                }
            }
        }

小軟體,有時候卻很有用.目前不足是:不能自動識別小元素,這個其實很好解決,但當時目的已經基本實現便沒有多花時間來解決這個問題.

切出來的圖: