-
2022-03-18 18:10:37
最近一段时间我学习了计算机图像处理这门课程,通过这门课程的学习,我了解到了图片具有灰度和彩色的区别,并且通过具体的代码可以将一些图片数据进行读写与转化。
第一部分:BMP图像的读写
1.BMP图像的读:
(1)首先定义BMP文件头和信息头变量BITMAPFILEHEADER bf; //BMP文件头结构体BITMAPINFOHEADER bi; //BMP信息头结构体(2)创建文件输入流 fp
fp=fopen(fileName,“rb”); //fileName为BMP图像文件名(3)读取信息头、文件头fread(&bf,sizeof(BITMAPFILEHEADER),1,fp); fread(&bi,sizeof(BITMAPINFOHEADER),1,fp);
注:经过这两条程序把BMP图像的信息头、文件头赋给bf和bi变量,可以根据bf和bi得到图像的各种属性。
(4) 读取BMP调色板fread(ipRGB2,sizeof(RGBQUAD),256,fp);
(5)读取BMP位图数据定义一个二维数Imgdata来存取BMP位图数据。
unsigned char * * Imgdata;
Imgdata=new unsigned char*[bi.biHeight]; //声明一个指针数组
for ( i=0;i<bi.biHeight;i++)
Imgdata[i]=new unsigned char[(bi.biWidth3+3)/44]; //每个数组元素也是一个指针数组
for ( i=0;i<bi.biHeight;i++ )
for(j=0;j<(bi.biWidth3+3)/44;j++)
fread(&Imgdata[i][j],1,1,fp);//每次只读取一个字节,存入数组2.BMP图像的写:
(1)创建一个输出流fp fp=fopen(“mybmp.bmp”,“wb”);(2) 写BMP图像的信息头、文件头fwrite(&bf2,sizeof(BITMAPFILEHEADER),1,fp); fwrite(&bi2,sizeof(BITMAPINFOHEADER),1,fp);
(3) 写BMP调色板fwrite(ipRGB2,sizeof(RGBQUAD),256,fp);
(4) 写BMP图像的位图数据部分
for (i=(bi.biHeight)-1 ;i>=0;i–)
for (j=0 ;j<(bi.biWidth3+3)/44;j++)
fwrite(&Imgdata[i][j],1,1,fp);注意:将图片信息导入到文件里(导入的图像数据与实际图像数据上下顺序颠倒,最后一行数据应该放在第一行,以此类推)
第二部分:主程序部分,利用上述函数,即可实现BMP图的存储与处理
#include “hxlbmpfile.h”
void ImageProcessing(HXLBMPFILE* bmp) {
int i = 0, j = 0;
HXLBMPFILE bf;
bf.iImagew = bmp->iImagew;
bf.iImageh = bmp->iImageh;
bf.iYRGBnum = bmp->iYRGBnum;
if (!bf.IspImageDataOk()) return;
for (i = 0; i < bf.iImageh; i++)
for (j = 0; j < bf.iImagew; j++)
{
bf.pDataAt(i)[j] = 255 - bmp->pDataAt(i)[j];
}
bf.SaveBMPFile(“2.bmp”);
}int main(int argc, char* argv[]) {
HXLBMPFILE bmpfile;
if(!bmpfile.LoadBMPFile(“C:\Users\lenovo\Downloads\b8color.bmp”))
{printf(“Load BMP file failed.”);return 1;}// do other processing with the imagedata
ImageProcessing(&bmpfile);
printf(“program ends!\n”);
return 0;
}
函数大体可以不发生改变,只需要改变能够决定图片处理色度部分的具体函数就可以进行灰度图片与彩色图片之间的转化。更多相关内容 -
C++读取保存BMP图像
2019-06-23 00:47:56C++读取保存BMP图像,包括8位,24位的读取和保存,灰度图的转换,不使用任何已有读取、转换、保存等库函数。跨平台使用,理论上Linux与Windows上均可使用,Windows上测试成功。 -
C语言读取BMP图像数据的
2020-09-05 13:48:44C语言读取BMP图像数据的源码,需要的朋友可以参考一下 -
BMP图像
2016-05-03 19:23:22BMP文件 -
24位bmp图像90°旋转
2018-11-14 11:34:02该代码适用于任何大小的bmp图像的旋转,不过当前仅实现了bmp图像的90°旋转 -
Bmp图像反色处理
2018-11-28 16:08:12256位的Bmp图像的反色处理 及一张256位的bmp图像 -
纯C++实现24位BMP图像的旋转、缩放、裁剪等一系列操作
2019-09-18 14:27:42纯C++实现24位BMP图像的旋转、缩放、裁剪等一系列操作,可以供大家参考学习。 -
Matlab读取BMP文件代码-bmp-image-with-HSI-and-RGB:具有HSI和RGB的bmp图像
2021-05-23 16:52:29Matlab读取BMP文件代码具有HSI和RGB的bmp图像 建立Matlab程式码 每种颜色“写入”和“读取”非压缩的8位.bmp文件。 从8位图像中读取其调色板,并创建一个显示调色板所有颜色的新图像。 这意味着我们将创建一个尺寸为... -
C# 读取dcm医学图像,格式转换为bmp图像的demo
2019-10-28 10:17:17导师接了校医院的项目,涉及到dcm医学图像的显示和存储问题。 demo实现 将本地的dcm图像转存为bmp图像 使用时 需要导入dicom包,只需修改dcm 路径即可。 -
BMP图像文件格式分析
2018-01-03 22:23:27多媒体技术中对BMP文件格式进行分析,摘要必须大于50个字节!, -
24位BMP图像的任意角度旋转
2018-07-04 19:00:52可以将24位BMP文件任意角度旋转。使用时只需将图片与此程序放在同一文件夹中,输入文件名,旋转角度即可。 -
图像处理-bmp图像均值滤波-C++
2017-04-16 11:55:24图像处理-读取bmp图像均值滤波-C++ -
bmp图像转为yuv图像
2016-04-13 10:27:44输入一幅bmp图像,将其转为YUV420图像 -
读取BMP图像RGB值以及简单生成BMP图像
2014-12-20 18:53:06读取BMP图像RGB值以及简单生成BMP图像 用C语言实现。 -
JAVA读写BMP图像函数
2016-12-06 13:16:17JAVA读写BMP图像函数 -
bmp图像转换为16位(565)数据软件源码
2018-04-04 14:03:49通过visual studio2013平台开发的bmp图像转换为16位(565)数据软件源码 -
bmp 图像格式
2014-08-08 20:28:37bmp 图像格式 -
bmp图像格式转换(ppm,pgm)
2017-04-28 16:04:06实现图像格式的转化,将bmp的彩色图像转化为其他简单格式,便于使用。 -
C语言读取BMP图像
2019-03-14 15:10:36c语言实现BMP图像的读取与复制,读取BMP文件表头54个的字节的表头,和再生成一个图片 -
BMP图像读取
2021-12-07 15:25:50根据百度百科对BMP的定义,我们知道BMP是Bitmap(位图)的简称,是Windows操作系统中的标准图像文件格式。其特点是由于几乎不进行压缩,所以包含的图像信息较丰富,但同时也到之占用的磁盘空间较大。 1 文件格式 ...0. BMP格式介绍
根据百度百科对BMP的定义,我们知道BMP是Bitmap(位图)的简称,是Windows操作系统中的标准图像文件格式。其特点是由于几乎不进行压缩,所以包含的图像信息较丰富,但同时也到之占用的磁盘空间较大。
1 文件格式
位图文件由4个部分组成:
- 位图头文件(bitmap-file header)
- 位图信息头(bitmap-information header)
- 颜色表(color table):使用索引来表示图像,此时颜色表就是索引与其对应的颜色之间的映射表(即通过索引值,结合颜色表,找到对应的像素信息)
- 位图数据(data bits)
上述不同的部分,有不同的数据结构,下面分别介绍前面3个部分的数据结构。
数据段名称 对应的Windows结构体定义 大小(Byte) bmp文件头 BITMAPFILEHEADER 14 bmp信息头 BITMAPINFOHEADER 40 颜色表 由颜色索引数决定 bmp数据 由图像尺寸决定 2 位图头文件
本文,以上图来分析BMP图像的文件格式。在分析图像数据之前,需要强调的是BMP文件中,数据的存储方式为小端方式(little endian),即假设一个数据需要多个字节来表示,那么数据的存放字节的顺序为“低地址存放地位数据,高地址存放高位数据”。在十六进制中,一个数字占4位,因此每个字节可以存储2个十六进制数字。
因此,对于数据0x1756在内存中的存储顺序为:
位图头文件的结构体定义如下:
typedef struct tagBITMAPFILEHEADER { UINT16 bfType; // 19778,必须是BM字符串,对应的十六进制为0x4d42,十进制为19778,否则不是bmp格式文件 DWORD bfSize; // 文件大小 以字节为单位(2-5字节) UINT16 bfReserved1; // 保留,必须设置为0 (6-7字节) UINT16 bfReserved2; // 保留,必须设置为0 (8-9字节) DWORD bfOffBits; // 从文件头到像素数据的偏移 (10-13字节) } BITMAPFILEHEADER;
在VScode中,可以通过安装hexdump插件来以二进制的形式查看BMP图像数据。
对照结构体和文件数据可以看到:
0-1 : 0x4d42='BM',表示这是Windows支持的位图格式
2-5 : 0x000088EA表示文件大小
6-9 : 保留段,为0
A-D : 0x00000436=1078,表示从文件头到位图数据需要偏移1078个字节
【注意】利用fopen打开文件,得到文件句柄读取相应的数据时,存在一个问题就是结构体内存对齐。这个会使得后续数据的读取出现错误。
何为内存对齐具体可以参考文章:结构体成员在内存中的对齐方式
上述问题的具体表现可以通过如下的代码进行实现:
#include <stdio.h> typedef struct tagBITMAPFILEHEADER { unsigned short bfType; // 19778,必须是BM字符串,对应的十六进制为0x4d42,十进制为19778,否则不是bmp格式文件(0-4) int bfSize; // 文件大小 以字节为单位(2-5字节) (4-8) unsigned short bfReserved1; // 保留,必须设置为0 (6-7字节) (8-10) unsigned short bfReserved2; // 保留,必须设置为0 (8-9字节) (10-12) int bfOffBits; // 从文件头到像素数据的偏移 (10-13字节) (12-16) } BITMAPFILEHEADER; int main(int argc, char* argv[]) { printf("sizeof(BITMAPFILEHEADER) = %lu\n", sizeof(BITMAPFILEHEADER)); return 0; } // sizeof(BITMAPFILEHEADER) = 16
那么如何关闭结构体的内存对齐 ,有两种方式:添加预处理指令 #pragma pack(1) 或者 __attribute__ ((packed))。这两种方式的区别在于:
- #pragma pack(1)预处理指令,是关闭整个文件的内存对齐模式
- __attribute__ ((packed))指令,则是针对指定的结构体
#include <stdio.h> // #pragma pack(1) typedef struct tagBITMAPFILEHEADER { unsigned short bfType; // 19778,必须是BM字符串,对应的十六进制为0x4d42,十进制为19778,否则不是bmp格式文件(0-4) int bfSize; // 文件大小 以字节为单位(2-5字节) (4-8) unsigned short bfReserved1; // 保留,必须设置为0 (6-7字节) (8-10) unsigned short bfReserved2; // 保留,必须设置为0 (8-9字节) (10-12) int bfOffBits; // 从文件头到像素数据的偏移 (10-13字节) (12-16) }__attribute__ ((packed)) BITMAPFILEHEADER; int main(int argc, char* argv[]) { printf("sizeof(BITMAPFILEHEADER) = %lu\n", sizeof(BITMAPFILEHEADER)); return 0; } // sizeof(BITMAPFILEHEADER) = 14
3 位图信息头
位图信息头的结构体定义如下:
typedef struct tagBITMAPINFOHEADER { unsigned int biSize; // 此结构体的大小 (14-17字节) long biWidth; // 图像的宽 (18-21字节) long biHeight; // 图像的高 (22-25字节) unsigned short biPlanes; // 表示bmp图片的平面属,显然显示器只有一个平面,所以恒等于1 (26-27字节) unsigned short biBitCount; // 一像素所占的位数,一般为24 (28-29字节) unsigned int biCompression; // 说明图象数据压缩的类型,0为不压缩。 (30-33字节) unsigned int biSizeImage; // 像素数据所占大小, 这个值应该等于上面文件头结构中bfSize-bfOffBits (34-37字节) long biXPelsPerMeter; // 说明水平分辨率,用象素/米表示。一般为0 (38-41字节) long biYPelsPerMeter; // 说明垂直分辨率,用象素/米表示。一般为0 (42-45字节) unsigned int biClrUsed; // 说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。 (46-49字节) unsigned int biClrImportant; // 说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。(50-53字节) } BITMAPINFOHEADER;
4 颜色表
颜色表本质上是一个查询表,通过颜色序号来查询对应的颜色。在文件中的布局类似一个二维数组palette[N][4]. 其中4个元素分别表示对应的B,G,R和Alpha的值,每个分量占一个字节。N一般等于256。
一共有256种颜色,每个颜色占用4个字节,就是一共1024个字节,再加上前面的文件信息头和位图信息头的54个字节加起来一共是1078个字节。
5. 位图数据
位图数据中,每个像素占一个字节,以该字节的数作为颜色索引去颜色表查询相应的颜色,并将其显示出来即可。
6. 参考链接
C实现BMP转JPG 附源码_等jzy的博客-CSDN博客_c语言bmp转jpg
用c、cpp实现位图(BMP)读入写出的思路及细节 - et3_tsy - 博客园 (cnblogs.com)
C语言实现BMP图像的读写功能_C 语言_脚本之家 (jb51.net)
-
VS2008+MFC显示Bmp图像
2018-07-18 11:25:50VS2008+MFC显示Bmp图像,包含opencv库可支持图像处理。 -
BMP图像文件读写操作类,C++实现,支持24位位图
2017-11-04 23:03:06BMP图像文件读写操作类,C++实现,支持24位位图。适合学习用。 -
论文研究-RLE-8格式的BMP图像解码 .pdf
2019-08-14 16:07:14RLE-8格式的BMP图像解码,罗希,,本文给出了作为WINDOWS操作系统主流图像格式BMP的结构组成,简要阐述BMP图像RLE-8压缩算法的工作原理以及RLE-8压缩算法编码方式。利用VC6. -
C语言读取bmp图像
2022-03-24 17:59:05BMP图像编码 BMP即bitmap,也就是位图,一般由4部分组成:文件头信息块、图像描述信息块、颜色表(在真彩色模式无颜色表)和图像数据区。 在图像数据之前,如图所示,共有54位数据 其中,0x424d在十进制为19778,...BMP图像编码
BMP即bitmap,也就是位图,一般由4部分组成:文件头信息块、图像描述信息块、颜色表(在真彩色模式无颜色表)和图像数据区。
在图像数据之前,如图所示,共有54位数据
其中,
0x424d
在十进制为19778
,对应的ASCII码为BM
,表示这是个bitmap
文件。在C语言中,
short
类型为16位,即2字节;int
为4字节。考虑到BMP格式的文件头中,每个信息基本都是2字节的倍数,故而用int
和short
便可描述出bmp
格式的文件头。文件信息头[14 bytes]存储着文件类型,文件大小等信息
// 文件信息头结构体 typedef struct tagBITMAPFILEHEADER{ unsigned short bfType; //必为'BM' unsigned int bfSize; //文件字节数(2-5) unsigned int bfReserved; //位图文件保留字,必为0(6-9) unsigned int bfOffBits; //像素数据偏移 (10-13) } bmpHeader;
接下来的40bytes存储图像的尺寸,颜色索引,位平面数等信息
#define uint unsigned int #define ushort unsigned short //图像信息头结构体 typedef struct tagBITMAPINFOHEADER{ uint biSize; // 结构体尺寸 (14-17) int biWidth; // 图像宽度 (18-21) int biHeight; // 图像高度 (22-25) ushort biPlanes; // 目标设备的级别,为1(26-27) ushort biBitCount; // 像素位数,为1、4、8或24(28-29) uint biCompression; // 位图压缩类型,0为不压缩、1为BI_RLE8、2为BI_RLE4(30-33) uint biSizeImage; // 单像素数据大小,等于bfSize-bfOffBits (34-37) int biXPelsPerMeter; // 水平分辨率,一般为0 (38-41) int biYPelsPerMeter; // 垂直分辨率,一般为0 (42-45) uint biClrUsed; // 位图颜色表中的颜色数,0表示使用所有调色板项(46-49) uint biClrImportant; // 重要颜色索引的数目,0表示都重要(50-53) } infoHeader;
在54位的文件头之后,如果需要的话,bmp文件可存放调色板信息,对于
rgb
图像来说,可以如下//24位图像素信息结构体,即调色板 typedef struct _PixelInfo { unsigned char rgbBlue; //蓝色分量 (0-255) unsigned char rgbGreen; //绿色分量 (0-255) unsigned char rgbRed; //红色分量 (0-255) unsigned char rgbReserved;// 保留,必须为0 } PixelInfo;
颜色表中
RGBQUAD
结构数据的个数由biBitCount来确定:- 当biBitCount=1,4,8时,分别有2,16,256个表项;
- 当biBitCount=24时,没有颜色表项。
位图信息头和颜色表组成位图信息,BITMAPINFO结构定义如下:
typedef struct tagBITMAPINFO { BITMAPINFOHEADER bmiHeader; // 位图信息头 RGBQUAD bmiColors[1]; // 颜色表 } bmpInfo;
颜色表接下来为图像数据区,存储每个像素对应的颜色号,单像素点颜色号的位长度与图像类型有关
图像类型 2色图像 16色图像 256色图像 真彩色图像 字节数 1bit 4bit 1B(8bit) 3B 由此可知,理想情况下图像数据区的字节数为 b i W i d t h × b i H e i g h t × b i B i t C o u n t / 8 \sf biWidth\times biHeight\times biBitCount/8 biWidth×biHeight×biBitCount/8。
但是,由于BMP以字节为单位,按行存储图片的数据,也就是说每一行必须为字节数。而对于16色以及2色图像而言,当每行像素个数为奇数时,则必然导致出现空位,从而实际所占存储空间要大于上述计算值。
读取BMP文件
读取文件之后第一件事即判断我们读取的是否为BMP图像,即
//判断是否是位图,在0-1字节 int IsBitMap(FILE *fp){ ushort s; fread(&s,1,2,fp); return s==BM ? 1 : 0; }
其中,
fread
命令表示读取文件fp
,并将读取到的内容存储在s
中。1
表示要读取的数据的大小,2
表示将要读取的元素的个数。由前文可知,位图的文件类型必须是BM
,十六进制下0x4d42,十进制为19778。然后需要得到图像的宽度和高度,从而确定数据区的范围
//获得图片的宽度,在18-21字节 int getWidth(FILE *fp){ int width; fseek(fp,18,SEEK_SET); fread(&width,1,4,fp); return width; } //获得图片的高度 ,在22-25字节 int getHeight(FILE *fp){ int height; fseek(fp,22,SEEK_SET); fread(&height,1,4,fp); return height; }
其中,
fseek
可以为fp
提供一个偏移量,SEEK_SET
表示从文件的开头进行移动。由上文可知,图片高度所在位置是第22个字节。若想读取其他信息,以此类推即可。
//test.c #include<stdio.h> #include<malloc.h> #define BM 19778 // 位图的标志 #define PATH "1.bmp" //打开的文件路径 #define ushort unsigned short #define uint unsigned int #define uchar unsigned char //判断是否是位图,在0-1字节 int IsBitMap(FILE *fp){ ushort s; fread(&s,1,2,fp); return s==BM ? 1 : 0; } //获得图片的宽度,在18-21字节 int getWidth(FILE *fp){ int width; fseek(fp,18,SEEK_SET); fread(&width,1,4,fp); return width; } //获得图片的高度 ,在22-25字节 int getHeight(FILE *fp){ int height; fseek(fp,22,SEEK_SET); fread(&height,1,4,fp); return height; } //获得每个像素的位数,在28-29字节 ushort getBit(FILE *fp) { ushort bit; fseek(fp,28,SEEK_SET); fread(&bit,1,2,fp); return bit; } //获得数据的起始位置,在10-13字节 uint getOffSet(FILE *fp){ uint OffSet; fseek(fp,10L,SEEK_SET); fread(&OffSet,1,4,fp); return OffSet; } int main(){ int width,height; FILE *fp=fopen(PATH,"r"); uchar *r,*g,*b; int i,j; r=(uchar *)malloc(4000); b=(uchar *)malloc(4000); g=(uchar *)malloc(4000); if(!IsBitMap(fp)){ printf("format error!\n"); fclose(fp); return 0; } printf("this file is a bitmap picture\n"); printf("width = %ld\nheight = %ld\n",getWidth(fp),getHeight(fp)); printf("bit size = %d bit\n",getBit(fp)); printf("OffSet = %d\n",getOffSet(fp)); return 0; }
验证
> gcc .\test.c > .\a.exe this file is a bitmap picture width = 3840 height = 2160 bit size = 24 bit OffSet = 138
-
bmp图像几何变换(近邻值、双线性、三次卷积)
2016-07-08 17:57:22资源关于bmp图片的几何变换,包括:旋转,缩放,近邻值,双线性,三次卷积;适合图像处理初学者学习,算法可能不是很精确,见谅! 刚好最近在学习这个,网上找了很多资料,不是很全,所以自己写了一个上传,仅供参考 -
VS2010实现bmp图像的显示
2015-11-10 20:01:04使用vs2010编写的bmp图像显示MFC界面,可以方便实现图像显示操作,也快很方便进行后续的图像处理算法的开发。 -
信息论课程设计哈夫曼,费诺编码,对BMP图像进行编解码
2020-08-27 19:16:33合肥工业大学信息论课程设计哈夫曼,菲诺编码,对BMP图像进行编解码,信息论 哈夫曼编码 与 菲诺编码的实现(对一幅BMP格式的灰度图像(个人 证件照片)进行二元霍夫曼编码和译码。并进行编码效率的计算,对一幅BMP... -
BMP图像处理
2013-06-15 14:52:42对BMP图像进行反色、叠置、距离场、中轴提取和粘连处理。 -
29张标准测试图像,bmp图像
2018-12-04 22:36:5629张标准测试图像,bmp图像,可以用来做图像处理 -
24位BMP图像用C++实现平移、旋转、镜像、错切、缩放操作
2015-12-13 15:36:42C++代码实现24位无调色板BMP图像的平移、旋转、镜像、错切和缩放等操作。 在命令行用g++编译即可运行,具体请看目录下的README