C语言编写的bmp读写程序 建议先把bmp的数据存储格式了解下

  1. <span style="font-size:16px;">#include "Windows.h"
  2. #include "stdio.h"
  3. #include "string.h"
  4. #include "malloc.h"
  5. unsigned char *pBmpBuf;//读入图像数据的指针
  6. int bmpWidth;//图像的宽
  7. int bmpHeight;//图像的高
  8. RGBQUAD *pColorTable;//颜色表指针
  9. int biBitCount;//图像类型,每像素位数
  10. bool readBmp(char *bmpName)
  11. {
  12. //二进制读方式打开指定的图像文件
  13. FILE *fp=fopen(bmpName,"rb");
  14. if(fp==0) return 0;
  15. //跳过位图文件头结构BITMAPFILEHEADER
  16. fseek(fp, sizeof(BITMAPFILEHEADER),0);
  17. //定义位图信息头结构变量,读取位图信息头进内存,存放在变量head中
  18. BITMAPINFOHEADER head;
  19. fread(&head, sizeof(BITMAPINFOHEADER), 1,fp);
  20. //获取图像宽、高、每像素所占位数等信息
  21. bmpWidth = head.biWidth;
  22. bmpHeight = head.biHeight;
  23. biBitCount = head.biBitCount;
  24. //定义变量,计算图像每行像素所占的字节数(必须是4的倍数)
  25. int lineByte=(bmpWidth * biBitCount/8+3)/4*4;
  26. //灰度图像有颜色表,且颜色表表项为256
  27. if(biBitCount==8){
  28. //申请颜色表所需要的空间,读颜色表进内存
  29. pColorTable=new RGBQUAD[256];
  30. fread(pColorTable,sizeof(RGBQUAD),256,fp);
  31. }
  32. //申请位图数据所需要的空间,读位图数据进内存
  33. pBmpBuf=new unsigned char[lineByte * bmpHeight];
  34. fread(pBmpBuf,1,lineByte * bmpHeight,fp);
  35. //关闭文件
  36. fclose(fp);
  37. return 1;
  38. }
  39. bool saveBmp(char *bmpName, unsigned char *imgBuf, int width, int height,
  40. int biBitCount, RGBQUAD *pColorTable)
  41. {
  42. //如果位图数据指针为0,则没有数据传入,函数返回
  43. if(!imgBuf)
  44. return 0;
  45. //颜色表大小,以字节为单位,灰度图像颜色表为1024字节,彩色图像颜色表大小为0
  46. int colorTablesize=0;
  47. if(biBitCount==8)
  48. colorTablesize=1024;
  49. //待存储图像数据每行字节数为4的倍数
  50. int lineByte=(width * biBitCount/8+3)/4*4;
  51. //以二进制写的方式打开文件
  52. FILE *fp=fopen(bmpName,"wb");
  53. if(fp==0) return 0;
  54. //申请位图文件头结构变量,填写文件头信息
  55. BITMAPFILEHEADER fileHead;
  56. fileHead.bfType = 0x4D42;//bmp类型
  57. //bfSize是图像文件4个组成部分之和
  58. fileHead.bfSize= sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)
  59. + colorTablesize + lineByte*height;
  60. fileHead.bfReserved1 = 0;
  61. fileHead.bfReserved2 = 0;
  62. //bfOffBits是图像文件前3个部分所需空间之和
  63. fileHead.bfOffBits=54+colorTablesize;
  64. //写文件头进文件
  65. fwrite(&fileHead, sizeof(BITMAPFILEHEADER),1, fp);
  66. //申请位图信息头结构变量,填写信息头信息
  67. BITMAPINFOHEADER head;
  68. head.biBitCount=biBitCount;
  69. head.biClrImportant=0;
  70. head.biClrUsed=0;
  71. head.biCompression=0;
  72. head.biHeight=height;
  73. head.biPlanes=1;
  74. head.biSize=40;
  75. head.biSizeImage=lineByte*height;
  76. head.biWidth=width;
  77. head.biXPelsPerMeter=0;
  78. head.biYPelsPerMeter=0;
  79. //写位图信息头进内存
  80. fwrite(&head, sizeof(BITMAPINFOHEADER),1, fp);
  81. //如果灰度图像,有颜色表,写入文件
  82. if(biBitCount==8)
  83. fwrite(pColorTable, sizeof(RGBQUAD),256, fp);
  84. //写位图数据进文件
  85. fwrite(imgBuf, height*lineByte, 1, fp);
  86. //关闭文件
  87. fclose(fp);
  88. return 1;
  89. }
  90. void main()
  91. {
  92. char inFileName[90],outFileName[90];
  93. printf("请输入原始位图文件的文件名:");
  94. scanf("%s",inFileName);
  95. printf("请输入加密程序产生的新位图文件的文件名:");
  96. scanf("%s",outFileName);
  97. //读入指定BMP文件进内存
  98. readBmp(inFileName);
  99. //输出图像的信息
  100. printf("width=%d,height=%d, biBitCount=%d\n",bmpWidth,bmpHeight, biBitCount);
  101. //将图像数据存盘
  102. saveBmp(outFileName, pBmpBuf, bmpWidth, bmpHeight, biBitCount, pColorTable);
  103. //清除缓冲区,pBmpBuf和pColorTable是全局变量,在文件读入时申请的空间
  104. delete []pBmpBuf;
  105. if(biBitCount==8)
  106. delete []pColorTable;
  107. }
  108. </span>

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

一、BMP文件结构

BMP文件组成 
BMP文件由文件头、位图信息头、颜色信息和图形数据四部分组成。   
BMP文件头 
BMP文件头数据结构含有BMP文件的类型、文件大小和位图起始位置等信息。   
其结构定义如下: 
typedef   struct   tagBITMAPFILEHEADER 

WORDbfType;   //   位图文件的类型,必须为BM 
DWORD   bfSize;   //   位图文件的大小,以字节为单位   
WORDbfReserved1;   //   位图文件保留字,必须为0 
WORDbfReserved2;   //   位图文件保留字,必须为0 
DWORD   bfOffBits;   //   位图数据的起始位置,以相对于位图 
//   文件头的偏移量表示,以字节为单位 
}   BITMAPFILEHEADER;

3.   位图信息头

BMP位图信息头数据用于说明位图的尺寸等信息。 
typedef   struct   tagBITMAPINFOHEADER{ 
DWORD   biSize;   //   本结构所占用字节数 
LONGbiWidth;   //   位图的宽度,以像素为单位 
LONGbiHeight;   //   位图的高度,以像素为单位 
WORD   biPlanes;   //   目标设备的级别,必须为1 
WORD   biBitCount//   每个像素所需的位数,必须是1(双色), 
//   4(16色),8(256色)或24(真彩色)之一 
DWORD   biCompression;   //   位图压缩类型,必须是   0(不压缩), 
//   1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一 
DWORD   biSizeImage;   //   位图的大小,以字节为单位 
LONGbiXPelsPerMeter;   //   位图水平分辨率,每米像素数 
LONGbiYPelsPerMeter;   //   位图垂直分辨率,每米像素数 
DWORD   biClrUsed;//   位图实际使用的颜色表中的颜色数 
DWORD   biClrImportant;//   位图显示过程中重要的颜色数 
}   BITMAPINFOHEADER;

4.   颜色表

  颜色表用于说明位图中的颜色,它有若干个表项,每一个表项是一个RGBQUAD类型的结构,定义一种颜色。RGBQUAD结构的定义如下: 
typedef   struct   tagRGBQUAD   { 
BYTErgbBlue;//   蓝色的亮度(值范围为0-255) 
BYTErgbGreen;   //   绿色的亮度(值范围为0-255) 
BYTErgbRed;   //   红色的亮度(值范围为0-255) 
BYTErgbReserved;//   保留,必须为0 
}   RGBQUAD; 
颜色表中RGBQUAD结构数据的个数有biBitCount来确定: 
当biBitCount=1,4,8时,分别有2,16,256个表项; 
当biBitCount=24时,没有颜色表项。 
位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下: 
typedef   struct   tagBITMAPINFO   { 
BITMAPINFOHEADER   bmiHeader;   //   位图信息头 
RGBQUAD   bmiColors[1];   //   颜色表 
}   BITMAPINFO;

5.   位图数据 
  位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。位图的一个像素值所占的字节数: 
当biBitCount=1时,8个像素占1个字节; 
当biBitCount=4时,2个像素占1个字节; 
当biBitCount=8时,1个像素占1个字节; 
当biBitCount=24时,1个像素占3个字节; 
Windows规定一个扫描行所占的字节数必须是 
4的倍数(即以long为单位),不足的以0填充, 
一个扫描行所占的字节数计算方法: 
DataSizePerLine=   (biWidth*   biBitCount+31)/8;   
//   一个扫描行所占的字节数 
DataSizePerLine=   DataSizePerLine/4*4;   //   字节数必须是4的倍数 
位图数据的大小(不压缩情况下): 
DataSize=   DataSizePerLine*   biHeight;

C语言编写的bmp读写程序的更多相关文章

  1. c语言编写51单片机中断程序,执行过程是怎样的?

    Q:c语言编写51单片机中断程序,执行过程是怎样的? 例如程序:#include<reg52.h>  void main(void)  {   EA=1;      //开放总中断   E ...

  2. 使用go语言编写IOS和Android程序

    go语言目前已可以用来开发android和ios手机app.相关资料: 1.IOS https://groups.google.com/forum/?utm_medium=email&utm_ ...

  3. 编写Spark的WordCount程序并提交到集群运行[含scala和java两个版本]

    编写Spark的WordCount程序并提交到集群运行[含scala和java两个版本] 1. 开发环境 Jdk 1.7.0_72 Maven 3.2.1 Scala 2.10.6 Spark 1.6 ...

  4. 近50种语言编写的“Hello, World”,你会几种?可不要贪杯哦~

    本文转自公众号CSDN(ID:CSDNnews)作者:Sylvain Saurel,译者:风车云马

  5. 基于php基础语言编写的小程序之计算器

    基于php基础语言编写的小程序之计算器 需求:在输入框中输入数字进行加.减.乘.除运算(html+php) 思路: 1首先要创建输入数字和运算符的输入框,数字用input的text属性,运算符用sel ...

  6. 【ZZ】C 语言中的指针和内存泄漏 & 编写高效的C程序与C代码优化

    C 语言中的指针和内存泄漏 http://www.ibm.com/developerworks/cn/aix/library/au-toughgame/ 本文讨论了几种在使用动态内存分配时可以避免的陷 ...

  7. 用C语言编写一个简单的词法分析程序

    问题描述: 用C或C++语言编写一个简单的词法分析程序,扫描C语言小子集的源程序,根据给定的词法规则,识别单词,填写相应的表.如果产生词法错误,则显示错误信息.位置,并试图从错误中恢复.简单的恢复方法 ...

  8. [转载] 使用C/C++语言编写基于DSP程序的注意事项

    原文地址:『转』使用C/C++语言编写基于DSP程序的注意事项作者:skysmile   1.不影响执行速度的情况下,可以使用c或c/c++语言提供的函数库,也可以自己设计函数,这样更易于使用“裁缝师 ...

  9. 编写优质嵌入式C程序

    前言:这是一年前我为公司内部写的一个文档,旨在向年轻的嵌入式软件工程师们介绍如何在裸机环境下编写优质嵌入式C程序.感觉是有一定的参考价值,所以拿出来分享,抛砖引玉. 转载请注明出处:http://bl ...

随机推荐

  1. 11181 - Probability|Given

    N friends go to the local super market together. The probability of their buying something from them ...

  2. ZJUT 1423 地下迷宫(期望DP&高斯消元)

    地下迷宫 Time Limit:1000MS  Memory Limit:32768K Description: 由于山体滑坡,DK被困在了地下蜘蛛王国迷宫.为了抢在DH之前来到TFT,DK必须尽快走 ...

  3. 网站遭遇DDOS简易处理

    网站遭遇DDOS攻击 netstat -an | grep ESTABLISHED 我们看到有大量的链接存在着,并且都是ESTABLISHED状态 for i in `netstat -an | gr ...

  4. 原码、反码、补码和移码事实上非常easy

    近期在备战软考,复习到计算机组成原理的时候,看到书中关于原码.反码.补码和移码的定义例如以下(n是机器字长): 原码: 反码: 补码: 移码: 看完这些定义以后,我的脑袋瞬间膨胀到原来的二倍!这样变态 ...

  5. 1352 - Colored Cubes (枚举方法)

    There are several colored cubes. All of them are of the same size but they may be colored differentl ...

  6. SQL Server使用问题总结

    1.datetime,smalldatetime,date的区别 1)datetime 从1753年1月1日到9999年12月31日的日期和时间数据,精确度为百分之三秒(等于   3.33毫秒或0.0 ...

  7. Boost::thread库的使用

    阅读对象 本文假设读者有几下Skills [1]在C++中至少使用过一种多线程开发库,有Mutex和Lock的概念. [2]熟悉C++开发,在开发工具中,能够编译.设置boost::thread库. ...

  8. UVALive 2519 Radar Installation 雷达扫描 区间选点问题

    题意:在坐标轴中给出n个岛屿的坐标,以及雷达的扫描距离,要求在y=0线上放尽量少的雷达能够覆盖全部岛屿. 很明显的区间选点问题. 代码: /* * Author: illuz <iilluzen ...

  9. Oracle Tablespace Transportation

    前提:进行表空间传输需要用户有SYSDBA的系统权限,被移动的表空间是自包含的表空间,不应有依赖于表空间外部对象的对象存在.确定是否自包含可使用系统包DBMS_TTS中的TRANSPORT_SET_C ...

  10. ListView+CheckBox两种解决方式及原因分析

    近期在用ListView+CheckBox搞一个item选中的项目,我将CheckBox的focus设置为false,另我大喜的是,CheckBox居然能够选中(窃喜中),这么简单就搞定了,由于数据量 ...