#include
#include"bmp.h"
#include "stdlib.h"
#include "math.h"
#include "time.h"
#include
#include
using namespace std;
#define PI 3.14159
#define LENGTH_NAME_BMP 30//文件名长度
#define U 0//高斯分布的均值
#define D 0//高斯分布的均方差
FILE *fpi, *fpw;
BITMAPFILEHEADER strHead;
RGBQUAD strPla[256];
BITMAPINFOHEADER strInfo;
int Roberts1[4] = { -1,0,0,1 };
int Roberts2[4] = { 0,-1,1,0 };
int Sobel1[9] = { -1,-2,-1,0,0,0,1,2,1 };
int Sobel2[9] = { -1,0,1,-2,0,2,-1,0,1 };
int Prewitt1[9] = { -1,-1,-1,0,0,0,1,1,1 };
int Prewitt2[9] = { -1,0,1,-1,0,1,-1,0,1 };
int Laplace1[9] = { 0,1,0,1,-4,1,0,1,0 };
int Laplace2[9] = { 1,1,1,1,-8,1,1,1,1 };
//显示位图文件头信息
void showBmpHead(BITMAPFILEHEADER pBmpHead)
{
cout << "位图文件头" << endl;
cout << "文件大小" << pBmpHead.bfSize << endl;
cout << "保留字_1" << pBmpHead.bfReserved1 << endl;
cout << "保留字_2" << pBmpHead.bfReserved2 << endl;
cout << "实际位图数据的偏移字节数:" << pBmpHead.bf0ffBits << endl;
}
void showBmpInforHead(tagBITMAPINFOHEADER pBmpInforHead)
{
cout << "位图信息头" << 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;
}
int main()
{
int Gaus_S();
void conv2(IMAGEDATA *filter, int arr1[], int arr2[], int res[], int filterW, int filterH, int arrW, int arrH);
void RobertsMethod(IMAGEDATA *filter, int filterW, int filterH);
void Laplace(IMAGEDATA *filter, int filterW, int filterH);
char strFile[LENGTH_NAME_BMP];//bmp文件名
IMAGEDATA *imagedata = NULL;//动态分配存储原图片的像素信息的二维数组
IMAGEDATA *imagedataRot = NULL;//动态分配处理后的图片像素信息
int width, height;//图片的宽度和高度
cout << "请输入所要读取的文件名(末尾要带有.bmp):" << endl;
cin >> strFile;
fopen_s(&fpi,strFile,"rb");
//读取bmp图片信息、初始化数组
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);
for (unsigned int nCounti = 0; nCounti < strInfo.biClrUsed; nCounti++)
{
fread((char *)&strPla[nCounti].rgbBlue, 1, sizeof(BYTE), fpi);
fread((char *)&strPla[nCounti].rgbGreen, 1, sizeof(BYTE), fpi);
fread((char *)&strPla[nCounti].rgbRed, 1, sizeof(BYTE), fpi);
cout << "strPla[nCounti].rgbBlue" << strPla[nCounti].rgbBlue << endl;
cout << "strPla[nCounti].rgbGreen" << strPla[nCounti].rgbGreen << endl;
cout << "strPla[nCounti].rgbRed" << strPla[nCounti].rgbRed << endl;
}
width = strInfo.biWidth;
height = strInfo.biHeight;
imagedata = (IMAGEDATA *)malloc(width*height*sizeof(IMAGEDATA));
//初始化原始图片的像素数组
for (int i = 0; i < height; ++i)
{
for (int j = 0; j < width; ++j)
{
(*(imagedata + i*width + j)).blue = 0;
(*(imagedata + i*width + j)).green = 0;
(*(imagedata + i*width + j)).red = 0;
}
}
fread(imagedata, sizeof(struct tagIMAGEDATA)*width, height, fpi);
fclose(fpi);
//加入高斯噪声
int x, y, p;
srand((unsigned)time(NULL));
for (y = 0; y < height; y++)
{
for (x = 0; x < width; x++)
{
(*(imagedata + y*width + x)).blue += Gaus_S();
(*(imagedata + y*width + x)).green += Gaus_S();
(*(imagedata + y*width + x)).red += Gaus_S();
}
}
//Roberts算子
int method;
cout << "选择Roberts算子请输入1,Sobel算子请输入2,Prewitt算子请输入3,Laplace算子请输入4:" << endl;
cin >> method;
switch (method)
{
case 1:
RobertsMethod(imagedata, width, height);
break;
case 2:
int res1[25];
for (y = 1; y < height - 2; y++)
{
for (x = 1; x < width - 2; x++)
{
conv2(imagedata + y*width + x, Sobel1, Sobel2, res1, 3, 3, 3, 3);
}
}
break;
case 3:
int res2[25];
for (y = 1; y < height - 2; y++)
{
for (x = 1; x < width - 2; x++)
{
conv2(imagedata + y*width + x, Prewitt1, Prewitt2, res2, 3, 3, 3, 3);
}
}
break;
case 4:
int res3[25];
for (y = 1; y < height - 2; y++)
{
for (x = 1; x < width - 2; x++)
{
conv2(imagedata + y*width + x, Laplace1, Laplace2, res3, 3, 3, 3, 3);
}
}
break;
default:
cout << "输入错误" << endl;
}
}
else
{
cout << "file open error" << endl;
system("pause");
return NULL;
}
//保存bmp图片
cout << "保存的文件名(必须在文件名后输入.bmp):" << endl;
char s[LENGTH_NAME_BMP];
cin >> s;
if (fopen_s(&fpw, s, "wb") != NULL)
{
cout << "create the bmp file error!" << endl;
system("pause");
return NULL;
}
WORD bfType_w = 0x4d42;
fwrite(&bfType_w, 1, sizeof(WORD), fpw);
fwrite(&strHead, 1, sizeof(tagBITMAPFILEHEADER), fpw);
strInfo.biWidth = width;
strInfo.biHeight = height;
fwrite(&strInfo, 1, sizeof(tagBITMAPINFOHEADER), fpw);
//保存调色板数据
for (unsigned int nCounti = 0; nCounti < strInfo.biClrUsed; nCounti++)
{
fwrite(&strPla[nCounti].rgbBlue, 1, sizeof(BYTE), fpw);
fwrite(&strPla[nCounti].rgbGreen, 1, sizeof(BYTE), fpw);
fwrite(&strPla[nCounti].rgbRed, 1, sizeof(BYTE), fpw);
}
//保存像素数据
for (int i = 0; i < height; ++i)
{
for (int j = 0; j < width; j++)
{
fwrite(&(*(imagedata + i * width + j)).red, 1, sizeof(BYTE), fpw);
fwrite(&(*(imagedata + i * width + j)).green, 1, sizeof(BYTE), fpw);
fwrite(&(*(imagedata + i * width + j)).blue, 1, sizeof(BYTE), fpw);
}
}
fclose(fpw);
//释放内存
delete[] imagedata;
system("pause");
return 0;
}
//产生高斯样本,以U为均值,D为均方差
int Gaus_S() {
double sum = 0;
for (int i = 0; i < 12; i++)
sum += rand() / 32767.00;
return int(U + D*(sum - 6));
}
//卷积计算
void conv2(IMAGEDATA *filter, int arr1[],int arr2[],int res[],int filterW,int filterH, int arrW, int arrH)
{
int temp1;
int temp2;
int i = 0, j = 0;
//blue
for (; i < filterH+arrH-1; i++)
{
for (; j = 0 && (i - m) < arrH && (j - n) >= 0 && (j - n) < arrW)
{
temp1 += (*(filter+m*filterW+n)).blue*arr1[(i - m)*arrW+j-n];
temp2 += (*(filter + m*filterW + n)).blue*arr2[(i - m)*arrW+j-n];
}
}
}
res[i*filterW+j]= (temp1^2+temp2^2)^(1/2);
}
}
(*(filter)).blue = res[((i-1)/2)*filterW+(j-1)/2];
//red
for (i=0; i < filterH + arrH - 1; i++)
{
for (j=0; j = 0 && (i - m) < arrH && (j - n) >= 0 && (j - n) < arrW)
{
temp1 += (*(filter + m*filterW + n)).red*arr1[(i - m)*arrW + j - n];
temp2 += (*(filter + m*filterW + n)).red*arr2[(i - m)*arrW + j - n];
}
}
}
res[i*filterW + j] = (temp1 ^ 2 + temp2 ^ 2)^(1/2);
}
}
(*(filter)).red = res[((i - 1) / 2)*filterW + (j - 1) / 2];
//green
for (i = 0; i < filterH + arrH - 1; i++)
{
for (j = 0; j = 0 && (i - m) < arrH && (j - n) >= 0 && (j - n) < arrW)
{
temp1 += (*(filter + m*filterW + n)).green*arr1[(i - m)*arrW + j - n];
temp2 += (*(filter + m*filterW + n)).green*arr2[(i - m)*arrW + j - n];
}
}
}
res[i*filterW + j] = (temp1 ^ 2 + temp2 ^ 2)^(1/2);
}
}
(*(filter)).green = res[((i - 1) / 2)*filterW + (j - 1) / 2];
}
//Roberts算子计算函数
void RobertsMethod(IMAGEDATA *filter,int filterW,int filterH)
{
for (int m = 1; m < filterH-2; m++)
for (int n = 1; n < filterW-2; n++)
{
(*(filter + m*filterW + n)).blue = (((*(filter + m*filterW + n)).blue - (*(filter + (m + 1)*filterW + n + 1)).blue) ^ 2 + ((*(filter + m*filterW + n + 1)).blue - (*(filter + (m + 1)*filterW + n)).blue)) ^ (1 / 2);
(*(filter + m*filterW + n)).green = (((*(filter + m*filterW + n)).green - (*(filter + (m + 1)*filterW + n + 1)).green) ^ 2 + ((*(filter + m*filterW + n + 1)).green - (*(filter + (m + 1)*filterW + n)).green)) ^ (1 / 2);
(*(filter + m*filterW + n)).red = (((*(filter + m*filterW + n)).red - (*(filter + (m + 1)*filterW + n + 1)).red) ^ 2 + ((*(filter + m*filterW + n + 1)).red - (*(filter + (m + 1)*filterW + n)).red)) ^ (1 / 2);
}
}