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. Emmet插件

    p{font-size: 18px; color: #666;} body{background-color:#F3F3F3} .code{color:#3974C3;font-size: 14px; ...

  2. 有N个正实数(注意是实数,大小升序排列) x1 , x2 ... xN,另有一个实数M。 需要选出若干个x,使这几个x的和与 M 最接近。 请描述实现算法,并指出算法复杂度

    题目:有N个正实数(注意是实数,大小升序排列) x1 , x2 ... xN,另有一个实数M. 需要选出若干个x,使这几个x的和与 M 最接近. 请描述实现算法,并指出算法复杂度. 代码如下: #in ...

  3. Maven项目红色叹号+JavaWeb: 报错信息The superclass &quot;javax.servlet.http.HttpServlet&quot; was not found on the Java B

    昨天写的关于解决JavaWeb: 报错信息The superclass "javax.servlet.http.HttpServlet" was not found on the ...

  4. 微软Ajax--UpdatePanel控件

    今天用做日历显示本月的考勤记录,用到了UpdatePanel控件,才发现对这个控件并不太了解,所以找了点儿资料,整理了一下给大家发上来! 一.UpdatePanel的结构 <asp:Script ...

  5. asp.net2.0安全性(1)--用户角色篇(代码实现1)--转载来自车老师

    创建用户: MembershipCreateStatus mc; Membership.CreateUser(txtUid.Text, txtPwd.Text, txtEmail.Text, txtQ ...

  6. OpenGL框架+QT版

    原地址:http://blog.chinaunix.net/uid-25799257-id-3498005.html 之前一直做地图的算法,没什么时间学习opengl,之前看nehe_OpenGL.c ...

  7. lucene做简单的文件索引

    package com.mylucene; import java.io.File; import java.io.FileReader; import java.io.IOException; im ...

  8. nohup命令与&区别,jobs,fg,bg,Ctrl-Z、Ctrl-C、Ctrl-D

    &方式: Unix/Linux下一般想让某个程序在后台运行,很多都是使用 & 在程序结尾来让程序自动运行.比如我们要运行mysql在后台:          /usr/local/my ...

  9. Centos系统各种日志存详解

    Centos系统各种日志存储路径和详细介绍 Linux常见的日志文件详述如下 1./var/log/boot.log(自检过程) 2./var/log/cron (crontab守护进程crond所派 ...

  10. hadoop学习之ZooKeeper

    1. 什么是ZooKeeper? ZooKeeper是一组工具,用来配置和支持分布式调度. 它能处理分布式应用的“部分失败”问题. 什么是部分失败? 部分失败是分布式处理系统的固有特征,即发送者无法知 ...