C#實現自動切割圖片
阿新 • • 發佈:2022-03-22
由於做一個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); } } }
小軟體,有時候卻很有用.目前不足是:不能自動識別小元素,這個其實很好解決,但當時目的已經基本實現便沒有多花時間來解決這個問題.
切出來的圖: