C语言读取和显示BMP文件

头哥baby 贡献于2013-05-16

作者 zhoushuqiang  创建于2009-11-21 08:26:00   修改者zhoushuqiang  修改于2009-11-21 08:54:00字数7421

文档摘要:C语言读取和显示BMP文件
关键词:

 C语言读取和显示BMP文件 (zt) 默认分类   2009-09-19 14:23   阅读106   评论0   字号: 大大  中中  小小 C语言读取和显示BMP文件 Posted on 2008-01-21 01:12 hoodlum1980 阅读(2624) 评论(0)  编辑 收藏 网摘 在TC2.0下,隶属于16位子系统,所以int是2字节,long是4字节,char是1字节。绘图系统模式是VGA,颜色当然也很有限,所以读取bmp像素后需要把像素颜色转换为“最近”的已有VGA颜色。用int GetColor(int r,int g,int b)实现返回一个颜色值(color code)。用putpixel(int x,int y,int color)绘制一个像素。       下图是几种在.NET Framework中的已知颜色和其RGB值(下图当然也是使用代码绘制的,代码略)。              16种颜色是位于RGB立方体中的16个点,相当于寻找一个最接近指定颜色的点。为了简化计算,计算出两点距离的平方即可。       为了加快搜索,我们可以用下面的类似绘制“金刚石”的代码提前求出最短距离的平方,这个数据将应用到GetColor函数中。原因是我们已知最近的两个颜色点的距离,如果某点与某颜色的距离小于最短距离的一半,则此颜色就是我们要找的结果。 Compute Minimum Dist^2 Code int COLORS[16][3]={.}; /* i,j - color index */ /* ret - distance^2 */ long GetDist(int i,int j) {         long dist=0;         dist+=(COLORS[i][0]-COLORS[j][0])*(COLORS[i][0]-COLORS[j][0]);         dist+=(COLORS[i][1]-COLORS[j][1])*(COLORS[i][1]-COLORS[j][1]);         dist+=(COLORS[i][2]-COLORS[j][2])*(COLORS[i][2]-COLORS[j][2]);         return dist; } void main(void) {         int i, j;         long dist,mindist=195075;         for(i=0;i<15;i++)         {                 for(j=i+1;j<16;j++)                 {                         dist=GetDist(i,j);                         if(dist #include  #include  #include  int MAX_Y=480; int MAX_X=640; int COLORS[16][3]=     {         /* R   G   B        Index    ColorName        */         {  0,  0,  0},     /* 00 Black                */         {  0,  0,255},     /* 01 Blue                */         {  0,128,  0},        /* 02 Green                */         {  0,255,255},     /* 03 Cyan                */         {255,  0,  0},     /* 04 Red                */         {255,  0,255},     /* 05 Magenta            */         {165, 42, 42},     /* 06 Brown                */         {211,211,211},     /* 07 LightGray        */         {169,169,169},     /* 08 DarkGray            */         {173,216,230},     /* 09 LightBlue        */         {144,238,144},     /* 10 LightGreen        */         {144,238,238},        /* 11 LightCyan        */         {238,144,144},     /* 12 LightRed            */         {238,144,238},     /* 13 LightMegenta    */         {255,255,  0},     /* 14 Yellow            */         {255,255,255},        /* 15 White                */     }; /* pixel : keep channel order with readfile order */ typedef struct _PIXEL {     unsigned char b;     unsigned char g;     unsigned char r; } PIXEL; /* color item in palette */ typedef struct _RGBQUAD {     unsigned char rgbBlue;     unsigned char rgbGreen;     unsigned char rgbRed;     unsigned char rgbReserved; } RGBQUAD; /* bitmap file header */ typedef struct _BITMAPFILEHEADER {     unsigned int type;     long fileSize;     long reserved;     long offbits; } BITMAPFILEHEADER,*PBITMAPFILEHEADER; /* bitmap info header */ typedef struct _BITMAPINFOHEADER {     long dwSize;     long width;     long height;     int  planes;     int  bpp;     long compression;     long sizeImage;     long hResolution;     long vResolution;     long colors;     long importantColors; } BITMAPINFOHEADER,*PBITMAPINFOHEADER; /* Functions Declare List */ int      GetColor(); void    ReadImage(); void    DrawAxes(); void    CopyScreen(); /* Entry Point Function */ void main() {     int driver,mode;     char filename[255];     printf("input the filename of bitmap file:\n");     scanf("%s",filename);     driver=DETECT;     initgraph(&driver,&mode,"c:\\tc\\");     /* draw a bitmap */     ReadImage(filename);     getch();     closegraph(); } /* read pixels from imagefile and display */ void ReadImage(char* filename) {     FILE* stream;     char string[255];     int i,j,width,height,color;     size_t bytesRead,stride,itemSize=1;     long offset;     BITMAPFILEHEADER fileHeader;     BITMAPINFOHEADER infoHeader;     unsigned char *pPixels,red,green,blue;     stream=fopen(filename,"rb");     if(stream==NULL)     {         printf("open file error!\n");         exit(0);     }     fseek(stream,0,0);     fread(&fileHeader,1,sizeof(fileHeader),stream);     fread(&infoHeader,1,sizeof(infoHeader),stream);     width=infoHeader.width;     height=infoHeader.height;     /* stride: scan line bytes count. padding for 4 bytes */     stride=(infoHeader.bpp*width+31)/32*4;     pPixels=malloc(stride);     for(j=height-1;j>=0;j--)     {         /* !!! stride (2 bytes) must be convert to long (4 bytes) */         offset=fileHeader.offbits+j*((long)stride);         fseek(stream,offset,0);         bytesRead=fread(pPixels,itemSize,stride,stream);         for(i=0;i=top;j--)     {         memset(pPixels,0,stride);         for(i=left;i<=right;i+=2)         {             /* 2 pixels to 1 byte */             index0=getpixel(i,j);             index1=(i==right)? 0: getpixel(i+1,j);             pPixels[i/2]=(index0<<4)+index1;         }         fwrite(pPixels,1,stride,stream);     }     fclose(stream); }   /* ---------END------------ */       首先我们要知道的几个概念:       bpp:位深度,单位是位/像素(bits per pixel),bpp决定了所能表示的颜色数量。例如bpp=1,则说明图像只有黑白两色(二值图像)。bpp=8,为普通的灰度图像。bpp=24,是最常见的RGB三通道彩色图片。       stride:扫描行宽度,单位是字节。这是一个在图像数据块(文件或内存中的)中进行定位非常重要的概念,指一行像素占据的内存大小。它必须是4bytes整数倍。因此stride从下面表达式的计算:       stride=(bm.Width*bpp+31)/32*4;             在这里我们必须注意,读取BMP文件时,文件地址是long型(4bytes),即32位的地址,当计算偏移地址时,我们必须把16位的size_t或者int类型首先转化为long型,以免高位地址丢失,导致不能正确定位文件。例如下面这句代码中的类型显示转换是不可缺少的。        offset=fileHeader.offbits+j*((long)stride);       由于在TC VGA绘图模式下无法截屏(没有DC),所以通过另存为一个4bpp的bmp图片来做示范。 (24 bpp Win32 bmp)->(TC VGA Graph Mode“截屏”)   0 0 0 (请您对文章做出评价)

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 2 金币 [ 分享文档获得金币 ] 0 人已下载

下载文档