.h
typedef unsigned char BYTE;
typedef unsigned short WORD;
typedef unsigned int DWORD;
typedef long LONG;
//位图文件头定义;
//其中不包含文件类型信息(由于结构体的内存结构决定,
//要是加了的话将不能正确读取文件信息)
typedef struct tagBITMAPFILEHEADER {
//WORD bfType;//文件类型,必须是0x4d42,即字符“BM”
DWORD bfSize;//文件大小
WORD bfReserved1;//保留字
WORD bfReserved2;//保留字
DWORD bfOffBits;//从文件头到实际位图数据的偏移字节数
}BITMAPFILEHEADER;
typedef struct tagBITMAPINFOHEADER {
DWORD biSize;//信息头大小
LONG biWidth;//图像宽度
LONG biHeight;//图像高度
WORD biPlanes;//位平面数,必须为1
WORD biBitCount;//每像素位数
DWORD biCompression; //压缩类型
DWORD biSizeImage; //压缩图像大小字节数
LONG biXPelsPerMeter; //水平分辨率
LONG biYPelsPerMeter; //垂直分辨率
DWORD biClrUsed; //位图实际用到的色彩数
DWORD biClrImportant; //本位图中重要的色彩数
}BITMAPINFOHEADER; //位图信息头定义
typedef struct tagRGBQUAD {
BYTE rgbBlue; //该颜色的蓝色分量
BYTE rgbGreen; //该颜色的绿色分量
BYTE rgbRed; //该颜色的红色分量
BYTE rgbReserved; //保留值
}RGBQUAD;//调色板定义
//像素信息
typedef struct tagIMAGEDATA
{
BYTE red;
BYTE green;
BYTE blue;
}IMAGEDATA;
.cpp
#include "ReadBmp.h"
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <opencv2\opencv.hpp>
#define INF 65535
using namespace cv;
using namespace std;
//变量定义
BITMAPFILEHEADER strHead;
RGBQUAD strPla[256];//256色调色板
BITMAPINFOHEADER strInfo;
//显示位图文件头信息
int nx[4] = { 0,1,0,-1 };
int ny[4] = { 1,0,-1,0 };
int minx = INF;
int miny = INF;
int maxx = 0;
int maxy = 0;
int wi;
int hi;
void dfs(int (&grid)[256][256], int x, int y) {
int n = wi;
int m = hi;
if (x < 0 || x >= n || y < 0 || y >= m || (grid[x][y] == 0) || (grid[x][y] == 2)) {
return;
}
//cout << x << " " << y << endl;
grid[x][y] = 2;
minx = min(minx, x);
miny = min(miny, y);
maxx = max(maxx, x);
maxy = max(maxy, y);
for (int i = 0; i < 4; i++) {
int xn = x + nx[i];
int yn = y + ny[i];
dfs(grid, xn, yn);
}
return;
}
void showBmpHead(BITMAPFILEHEADER pBmpHead) {
cout << "位图文件头" << endl <<endl;
//cout<<"bfType value is "<<hex<<pBmpHead.bfType<<endl;
cout << "文件大小:" << pBmpHead.bfSize << endl;
cout << "保留字_1:" << pBmpHead.bfReserved1 << endl;
cout << "保留字_2:" << pBmpHead.bfReserved2 << endl;
cout << "实际位图数据的偏移字节数:" << pBmpHead.bfOffBits << endl << endl;
}
void showBmpInforHead(tagBITMAPINFOHEADER pBmpInforHead) {
cout << "位图信息头" << endl << endl;
cout << "结构体的长度:" << pBmpInforHead.biSize << endl;
cout << "位图宽:" << pBmpInforHead.biWidth << endl;
cout << "位图高:" << pBmpInforHead.biHeight << endl;
cout << "biPlanes平面数:" << pBmpInforHead.biPlanes << endl;
cout << "biBitCount采用颜色位数:" << pBmpInforHead.biBitCount << endl;
cout << "压缩方式:" << pBmpInforHead.biCompression << endl;
cout << "biSizeImage实际位图数据占用的字节数:" << pBmpInforHead.biSizeImage << endl;
cout << "X方向分辨率:" << pBmpInforHead.biXPelsPerMeter << endl;
cout << "Y方向分辨率:" << pBmpInforHead.biYPelsPerMeter << endl;
cout << "使用的颜色数:" << pBmpInforHead.biClrUsed << endl;
cout << "重要颜色数:" << pBmpInforHead.biClrImportant << endl;
wi = pBmpInforHead.biWidth;
hi = pBmpInforHead.biHeight;
}
tagRGBQUAD* ReadFile(char *strFile) {
FILE *fpi;
int i;
fpi = fopen(strFile, "rb");
if (fpi != NULL) {
//先读取文件类型
WORD bfType;
fread(&bfType, 1, sizeof(WORD), fpi);
if (0x4d42 != bfType) {
cout << "the file is not a bmp file!" << endl;
return NULL;
}
//读取bmp文件的文件头和信息头
fread(&strHead, 1, sizeof(tagBITMAPFILEHEADER), fpi);
showBmpHead(strHead);//显示文件头
fread(&strInfo, 1, sizeof(tagBITMAPINFOHEADER), fpi);
showBmpInforHead(strInfo);//显示文件信息头
//读出图片的像素数据
cout << endl;
IMAGEDATA **imagedata;//存储像素信息
imagedata = (IMAGEDATA **)malloc(sizeof(IMAGEDATA*)*strInfo.biHeight);
for (i = 0; i < strInfo.biHeight; i++) {
*(imagedata + i) = (IMAGEDATA*)malloc(sizeof(IMAGEDATA)*strInfo.biWidth);
}
//fseek(fpi,54,SEEK_SET);
for (i = 0; i < strInfo.biHeight; i++) {
for (int j = 0; j < strInfo.biWidth; j++) {
fread(*(imagedata + i) + j, sizeof(IMAGEDATA), 1, fpi);
}
}
/*cout << "==================red======================" << endl;
for (i = strInfo.biHeight - 1; i >= 0; i--) {
for (int j = 0; j < strInfo.biWidth; j++) {
printf("%d ", imagedata[i][j].red);
}
cout << endl;
}
cout<<"===================green====================="<<endl;
for(i = strInfo.biHeight - 1; i >= 0; i--) {
for(int j = 0;j < strInfo.biWidth; j++){
printf("%d ", imagedata[i][j].green);
}
cout << endl;
}
cout<<"====================blue===================="<<endl;
for(i = strInfo.biHeight - 1; i >= 0 ;i--) {
for(int j = 0;j < strInfo.biWidth; j++){
printf("%d ", imagedata[i][j].blue);
}
cout << endl;
} */
int search[256][256] = { 0 };//用于操作的数组求矩形框的左上坐标和长度。
memset(search,0,sizeof(search));
for (i = strInfo.biHeight - 1; i >= 0; i--) {
for (int j = 0; j < strInfo.biWidth; j++) {
if (imagedata[i][j].red != 255) {
search[i][j] = 1;
}
}
}
//cout << endl << "hello" << endl;
/*for (i = strInfo.biHeight - 1; i >= 0; i--) {
for (int j = 0; j < strInfo.biWidth; j++) {
cout << search[i][j];
}
cout << endl;
}*/
/*for (i = strInfo.biHeight - 1; i >= 0; i--) {
for (int j = 0; j < strInfo.biWidth; j++) {
cout << search[i][j];
}
cout << endl;
}*/
Mat src = imread("E:\\wwwww.bmp");
for (i = strInfo.biHeight - 1; i >= 0; i--) {
for (int j = 0; j < strInfo.biWidth; j++) {
if (search[i][j] == 1) {
dfs(search, i, j);
//cout<<endl<< minx << " " << maxy << endl;
Rect rect(miny, strInfo.biHeight - maxx, maxy-miny, maxx-minx);//左上坐标(x,y)和矩形的长(x)宽(y)
cv::rectangle(src, rect, Scalar(0, 0, 0), 1, LINE_8, 0);
//cout << endl;
}
else {
minx = INF;
miny = INF;
maxx = 0;
maxy = 0;
}
}
}
imwrite("E:\\result.bmp", src);
printf("操作后的search数组\n");
for (i = strInfo.biHeight - 1; i >= 0; i--) {
for (int j = 0; j < strInfo.biWidth; j++) {
cout << search[i][j];
}
cout << endl;
}
fclose(fpi);
cout << "成功!" << endl;
}
else {
cout << "file open error!" << endl;
return NULL;
}
}
int main() {
char strFile[30] = "E:\\wwwww.bmp";
cout << strFile << endl;
ReadFile(strFile);
/*Mat src = imread("E:\\exp3.bmp");
Rect rect(7, 1, 7, 5);//左上坐标(x,y)和矩形的长(x)宽(y)
cv::rectangle(src, rect, Scalar(255, 0, 0), 1, LINE_8, 0);
imwrite("E:\\rec.bmp", src);
imshow("src", src);
waitKey(20172019);*/
system("pause"); //运行框闪退处理
//return 0;
}
效果: