#include<stdio.h>
#pragma pack(1)
typedef struct{
unsigned short bfType; //filetype 0x4D42
int bfSize; //锟侥硷拷锟斤拷小锟斤拷锟斤拷锟街斤拷为锟斤拷位
unsigned short bfReserved1; //锟斤拷锟斤拷值,锟斤拷锟斤拷为0
unsigned short bfReserved2; //锟斤拷锟斤拷值,锟斤拷锟斤拷为0
int bfOffBits; //锟斤拷锟侥硷拷锟斤拷头锟斤拷锟斤拷锟斤拷图锟斤拷锟斤拷锟捷碉拷锟街斤拷偏锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷锟侥硷拷头锟斤拷14byte锟斤拷+位图锟斤拷息头锟斤拷40byte锟斤拷+锟斤拷色锟藉)
}BITMAPFILEHEADER;
typedef struct{
unsigned int biSize; //位图锟斤拷息头锟侥达拷小,锟斤拷为40锟街斤拷
int biWidth; //位图锟斤拷锟饺o拷锟斤拷位为锟斤拷锟斤拷
int biHeight; //位图锟竭度o拷锟斤拷位为锟斤拷锟斤拷
unsigned short biPlanes; //位图锟斤拷平锟斤拷锟斤拷锟斤拷锟斤拷锟斤拷为1
unsigned short biBitCount; //锟斤拷锟斤拷位锟斤拷锟斤拷锟斤拷1锟斤拷4锟斤拷8锟斤拷16锟斤拷24锟斤拷32锟斤拷
unsigned int biCompression; //位图压锟斤拷锟斤拷锟酵o拷0为锟斤拷压锟斤拷锟斤拷1为BI_RLE8锟斤拷2为BI_RLE4(30-33)
unsigned int biSizeImage; //图锟斤拷锟斤拷锟捷诧拷锟街达拷小,锟斤拷锟斤拷bfSize-bfOffBits (34-37)
int biXPelsPerMeter; // 锟斤拷锟斤拷锟斤拷/锟阶憋拷示锟斤拷水平锟街憋拷锟斤拷
int biYPelsPerMeter; // 锟斤拷锟斤拷锟斤拷/锟阶憋拷示锟侥达拷直锟街憋拷锟斤拷
unsigned int biClrUsed; // 锟斤拷色锟斤拷锟叫碉拷锟斤拷色锟斤拷锟斤拷锟斤拷,0为图片锟叫碉拷色锟斤拷
unsigned int biClrImportant; // 锟斤拷要锟斤拷色锟斤拷锟斤拷锟斤拷锟斤拷目锟斤拷0锟斤拷示锟斤拷锟斤拷要(50-53)
}BITMAPINFOHEADER;
typedef struct
{
unsigned char rgbBlue; //锟斤拷色锟斤拷锟斤拷锟斤拷锟斤拷
unsigned char rgbGreen; //锟斤拷色锟斤拷锟斤拷锟斤拷锟斤拷
unsigned char rgbRed; //锟斤拷色锟斤拷锟斤拷锟斤拷锟斤拷
unsigned char rgbReserved;
}RGBQUAD;
void showbmp(BITMAPFILEHEADER bmp){
printf("****************************************文件头信息打印*******************************************************\n");
printf("文件类型:%x\n",bmp.bfType);
printf("文件大小=%d\n",bmp.bfSize);
printf("文件保留值1=%d\n",bmp.bfReserved1);
printf("文件保留值2=%d\n",bmp.bfReserved2);
printf("文件信息区的大小=%d\n",bmp.bfOffBits);
}
void showbmpinfo(BITMAPINFOHEADER info){
printf("结构体大小=%d\n",info.biSize);
printf("图像宽=%d\n",info.biWidth);
printf("图像高=%d\n",info.biHeight);
printf("图像位面数=%d\n",info.biPlanes);
printf("像素位数=%d\n",info.biBitCount);
printf("位图压缩类型:%d\n",info.biCompression);
printf("图像数据部分大小:%d\n",info.biSizeImage);
printf("水平分辨率:%d\n",info.biXPelsPerMeter);
printf("垂直分辨率:%d\n",info.biYPelsPerMeter);
printf("位图颜色表中的颜色数:%d\n",info.biClrUsed);
printf("重要颜色索引的数目:%d\n",info.biClrImportant);
}
int abs(int x){
return (x>0)?x:-x;
}
void sobel(unsigned char* src,unsigned char* dest,int height,int width,int thr){
int height_o=height-3+1;
int width_o=width-3+1;
int width_o_pack=(width_o+3)/4*4; //4byte
printf("height_o=%d,width_o=%d,width_o_pack=%d\n",height_o,width_o,width_o_pack);
for(int i=1;i<height-1;i++)
for(int j=1;j<width-1;j++)
{
//Gx=-src[i-1][j-1]+src[i-1][j+1]-2src[i][j-1]+2src[i][j+1]-src[i+1][j-1]+src[i+1][j+1]
//Gy=-src[i-1][j-1]-2src[i-1][j]-src[i-1][j+1]+src[i+1][j-1]+2src[i+1][j]+src[i+1][j+1]
//G=|Gx|+|Gy|
int Gx=-(int)src[(i-1)*width+(j-1)]+(int)src[(i-1)*width+(j+1)]-2*(int)src[i*width+j-1]+2*(int)src[i*width+j+1]-(int)src[(i+1)*width+j-1]+(int)src[(i+1)*width+j+1];
int Gy=(int)src[(i-1)*width+j-1]+2*(int)src[(i-1)*width+j]+(int)src[(i-1)*width+j+1]-(int)src[(i+1)*width+j-1]-2*(int)src[(i+1)*width+j]-(int)src[(i+1)*width+j+1];
dest[(i-1)*width_o_pack+(j-1)]=(unsigned char)(((abs(Gx)+abs(Gy))>thr)?255:0);
}
}
int main(){
BITMAPFILEHEADER bmp;
BITMAPINFOHEADER bmp_info;
//
FILE* fp1;
FILE* fp2;
FILE* fp3;
fp1=fopen("./test.bmp","rb");
fread(&bmp,14,1,fp1);
fread(&bmp_info,40,1,fp1);
//show infomation
showbmp(bmp);
showbmpinfo(bmp_info);
int height_o=bmp_info.biHeight-2;
int width_o=bmp_info.biWidth-2;
printf("height and width after sobel:%d x %d\n",height_o,width_o);
//
int lineByte=(bmp_info.biWidth*3+3)/4*4; //4锟街节讹拷锟斤拷锟揭伙拷械锟斤拷纸锟斤拷锟?,锟斤拷位锟街斤拷
int lineByte_gray=(bmp_info.biWidth+3)/4*4;
int lineBtye_sobel=(width_o+3)/4*4;
printf("lineByte=%d\n",lineByte);
printf("lineByte_gray=%d\n",lineByte_gray);
printf("lineByte_sobel=%d\n",lineBtye_sobel);
//
unsigned char* src_img=new unsigned char[bmp_info.biSizeImage]; //rgb pic
unsigned char* dest_img=new unsigned char[bmp_info.biHeight*lineByte_gray]; //gray pic
unsigned char* dest_img_sobel=new unsigned char[height_o*lineBtye_sobel]; //sobel pic
fseek(fp1,bmp.bfOffBits,SEEK_SET);
fread(src_img,1,bmp_info.biSizeImage,fp1);
for(int i=0;i<bmp_info.biHeight;i++)
for(int j=0;j<bmp_info.biWidth;j++){
unsigned char b=src_img[i*lineByte+j*3+0];
unsigned char g=src_img[i*lineByte+j*3+1];
unsigned char r=src_img[i*lineByte+j*3+2];
unsigned char gray=((unsigned int)r+(unsigned int)g+(unsigned int)b)/3;
dest_img[i*lineByte_gray+j]=gray;
}
sobel(dest_img,dest_img_sobel,bmp_info.biHeight,bmp_info.biWidth,100);
fclose(fp1);
//color table
RGBQUAD* pRgbQuards=new RGBQUAD[256];
for(int i=0;i<256;i++)
{
pRgbQuards[i].rgbBlue=i;
pRgbQuards[i].rgbRed=i;
pRgbQuards[i].rgbGreen=i;
}
fp2=fopen("./test_gray.bmp","wb");
//gray pic
bmp_info.biBitCount=24/3; //gray pic
bmp_info.biSize=40;
bmp_info.biSizeImage=bmp_info.biHeight*lineByte_gray;
bmp.bfOffBits=14+40+256*sizeof(RGBQUAD); //锟斤拷锟斤拷锟斤拷锟斤拷色锟斤拷
bmp.bfSize=bmp.bfOffBits+bmp_info.biSizeImage;
//print info
showbmp(bmp);
showbmpinfo(bmp_info);
//
fwrite(&bmp,1,14,fp2);
fwrite(&bmp_info,1,40,fp2);
fwrite(pRgbQuards,1,256*sizeof(RGBQUAD),fp2);
fwrite(dest_img,1,bmp_info.biSizeImage,fp2);
fclose(fp2);
//sobel
fp3=fopen("./test_sobel.bmp","wb");
//sobel pic
bmp_info.biBitCount=24/3; //锟揭讹拷图
bmp_info.biSize=40;
bmp_info.biHeight=height_o;
bmp_info.biWidth=width_o;
bmp_info.biSizeImage=height_o*lineBtye_sobel;
bmp.bfOffBits=14+40+256*sizeof(RGBQUAD); //锟斤拷锟斤拷锟斤拷锟斤拷色锟斤拷
bmp.bfSize=bmp.bfOffBits+bmp_info.biSizeImage;
//show info
showbmp(bmp);
showbmpinfo(bmp_info);
//write pic
fwrite(&bmp,1,14,fp3);
fwrite(&bmp_info,1,40,fp3);
fwrite(pRgbQuards,1,256*sizeof(RGBQUAD),fp3);
fwrite(dest_img_sobel,1,bmp_info.biSizeImage,fp3);
fclose(fp3);
return 0;
}