现在的位置: 首页 > 综合 > 正文

C语言 BMP图片处理 C语言 BMP图片处理

2013年10月05日 ⁄ 综合 ⁄ 共 13254字 ⁄ 字号 评论关闭

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代码 复制代码
  1. //ReadBitMap
      
  2. //
      
  3. #include <string.h> 
      
  4. #include <math.h>   
      
  5. #include <stdio.h>   
      
  6. #include <stdlib.h>   
      
  7. #include <malloc.h>
      
  8.   
  9.   
  10. #define   WIDTHBYTES(bits) (((bits)+31)/32*4)
      
  11.   
  12. typedef
     unsigned char
     BYTE
    ;   
  13. typedef
     unsigned short
     WORD
    ;   
  14. typedef
     unsigned long
     DWORD
    ;   
  15. typedef
     long
     LONG
    ;   
  16.   
  17.   
  18. //位图文件头信息结构定义
      
  19. //其中不包含文件类型信息(由于结构体的内存结构决定,要是加了的话将不能正确读取文件信息)
      
  20.   
  21. typedef
     struct
     tagBITMAPFILEHEADER {   
  22.   
  23. DWORD
     bfSize;           //文件大小
      
  24. WORD
       bfReserved1;     //保留字,不考虑
      
  25. WORD
       bfReserved2;     //保留字,同上
      
  26. DWORD
     bfOffBits;        //实际位图数据的偏移字节数,即前三个部分长度之和
      
  27. } BITMAPFILEHEADER;    
  28.   
  29.   
  30. //信息头BITMAPINFOHEADER,也是一个结构,其定义如下:
      
  31.   
  32. typedef
     struct
     tagBITMAPINFOHEADER{   
  33. //public:
      
  34. DWORD
       biSize;             //指定此结构体的长度,为40
      
  35. LONG
        biWidth;            //位图宽
      
  36. LONG
        biHeight;           //位图高
      
  37. WORD
        biPlanes;           //平面数,为1
      
  38. WORD
        biBitCount;         //采用颜色位数,可以是1,2,4,8,16,24,新的可以是32
      
  39. DWORD
       biCompression;      //压缩方式,可以是0,1,2,其中0表示不压缩
      
  40. DWORD
       biSizeImage;        //实际位图数据占用的字节数
      
  41. LONG
        biXPelsPerMeter;    //X方向分辨率
      
  42. LONG
        biYPelsPerMeter;    //Y方向分辨率
      
  43. DWORD
       biClrUsed;          //使用的颜色数,如果为0,则表示默认值(2^颜色位数)
      
  44. DWORD
       biClrImportant;     //重要颜色数,如果为0,则表示所有颜色都是重要的
      
  45. } BITMAPINFOHEADER;    
  46.   
  47.   
  48. //调色板Palette,当然,这里是对那些需要调色板的位图文件而言的。24位和32位是不需要调色板的。
      
  49. //(似乎是调色板结构体个数等于使用的颜色数。)
      
  50.   
  51. typedef
     struct
     tagRGBQUAD {    
  52. //public:
      
  53. BYTE
         rgbBlue; //该颜色的蓝色分量
      
  54. BYTE
         rgbGreen; //该颜色的绿色分量
      
  55. BYTE
         rgbRed; //该颜色的红色分量
      
  56. BYTE
         rgbReserved; //保留值
      
  57. } RGBQUAD;   
  58.   
  59.   
  60.   
  61. void
     showBmpHead(BITMAPFILEHEADER* pBmpHead)   
  62. {   
  63. printf("位图文件头:/n"
    );   
  64. printf("文件大小:%d/n"
    ,pBmpHead->bfSize);   
  65. printf("保留字:%d/n"
    ,pBmpHead->bfReserved1);   
  66. printf("保留字:%d/n"
    ,pBmpHead->bfReserved2);   
  67. printf("实际位图数据的偏移字节数:%d/n"
    ,pBmpHead->bfOffBits);   
  68.   
  69. }   
  70.   
  71.   
  72. void
     showBmpInforHead(tagBITMAPINFOHEADER* pBmpInforHead)   
  73. {   
  74. printf("位图信息头:/n"
    );   
  75. printf("结构体的长度:%d/n"
    ,pBmpInforHead->biSize);   
  76. printf("位图宽:%d/n"
    ,pBmpInforHead->biWidth);   
  77. printf("位图高:%d/n"
    ,pBmpInforHead->biHeight);   
  78. printf("biPlanes平面数:%d/n"
    ,pBmpInforHead->biPlanes);   
  79. printf("biBitCount采用颜色位数:%d/n"
    ,pBmpInforHead->biBitCount);   
  80. printf("压缩方式:%d/n"
    ,pBmpInforHead->biCompression);   
  81. printf("biSizeImage实际位图数据占用的字节数:%d/n"
    ,pBmpInforHead->biSizeImage);   
  82. printf("X方向分辨率:%d/n"
    ,pBmpInforHead->biXPelsPerMeter);   
  83. printf("Y方向分辨率:%d/n"
    ,pBmpInforHead->biYPelsPerMeter);   
  84. printf("使用的颜色数:%d/n"
    ,pBmpInforHead->biClrUsed);   
  85. printf("重要颜色数:%d/n"
    ,pBmpInforHead->biClrImportant);   
  86. }   
  87.   
  88. void
     showRgbQuan(tagRGBQUAD* pRGB)   
  89. {    
  90. printf("(%-3d,%-3d,%-3d)   "
    ,pRGB->rgbRed,pRGB->rgbGreen,pRGB->rgbBlue);   
  91.   
  92. }   
  93.   
  94.   
  95.   
  96. void
     main()   
  97. {   
  98.   
  99. BITMAPFILEHEADER   bitHead;   
  100. BITMAPINFOHEADER bitInfoHead;    
  101. FILE
    * pfile;   
  102.   
  103. char
     strFile[50];   
  104. printf("please input the .bmp file name:/n"
    );   
  105. scanf("%s"
    ,strFile);   
  106.   
  107. pfile = fopen(strFile,"rb"
    );//打开文件   
  108.   
  109. if
    (pfile!=NULL)   
  110. {   
  111.    printf("file bkwood.bmp open success./n"
    );   
  112.    //读取位图文件头信息
      
  113.    WORD
     fileType;   
  114.    fread(&fileType,1,sizeof
    (WORD
    ),pfile);   
  115.    if
    (fileType != 0x4d42)   
  116.    {   
  117.     printf("file is not .bmp file!"
    );   
  118.     return
    ;   
  119.    }   
  120.    //fseek(pfile,2,SEEK_CUR);   // "BM"
      
  121.    fread(&bitHead,1,sizeof
    (tagBITMAPFILEHEADER),pfile);   
  122.      
  123.    showBmpHead(&bitHead);   
  124.    printf("/n/n"
    );   
  125.   
  126.    //读取位图信息头信息
      
  127.    fread(&bitInfoHead,1,sizeof
    (BITMAPINFOHEADER),pfile);   
  128.    showBmpInforHead(&bitInfoHead);   
  129.    printf("/n"
    );   
  130. }   
  131. else
      
  132. {   
  133.    printf("file open fail!/n"
    );   
  134.    return
    ;   
  135. }   
  136.   
  137.   
  138. tagRGBQUAD *pRgb ;   
  139.   
  140. if
    (bitInfoHead.biBitCount < 24)//有调色板
      
  141. {    
  142.    //读取调色盘结信息
      
  143.    long
     nPlantNum = long
    (pow(2,double
    (bitInfoHead.biBitCount)));    //   Mix color Plant Number;
      
  144.    pRgb=(tagRGBQUAD *)malloc(nPlantNum*sizeof
    (tagRGBQUAD));    
  145.    memset(pRgb,0,nPlantNum*sizeof
    (tagRGBQUAD));   
  146.    int
     num = fread(pRgb,4,nPlantNum,pfile);   
  147.      
  148.    printf("Color Plate Number: %d/n"
    ,nPlantNum);   
  149.   
  150.    printf("颜色板信息:/n"
    );   
  151.    for
     (int
     i =0; i<nPlantNum;i++)   
  152.    {   
  153.     if
     (i%5==0)   
  154.     {   
  155.      printf("/n"
    );   
  156.     }   
  157.     showRgbQuan(&pRgb[i]);   
  158.       
  159.    }   
  160.   
  161.    printf("/n"
    );   
  162.      
  163. }   
  164.   
  165.   
  166. int
     width = bitInfoHead.biWidth;   
  167. int
     height = bitInfoHead.biHeight;   
  168. //分配内存空间把源图存入内存   
      
  169. int
     l_width   = WIDTHBYTES(width* bitInfoHead.biBitCount);//计算位图的实际宽度并确保它为32的倍数
      
  170. BYTE
        *pColorData=(BYTE
     *)malloc(height*l_width);      
  171. memset(pColorData,0,height*l_width);      
  172. long
     nData = height*l_width;   
  173.   
  174. //把位图数据信息读到数组里   
      
  175. fread(pColorData,1,nData,pfile);      
  176.        
  177.   
  178.   
  179. //将位图数据转化为RGB数据
      
  180. tagRGBQUAD* dataOfBmp;   
  181. dataOfBmp = (tagRGBQUAD *)malloc(width*height*sizeof
    (tagRGBQUAD));//用于保存各像素对应的RGB数据
      
  182. memset(dataOfBmp,0,width*height*sizeof
    (tagRGBQUAD));   
  183.   
  184. if
    (bitInfoHead.biBitCount<24)//有调色板,即位图为非真彩色 
      
  185. {   
  186.    int
     k;   
  187.    int
     index = 0;   
  188.    if
     (bitInfoHead.biBitCount == 1)   
  189.    {   
  190.     for
    (int
     i=0;i<height;i++)   
  191.      for
    (int
     j=0;j<width;j++)   
  192.      {   
  193.       BYTE
     mixIndex= 0;   
  194.       k = i*l_width + j/8;//k:取得该像素颜色数据在实际数据数组中的序号
      
  195.       //j:提取当前像素的颜色的具体值    
      
  196.       mixIndex = pColorData[k];   
  197.       switch
    (j%8)   
  198.       {   
  199.       case
     0:   
  200.        mixIndex = mixIndex<<7;   
  201.        mixIndex = mixIndex>>7;   
  202.        break
    ;   
  203.       case
     1:   
  204.        mixIndex = mixIndex<<6;   
  205.        mixIndex = mixIndex>>7;   
  206.        break
    ;   
  207.       case
     2:   
  208.        mixIndex = mixIndex<<5;   
  209.        mixIndex = mixIndex>>7;   
  210.        break
    ;   
  211.   
  212.       case
     3:   
  213.        mixIndex = mixIndex<<4;   
  214.        mixIndex = mixIndex>>7;   
  215.        break
    ;   
  216.       case
     4:   
  217.        mixIndex = mixIndex<<3;   
  218.        mixIndex = mixIndex>>7;   
  219.        break
    ;   
  220.   
  221.       case
     5:   
  222.        mixIndex = mixIndex<<2;   
  223.        mixIndex = mixIndex>>7;   
  224.        break
    ;   
  225.       case
     6:   
  226.        mixIndex = mixIndex<<1;   
  227.        mixIndex = mixIndex>>7;   
  228.        break
    ;   
  229.   
  230.       case
     7:   
  231.        mixIndex = mixIndex>>7;   
  232.        break
    ;   
  233.       }   
  234.   
  235.       //将像素数据保存到数组中对应的位置
      
  236.       dataOfBmp[index].rgbRed = pRgb[mixIndex].rgbRed;   
  237.       dataOfBmp[index].rgbGreen = pRgb[mixIndex].rgbGreen;   
  238.       dataOfBmp[index].rgbBlue = pRgb[mixIndex].rgbBlue;   
  239.       dataOfBmp[index].rgbReserved = pRgb[mixIndex].rgbReserved;   
  240.       index++;   
  241.   
  242.     }   
  243.    }   
  244.   
  245.    if
    (bitInfoHead.biBitCount==2)   
  246.    {   
  247.     for
    (int
     i=0;i<height;i++)   
  248.      for
    (int
     j=0;j<width;j++)   
  249.      {   
  250.       BYTE
     mixIndex= 0;   
  251.       k = i*l_width + j/4;//k:取得该像素颜色数据在实际数据数组中的序号
      
  252.       //j:提取当前像素的颜色的具体值    
      
  253.       mixIndex = pColorData[k];   
  254.       switch
    (j%4)   
  255.       {   
  256.       case
     0:   
  257.        mixIndex = mixIndex<<6;   
  258.        mixIndex = mixIndex>>6;   
  259.        break
    ;   
  260.       case
     1:   
  261.        mixIndex = mixIndex<<4;   
  262.        mixIndex = mixIndex>>6;   
  263.        break
    ;   
  264.       case
     2:   
  265.        mixIndex = mixIndex<<2;   
  266.        mixIndex = mixIndex>>6;   
  267.        break
    ;   
  268.       case
     3:   
  269.        mixIndex = mixIndex>>6;   
  270.        break
    ;   
  271.       }   
  272.   
  273.       //将像素数据保存到数组中对应的位置
      
  274.       dataOfBmp[index].rgbRed = pRgb[mixIndex].rgbRed;   
  275.       dataOfBmp[index].rgbGreen = pRgb[mixIndex].rgbGreen;   
  276.       dataOfBmp[index].rgbBlue = pRgb[mixIndex].rgbBlue;   
  277.       dataOfBmp[index].rgbReserved = pRgb[mixIndex].rgbReserved;   
  278.       index++;   
  279.   
  280.   
  281.      }   
  282.    }   
  283.    if
    (bitInfoHead.biBitCount == 4)   
  284.    {   
  285.     for
    (int
     i=0;i<height;i++)   
  286.      for
    (int
     j=0;j<width;j++)   
  287.      {   
  288.       BYTE
     mixIndex= 0;   
  289.       k = i*l_width + j/2;   
  290.       mixIndex = pColorData[k];   
  291.       if
    (j%2==0)   
  292.       {//低      
      
  293.        mixIndex = mixIndex<<4;   
  294.        mixIndex = mixIndex>>4;   
  295.       }   
  296.       else
      
  297.       {//高
      
  298.        mixIndex = mixIndex>>4;   
  299.       }   
  300.   
  301.       dataOfBmp[index].rgbRed = pRgb[mixIndex].rgbRed;   
  302.       dataOfBmp[index].rgbGreen = pRgb[mixIndex].rgbGreen;   
  303.       dataOfBmp[index].rgbBlue = pRgb[mixIndex].rgbBlue;   
  304.       dataOfBmp[index].rgbReserved = pRgb[mixIndex].rgbReserved;   
  305.       index++;   
  306.   
  307.      }   
  308.   
  309.    }   
  310.    if
    (bitInfoHead.biBitCount == 8)   
  311.    {   
  312.     for
    (int
     i=0;i<height;i++)   
  313.      for
    (int
     j=0;j<width;j++)   
  314.      {   
  315.       BYTE
     mixIndex= 0;   
  316.   
  317.       k = i*l_width + j;   
  318.   
  319.       mixIndex = pColorData[k];   
  320.   
  321.       dataOfBmp[index].rgbRed = pRgb[mixIndex].rgbRed;   
  322.       dataOfBmp[index].rgbGreen = pRgb[mixIndex].rgbGreen;   
  323.       dataOfBmp[index].rgbBlue = pRgb[mixIndex].rgbBlue;   
  324.       dataOfBmp[index].rgbReserved = pRgb[mixIndex].rgbReserved;   
  325.       index++;   
  326.         
  327.         
  328.   
  329.      }   
  330.    }   
  331.    if
    (bitInfoHead.biBitCount == 16)   
  332.    {   
  333.     for
    (int
     i=0;i<height;i++)   
  334.      for
    (int
     j=0;j<width;j++)   
  335.      {   
  336.       WORD
     mixIndex= 0;   
  337.   
  338.       k = i*l_width + j*2;   
  339.       WORD
     shortTemp;   
  340.       shortTemp = pColorData[k+1];   
  341.       shortTemp = shortTemp<<8;   
  342.        
  343.       mixIndex = pColorData[k] + shortTemp;   
  344.   
  345.       dataOfBmp[index].rgbRed = pRgb[mixIndex].rgbRed;   
  346.       dataOfBmp[index].rgbGreen = pRgb[mixIndex].rgbGreen;   
  347.       dataOfBmp[index].rgbBlue = pRgb[mixIndex].rgbBlue;   
  348.       dataOfBmp[index].rgbReserved = pRgb[mixIndex].rgbReserved;   
  349.       index++;   
  350.      }   
  351.    }   
  352. }   
  353. else
    //位图为24位真彩色
      
  354. {   
  355.    int
     k;   
  356.    int
     index = 0;   
  357.    for
    (int
     i=0;i<height;i++)   
  358.     for
    (int
     j=0;j<width;j++)   
  359.     {   
  360.      k = i*l_width + j*3;   
  361.      dataOfBmp[index].rgbRed = pColorData[k+2];      
  362.      dataOfBmp[index].rgbGreen = pColorData[k+1];      
  363.      dataOfBmp[index].rgbBlue = pColorData[k];       
  364.      index++;   
  365.     }               
  366. }   
  367.   
  368.   
  369. printf("像素数据信息:/n"
    );   
  370. for
     (int
     i=0; i<width*height; i++)   
  371. {   
  372.    if
     (i%5==0)   
  373.    {   
  374.     printf("/n"
    );   
  375.    }   
  376.    showRgbQuan(&dataOfBmp[i]);   
  377. }   
  378.   
  379. fclose(pfile);    
  380. if
     (bitInfoHead.biBitCount<24)   
  381. {   
  382.    free(pRgb);   
  383. }   
  384. free(dataOfBmp);   
  385. free(pColorData);   
  386. printf("/n"
    );   
  387.   
  388. }  

转载自:http://www.cnblogs.com/macou/archive/2009/02/20/1394815.html

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代码 复制代码
  1. //ReadBitMap
      
  2. //
      
  3. #include <string.h> 
      
  4. #include <math.h>   
      
  5. #include <stdio.h>   
      
  6. #include <stdlib.h>   
      
  7. #include <malloc.h>
      
  8.   
  9.   
  10. #define   WIDTHBYTES(bits) (((bits)+31)/32*4)
      
  11.   
  12. typedef
     unsigned char
     BYTE
    ;   
  13. typedef
     unsigned short
     WORD
    ;   
  14. typedef
     unsigned long
     DWORD
    ;   
  15. typedef
     long
     LONG
    ;   
  16.   
  17.   
  18. //位图文件头信息结构定义
      
  19. //其中不包含文件类型信息(由于结构体的内存结构决定,要是加了的话将不能正确读取文件信息)
      
  20.   
  21. typedef
     struct
     tagBITMAPFILEHEADER {   
  22.   
  23. DWORD
     bfSize;           //文件大小
      
  24. WORD
       bfReserved1;     //保留字,不考虑
      
  25. WORD
       bfReserved2;     //保留字,同上
      
  26. DWORD
     bfOffBits;        //实际位图数据的偏移字节数,即前三个部分长度之和
      
  27. } BITMAPFILEHEADER;    
  28.   
  29.   
  30. //信息头BITMAPINFOHEADER,也是一个结构,其定义如下:
      
  31.   
  32. typedef
     struct
     tagBITMAPINFOHEADER{   
  33. //public:
      
  34. DWORD
       biSize;             //指定此结构体的长度,为40
      
  35. LONG
        biWidth;            //位图宽
      
  36. LONG
        biHeight;           //位图高
      
  37. WORD
        biPlanes;           //平面数,为1
      
  38. WORD
        biBitCount;         //采用颜色位数,可以是1,2,4,8,16,24,新的可以是32
      
  39. DWORD
       biCompression;      

抱歉!评论已关闭.