使用C语言读取位图.docx

上传人:b****2 文档编号:16917865 上传时间:2023-04-24 格式:DOCX 页数:16 大小:18.10KB
下载 相关 举报
使用C语言读取位图.docx_第1页
第1页 / 共16页
使用C语言读取位图.docx_第2页
第2页 / 共16页
使用C语言读取位图.docx_第3页
第3页 / 共16页
使用C语言读取位图.docx_第4页
第4页 / 共16页
使用C语言读取位图.docx_第5页
第5页 / 共16页
点击查看更多>>
下载资源
资源描述

使用C语言读取位图.docx

《使用C语言读取位图.docx》由会员分享,可在线阅读,更多相关《使用C语言读取位图.docx(16页珍藏版)》请在冰豆网上搜索。

使用C语言读取位图.docx

使用C语言读取位图

使用C语言读取位图  

2010-09-1616:

04:

43|  分类:

 C语言 |  标签:

c语言处理位图  |字号 订阅

一、位图文件结构

位图文件由三部分组成:

文件头+位图信息+位图像素数据

1、位图文件头。

位图文件头主要用于识别位图文件。

以下是位图文件头结构的定义:

typedefstructtagBITMAPFILEHEADER{//bmfh

WORDbfType;

DWORDbfSize;

WORDbfReserved1;

WORDbfReserved2;

DWORDbfOffBits;

}BITMAPFILEHEADER;

其中的bfType值应该是“BM”(0x4d42),标志该文件是位图文件。

bfSize的值是位图文件的大小。

2、位图信息中所记录的值用于分配内存,设置调色板信息,读取像素值等。

以下是位图信息结构的定义:

typedefstructtagBITMAPINFO{

BITMAPINFOHEADERbmiHeader;

RGBQUADbmiColors[1];

}BITMAPINFO;

可见位图信息也是由两部分组成的:

位图信息头+颜色表 

2.1位图信息头。

位图信息头包含了单个像素所用字节数以及描述颜色的格式,此外还包括位图的宽度、高度、目标设备的位平面数、图像的压缩格式。

以下是位图信息头结构的定义:

typedefstructtagBITMAPINFOHEADER{//bmih

DWORDbiSize;

LONGbiWidth;

LONGbiHeight;

WORDbiPlanes;

WORDbiBitCount

DWORDbiCompression;

DWORDbiSizeImage;

LONGbiXPelsPerMeter;

LONGbiYPelsPerMeter;

DWORDbiClrUsed;

DWORDbiClrImportant;

}BITMAPINFOHEADER;

下表是对结构体当中各个成员的说明:

 

结构成员

说明

biSize

结构BITMAPINFOHEADER的字节数,即sizeof(BITMAPINFOHEADER)*

biWidth

以像素为单位的图像宽度*

biHeight

以像素为单位的图像长度*

biplanes

目标设备的位平面数

biBitCount

每个像素的位数*

(1)

biCompression

图像的压缩格式(这个值几乎总是为0)

biSizeImage

以字节为单位的图像数据的大小(对BI_RGB压缩方式而言)

biXPelsPermeter

水平方向上的每米的像素个数

biYpelsPerMeter

垂直方向上的每米的像素个数

biClrused

调色板中实际使用的颜色数

(2)

biClrImportant

现实位图时必须的颜色数(3)

说明:

*是需要加以注意的部分,因为它们是我们在进行位图操作时经常参考的变量

(1)对于每个像素的字节数,分别有一下意义:

0,用在JPEG格式中

1,单色图,调色板中含有两种颜色,也就是我们通常说的黑白图片

4,16色图

8,256色图,通常说的灰度图

16,64K图,一般没有调色板,图像数据中每两个字节表示一个像素,5个或6个位表示一个RGB分量

24,16M真彩色图,一般没有调色板,图像数据中每3个字节表示一个像素,每个字节表示一个RGB分量

32,4G真彩色,一般没有调色板,每4个字节表示一个像素,相对24位真彩图而言,加入了一个透明度,即RGBA模式

(2)这个值通常为0,表示使用biBitCount确定的全部颜色,例外是使用的颜色树木小于制定的颜色深度的颜色数目的最大值。

(3)这个值通常为0,表示所有的颜色都是必需的

2.2颜色表。

颜色表一般是针对16位一下的图像而设置的,对于16位和16位以上的图像,由于其位图像素数据中直接对对应像素的RGB(A)颜色进行描述,因而省却了调色板。

而对于16位一下的图像,由于其位图像素数据中记录的只是调色板索引值,因而需要根据这个索引到调色板去取得相应的RGB(A)颜色。

颜色表的作用就是创建调色板。

颜色表是由颜色表项组成的,颜色表项结构的定义如下:

typedefstructtagRGBQUAD{//rgbq

BYTErgbBlue;

BYTErgbGreen;

BYTErgbRed;

BYTErgbReserved;

}RGBQUAD;

其中需要注意的问题是,RGBQUAD结构中的颜色顺序是BGR,而不是平常的RGB。

3、位图数据。

最后,在位图文件头、位图信息头、位图颜色表之后,便是位图的主体部分:

位图数据。

根据不同的位图,位图数据所占据的字节数也是不同的,比如,对于8位位图,每个字节代表了一个像素,对于16位位图,每两个字节代表了一个像素,对于24位位图,每三个字节代表了一个像素,对于32位位图,每四个字节代表了一个像素。

 

下面附上代码:

//Bmp.cpp:

定义控制台应用程序的入口点。

//

#include"stdafx.h"

 

int_tmain(intargc,_TCHAR*argv[])

{

   intReadFileHeader(char*filepath,BITMAPFILEHEADER*bmfh);

   intReadInfoHeader(char*filepaht,BITMAPINFOHEADER*bmih);

   intReadPixelData(char*filepath);

   DWORDGetLineBytes(intwidth,intbitCount);

   //BYTE*imgData;

   //inti=ReadPixelData("E:

\\1\\1.bmp");

   inti=ReadPixelData("D:

\\2.bmp");

   scanf("%d");

   return0;

}

 

//读入文件头  

intReadFileHeader(char*filepath,BITMAPFILEHEADER*bmfh)

{

 FILE*fp;

 //打开文件

 fp=fopen(filepath,"rb");

 if(!

fp)

 {//如果打开失败

    printf("Cannotopenthefile:

%s\n",filepath);

    return-1;

 }

 //读入bfType

 if(fread(&bmfh->bfType,sizeof(WORD),1,fp)!

=1)

 {

 printf("CannotreadbfTypeinthefileheader.\n");

 fclose(fp);

 return-1;

 }

 //读入bfSize

 if(fread(&bmfh->bfSize,sizeof(DWORD),1,fp)!

=1)

 {

 printf("CannotreadbfSizeinthefileheader.\n");

 fclose(fp);

 return-1;

 }

 //读入bfReserved1

 if(fread(&bmfh->bfReserved1,sizeof(WORD),1,fp)!

=1)

 {

 printf("CannotreadbfReserved1inthefileheader.\n");

 fclose(fp);

 return-1;

 }

 //读入bfReserved2

 if(fread(&bmfh->bfReserved2,sizeof(WORD),1,fp)!

=1)

 {

 printf("CannotreadbfReserved2inthefileheader.\n");

 fclose(fp);

 return-1;

 }

 //读入bfOffBits

 if(fread(&bmfh->bfOffBits,sizeof(DWORD),1,fp)!

=1)

 {

 printf("CannotreadbfOffBitsinthefileheader.\n");

 fclose(fp);

 return-1;

 }

 //关闭文件指针

 fclose(fp);

 return0;

}

//读入信息头  

intReadInfoHeader(char*filepath,BITMAPINFOHEADER*bmih) 

{

 FILE*fp;

 //打开文件

 fp=fopen(filepath,"rb");

 if(!

fp)

 {

 printf("Cannotopenthefile:

%s\n",filepath);

 return-1;

 }

 //使文件指针跳过文件头(14字节)

 fseek(fp,14,SEEK_SET);

 //读入biSize

 if(fread(&bmih->biSize,sizeof(DWORD),1,fp)!

=1)

 {

 printf("CannotreadbiSizeintheinfoheader.\n");

 fclose(fp);

 return-1;

 }

 //读入biWidth

 if(fread(&bmih->biWidth,sizeof(LONG),1,fp)!

=1)

 {

 printf("CannotreadbiWidthintheinfoheader.\n");

 fclose(fp);

 return-1;

 }

 //读入biHeight

 if(fread(&bmih->biHeight,sizeof(LONG),1,fp)!

=1)

 {

 printf("CannotreadbiHeightintheinfoheader.\n");

 fclose(fp);

 return-1;

 }

 //读入biPlanes

 if(fread(&bmih->biPlanes,sizeof(WORD),1,fp)!

=1)

 {

 printf("CannotreadbiPlanesintheinfoheader.\n");

 fclose(fp);

 return-1;

 }

 //读入biBitCount

 if(fread(&bmih->biBitCount,sizeof(WORD),1,fp)!

=1)

 {

 printf("CannotreadbiBitCountintheinfoheader.\n");

 fclose(fp);

 return-1;

 }

 //读入biCompression

 if(fread(&bmih->biCompression,sizeof(DWORD),1,fp)!

=1)

 {

 printf("CannotreadbiCompressionintheinfoheader.\n");

 fclose(fp);

 return-1;

 }

 //读入biSizeImage

 if(fread(&bmih->biSizeImage,sizeof(DWORD),1,fp)!

=1)

 {

 printf("CannotreadbiSizeImageintheinfoheader.\n");

 fclose(fp);

 return-1;

 }

 //读入biXPelsPerMeter

 if(fread(&bmih->biXPelsPerMeter,sizeof(LONG),1,fp)!

=1)

 {

 printf("CannotreadbiXPelsPerMeterintheinfoheader.\n");

 fclose(fp);

 return-1;

 }

 //读入biYPelsPerMeter

 if(fread(&bmih->biYPelsPerMeter,sizeof(LONG),1,fp)!

=1)

 {

 printf("CannotreadbiYPelsPerMeterintheinfoheader.\n");

 fclose(fp);

 return-1;

 }

 //读入biClrUsed

 if(fread(&bmih->biClrUsed,sizeof(DWORD),1,fp)!

=1)

 {

 printf("CannotreadbiClrUsedintheinfoheader.\n");

 fclose(fp);

 return-1;

 }

 //读入biClrImportant

 if(fread(&bmih->biClrImportant,sizeof(DWORD),1,fp)!

=1)

 {

 printf("CannotreadbiClrImportantintheinfoheader.\n");

 fclose(fp);

 return-1;

 }

 //关闭文件

 fclose(fp);

 return0;

}

//读取像素数据

intReadPixelData(char*filepath)

{

   BITMAPINFOHEADERbmih;

   BITMAPFILEHEADERbmfh;

   BYTE*imgdata;

   FILE*fp;

   intn;

   intwidth;

   intheight;

   intbitCount;

   longbiSizeImage;

   inti;

   intj;

   longa[256]={0};

   intp;

   DWORDdwLineBytes;

   //读入文件头

   n=ReadFileHeader(filepath,&bmfh);

   if(n==-1)

   {

      printf("CannotreadthefileheaderofBMPfile.\n");

      return-1;

   }

   //读入信息头

   n=ReadInfoHeader(filepath,&bmih);

   if(n==-1)

   {

      printf("CannotreadtheinfoheaderofBMPfile.\n");

      return-1;

   }

   //获取信息头有用信息

   width=bmih.biWidth;

   height=bmih.biHeight;

   bitCount=bmih.biBitCount;

   biSizeImage=bmih.biSizeImage;

   dwLineBytes=GetLineBytes(width,bitCount);

   //printf("%ld\n",dwLineBytes);

   printf("位图宽:

%ld\n",width);

   printf("位图高:

%ld\n",height);

   printf("位图位数:

%d\n",bitCount);

   printf("位图所占字节数:

%ld\n",biSizeImage);

   fp=fopen(filepath,"rb");

   if(!

fp)

   {

      printf("Cannotopenthefile:

%s\n",filepath);

      return-1;

   }

   if(bitCount==8||bitCount==24)

   {

      fseek(fp,bmfh.bfOffBits,SEEK_SET);//直接跳到像素数据

   }else

   {

      printf("此位图为%d位!

",bitCount);

      printf("只支持8或24位");

      fclose(fp);

      return-1;

   }

    

   //给imgdata分配内存

   imgdata=(BYTE*)malloc(dwLineBytes*height*sizeof(BYTE));

   if(!

imgdata)

   {

      printf("Cannotallocatememoryforthepixeldata.\n");

      return-1;

   }

    

    

   //读入像素数据,大小为高度乘上每行所占字节数

   n=fread(imgdata,dwLineBytes*height*sizeof(BYTE),1,fp);

   if(n==0)

   {

      if(ferror(fp))

      {

           printf("Cannotreadthepixeldata.\n");

         free(imgdata);

         fclose(fp);

         return-1;

      }

   }

   printf("图片像素值首地址:

%ld\n",imgdata);

    

   //读取位图像素值

   if(bitCount==8)

   {

      for(i=0;i

      {

         for(j=0;j

         {

         //读取灰度值

         p=*(imgdata+dwLineBytes*(height-1-i)+j);

         a[p]++;

         //printf("%d,",p);

         }

      }

      printf("\n");

   }elseif(bitCount==24)

   {

      for(i=0;i

      {

         for(j=0;j

         {

            printf("(");

            //读取蓝色分量

            p=*(imgdata+dwLineBytes*(height-1-i)+j);

            printf("%d,",p);

            j++;

            //读取绿色分量

            p=*(imgdata+dwLineBytes*(height-1-i)+j);

            printf("%d,",p);

            j++;

            //读取红色分量

            p=*(imgdata+dwLineBytes*(height-1-i)+j);

            printf("%d,",p);

            printf(")");

         }

         printf("\n");

      }

   }else

   {

      printf("只支持8或24位");

   }

   free(imgdata);

   fclose(fp);

   printf("统计结果如下:

\n");

   for(i=0;i<256;i++)

   {

      printf("位图中%3d有%ld个\n",i,a[i]);

   }

    

   return0;

}

 

DWORDGetLineBytes(intwidth,intbitCount) 

{

   //首先bitCount是指位图的每个像素所占的二进制位数,不是字节数;

   //其次,windows中位图每行所占的字节数必须为4的倍数,

   //例如灰度图中每行200个像素占用200个字节,如果每行有201个像素就占用204个字节。

   //return((width*bitCount/8+3)/4)*4;

   return(width*bitCount+31)/32*4;

}

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

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

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

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