要求:
1. Image binarization
2. Binary image erosion
3. Binary image delation
4. Binary image opening
5. Binary image closing
#include <stdio.h>
#include <Windows.h>
void ToRGB(char* a, char* b)
{
BITMAPFILEHEADER fileHeader;// 位图文件头
BITMAPINFOHEADER infoHeader;// 位图信息头
FILE* pFile = fopen(a, "rb");
if (pFile == NULL)
{
printf("打开位图失败\n");
exit(-1);
}
fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, pFile); //读取文件头
fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pFile); //读取信息头
WORD bitCount = infoHeader.biBitCount; //颜色位数
if (bitCount == 16)
{
exit(-1);
}
int Clr = 0;
RGBQUAD *QUAD = NULL;
if (bitCount < 16)
{
Clr = infoHeader.biClrUsed ? infoHeader.biClrUsed : 1 << bitCount;
if (Clr>256)
Clr = 0;
}
// 读取调色板
int i = 0, j = 0;
if (Clr > 0)
{
QUAD = (RGBQUAD*)malloc(sizeof(RGBQUAD)*Clr);
fread(QUAD, sizeof(RGBQUAD)*Clr, 1, pFile);
for (i = 0; i < Clr; i++)
{
QUAD[i].rgbRed = QUAD[i].rgbBlue = QUAD[i].rgbGreen =
(BYTE)(0.3 * QUAD[i].rgbRed + 0.59 * QUAD[i].rgbGreen + 0.11 * QUAD[i].rgbBlue);
}
}
LONG pW = infoHeader.biWidth; //图像数据的宽度
LONG pH = infoHeader.biHeight; //图像数据的高度
int pSize = ((pW * bitCount)>>3)*pH; //图像数据大小
BYTE* P = (BYTE*)malloc(pSize); //申请空间保存图像数据
int LineSize = ((pW * bitCount)>> 3); //行数据大小
fread(P, pSize, 1, pFile); //存入图像数据
if (Clr == 0)
{
for (i = 0; i < pH; i++)//行
{
if (bitCount == 24)
{
for (j = 0; j < pW * 3; j = j + 3)// 列,因为每个像素占3个字节
{
int n = i*LineSize + j;
int r = P[n];
int g = P[n+1];
int b = P[n + 2];
int y = 0.299*r + 0.587*g + 0.114*b;
int u = 0.492*(b - y);
int v = 0.877*(r - y);
y = y + 31; //把所有像素点的y增大31
/*if (y > 255) //如果越界则置为255
y = 255;
if (y < 0)
y = 0;
if (u > 255) //如果越界则置为255
u = 255;
if (u < 0)
u = 0;
if (v > 255) //如果越界则置为255
v = 255;
if (v < 0)
v = 0; */
int R = y + 1.14*v;
int G = y -0.394*u - 0.581*v;
int B = y + 2.032*u;
if (R > 255) //R如果越界则置为255
R = 255;
if (R < 0)
R = 0;
if (G > 255) //如果越界则置为255
G = 255;
if (G < 0)
G = 0;
if (B > 255) //如果越界则置为255
B = 255;
if (B < 0)
B = 0;
P[n] = (BYTE)(R); //分别是新r.g.b分量
P[n + 1] = (BYTE)(G);
P[n + 2] = (BYTE)(B);
}
}
}
}
FILE* dFile = fopen(b, "wb");//创建目标文件
fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, dFile); //写入文件头
fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, dFile); //写入文件信息头
if (QUAD)
{
fwrite(QUAD, sizeof(RGBQUAD)* Clr, 1, dFile);
}
//写入图像数据
fwrite(P, pSize, 1, dFile);
fclose(dFile);
if (QUAD)
{
free(QUAD);
QUAD = NULL;
}
if (P)
{
free(P);
P=NULL;
}
}
void ToGrey(char* a, char* b)
{
BITMAPFILEHEADER fileHeader;// 位图头文件
BITMAPINFOHEADER infoHeader;// 位图信息头
FILE* pFile = fopen(a, "rb");
if (pFile == NULL)
{
printf("打开文件失败\n");
exit(-1);
}
// 读取头信息
fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, pFile); //读取文件头
fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pFile); //读取信息头
WORD bitCount = infoHeader.biBitCount;//色彩的位数
if (bitCount == 16)
{
exit(-1);
}
int Clr = 0;
RGBQUAD *QUAD = NULL;
if (bitCount < 16)
{
Clr = infoHeader.biClrUsed ? infoHeader.biClrUsed : 1 << bitCount;
if (Clr>256)
Clr = 0;
}
// 读取调色板
int i = 0, j = 0;
if (Clr > 0)
{
QUAD = (RGBQUAD*)malloc(sizeof(RGBQUAD)*Clr);
fread(QUAD, sizeof(RGBQUAD)*Clr, 1, pFile);
for (i = 0; i < Clr; i++)
{
QUAD[i].rgbRed = QUAD[i].rgbBlue = QUAD[i].rgbGreen =
(BYTE)(0.3 * QUAD[i].rgbRed + 0.59 * QUAD[i].rgbGreen + 0.11 * QUAD[i].rgbBlue); //灰度图像三个都是y
}
}
LONG pW = infoHeader.biWidth; //图像数据的宽度
LONG pH = infoHeader.biHeight; //图像数据的高度
int pSize = ((pW * bitCount)>>3)*pH; //图像数据大小
BYTE* P = (BYTE*)malloc(pSize); //申请空间保存图像数据
int LineSize = ((pW * bitCount)>> 3); //行数据大小
fread(P, pSize, 1, pFile); //存入图像数据
for(i = 0; i < pH; i++)//行
{
for (j = 0; j < pW*3; j = j + 3)// 列
{
int n = i*LineSize + j;
if(0.299*P[n] + 0.587*P[n + 1] + 0.114*P[n + 2]>120)
P[n] = P[n + 1] = P[n + 2] = (BYTE)255;
else
P[n] = P[n + 1] = P[n + 2] = (BYTE)0;
}
}
FILE* dFile = fopen(b, "wb");//创建目标文件
fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, dFile); //写入文件头
fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, dFile); //写入文件信息头
if (QUAD)
{
fwrite(QUAD, sizeof(RGBQUAD)* Clr, 1, dFile);
}
//写入图像数据
fwrite(P, pSize, 1, dFile);
fclose(dFile);
if (QUAD)
{
free(QUAD);
QUAD = NULL;
}
if (P)
{
free(P);
P = NULL;
}
}
void Delation(char* a, char* b)
{
BITMAPFILEHEADER fileHeader;// 位图头文件
BITMAPINFOHEADER infoHeader;// 位图信息头
FILE* pFile = fopen(a, "rb");
if (pFile == NULL)
{
printf("打开文件失败\n");
exit(-1);
}
// 读取头信息
fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, pFile); //读取文件头
fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pFile); //读取信息头
WORD bitCount = infoHeader.biBitCount;//色彩的位数
int Clr = 0;
RGBQUAD *QUAD = NULL;
int i = 0, j = 0;
LONG pW = infoHeader.biWidth; //图像数据的宽度
LONG pH = infoHeader.biHeight; //图像数据的高度
int pSize = ((pW * bitCount)>>3)*pH; //图像数据大小
BYTE* P = (BYTE*)malloc(pSize); //申请空间保存图像数据
int LineSize = ((pW * bitCount)>> 3); //行数据大小
fread(P, pSize, 1, pFile); //存入图像数据
//先二值化
for(i = 0; i < pH; i++)//行
{
for (j = 0; j < pW*3; j = j + 3)// 列
{
int n = i*LineSize + j;
if(0.299*P[n] + 0.587*P[n + 1] + 0.114*P[n + 2]>120)
P[n] = P[n + 1] = P[n + 2] = (BYTE)255;
else
P[n] = P[n + 1] = P[n + 2] = (BYTE)0;
}
}
//再delation
int width=3,height=3;
int mid=(width+1)/2-1;
int p,q;
int n;
BYTE v = 255;
for(i = mid; i < pH - mid; i++)//行
{
for (j = mid; j < (pW-mid) * 3; j = j + 3)// 列
{
for(p = 0; p < height; p++)
{
for(q = 0; q < width * 3; q = q + 3)
{
if(p == mid && q == mid) continue;
n=(i+p)*LineSize + (j+q);
v &= P[n];
}
}
n = i * LineSize + j;
P[n] = P[n + 1] = P[n + 2] = v;
v = 255;
}
}
FILE* dFile = fopen(b, "wb");//创建目标文件
fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, dFile); //写入文件头
fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, dFile); //写入文件信息头
if (QUAD)
{
fwrite(QUAD, sizeof(RGBQUAD)* Clr, 1, dFile);
}
//写入图像数据
fwrite(P, pSize, 1, dFile);
fclose(dFile);
if (QUAD)
{
free(QUAD);
QUAD = NULL;
}
if (P)
{
free(P);
P = NULL;
}
}
void Erosion(char* a, char* b)
{
BITMAPFILEHEADER fileHeader;// 位图头文件
BITMAPINFOHEADER infoHeader;// 位图信息头
FILE* pFile = fopen(a, "rb");
// 读取头信息
fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, pFile); //读取文件头
fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pFile); //读取信息头
WORD bitCount = infoHeader.biBitCount;//色彩的位数
int Clr = 0;
RGBQUAD *QUAD = NULL;
int i = 0, j = 0;
LONG pW = infoHeader.biWidth; //图像数据的宽度
LONG pH = infoHeader.biHeight; //图像数据的高度
int pSize = ((pW * bitCount)>>3)*pH; //图像数据大小
BYTE* P = (BYTE*)malloc(pSize); //申请空间保存图像数据
int LineSize = ((pW * bitCount)>> 3); //行数据大小
fread(P, pSize, 1, pFile); //存入图像数据
//先二值化
for(i = 0; i < pH; i++)//行
{
for (j = 0; j < pW*3; j = j + 3)// 列
{
int n = i*LineSize + j;
if(0.299*P[n] + 0.587*P[n + 1] + 0.114*P[n + 2]>120)
P[n] = P[n + 1] = P[n + 2] = (BYTE)255;
else
P[n] = P[n + 1] = P[n + 2] = (BYTE)0;
}
}
//再erosion
int width=3,height=3;
int mid=(width+1)/2-1;
int p,q;
int n;
BYTE v = 0;
for(i = mid; i < pH - mid; i++)//行
{
for (j = mid; j < (pW-mid) * 3; j = j + 3)// 列
{
for(p = 0; p < height; p++)
{
for(q = 0; q < width * 3; q = q + 3)
{
if(p == mid && q == mid) continue;
n=(i+p)*LineSize + (j+q);
v |= P[n];
}
}
n = i * LineSize + j;
P[n] = P[n + 1] = P[n + 2] = v;
v = 0;
}
}
FILE* dFile = fopen(b, "wb");//创建目标文件
fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, dFile); //写入文件头
fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, dFile); //写入文件信息头
if (QUAD)
{
fwrite(QUAD, sizeof(RGBQUAD)* Clr, 1, dFile);
}
//写入图像数据
fwrite(P, pSize, 1, dFile);
fclose(dFile);
if (QUAD)
{
free(QUAD);
QUAD = NULL;
}
if (P)
{
free(P);
P = NULL;
}
}
void Opening(char* a, char* b)
{
BITMAPFILEHEADER fileHeader;// 位图头文件
BITMAPINFOHEADER infoHeader;// 位图信息头
FILE* pFile = fopen(a, "rb");
// 读取头信息
fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, pFile); //读取文件头
fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pFile); //读取信息头
WORD bitCount = infoHeader.biBitCount;//色彩的位数
int Clr = 0;
RGBQUAD *QUAD = NULL;
int i = 0, j = 0;
LONG pW = infoHeader.biWidth; //图像数据的宽度
LONG pH = infoHeader.biHeight; //图像数据的高度
int pSize = ((pW * bitCount)>>3)*pH; //图像数据大小
BYTE* P = (BYTE*)malloc(pSize); //申请空间保存图像数据
int LineSize = ((pW * bitCount)>> 3); //行数据大小
fread(P, pSize, 1, pFile); //存入图像数据
//先二值化
for(i = 0; i < pH; i++)//行
{
for (j = 0; j < pW*3; j = j + 3)// 列
{
int n = i*LineSize + j;
if(0.299*P[n] + 0.587*P[n + 1] + 0.114*P[n + 2]>120)
P[n] = P[n + 1] = P[n + 2] = (BYTE)255;
else
P[n] = P[n + 1] = P[n + 2] = (BYTE)0;
}
}
//再erosion
int width=3,height=3;
int mid=(width+1)/2-1;
int p,q;
int n;
BYTE v = 0;
for(i = mid; i < pH - mid; i++)//行
{
for (j = mid; j < (pW-mid) * 3; j = j + 3)// 列
{
for(p = 0; p < height; p++)
{
for(q = 0; q < width * 3; q = q + 3)
{
if(p == mid && q == mid) continue;
n=(i+p)*LineSize + (j+q);
v |= P[n];
}
}
n = i * LineSize + j;
P[n] = P[n + 1] = P[n + 2] = v;
v = 0;
}
}
//再Delation
v = 255;
for(i = mid; i < pH - mid; i++)//行
{
for (j = mid; j < (pW-mid) * 3; j = j + 3)// 列
{
for(p = 0; p < height; p++)
{
for(q = 0; q < width * 3; q = q + 3)
{
if(p == mid && q == mid) continue;
n=(i+p)*LineSize + (j+q);
v &= P[n];
}
}
n = i * LineSize + j;
P[n] = P[n + 1] = P[n + 2] = v;
v = 255;
}
}
FILE* dFile = fopen(b, "wb");//创建目标文件
fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, dFile); //写入文件头
fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, dFile); //写入文件信息头
if (QUAD)
{
fwrite(QUAD, sizeof(RGBQUAD)* Clr, 1, dFile);
}
//写入图像数据
fwrite(P, pSize, 1, dFile);
fclose(dFile);
if (QUAD)
{
free(QUAD);
QUAD = NULL;
}
if (P)
{
free(P);
P = NULL;
}
}
void Closing(char* a, char* b)
{
BITMAPFILEHEADER fileHeader;// 位图头文件
BITMAPINFOHEADER infoHeader;// 位图信息头
FILE* pFile = fopen(a, "rb");
// 读取头信息
fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, pFile); //读取文件头
fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, pFile); //读取信息头
WORD bitCount = infoHeader.biBitCount;//色彩的位数
int Clr = 0;
RGBQUAD *QUAD = NULL;
int i = 0, j = 0;
LONG pW = infoHeader.biWidth; //图像数据的宽度
LONG pH = infoHeader.biHeight; //图像数据的高度
int pSize = ((pW * bitCount)>>3)*pH; //图像数据大小
BYTE* P = (BYTE*)malloc(pSize); //申请空间保存图像数据
int LineSize = ((pW * bitCount)>> 3); //行数据大小
fread(P, pSize, 1, pFile); //存入图像数据
//先二值化
for(i = 0; i < pH; i++)//行
{
for (j = 0; j < pW*3; j = j + 3)// 列
{
int n = i*LineSize + j;
if(0.299*P[n] + 0.587*P[n + 1] + 0.114*P[n + 2]>120)
P[n] = P[n + 1] = P[n + 2] = (BYTE)255;
else
P[n] = P[n + 1] = P[n + 2] = (BYTE)0;
}
}
//先Delation
int width=3,height=3;
int mid=(width+1)/2-1;
int p,q;
int n;
BYTE v = 255;
for(i = mid; i < pH - mid; i++)//行
{
for (j = mid; j < (pW-mid) * 3; j = j + 3)// 列
{
for(p = 0; p < height; p++)
{
for(q = 0; q < width * 3; q = q + 3)
{
if(p == mid && q == mid) continue;
n=(i+p)*LineSize + (j+q);
v &= P[n];
}
}
n = i * LineSize + j;
P[n] = P[n + 1] = P[n + 2] = v;
v = 255;
}
}
//再erosion
v = 0;
for(i = mid; i < pH - mid; i++)//行
{
for (j = mid; j < (pW-mid) * 3; j = j + 3)// 列
{
for(p = 0; p < height; p++)
{
for(q = 0; q < width * 3; q = q + 3)
{
if(p == mid && q == mid) continue;
n=(i+p)*LineSize + (j+q);
v |= P[n];
}
}
n = i * LineSize + j;
P[n] = P[n + 1] = P[n + 2] = v;
v = 0;
}
}
FILE* dFile = fopen(b, "wb");//创建目标文件
fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, dFile); //写入文件头
fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, dFile); //写入文件信息头
if (QUAD)
{
fwrite(QUAD, sizeof(RGBQUAD)* Clr, 1, dFile);
}
//写入图像数据
fwrite(P, pSize, 1, dFile);
fclose(dFile);
if (QUAD)
{
free(QUAD);
QUAD = NULL;
}
if (P)
{
free(P);
P = NULL;
}
}
int main()
{
ToGrey("d.bmp", "grayd.bmp");
ToRGB("d.bmp", "rgbd.bmp");
Erosion("d.bmp", "erosiond.bmp");
Delation("d.bmp","delationd.bmp");
Opening("d.bmp","opend.bmp");
Closing("d.bmp","closed.bmp");
return 0;
}