//=======================================================
// 子图的分割,子图依据图片中的透明区域自行分割
//=======================================================
/// <summary>
/// 对图像pic进行图块分割,分割为一个个的矩形子图块区域
/// 分割原理: 相邻的连续区域构成一个图块,透明区域为分割点
/// </summary>
public Rectangle[] GetRects(Bitmap pic)
{
List<Rectangle> Rects = new List<Rectangle>();
Rectangle rect;
bool[][] Colors = getColors(pic); //获取图像对应的非透明像素点
for (int i = 0; i < pic.Height; i++)
{
for (int j = 0; j < pic.Width; j++)
{
if (Exist(Colors, i, j))
{
rect = GetRect(Colors, i, j); //获取非透明像素点所在的矩形区域
if (rect.Width > 10 && rect.Height > 10) //剔除尺寸小于10x10的子图区域
Rects.Add(rect); //记录区域范围
}
}
}
return Rects.ToArray();
}
//获取图像buildPic的所有子图区域的图像
private Bitmap[] getSubPics(Image buildPic, Rectangle[] buildRects)
{
//创建建筑块图像
Bitmap[] buildTiles = new Bitmap[buildRects.Length];
for (int i = 0; i < buildRects.Length; i++)
{
buildTiles[i] = GetRect(buildPic, buildRects[i]); //获取建筑块的图像
}
return buildTiles;
}
//判断所有像素点是否存在非透明像素
public bool[][] getColors(Bitmap pic)
{
Color C;
bool[][] has = new bool[pic.Height][];
int count;
for (int i = 0; i < pic.Height; i++)
{
has[i] = new bool[pic.Width];
for (int j = 0; j < pic.Width; j++)
{
C = pic.GetPixel(j, i);
//统计RGB值近似为0的数目
count = 0;
if(C.R < 4) count++;
if (C.G < 4) count++;
if (C.B < 4) count++;
//若透明度近似为0,视为透明像素。或RGB中有两个值近似为0且透明度很小,也视为透明像素。
if (C.A < 3 || (count >= 2 && C.A < 30)) has[i][j] = false;
else has[i][j] = true;
}
}
return has;
}
//判断坐标处是否存在非透明像素值
public bool Exist(bool[][] Colors, int x, int y)
{
if (x < 0 || y < 0 || x >= Colors.Length || y >= Colors[0].Length) return false;
else return Colors[x][y];
}
//判定区域Rect右侧是否存在像素点
public bool R_Exist(bool[][] Colors, Rectangle Rect)
{
if (Rect.Right >= Colors[0].Length || Rect.Left < 0) return false;
for (int i = 0; i < Rect.Height; i++)
if (Exist(Colors, Rect.Top + i, Rect.Right + 1)) return true;
return false;
}
public bool D_Exist(bool[][] Colors, Rectangle Rect)
{
if (Rect.Bottom >= Colors.Length || Rect.Top < 0) return false;
for (int i = 0; i < Rect.Width; i++)
if (Exist(Colors, Rect.Bottom + 1, Rect.Left + i)) return true;
return false;
}
public bool L_Exist(bool[][] Colors, Rectangle Rect)
{
if (Rect.Right >= Colors[0].Length || Rect.Left < 0) return false;
for (int i = 0; i < Rect.Height; i++)
if (Exist(Colors, Rect.Top + i, Rect.Left - 1)) return true;
return false;
}
public bool U_Exist(bool[][] Colors, Rectangle Rect)
{
if (Rect.Bottom >= Colors.Length || Rect.Top < 0) return false;
for (int i = 0; i < Rect.Width; i++)
if (Exist(Colors, Rect.Top - 1, Rect.Left + i)) return true;
return false;
}
//获取坐标所在图块的区域范围
public Rectangle GetRect0(bool[][] Colors, int x, int y)
{
Rectangle Rect = new Rectangle(new Point(y, x), new Size(1, 1)); //创建所在区域
bool flag;
do
{
flag = false;
while (R_Exist(Colors, Rect)) { Rect.Width++; flag = true; }
while (D_Exist(Colors, Rect)) { Rect.Height++; flag = true; }
while (L_Exist(Colors, Rect)) { Rect.Width++; Rect.X--; flag = true; }
while (U_Exist(Colors, Rect)) { Rect.Height++; Rect.Y--; flag = true; }
}
while (flag == true);
区域范围放大1个像素
if (Rect.X > 0) { Rect.X--; Rect.Width++; }
if (Rect.Y > 0) { Rect.Y--; Rect.Height++; }
if (Rect.X + Rect.Width + 1 < Colors[0].Length) { Rect.Width++; }
if (Rect.Y + Rect.Height + 1 < Colors.Length) { Rect.Height++; }
//区域范围放大1个像素
if (Rect.X > 0) { Rect.X--; Rect.Width++; }
if (Rect.Y > 0) { Rect.Y--; Rect.Height++; }
if (Rect.X + Rect.Width + 1 < Colors[0].Length) { Rect.Width++; }
if (Rect.Y + Rect.Height + 1 < Colors.Length) { Rect.Height++; }
//Rect = expend2pix(Colors, Rect); //区域范围扩大2个像素
clearRect(Colors, Rect); //清空已选择的区域
return Rect;
}
//获取坐标所在图块的区域范围
public Rectangle GetRect(bool[][] Colors, int x, int y)
{
Rectangle Rect = new Rectangle(new Point(y, x), new Size(1, 1)); //创建所在区域
bool flag;
do
{
flag = false;
while (R_Exist(Colors, Rect)) { Rect.Width++; flag = true; }
while (D_Exist(Colors, Rect)) { Rect.Height++; flag = true; }
while (L_Exist(Colors, Rect)) { Rect.Width++; Rect.X--; flag = true; }
while (U_Exist(Colors, Rect)) { Rect.Height++; Rect.Y--; flag = true; }
}
while (flag == true);
clearRect(Colors, Rect); //清空已选择的区域
Rect.Width++;
Rect.Height++;
return Rect;
}
//清空区域内的像素非透明标记
public void clearRect(bool[][] Colors, Rectangle Rect)
{
for (int i = Rect.Top; i <= Rect.Bottom; i++)
for (int j = Rect.Left; j <= Rect.Right; j++)
Colors[i][j] = false;
}
/// <summary>
/// 从图像pic中截取区域Rect构建新的图像
/// </summary>
public Bitmap GetRect(Image pic, Rectangle Rect)
{
//创建图像
Rectangle drawRect = new Rectangle(0, 0, Rect.Width, Rect.Height); //绘制整块区域
Bitmap tmp = new Bitmap(drawRect.Width, drawRect.Height); //按指定大小创建位图
//绘制
Graphics g = Graphics.FromImage(tmp); //从位图创建Graphics对象
g.Clear(Color.FromArgb(0, 0, 0, 0)); //清空
g.DrawImage(pic, drawRect, Rect, GraphicsUnit.Pixel); //从pic的给定区域进行绘制
return tmp; //返回构建的新图像
}