bitmap格式图片是未经压缩的,一般24bit位图(即一个像素点以24个二进制位表示)。

分别用8个二进制位表示R/G/B三种颜色,这样一共可以表示256*256*256=16777216种颜色。

8bit的位图则为黑白图像,32bit位图除16777216种颜色外还有8个bit表示光栅(有待具体研究)。

BMP图像文件被分成4个部分:位图文件头(Bitmap File Header)、位图信息头(Bitmap Info Header)、颜色表(Color Map)和位图数据(即图像数据,Data Bits或Data Body)。

第1部分为位图文件头BITMAPFILEHEADER,是一个结构体类型,该结构的长度是固定的,为14个字节。其定义如下:

typedef struct FileHeader
{unsigned short bfType;unsigned int bfSize;unsigned short   bfReserved1;unsigned short  bfReserved2;unsigned int    bfOffBits;
}__attribute__((packed))FileHeader;

BITMAPFILEHEADER结构的各个域详细说明如下:

bfType:位图文件类型,必须是0x424D,即字符串“BM”,也就是说,所有的“*.bmp”文件的头两个字节都是“BM”。

bfSize:位图文件大小,包括这14个字节。

bfReserved1, bfReserved2:Windows保留字,暂不用。

bfOffBits:从文件头到实际的位图数据的偏移字节数,bitmap文件前3个部分(文件头、信息头、颜色表)的长度之和。

第2部分为位图信息头BITMAPINFOHEADER,也是一个结构体类型的数据结构,该结构的长度也是固定的,为40个字节。其定义如下:

typedef struct InfoHeader
{unsigned int   biSize;int              biWidth;int             biHeight;unsigned short biPlanes;unsigned short biBitCount;unsigned int biCompression;unsigned int  biSizeImage;int             biXPelsPerMeter;int             biYPelsPerMeter;unsigned int    biClrUsed;unsigned int  biClrImportant;
}__attribute__((packed))InfoHeader;

BITMAPINFOHEADER结构的各个域的详细说明如下:

biSize:本结构的长度,为40个字节。

biWidth:位图的宽度,以像素为单位。

biHeight:位图的高度,以像素为单位。

biPlanes:目标设备的级别,必须是1。

biBitCount:每个像素所占的位数(bit),其值必须为1(黑白图像)、4(16色图)、8(256色)、24(真彩色图),新的BMP格式支持32位色。

biCompresssion:位图压缩类型,有效的值为BI_RGB(未经压缩)、BI_RLE8、BI_RLE4、BI_BITFILEDS(均为Windows定义常量)。这里只讨论未经压缩的情况,即biCompression=BI_RGB。

biSizeImage:实际的位图数据占用的字节数,该值的大小在第4部分位图数据中有具体解释。

biXPelsPerMeter:指定目标设备的水平分辨率,单位是像素/米。

biYPelsPerMeter:指定目标设备的垂直分辨率,单位是像素/米。

biClrUsed:位图实际用到的颜色数,如果该值为零,则用到的颜色数为2的biBitCount次幂。

biClrImportant:位图显示过程中重要的颜色数,如果该值为零,则认为所有的颜色都是重要的。

第3部分为颜色表。颜色表实际上是一个RGBQUAD结构的数组,数组的长度由biClrUsed指定(如果该值为零,则由biBitCount指定,即2的biBitCount次幂个元素)。RGBQUAD结构是一个结构体类型,占4个字节,其定义如下:

typedef struct tagRGBQUAD
{unsigned char  rgbBlue;unsigned char   rgbGreen;unsigned char  rgbRed;unsigned char    rgbReserved;
}RGBQUAD;

RGBQUAD结构的各个域的详细说明如下:

rgbBlue:该颜色的蓝色分量;

rgbGreen:该颜色的绿色分量;

rgbRed:该颜色的红色分量;

rgbReserved:保留字节,暂不用。

有些位图需要颜色表;有些位图(如真彩色图)则不需要颜色表,颜色表的长度由BITMAPINFOHEADER结构中biBitCount分量决定。对于biBitCount值为1的二值图像,每像素占1bit,图像中只有两种(如黑白)颜色,颜色表也就有21=2个表项,整个颜色表的大小为 2*siezof(RGBQUAD)=2x4=8个字节;对于biBitCount值为8的灰度图像,每像素占8bit,图像中有2^8=256 颜色,颜色表也就有256个表项,且每个表项的R、G、B分量相等,整个颜色表的大小为 个字节;而对于biBitCount=24的真彩色图像,由于每像素3个字节中分别代表了R、G、B三分量的值,此时不需要颜色表,因此真彩色图的BITMAPINFOHEADER结构后面直接就是位图数据。

第4部分是位图数据,即图像数据,其紧跟在位图文件头、位图信息头和颜色表(如果有颜色表的话)之后,记录了图像的每一个像素值。对于有颜色表的位图,位图数据就是该像素颜色在调色板中的索引值;对于真彩色图,位图数据就是实际的R、G、B值(三个分量的存储顺序是B、G、R)。下面分别就2色、16色、256色和真彩色位图的位图数据进行说明:

对于2色位图,用1位就可以表示该像素的颜色,所以1个字节能存储8个像素的颜色值。
对于16色位图,用4位可以表示一个像素的颜色。所以一个字节可以存储2个像素的颜色值。
对于256色位图,1个字节刚好存储1个像素的颜色值。
 
对于真彩色位图,3个字节才能表示1个像素的颜色值。

需要注意两点:

第一,图像格式规定一个扫描行所占的字节数必须是4的倍数,不足4的倍数则要对其进行扩充。假设图像的宽为biWidth个像素、每像素biBitCount个比特,其一个扫描行所占的真实字节数的计算公式如下:

DataSizePerLine = (biWidth * biBitCount /8+ 3) / 4*4

那么,不压缩情况下位图数据的大小(BITMAPINFOHEADER结构中的biSizeImage成员)计算如下:

biSizeImage = DataSizePerLine * biHeight

第二,一般来说,BMP文件的数据是从图像的左下角开始逐行扫描图像的,即从下到上、从左到右,将图像的像素值一一记录下来,因此图像坐标零点在图像左下角。

以下代码是C语言读写bitmap格式图片的几个函数,main()函数作为测试用。

为了兼容Linux 和windows平台用fopen、fread、fseek、fclose替换掉了open、read、lseek、close系列函数。

#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
//#include "window.h"/*bmp file header*/
typedef struct FileHeader
{unsigned short bfType;unsigned int bfSize;unsigned short   bfReserved1;unsigned short  bfReserved2;unsigned int    bfOffBits;
}__attribute__((packed))FileHeader;/*bmp info header*/
typedef struct InfoHeader
{unsigned int   biSize;int              biWidth;int             biHeight;unsigned short biPlanes;unsigned short biBitCount;unsigned int biCompression;unsigned int  biSizeImage;int             biXPelsPerMeter;int             biYPelsPerMeter;unsigned int    biClrUsed;unsigned int  biClrImportant;
}__attribute__((packed))InfoHeader;//we won't use it while BitCount=24
typedef struct tagRGBQUAD
{unsigned char  rgbBlue;unsigned char   rgbGreen;unsigned char  rgbRed;unsigned char    rgbReserved;
}RGBQUAD;typedef struct
{unsigned char b;unsigned char g;unsigned char r;
}RGB_data;/*for test global variable*/
/*maybe can not use this in the project*/
unsigned char   *pBmpBuf,*pBmpBufOne,*pBmpBufTwo,*pBmpBufThree;
RGBQUAD         *pColorTable;
int     bmpWidth,bmpWidthback,bmpWidthsky;
int     bmpHeight,bmpHeightback,bmpHeightsky;
int     biBitCount,biBitCountback,biBitCountsky;char * readBmp(char *bmpName)
{FILE *fp = fopen(bmpName, "rb");//int fp;       /*maybe fd should be more comfortably*///fp = open(bmpName, O_RDONLY);if (NULL == fp){printf("There is no fp!!!\n");return 0;}fseek(fp, sizeof(FileHeader), SEEK_SET);//lseek(fp, sizeof(FileHeader), SEEK_SET);InfoHeader head;fread(&head, sizeof(InfoHeader), 1, fp);//read(fp, &head, sizeof(InfoHeader));bmpWidth = head.biWidth;bmpHeight = head.biHeight;biBitCount = head.biBitCount;int lineByte = (bmpWidth * biBitCount / 8 + 3) / 4 * 4;if (biBitCount == 8){//pColorTable=new RGBQUAD[256];pColorTable = (RGBQUAD *)malloc(sizeof(RGBQUAD) * 1024);fread(pColorTable, sizeof(RGBQUAD), 256, fp);}pBmpBuf = (unsigned char *)malloc(sizeof(unsigned char) * lineByte * bmpHeight);fread(pBmpBuf, 1, lineByte * bmpHeight, fp);fclose(fp);return pBmpBuf;
}int saveBmp(char *bmpName, unsigned char *imgBuf, int width, int height, int biBitCount, RGBQUAD *pColorTable)
{if(imgBuf == NULL){printf("imgBuf is NULL!!\n");return -1;}int colorTablesize = 0;if (biBitCount == 8){colorTablesize=1024;}int lineByte = (width * biBitCount / 8 + 3) / 4 * 4;FILE *fp = fopen(bmpName, "wb");if (fp == NULL){printf("fopen error...\n");return -1;}FileHeader fileHead;fileHead.bfType=0x4D42;fileHead.bfSize = sizeof(FileHeader) + sizeof(InfoHeader) + colorTablesize + lineByte * height;fileHead.bfReserved1 = 0;fileHead.bfReserved2 = 0;fileHead.bfOffBits = 54 + colorTablesize;fwrite(&fileHead, sizeof(FileHeader), 1, fp);InfoHeader infoHead;infoHead.biBitCount = biBitCount;infoHead.biClrImportant = 0;infoHead.biClrUsed = 0;infoHead.biCompression = 0;infoHead.biHeight = height;infoHead.biPlanes = 1;infoHead.biSize = 40;infoHead.biSizeImage = lineByte * height;infoHead.biWidth = width;infoHead.biXPelsPerMeter = 0;infoHead.biYPelsPerMeter = 0;fwrite(&infoHead, sizeof(InfoHeader), 1, fp);if (biBitCount == 8){fwrite(pColorTable,sizeof(RGBQUAD),256,fp);}fwrite(imgBuf, height * lineByte, 1, fp);fclose(fp);return 0;
}/* main function test program*/
#if 1
int main(int argc, char *argv[])
{char readPath[] = "logo256.bmp";readBmp(readPath);printf("width = %d, height = %d, biBitCount = %d \n", bmpWidth, bmpHeight, biBitCount);char writePath[] = "logo256copy.bmp";saveBmp(writePath, pBmpBuf, bmpWidth, bmpHeight, biBitCount, pColorTable);free(pBmpBuf);if (biBitCount == 8){free(pColorTable);}return 0;
}
#endif#if 0
extern int a1,b1,n;
extern int a[50],b[50];//int reviseBitMap(void)
int main(int argc,char *argv[])
{int i,j;int x,y;int k;char readPathOne[] = "back.bmp";pBmpBufOne = readBmp(readPathOne);printf("width = %d, height = %d, biBitCount = %d \n", bmpWidth, bmpHeight, biBitCount);bmpWidthback = bmpWidth;bmpHeightback = bmpHeight;biBitCountback = biBitCount;int lineByteback = (bmpWidthback * biBitCountback / 8 + 3) / 4 * 4;char readPathThree[] = "sky.bmp";pBmpBufThree = readBmp(readPathThree);printf("width = %d, height = %d, biBitCount = %d \n", bmpWidth, bmpHeight, biBitCount);bmpWidthsky = bmpWidth;bmpHeightsky = bmpHeight;biBitCountsky = biBitCount;int lineBytesky = (bmpWidthsky * biBitCountsky / 8 + 3) / 4 * 4;char readPathTwo[] = "plane.bmp";pBmpBufTwo = readBmp(readPathTwo);printf("wdith = %d, height = %d, biBitCount = %d \n", bmpWidth, bmpHeight, biBitCount);int lineByteplane = (bmpWidth * biBitCount / 8 + 3) / 4 * 4;     if (biBitCount == 8){for (i = 0; i < bmpHeight / 2; i++){for (j = 0; j < bmpWidth / 2; j++){*(pBmpBuf + i * lineByteplane + j) = 0;}}}else if (biBitCount == 24){x = a[a1];y = b[b1];for (i = 0; i < bmpHeight; i++){for(j=0;j<bmpWidth;j++){for(k=0;k<3;k++){*(pBmpBufOne+(x+i)*lineByteback+(y+j)*3+k) &= (*(pBmpBufThree+i*lineBytesky+j*3+k));*(pBmpBufOne+(x+i)*lineByteback+(y+j)*3+k) |= (*(pBmpBufTwo+i*lineByteplane+j*3+k));if (lineBytesky != lineByteplane){printf("............................\n");}}}}char writePath[]="hncuduplicate.bmp";saveBmp(writePath,pBmpBufOne,bmpWidthback,bmpHeightback,biBitCountback,pColorTable);}free(pBmpBufOne);free(pBmpBufTwo);free(pBmpBufThree);if (biBitCount == 8){free(pColorTable);}return 0;
}#endif

如有转载请注明出处。

作者:super_bert@csdn

C语言读写bmp位图文件相关推荐

  1. 写入数据到bmp位图文件(C语言)

    在上一篇文章  读取bmp格式位图文件到二维数组(C语言)  中已经实现了读取24bits Bmp位图文件到二维数组的过程. 这次接着上一次的工作,试着用C语言将数据写入位图文件中. 基本原理和读取文 ...

  2. 将HBITMAP转换成BMP位图文件的各个部分,可以在1BIT,4BIT,8BIT,16BIT,24BIT,32BIT之间转换

    VC将HBITMAP转换成BMP位图文件的各个部分,可以在1BIT,4BIT,8BIT,16BIT,24BIT,32BIT之间转换 http://blog.ednchina.com/wxleasyla ...

  3. C++ 处理HBITMAP类型的.bmp位图文件, 代码工具

    1. 存储为HBITMAP类型的.bmp位图文件 参考:C++保存HBITMAP为位图文件的实现方法(IT技术) (qb5200.com) ImageHelper.h  #pragma once#in ...

  4. java bmp rgb数组_将RGB数据写入BMP位图文件

    CFile file; //定义一个文件对象 _ASSERTE(file.Open(CString("E:\\94.bmp"), CFile::modeRead));//打开文件 ...

  5. BMP编程实践1:C语言实现bmp位图分析与创建

    前言 本次实验使用的BMP图片是256位的灰度图片. 本次实验分两步,第一个源码是读图片信息,第二个源码是生成图片.这种操作适用于已知一个图片的格式,然后生成一个和它一样的图片的格式,例如给带屏的单片 ...

  6. 将RGB数据写入BMP位图文件

    <span style="font-size:18px;">CFile file; //定义一个文件对象 _ASSERTE(file.Open(CString(&quo ...

  7. 通过c语言访问bmp图片文件修改图片信息

    在c语言中访问设定路径下的bmp图片文件,修改图片中像素RGB信息,从而达到修改图片中颜色的目的. 本程序实现的是将原图片中蜡笔小新的眼睛和嘴巴改了. #include <head.h> ...

  8. C语言读写BMP图片(附Github下载链接和视频讲解地址)

    BMP全称(BITMAP)是微软WINDOWS系统默认使用的一种通用图片数据存储格式,特点是结构清晰,解析简单和多平台支持广泛.其文件结构由文件头结构体,文件信息头结构体,调色板(可选),以及图片数据 ...

  9. BMP位图文件的4个组成部分

    bmp文件大体上分成四个部分. 位图文件头BITMAPFILEHEADER . 位图信息头BITMAPINFOHEADER . 调色板Palette . 实际的位图数据ImageDate 第1部分为位 ...

最新文章

  1. 操作符重载——C/C++学习笔记
  2. doc es 中type_ES系列07:match_phrase与match_phrase_prefix query
  3. 全能HOOK框架 JNI NATIVE JAVA ART DALVIK
  4. SpringBoot————JPA快速使用
  5. Mac os更新系统后安装scrapy报错error: command ‘xcrun‘ failed with exit status 1
  6. (九)ubuntu解决resolv.conf被重写问题
  7. node 修改文件自启动
  8. ASP.NET Core 用户注册 - ASP.NET Core 基础教程 - 简单教程,简单编程
  9. ospf 指定dr_OSPF的基本配置及DR /BDR选举的实验
  10. 计算机二级vfp考试怎么学,计算机二级VFP考试基础教程(7)
  11. 优思学院|2021中质协六西格玛绿带考题及答案
  12. Power Switching ----- Controlling power for power shutoff
  13. 云计算机运用 技术,云计算技术在计算机数据处理中的应用
  14. 别错过这张AI商用清单:你的生产难题可能被一个应用解决!
  15. awesome-spider
  16. Vue+el-tree,元素拖拽时出现禁用图标, 请看解决办法
  17. Java聊天室——实现多人聊天、私聊、群聊
  18. Linux安装小企鹅输入法
  19. Linux的20个常用命令
  20. 10分钟搞定!Golang分布式ID集合

热门文章

  1. 华为手机打开图片很慢是怎么回事_华为手机相册打开很慢怎么解决?
  2. VMware 网络连接设置 解决Ubuntu,Fedora 不能上网的问题
  3. 范数的物理意义(转)
  4. Word2007 SoftEdge和棱台属性
  5. 【DFS深搜】四色问题
  6. 数据结构与算法分析1.2 Python采用栈的回溯解决四色问题
  7. [Warning] implicit declaration of function ‘clrscr‘ [-Wimplicit-function-declaration]
  8. 入托不焦虑 | 如何帮宝宝更好地融入托班?
  9. CSDN如何转载别人的博客(以及遇到的问题)
  10. python中argmin函数_python中argmin函数_Python numpy.argmin()用法及代码示例