类似Unity图集分离的C++实现

代码如下:
第一次写博客,欢迎指教

#include <iostream>
#include <windows.h>
#include <vector>
void main()
{
	char Name[64];
	FILE* pf = NULL;
	do {
		std::cout << "请输入需要分离的BMP文件名:";
		std::cin >> Name;
		pf = fopen(Name, "rb");
	} while (pf == NULL);
	fseek(pf, 0, SEEK_END);
	int FileSize = ftell(pf);
	rewind(pf);
	unsigned char* pFile = (unsigned char*)malloc(FileSize);
	fread(pFile, 1, FileSize, pf);
	fclose(pf);
	pf = NULL;

	BITMAPFILEHEADER* p = (BITMAPFILEHEADER*)pFile;
	BITMAPINFOHEADER* q = (BITMAPINFOHEADER*)(p + 1);
	int W = q->biWidth;
	int H = q->biHeight;
	unsigned char* c = pFile + p->bfOffBits;

	int realw = W * 3;
	if ((W * 3) % 4 != 0)
		realw += 4 - (W * 3) % 4;
	//背景色
	int R;
	int G;
	int B;
	std::cout << "请输入背景色(R:0-255)(G:0-255)(B:0-255):";
	std::cin >> R >> G >> B; //这里不作范围判断了
	//当前像素点的周围位置
	int dir[4] = { 3, realw, -3, -realw };
	//记录非背景色的包围圈位置
	std::vector<int> Pos;

	//作为快速判断是否记录过的辅助数组:false未出现,true出现
	bool* HelpPos = (bool*)malloc(FileSize - 54);
	memset(HelpPos, false, FileSize - 54);

	//找出各图形最大的宽高,利用PicPos去遍历每个图形,找出每个图形的最大和最小x、最大和最小y
	std::vector<int> PicMinW;
	std::vector<int> PicMaxW;
	std::vector<int> PicMinH;
	std::vector<int> PicMaxH;

	//遍历每个像素点
	for (int j = 0; j < H; ++j)
	{
		for (int i = 0; i < W; ++i)
		{
			//当前整个图片的遍历点位置
			int d = 3 * i + j * realw;
			//对图形的第一个遍历点开始进行查找链接像素点并记录
			if ((c[d] != R || c[d + 1] != G || c[d + 2] != B) && HelpPos[d] == false)
			{
				Pos.push_back(d);

				//当前整个图形的第一个遍历点位置
				int dd = Pos.size() - 1;
				HelpPos[dd] = true;
				//把每个图形的第一个记录点的x,y设置为最大最小,不断更新
				int min_x = Pos[dd] % realw, max_x = Pos[dd] % realw;
				int min_y = Pos[dd] / realw, max_y = Pos[dd] / realw;

				//利用Pos.size()可以动态遍历Pos数组
				for (int n = dd; n < Pos.size(); ++n)
				{
					for (int k = 0; k < 4; ++k)
					{
						//当前遍历点的周围相邻点的位置
						int ddd = Pos[n] + dir[k];
						if ((c[ddd] != R || c[ddd + 1] != G || c[ddd + 2] != B) && HelpPos[ddd] == false
							&& ((ddd) / realw == Pos[n] / realw || (ddd) % realw == Pos[n] % realw))
						{
							Pos.push_back(ddd);
							HelpPos[ddd] = true;
						}
					}

					if (n != dd)
					{
						if (Pos[n] % realw < min_x)
							min_x = Pos[n] % realw;
						else if (Pos[n] % realw > max_x)
							max_x = Pos[n] % realw;

						if (Pos[n] / realw < min_y)
							min_y = Pos[n] / realw;
						else if (Pos[n] / realw > max_y)
							max_y = Pos[n] / realw;
					}
				}
				PicMinW.push_back(min_x - 3);
				PicMaxW.push_back(max_x + 3);

				PicMinH.push_back(min_y - 1);
				PicMaxH.push_back(max_y + 1);
			}
		}
	}

	//对每个图形加框
	for (int i = 0; i < PicMinW.size(); ++i)
	{
		//设置上下边框
		for (int j = PicMinW[i]; j <= PicMaxW[i]; ++j)
		{
			int dddd1 = j + PicMinH[i] * realw;
			c[dddd1] = 0;
			c[dddd1 + 1] = 0;
			c[dddd1 + 2] = 0;

			int dddd2 = j + PicMaxH[i] * realw;
			c[dddd2] = 0;
			c[dddd2 + 1] = 0;
			c[dddd2 + 2] = 0;
		}
		//设置左右边框
		for (int j = PicMinH[i]; j <= PicMaxH[i]; ++j)
		{
			int dddd1 = PicMinW[i] + j * realw;
			c[dddd1] = 0;
			c[dddd1 + 1] = 0;
			c[dddd1 + 2] = 0;

			int dddd2 = PicMaxW[i] + j * realw;
			c[dddd2] = 0;
			c[dddd2 + 1] = 0;
			c[dddd2 + 2] = 0;
		}
	}

	//保存,释放堆
	pf = fopen(strcat(Name, "_修改.bmp"), "wb");
	fwrite(pFile, 1, FileSize, pf);
	fclose(pf);
	pf = NULL;
	free(pFile);
	pFile = NULL;
	system("pause");
}

效果图如下:
原图

运行后的图

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值