C语言读取BMP格式图片

BMP

维基百科,自由的百科全书
汉漢▼
位图
扩展名 .bmp
开发者 Microsoft
格式 图像文件格式
 本文介绍的是一种图像文件格式。

  • 关于Unicode的第1区编码,详见“基本多文种平面”。
  • 关于Linux/Unix平台下的音乐播放器,详见“Beep Media Player”。

BMP取自位图BitMaP的缩写,也称为DIB(与设备无关的位图)是微软视窗图形子系统(Graphics Device Interface)内部使用的一种位图图形格式,它是微软视窗平台上的一个简单的图形文件格式。

图像通常保存的颜色深度有2(1位)、16(4位)、256(8位)、65536(16位)和1670万(24位)种颜色(其中位是表示每点所用的数据位)。8位图像可以是索引彩色图像外,也可以是灰阶图像。表示透明的alpha通道也可以保存在一个类似于灰阶图像的独立文件中。带有集成的alpha通道的32位版本已经随着Windows XP出现,它在视窗的登录和主题系统中都有使用,但是还没有多少图像编辑软件支持。

目录

[隐藏]

  • 1 存储算法
  • 2 典型的文件格式
    • 2.1 位图头
    • 2.2 位图信息
    • 2.3 调色板
    • 2.4 位图数据
  • 3 其他
  • 4 参见
  • 5 外部链接

[编辑]存储算法

BMP文件通常是不压缩的,所以它们通常比同一幅图像的压缩图像文件格式要大很多。例如,一个800×600的24位几乎占据1.4MB空间。因此它们通常不适合在因特网或者其他低速或者有容量限制的媒介上进行传输。

根据颜色深度的不同,图像上的一个像素可以用一个或者多个字节表示,它由n/8所确定(n是位深度,1字节包含8个数据位)。图片浏览器等基于字节的ASCII值计算像素的颜色,然后从调色板中读出相应的值。更为详细的信息请参阅下面关于位图文件的部分。

n位2n种颜色的包含调色板的位图近似字节数可以用下面的公式计算:

BMP文件大小 ,其中高度(height)和宽度(width)都以像素为单位。

需要注意的是上面公式中的54是位图文件的文件头,是彩色调色板的大小。 如果位图文件不包含调色板,如24位,32位位图,则位图的近似字节数可以用下面的公式计算:

BMP文件大小 ,其中高度(height)和宽度(width)都以像素为单位。

另外需要注意的是这是一个近似值,对于n位的位图图像来说,尽管可能有最多种颜色,一个特定的图像可能并不会使用这些所有的颜色。由于彩色调色板仅仅定义了图像所用的颜色,所以实际的彩色调色板将小于

如果想知道这些值是如何得到的,请参考下面文件格式的部分。

由于存储算法本身决定的因素,根据几个图像参数的不同计算出的大小与实际的文件大小将会有一些细小的差别。

[编辑]典型的文件格式

典型的位图文件格式通常包含下面几个数据块:

  • 位图头:保存位图文件的总体信息。
  • 位图信息:保存位图图像的详细信息。
  • 调色板:保存所用颜色的定义。
  • 位图数据:保存一个又一个像素的实际图像。

下面的部分将会详细地描述位图文件中保存的数据。需要注意的是这是标准位图的文件格式,其他一些位图图像可能根据生成文件的应用程序不同所使用格式可能会有细微的区别。

[编辑]位图头

这部分是识别信息,典型的应用程序会首先普通读取这部分数据以确保的确是位图文件并且没有损坏。

  • 字节 #0-1 保存位图文件的标识符,这两个字节的典型数据是BM
  • 字节 #2-5 使用一个dword保存位图文件大小。
  • 字节 #6-9 是保留部分,留做以后的扩展使用,对实际的解码格式没有影响。
  • 字节 #10-13 保存位图数据位置的地址偏移,也就是起始地址。

[编辑]位图信息

这部分告诉应用程序图像的详细信息,在屏幕上显示图像将会使用这些信息,它从文件的第15个字节开始。

  • 字节 #14-17 定义以下用来描述影像的区块(BitmapInfoHeader)的大小。它的值是:40 - Windows 3.2、95、NT、12 - OS/2 1.x、240 - OS/2 2.x
  • 字节 #18-21 保存位图宽度(以像素个数表示)。
  • 字节 #22-25 保存位图高度(以像素个数表示)。
  • 字节 #26-27 保存所用彩色位面的个数。不经常使用。
  • 字节 #28-29 保存每个像素的位数,它是图像的颜色深度。常用值是1、4、8(灰阶)和24(彩色)。
  • 字节 #30-33 定义所用的压缩算法。允许的值是0、1、2、3、4、5。
0 - 没有压缩(也用BI_RGB表示)
1 - 行程长度编码 8位/像素(也用BI_RLE8表示)
2 - 行程长度编码4位/像素(也用BI_RLE4表示)
3 - Bit field(也用BI_BITFIELDS表示)
4 - JPEG图像(也用BI_JPEG表示)
5 - PNG图像(也用BI_PNG表示)

然而,由于大多数位图文件都是不压缩的,所以最常用的值是0。

  • 字节 #34-37 保存图像大小。这是原始(en:raw)位图数据的大小,不要与文件大小混淆。
  • 字节 #38-41 保存图像水平方向分辨率。
  • 字节 #42-45 保存图像竖直方向分辨率。
  • 字节 #46-49 保存所用颜色数目。
  • 字节 #50-53 保存所用重要颜色数目。当每个颜色都重要时这个值与颜色数目相等。

[编辑]调色板

这部分定义了图像中所用的颜色。如上所述,位图图像一个像素接着一个像素储存,每个像素使用一个或者多个字节的值表示,所以调色板的目的就是要告诉应用程序这些值所对应的实际颜色。

典型的位图文件使用RGB彩色模型。在这种模型中,每种颜色都是由不同强度(从0到最大强度)的红色(R)、绿色(G)和蓝色(B)组成的,也就是说,每种颜色都可以使用红色、绿色和蓝色的值所定义。

在位图文件的实现中,调色板可以包含很多条目,条目个数就是图像中所使用的颜色的个数。每个条目包含4个字节:其中三个表示红色、绿色和蓝色,第四个字节没有使用(大多数应用程序将它设为0)。对于每个字节,数值0表示相应的颜色在当前的图像文件中没有使用,而数值255表示那个颜色使用最大的强度。

[编辑]位图数据

这部分逐个像素表示图像。像素是从下到上、从左到右保存的。每个像素使用一个或者多个字节表示。如果一个图像水平线的字节数不是4的倍数,这行就使用空字节补齐,通常是ASCII码0。

范例: 有一张5*5的图片,应该会有25个pixels,但是因为5不是4的倍数所以会显示成: xxxxx000 xxxxx000 xxxxx000 xxxxx000 xxxxx000

x代表调色盘的编号 0代表Null_character

有一张4*4的图片,应该会有16个pixels,但是因为是4的倍数所以会显示成:

xxxx xxxx xxxx xxxx

[编辑]其他

尽管文件大小比较大,但是位图文件的简单性、在微软视窗和其他地方的广泛使用以及这种格式的优秀文档标准以及没有专利约束,使得它成为其他操作系统图像处理程序能够读写的一种最为常用的格式。

X Window System使用类似的.XBM格式表示一位黑白图像以及.XPMpixelmap)表示彩色图像。另外还有一种.RAW格式,它除了保存原始数据之外没有任何其他信息。其他还有Portable Pixmap file format(.PPM)和Truevision TGA(.TGA),但是它们用得很少或者只用于特殊目的。尽管其他格式也保存为“位图”(与矢量图不同),但是它们使用数据压缩或者颜色索引,所以它们不是严格意义上的位图。

由于包含有冗余信息,许多BMP文件使用类似于ZIP这样的无损数据压缩算法能够取得很好的压缩效果。

如果您已经详细阅读维基百科对bmp文件格式的描述,就不难发现,读取bmp大致只需要用到fseek,fopen,fread等函数即可以完成,下面我给出相应的C代码,读取的图像头文件信息主要是offset,width,height,数据信息主要是r[][],g[][],b[][],同时把数据输出到相应的txt文件中。

#include <stdio.h>
#include <stdlib.h>

#define BITMAPFILEHEADERLENGTH 14   // The bmp FileHeader length is 14
#define BM 19778                    // The ASCII code for BM

/* Test the file is bmp file or not */
void bmpFileTest(FILE* fpbmp);
/* To get the OffSet of header to data part */
void bmpHeaderPartLength(FILE* fpbmp);
/* To get the width and height of the bmp file */
void BmpWidthHeight(FILE* fpbmp);
//get r,g,b data
void bmpDataPart(FILE* fpbmp);
// output data to corresponding txt file
void bmpoutput(FILE *fpout);

unsigned int OffSet = 0;    // OffSet from Header part to Data Part
long width ;          // The Width of the Data Part
long height ;         // The Height of the Data Part
unsigned char r[2000][2000],output_r[2000][2000];
unsigned char g[2000][2000],output_g[2000][2000];
unsigned char b[2000][2000],output_b[2000][2000];

int main(int argc, char* argv[])
{
     /* Open bmp file */
unsigned char *fp_temp;

FILE *fpbmp;
     FILE *fpout;

fpbmp= fopen("1.bmp", "rb");

if (fpbmp == NULL)
     {
 printf("Open bmp failed!!!\n");
 return 1;
     }

fpout= fopen("out.bmp", "wb+");
     if (fpout == NULL)
     {
 printf("Open out.bmp failed!!!\n");
 return 1;
     }
     
     bmpFileTest(fpbmp);                //Test the file is bmp file or not
     bmpHeaderPartLength(fpbmp);        //Get the length of Header Part
     BmpWidthHeight(fpbmp);             //Get the width and width of the Data Part
     
     
//
fseek(fpbmp, 0L, SEEK_SET);
fseek(fpout, 0L, SEEK_SET);
 
fp_temp=malloc(OffSet);
         fread(fp_temp, 1, OffSet, fpbmp);
fwrite(fp_temp,1,OffSet,fpout);
     
bmpDataPart(fpbmp);                //Reserve the data to file

/*
 
 
 如果您想对图片进行处理,请您再这里插入处理函数!!!!!!!!!!!!!!!!!!
 
*/
bmpoutput(fpout);
fclose(fpbmp);
fclose(fpout);
         return 0;
}

void bmpoutput(FILE* fpout)
{
         int i, j=0;
         int stride;
unsigned char* pixout=NULL;
   
stride=(24*width+31)/8;
stride=stride/4*4;
pixout=malloc(stride);
 
fseek(fpout, OffSet, SEEK_SET);

for(j=0;j<height;j++)
{

for(i=0;i<width;i++)
        {
            pixout[i*3+2]=output_r[height-1-j][i];
            pixout[i*3+1]=output_g[height-1-j][i];
            pixout[i*3]  =output_b[height-1-j][i];
        }
fwrite(pixout, 1, stride, fpout);

}
}

void bmpDataPart(FILE* fpbmp)
{
         int i, j=0;
int stride;
unsigned char* pix=NULL;

FILE* fpr;
         FILE* fpg;
FILE* fpb;
     
     if((fpr=fopen("bmpr.txt","w+")) == NULL)
     {
    printf("Failed to construct file bmpr.txt.!!!");
exit(1);
     }

if((fpg=fopen("bmpg.txt","w+")) == NULL)
     {
 printf("Failed to construct file bmpg.txt.!!!");
 exit(1);
     }

if((fpb=fopen("bmpb.txt","w+")) == NULL)
     {
printf("Failed to construct file bmpb.txt.!!!");
exit(1);
     }
 
     fseek(fpbmp, OffSet, SEEK_SET);
stride=(24*width+31)/8;
stride=stride/4*4;
pix=malloc(stride);
 
for(j=0;j<height;j++)
{
fread(pix, 1, stride, fpbmp);

for(i=0;i<width;i++)
        {
            r[height-1-j][i]   =pix[i*3+2];
            g[height-1-j][i]   =pix[i*3+1];
            b[height-1-j][i]   =pix[i*3];

output_r[height-1-j][i]   =pix[i*3+2];
            output_g[height-1-j][i]   =pix[i*3+1];
            output_b[height-1-j][i]   =pix[i*3];
        }

}

for(i =0; i < height; i++)
     {
for(j = 0; j < width-1; j++)
{   
fprintf(fpb,"%4d",b[i][j]);
fprintf(fpg,"%4d",g[i][j]);
fprintf(fpr,"%4d",r[i][j]);
}
fprintf(fpb,"%4d\n",b[i][j]);
fprintf(fpg,"%4d\n",g[i][j]);
fprintf(fpr,"%4d\n",r[i][j]);
 }
  
fclose(fpr);
fclose(fpg);
fclose(fpb);
 
}

void bmpFileTest(FILE* fpbmp)
{     
     unsigned short bfType = 0;
 
     fseek(fpbmp, 0L, SEEK_SET);//seek_set 起始位置
     fread(&bfType, sizeof(char), 2, fpbmp);
     if (BM != bfType)
     {
 printf("This file is not bmp file.!!!\n");
 exit(1);
     }
}

/* To get the OffSet of header to data part */
void bmpHeaderPartLength(FILE* fpbmp)
{
     fseek(fpbmp, 10L, SEEK_SET);
     fread(&OffSet, sizeof(char), 4, fpbmp);
     printf("The Header Part is of length %d.\n", OffSet);
}

/* To get the width and height of the bmp file */
void BmpWidthHeight(FILE* fpbmp)
{
     fseek(fpbmp, 18L, SEEK_SET);
     fread(&width, sizeof(char), 4, fpbmp);
     fseek(fpbmp, 22L, SEEK_SET);
     fread(&height, sizeof(char), 4, fpbmp);
     printf("The Width of the bmp file is %ld.\n", width);
     printf("The Height of the bmp file is %ld.\n", height);
}

C语言读取BMP格式图片相关推荐

  1. c语言实现pdf显示图片,C语言读取BMP格式图片.pdf

    C语言读取BMP格式图片 C 语言读取BMP 格式图片 以下摘自维基百科,自由的百科全书 BMP 取自位图BitMaP 的缩写,也称为DIB (与设备无关的位图)是微软视窗图形 子系统(Graphic ...

  2. linux下通过C语言读取BMP格式图片,在文本终端显示该图片

    第一步:打开需要读取的图片文件 fd = open(picture, O_RDONLY): //只读方式打开文件 第二步:读取图片的长,宽,每个像素占多少字节,偏移量 查看bmp格式就能知道各个数据两 ...

  3. C++读取bmp格式图片

    类的格式按照bmp的文件头.信息头.调色板和数据域写好即可 因为图片是按字节读的,所以要强制让编译器不对结构体进行字节对齐,否则会出错 因为bmp格式规定存储时每行的像素数要补齐至4的整数倍,所以读入 ...

  4. verilog读取bmp格式图片

    代码如下: `timescale 1 ns/1 ns module test_t; integer fileId, cc,out_file,i; reg [7:0] bmp_data [0:20000 ...

  5. 将BMP 格式图片转换为 JPEG 格式【c语言】

    源码链接: https://blog.csdn.net/qq_44394952/article/details/122587475?spm=1001.2014.3001.5502. 一.任务及目标 利 ...

  6. C语言读取和存储bmp格式图片

    开发过程中有时候需要解析bmp数据,下面先简单介绍bmp数据组成,后面附上C语言读取和存储bmp格式图片代码. 典型的位图文件格式通常包含下面几个数据块: BMP文件头:保存位图文件的总体信息. 位图 ...

  7. 将BMP 格式图片转换为 JPEG 格式【c语言源码】

    原理及代码讲解链接: https://blog.csdn.net/qq_44394952/article/details/122587306?spm=1001.2014.3001.5502. 主函数m ...

  8. C语言实现RGB888转BMP格式图片功能

    1.bmp格式介绍 bmp格式图片里实际存储的也是RGB原始数据,可以分为8bit.16bit.24bit.32bit的bmp格式,也就是指bmp图片中保存的RGB是用8bit.16bit.24bit ...

  9. 【数字图像处理】一.MFC详解显示BMP格式图片

    本文主要是讲述<数字图像处理>系列栏目中的第一篇文章.主要详细介绍了BMP图片格式,同时使用C++和MFC显示BMP格式,主要结合自己的<数字图像处理>课程和以前的项目叙述讲解 ...

最新文章

  1. 优达学城《DeepLearning》1-1:神经网络概论
  2. SpringMVC实现文件的上传和下载
  3. 上海交通大学c语言章节作业,上海交通大学级C语言测试题.doc
  4. WDS使用捕获映像制作企业自定义映像
  5. 本地项目关联到远程git仓库
  6. 后端开发除了编码还要做什么_每个开发人员都应掌握的基本技能(除了编码)
  7. 工作资讯003---甘特图
  8. 《嵌入式系统项目分析入门与实践》 读后感(1)
  9. HashMap 容量为什么总是为 2 的次幂?
  10. byte转换字符串(string)+字符串转换byte
  11. 剖析WordPress模板文件【转】
  12. css网页设计作业_运动中心网页设计作业成品
  13. PyQt5简易本地视频播放器
  14. U盘文件变成exe后被杀毒消失
  15. 日积(Running)月累(ZSSURE):看山不是山看水不是水,2017
  16. VS2017--无法添加引用--提示“未能完成操作。不支持此接口”
  17. 带动画的好看的按钮集合HTML + CSS各种好看按钮组件
  18. linux下解压iso镜像文件方法
  19. MFC制作Windows画图程序(一)
  20. 说下类加载器与类加载?加载的信息放在哪个区域?

热门文章

  1. [Android]简易播放视频
  2. miRNA信息包:miRBaseVersions.db
  3. ubuntu12.04打开qt5.2.0時出现异常
  4. 2019牛客多校第九场AThe power of Fibonacci——扩展BM
  5. 【转】git中如何忽略xcuserstate
  6. JS 解密剖析—爬虫之网易云音乐加密破解
  7. 产品经理如何做好行业研究及竞争对手分析工作
  8. 青山依旧在,2021这一年
  9. 无组织排放管控治一体化解决方案
  10. CHB-STATCOM 整体仿真模型 低电容下 CHB-STATCOM 直流侧电容电压的平衡控制