惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Y
Y Combinator Blog
The GitHub Blog
The GitHub Blog
云风的 BLOG
云风的 BLOG
Engineering at Meta
Engineering at Meta
Google DeepMind News
Google DeepMind News
aimingoo的专栏
aimingoo的专栏
Recent Announcements
Recent Announcements
A
About on SuperTechFans
U
Unit 42
MyScale Blog
MyScale Blog
J
Java Code Geeks
博客园_首页
Blog — PlanetScale
Blog — PlanetScale
D
Docker
Microsoft Azure Blog
Microsoft Azure Blog
博客园 - 司徒正美
量子位
月光博客
月光博客
G
Google Developers Blog
V
V2EX
博客园 - 聂微东
宝玉的分享
宝玉的分享
IT之家
IT之家
Vercel News
Vercel News

博客园 - Macou

[转]软件标准项目文档 INTEL 汇编指令集 周未钓鱼钓到一只花罗汉,价值大概3000RMB [原创]一个数组整数环绕算法 个人整理的Linux Shell语法速查表(用C语言语法来作对比) [转]MONO之Red Hat5.5企业版 Linux系统ASP.NET环境配置 [转]在Eclipse3.3中安装VE插件 png 文件分析 PNG (Portable Network Graphics) Specification [转]UML中数据流图,用例图,类图,对象图,角色图,活动图,序列图详细讲述保存供参考 中断向量表 [转]程序人生--我已经努力了七年 [转]成功人士的20个优良习惯 [转]ViewState机制由浅入深3 [转]ViewState机制由浅入深2 [转]ViewState机制由浅入深1 [转].NET开源地理信息系统(GIS) [转]60多个精品源码站 [转]与动态执行的C# 代码进行通讯
C语言 BMP图片处理
Macou · 2009-02-20 · via 博客园 - Macou

     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.   
  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.   
  31.   
  32. typedef struct tagBITMAPINFOHEADER{   
  33.   
  34. DWORD   biSize;               
  35. LONG    biWidth;              
  36. LONG    biHeight;             
  37. WORD    biPlanes;             
  38. WORD    biBitCount;           
  39. DWORD   biCompression;        
  40. DWORD   biSizeImage;          
  41. LONG    biXPelsPerMeter;      
  42. LONG    biYPelsPerMeter;      
  43. DWORD   biClrUsed;            
  44. DWORD   biClrImportant;       
  45. } BITMAPINFOHEADER;    
  46.   
  47.   
  48.   
  49.   
  50.   
  51. typedef struct tagRGBQUAD {    
  52.   
  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.      
  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)));      
  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);  
  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.   
  180. tagRGBQUAD* dataOfBmp;   
  181. dataOfBmp = (tagRGBQUAD *)malloc(width*height*sizeof(tagRGBQUAD));  
  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;  
  195.         
  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;  
  252.         
  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  
  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. }