C语言 BMP图片处理.docx

上传人:b****8 文档编号:10229345 上传时间:2023-02-09 格式:DOCX 页数:13 大小:18.57KB
下载 相关 举报
C语言 BMP图片处理.docx_第1页
第1页 / 共13页
C语言 BMP图片处理.docx_第2页
第2页 / 共13页
C语言 BMP图片处理.docx_第3页
第3页 / 共13页
C语言 BMP图片处理.docx_第4页
第4页 / 共13页
C语言 BMP图片处理.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

C语言 BMP图片处理.docx

《C语言 BMP图片处理.docx》由会员分享,可在线阅读,更多相关《C语言 BMP图片处理.docx(13页珍藏版)》请在冰豆网上搜索。

C语言 BMP图片处理.docx

C语言BMP图片处理

C语言BMP图片处理

 

BMP是bitmap的缩写形式,bitmap顾名思义,就是位图也即Windows位图。

它一般由4部分组成:

文件头信息块、图像描述信息块、颜色表(在真彩色模式无颜色表)和图像数据区组成。

在系统中以BMP为扩展名保存。

  打开Windows的画图程序,在保存图像时,可以看到三个选项:

2色位图(黑白)、16色位图、256色位图和24位位图。

这是最普通的生成位图的工具,在这里讲解的BMP位图形式,主要就是指用画图生成的位图(当然,也可以用其它工具软件生成)。

  现在讲解BMP的4个组成部分:

1.文件头信息块

0000-0001:

文件标识,为字母ASCII码“BM”。

0002-0005:

文件大小。

0006-0009:

保留,每字节以“00”填写。

000A-000D:

记录图像数据区的起始位置。

各字节的信息依次含义为:

文件头信息块大小,图像描述信息块的大小,图像颜色表的大小,保留(为01)。

2.图像描述信息块

000E-0011:

图像描述信息块的大小,常为28H。

0012-0015:

图像宽度。

0016-0019:

图像高度。

001A-001B:

图像的plane(平面?

)总数(恒为1)。

001C-001D:

记录像素的位数,很重要的数值,图像的颜色数由该值决定。

001E-0021:

数据压缩方式(数值位0:

不压缩;1:

8位压缩;2:

4位压缩)。

0022-0025:

图像区数据的大小。

0026-0029:

水平每米有多少像素,在设备无关位图(.DIB)中,每字节以00H填写。

002A-002D:

垂直每米有多少像素,在设备无关位图(.DIB)中,每字节以00H填写。

002E-0031:

此图像所用的颜色数,如值为0,表示所有颜色一样重要。

3.颜色表

  颜色表的大小根据所使用的颜色模式而定:

2色图像为8字节;16色图像位64字节;256色图像为1024字节。

其中,每4字节表示一种颜色,并以B(蓝色)、G(绿色)、R(红色)、alpha(像素的透明度值,一般不需要)。

即首先4字节表示颜色号0的颜色,接下来表示颜色号1的颜色,依此类推。

4.图像数据区

  颜色表接下来位为位图文件的图像数据区,在此部分记录着每点像素对应的颜色号,其记录方式也随颜色模式而定,既2色图像每点占1位(8位为1字节);16色图像每点占4位(半字节);256色图像每点占8位(1字节);真彩色图像每点占24位(3字节)。

所以,整个数据区的大小也会随之变化。

究其规律而言,可的出如下计算公式:

图像数据信息大小=(图像宽度*图像高度*记录像素的位数)/8。

然而,未压缩的图像信息区的大小。

除了真彩色模式外,其余的均大于或等于数据信息的大小。

这是为什么呢?

原因有两个:

  1.BMP文件记录一行图像是以字节为单位的。

因此,就不存在一个字节中的数据位信息表示的点在不同的两行中。

也就是说,设显示模式位16色,在每个字节分配两个点信息时,如果图像的宽度位奇数,那么最后一个像素点的信息将独占一个字节,这个字节的后4位将没有意义。

接下来的一个字节将开始记录下一行的信息。

  2.为了显示的方便,除了真彩色外,其他的每中颜色模式的行字节数要用数据“00”补齐为4的整数倍。

如果显示模式为16色,当图像宽为19时,存储时每行则要补充4-(19/2+1)%4=2个字节(加1是因为里面有一个像素点要独占了一字节)。

如果显示模式为256色,当图像宽为19时,每行也要补充4-19%4=1个字节。

  还有一点我要申明,当屏幕初始化为16或256色模式时,一定要设置调色板或修正颜色值,否则无法得到正确的图像颜色。

C代码

//ReadBitMap

//

#include

#include

#include

#include

#include

#defineWIDTHBYTES(bits)(((bits)+31)/32*4)

typedefunsignedcharBYTE;

typedefunsignedshortWORD;

typedefunsignedlongDWORD;

typedeflongLONG;

//位图文件头信息结构定义

//其中不包含文件类型信息(由于结构体的内存结构决定,要是加了的话将不能正确读取文件信息)

typedefstructtagBITMAPFILEHEADER{

DWORDbfSize;//文件大小

WORDbfReserved1;//保留字,不考虑

WORDbfReserved2;//保留字,同上

DWORDbfOffBits;//实际位图数据的偏移字节数,即前三个部分长度之和

}BITMAPFILEHEADER;

//信息头BITMAPINFOHEADER,也是一个结构,其定义如下:

typedefstructtagBITMAPINFOHEADER{

//public:

DWORDbiSize;//指定此结构体的长度,为40

LONGbiWidth;//位图宽

LONGbiHeight;//位图高

WORDbiPlanes;//平面数,为1

WORDbiBitCount;//采用颜色位数,可以是1,2,4,8,16,24,新的可以是32

DWORDbiCompression;//压缩方式,可以是0,1,2,其中0表示不压缩

DWORDbiSizeImage;//实际位图数据占用的字节数

LONGbiXPelsPerMeter;//X方向分辨率

LONGbiYPelsPerMeter;//Y方向分辨率

DWORDbiClrUsed;//使用的颜色数,如果为0,则表示默认值(2^颜色位数)

DWORDbiClrImportant;//重要颜色数,如果为0,则表示所有颜色都是重要的

}BITMAPINFOHEADER;

//调色板Palette,当然,这里是对那些需要调色板的位图文件而言的。

24位和32位是不需要调色板的。

//(似乎是调色板结构体个数等于使用的颜色数。

typedefstructtagRGBQUAD{

//public:

BYTErgbBlue;//该颜色的蓝色分量

BYTErgbGreen;//该颜色的绿色分量

BYTErgbRed;//该颜色的红色分量

BYTErgbReserved;//保留值

}RGBQUAD;

voidshowBmpHead(BITMAPFILEHEADER*pBmpHead)

{

printf("位图文件头:

\n");

printf("文件大小:

%d\n",pBmpHead->bfSize);

printf("保留字:

%d\n",pBmpHead->bfReserved1);

printf("保留字:

%d\n",pBmpHead->bfReserved2);

printf("实际位图数据的偏移字节数:

%d\n",pBmpHead->bfOffBits);

}

voidshowBmpInforHead(tagBITMAPINFOHEADER*pBmpInforHead)

{

printf("位图信息头:

\n");

printf("结构体的长度:

%d\n",pBmpInforHead->biSize);

printf("位图宽:

%d\n",pBmpInforHead->biWidth);

printf("位图高:

%d\n",pBmpInforHead->biHeight);

printf("biPlanes平面数:

%d\n",pBmpInforHead->biPlanes);

printf("biBitCount采用颜色位数:

%d\n",pBmpInforHead->biBitCount);

printf("压缩方式:

%d\n",pBmpInforHead->biCompression);

printf("biSizeImage实际位图数据占用的字节数:

%d\n",pBmpInforHead->biSizeImage);

printf("X方向分辨率:

%d\n",pBmpInforHead->biXPelsPerMeter);

printf("Y方向分辨率:

%d\n",pBmpInforHead->biYPelsPerMeter);

printf("使用的颜色数:

%d\n",pBmpInforHead->biClrUsed);

printf("重要颜色数:

%d\n",pBmpInforHead->biClrImportant);

}

voidshowRgbQuan(tagRGBQUAD*pRGB)

{

printf("(%-3d,%-3d,%-3d)",pRGB->rgbRed,pRGB->rgbGreen,pRGB->rgbBlue);

}

voidmain()

{

BITMAPFILEHEADERbitHead;

BITMAPINFOHEADERbitInfoHead;

FILE*pfile;

charstrFile[50];

printf("pleaseinputthe.bmpfilename:

\n");

scanf("%s",strFile);

pfile=fopen(strFile,"rb");//打开文件

if(pfile!

=NULL)

{

printf("filebkwood.bmpopensuccess.\n");

//读取位图文件头信息

WORDfileType;

fread(&fileType,1,sizeof(WORD),pfile);

if(fileType!

=0x4d42)

{

printf("fileisnot.bmpfile!

");

return;

}

//fseek(pfile,2,SEEK_CUR);//"BM"

fread(&bitHead,1,sizeof(tagBITMAPFILEHEADER),pfile);

showBmpHead(&bitHead);

printf("\n\n");

//读取位图信息头信息

fread(&bitInfoHead,1,sizeof(BITMAPINFOHEADER),pfile);

showBmpInforHead(&bitInfoHead);

printf("\n");

}

else

{

printf("fileopenfail!

\n");

return;

}

tagRGBQUAD*pRgb;

if(bitInfoHead.biBitCount<24)//有调色板

{

//读取调色盘结信息

longnPlantNum=long(pow(2,double(bitInfoHead.biBitCount)));//MixcolorPlantNumber;

pRgb=(tagRGBQUAD*)malloc(nPlantNum*sizeof(tagRGBQUAD));

memset(pRgb,0,nPlantNum*sizeof(tagRGBQUAD));

intnum=fread(pRgb,4,nPlantNum,pfile);

printf("ColorPlateNumber:

%d\n",nPlantNum);

printf("颜色板信息:

\n");

for(inti=0;i

{

if(i%5==0)

{

printf("\n");

}

showRgbQuan(&pRgb[i]);

}

printf("\n");

}

intwidth=bitInfoHead.biWidth;

intheight=bitInfoHead.biHeight;

//分配内存空间把源图存入内存

intl_width=WIDTHBYTES(width*bitInfoHead.biBitCount);//计算位图的实际宽度并确保它为32的倍数

BYTE*pColorData=(BYTE*)malloc(height*l_width);

memset(pColorData,0,height*l_width);

longnData=height*l_width;

//把位图数据信息读到数组里

fread(pColorData,1,nData,pfile);

//将位图数据转化为RGB数据

tagRGBQUAD*dataOfBmp;

dataOfBmp=(tagRGBQUAD*)malloc(width*height*sizeof(tagRGBQUAD));//用于保存各像素对应的RGB数据

memset(dataOfBmp,0,width*height*sizeof(tagRGBQUAD));

if(bitInfoHead.biBitCount<24)//有调色板,即位图为非真彩色

{

intk;

intindex=0;

if(bitInfoHead.biBitCount==1)

{

for(inti=0;i

for(intj=0;j

{

BYTEmixIndex=0;

k=i*l_width+j/8;//k:

取得该像素颜色数据在实际数据数组中的序号

//j:

提取当前像素的颜色的具体值

mixIndex=pColorData[k];

switch(j%8)

{

case0:

mixIndex=mixIndex<<7;

mixIndex=mixIndex>>7;

break;

case1:

mixIndex=mixIndex<<6;

mixIndex=mixIndex>>7;

break;

case2:

mixIndex=mixIndex<<5;

mixIndex=mixIndex>>7;

break;

case3:

mixIndex=mixIndex<<4;

mixIndex=mixIndex>>7;

break;

case4:

mixIndex=mixIndex<<3;

mixIndex=mixIndex>>7;

break;

case5:

mixIndex=mixIndex<<2;

mixIndex=mixIndex>>7;

break;

case6:

mixIndex=mixIndex<<1;

mixIndex=mixIndex>>7;

break;

case7:

mixIndex=mixIndex>>7;

break;

}

//将像素数据保存到数组中对应的位置

dataOfBmp[index].rgbRed=pRgb[mixIndex].rgbRed;

dataOfBmp[index].rgbGreen=pRgb[mixIndex].rgbGreen;

dataOfBmp[index].rgbBlue=pRgb[mixIndex].rgbBlue;

dataOfBmp[index].rgbReserved=pRgb[mixIndex].rgbReserved;

index++;

}

}

if(bitInfoHead.biBitCount==2)

{

for(inti=0;i

for(intj=0;j

{

BYTEmixIndex=0;

k=i*l_width+j/4;//k:

取得该像素颜色数据在实际数据数组中的序号

//j:

提取当前像素的颜色的具体值

mixIndex=pColorData[k];

switch(j%4)

{

case0:

mixIndex=mixIndex<<6;

mixIndex=mixIndex>>6;

break;

case1:

mixIndex=mixIndex<<4;

mixIndex=mixIndex>>6;

break;

case2:

mixIndex=mixIndex<<2;

mixIndex=mixIndex>>6;

break;

case3:

mixIndex=mixIndex>>6;

break;

}

//将像素数据保存到数组中对应的位置

dataOfBmp[index].rgbRed=pRgb[mixIndex].rgbRed;

dataOfBmp[index].rgbGreen=pRgb[mixIndex].rgbGreen;

dataOfBmp[index].rgbBlue=pRgb[mixIndex].rgbBlue;

dataOfBmp[index].rgbReserved=pRgb[mixIndex].rgbReserved;

index++;

}

}

if(bitInfoHead.biBitCount==4)

{

for(inti=0;i

for(intj=0;j

{

BYTEmixIndex=0;

k=i*l_width+j/2;

mixIndex=pColorData[k];

if(j%2==0)

{//低

mixIndex=mixIndex<<4;

mixIndex=mixIndex>>4;

}

else

{//高

mixIndex=mixIndex>>4;

}

dataOfBmp[index].rgbRed=pRgb[mixIndex].rgbRed;

dataOfBmp[index].rgbGreen=pRgb[mixIndex].rgbGreen;

dataOfBmp[index].rgbBlue=pRgb[mixIndex].rgbBlue;

dataOfBmp[index].rgbReserved=pRgb[mixIndex].rgbReserved;

index++;

}

}

if(bitInfoHead.biBitCount==8)

{

for(inti=0;i

for(intj=0;j

{

BYTEmixIndex=0;

k=i*l_width+j;

mixIndex=pColorData[k];

dataOfBmp[index].rgbRed=pRgb[mixIndex].rgbRed;

dataOfBmp[index].rgbGreen=pRgb[mixIndex].rgbGreen;

dataOfBmp[index].rgbBlue=pRgb[mixIndex].rgbBlue;

dataOfBmp[index].rgbReserved=pRgb[mixIndex].rgbReserved;

index++;

}

}

if(bitInfoHead.biBitCount==16)

{

for(inti=0;i

for(intj=0;j

{

WORDmixIndex=0;

k=i*l_width+j*2;

WORDshortTemp;

shortTemp=pColorData[k+1];

shortTemp=shortTemp<<8;

mixIndex=pColorData[k]+shortTemp;

dataOfBmp[index].rgbRed=pRgb[mixIndex].rgbRed;

dataOfBmp[index].rgbGreen=pRgb[mixIndex].rgbGreen;

dataOfBmp[index].rgbBlue=pRgb[mixIndex].rgbBlue;

dataOfBmp[index].rgbReserved=pRgb[mixIndex].rgbReserved;

index++;

}

}

}

else//位图为24位真彩色

{

intk;

intindex=0;

for(inti=0;i

for(intj=0;j

{

k=i*l_width+j*3;

dataOfBmp[index].rgbRed=pColorData[k+2];

dataOfBmp[index].rgbGreen=pColorData[k+1];

dataOfBmp[index].rgbBlue=pColorData[k];

index++;

}

}

printf("像素数据信息:

\n");

for(inti=0;i

{

if(i%5==0)

{

printf("\n");

}

showRgbQuan(&dataOfBmp[i]);

}

fclose(pfile);

if(bitInfoHead.biBitCount<24)

{

free(pRgb);

}

free(dataOfBmp);

free(pColorData);

printf("\n");

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1