代码如下:
第一次写博客,欢迎指教
#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");
}
效果图如下: