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