任意宽度灰度BMP图像读写 V1

来源:互联网 发布:魔灵召唤淘宝刷塔 编辑:程序博客网 时间:2024/05/20 03:42

转自:http://blog.csdn.net/lyc_daniel/article/details/8177346

 一般BMP图像读写程序只能正确读写宽度为4的倍数的图像,而在图像处理领域所用到的图像宽度不一定满足4的倍数。我在一般BMP图像读写程序基础上进行了改进,使得程序可以读写任意宽度的灰度BMP图像。特分享给大家,希望能够给大家带来帮助。

头文件:myRdWtIm.h
[cpp] view plaincopy
  1. #ifndef RWBMP_H  
  2. #define RWBMP_H  
  3.   
  4. #include <windows.h>  
  5. #include <stdio.h>  
  6. #include <string.h>  
  7. #include <math.h>  
  8. #include <stdlib.h>  
  9.   
  10. BYTE *Read8bitbmp(char *bmpName,int *bmpWidth,int *bmpHeight);  //读BMP图像  
  11. bool Writebitmapbmp(unsigned char *imgBuf, int width, int height, char *bmpName);   //写BMP图像  
  12.   
  13. #endif  

源文件:myRdWtIm.cpp

[cpp] view plaincopy
  1. #include "myRdWtIm.h"  
  2.   
  3. /*------------------------------------------------ 
  4. *函数名称: 
  5. *   readBmp() 
  6. * 
  7. *函数参数: 
  8. *   char *bmpName -文件名字及路径 
  9. *   int *bmpWidth -图像宽度指针变量 
  10. *   int *bmpHeight -图像高度指针变量 
  11. * 
  12. *返回值: 
  13. *   unsigned char * -有效图像数据指针 
  14. * 
  15. *说明: 
  16. *   (1)给定一个图像文件名及其路径,读图像的位图数据、宽、高、颜色表及每像素 
  17. *位数等数据进内存。 
  18. *   (2)该读程序仅针对灰度图像(biBitCount=8)格式 
  19. ------------------------------------------------*/  
  20. BYTE* Read8bitbmp(char *bmpName,int *bmpWidth,int *bmpHeight)  
  21. {  
  22.     //二进制读方式打开指定的图像文件  
  23.     FILE *fp=fopen(bmpName,"rb");  
  24.     if(fp==0) return 0;  
  25.   
  26.     //跳过位图文件头结构BITMAPFILEHEADER  
  27.     fseek(fp, sizeof(BITMAPFILEHEADER),0);  //moves the file pointer to a specified location  
  28.   
  29.     //定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中  
  30.     BITMAPINFOHEADER head;  
  31.     fread(&head, sizeof(BITMAPINFOHEADER), 1,fp);   
  32.   
  33.     //获取图像宽、高等信息  
  34.     *bmpWidth = head.biWidth;   //位图的宽度,以像素为单位  
  35.     *bmpHeight = head.biHeight; //位图的高度,以像素为单位  
  36.   
  37.     //定义变量,计算图像每行像素所占的字节数(必须是4的倍数)  
  38.     int biBitCount=8;   //8位灰度图像  
  39.     int lineByte=((*bmpWidth)*biBitCount/8+3)/4*4;  
  40.   
  41.     //灰度图像有颜色表,且颜色表表项为256     
  42.     RGBQUAD *pColorTable=new RGBQUAD[256];  //申请颜色表所需要的空间  
  43.     fread(pColorTable,sizeof(RGBQUAD),256,fp);  //读颜色表进内存  
  44.   
  45.     //申请位图数据所需要的空间,读位图数据进内存  
  46.     unsigned char *pBmpBuf=new unsigned char[lineByte*(*bmpHeight)];  
  47.     fread(pBmpBuf,1,lineByte*(*bmpHeight),fp);  
  48.       
  49.     //关闭文件  
  50.     fclose(fp);  
  51.   
  52.     //提取有效数据,并返回  
  53.     if (*bmpWidth<lineByte)  
  54.     {  
  55.         unsigned char *pBmpBufData=new unsigned char[(*bmpWidth)*(*bmpHeight)];  
  56.         for (int i=0;i<*bmpHeight;i++)  
  57.         {  
  58.             for (int j=0;j<*bmpWidth;j++)  
  59.             {  
  60.                 pBmpBufData[i*(*bmpWidth)+j]=*(pBmpBuf+i*lineByte+j);   //第一种赋值方法  
  61.                 //*(pBmpBufData+i*(*bmpWidth)+j)=*(pBmpBuf+i*lineByte+j);   //第二种赋值方法  
  62.             }  
  63.         }  
  64.         return pBmpBufData; //返回提取的有效数据  
  65.     }  
  66.     else  
  67.     {  
  68.         return pBmpBuf; //返回有效数据  
  69.     }  
  70. }  
  71.   
  72. /*------------------------------------------------  
  73. *函数名称:  
  74. *   saveBmp()  
  75. *  
  76. *函数参数:  
  77. *   unsigned char *imgBuf-待存盘的位图数据  
  78. *   <span style="WHITE-SPACE: pre"> </span>int width-以像素为单位待存盘位图的宽  
  79. *   <span style="WHITE-SPACE: pre"> </span>int height-以像素为单位待存盘位图高  
  80. *   char *bmpName-文件名字及路径  
  81. *  
  82. *返回值:  
  83. *   0为失败,1为成功  
  84. *  
  85. *说明:  
  86. *   1.给定一个图像的位图数据、宽、高等信息,将其写到指定文件中。  
  87. *   2.该读程序仅针对灰度图像(biBitCount=8)格式  
  88. ------------------------------------------------*/  
  89. bool Writebitmapbmp(unsigned char *imgBuf, int width, int height, char *bmpName)   
  90. {  
  91.     //如果位图数据指针为0,则没有数据传入,函数返回  
  92.     if(!imgBuf) return 0;  
  93.   
  94.     int biBitCount=8;   //每个像素所占的位数(bit)  
  95.   
  96.     //颜色表大小,以字节为单位,灰度图像颜色表为1024字节  
  97.     int colorTablesize=1024;  
  98.   
  99.     //待存储图像数据每行字节数为4的倍数  
  100.     int lineByte=(width * biBitCount/8+3)/4*4;  
  101.   
  102.     //以二进制写的方式打开文件  
  103.     FILE *fp=fopen(bmpName,"wb");  
  104.     if(fp==0) return 0;  
  105.   
  106.     //申请位图文件头结构变量,填写文件头信息  
  107.     BITMAPFILEHEADER fileHead;  
  108.     fileHead.bfType=0x4D42; //bmp类型  
  109.   
  110.     //bfSize是图像文件4个组成部分之和  
  111.     fileHead.bfSize=sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+colorTablesize+lineByte*height;  
  112.     fileHead.bfReserved1=0;  
  113.     fileHead.bfReserved2=0;  
  114.   
  115.     //bfOffBits是图像文件前3个部分所需空间之和  
  116.     fileHead.bfOffBits=54+colorTablesize;  
  117.   
  118.     //写文件头进文件  
  119.     fwrite(&fileHead, sizeof(BITMAPFILEHEADER),1, fp);  
  120.   
  121.     //申请位图信息头结构变量,填写信息头信息  
  122.     BITMAPINFOHEADER head;  
  123.     head.biSize=40; //本结构的长度  
  124.     head.biWidth=width; //位图的宽度,以像素为单位  
  125.     head.biHeight=height;   //位图的宽度,以像素为单位  
  126.     head.biPlanes=1;    //目标设备的级别,必须是1  
  127.     head.biBitCount=8;  //每个像素所占的位数(bit),其值必须为1(黑白图像),4(16色图),8(256色),24(真彩色图)  
  128.     head.biCompression=BI_RGB;  //位图压缩类型,有效的值为BI_RGB(未经压缩)、BI_RLE4,BI_RLE8,BI_BITFIEDS(均为Windows定义常量)。  
  129.     head.biSizeImage=lineByte*height;   //实际的位图数据占用的字节数  
  130.     head.biXPelsPerMeter=0; //指定目标数据的水平分辨率,单位是像素/米。  
  131.     head.biYPelsPerMeter=0; ////指定目标数据的垂直分辨率,单位是像素/米。  
  132.     head.biClrUsed=0;   //位图实际用到的颜色数,如果该值为零,则用到的颜色数为2的biBitCount次幂  
  133.     head.biClrImportant=0;  //位图显示过程中重要的颜色数,如果该值为零,则认为所有的颜色都是重要的。  
  134.   
  135.     //写位图信息头进内存  
  136.     fwrite(&head, sizeof(BITMAPINFOHEADER),1, fp);  
  137.   
  138.     //申请颜色表所需要的空间,写颜色表进文件  
  139.     RGBQUAD *pColorTable=new RGBQUAD[256];  
  140.     for (int i=0;i<256;i++)  
  141.     {  
  142.         pColorTable[i].rgbRed=i;  
  143.         pColorTable[i].rgbGreen=i;  
  144.         pColorTable[i].rgbBlue=i;  
  145.         pColorTable[i].rgbReserved=0;  
  146.     }  
  147.     fwrite(pColorTable,sizeof(RGBQUAD),256,fp);  
  148.   
  149.     //判断位图数据宽度是否正确,并写数据进入BMP  
  150.     if (width<lineByte)  //如果有效数据宽度小于BMP格式要求宽度  
  151.     {  
  152.         unsigned char *imgBufBMP=new unsigned char [lineByte*height];  
  153.         //将有效数据赋给用于写BMP的数据空间  
  154.         for (int i=0;i<height;i++)  
  155.         {  
  156.             for (int j=0;j<width;j++)  
  157.             {  
  158.                 *(imgBufBMP+i*lineByte+j)=*(imgBuf+i*width+j);    
  159.             }  
  160.         }  
  161.         //将大于有效数据宽度的部分补0  
  162.         for (int i=0;i<height;i++)  
  163.         {  
  164.             for (int j=width;j<lineByte;j++)  
  165.             {  
  166.                 *(imgBufBMP+i*lineByte+j)=0;      
  167.             }  
  168.         }  
  169.         //写BMP格式要求的图数据写进文件  
  170.         fwrite(imgBufBMP, height*lineByte, 1, fp);  
  171.     }  
  172.     else  
  173.     {  
  174.         //写有效图数据写进文件  
  175.         fwrite(imgBuf, height*lineByte, 1, fp);  
  176.     }  
  177.   
  178.     //关闭文件  
  179.     fclose(fp);   
  180.   
  181.     return 1;  
  182. }  

0 0
原创粉丝点击