BMP取自位图BitMaP的缩写,也称为DIB(与设备无关的位图),是微软视窗图形子系统(Graphics Device Interface)内部使用的一种位图图形格式,它是微软视窗平台上的一个简单的图形文件格式。
详细介绍可以参考维基百科:http://zh.wikipedia.org/wiki/BMP
学习的目的是解析一个为图文件并显示位图。在位图图像数据之前,有文件头和信息头,Windows环境下wingdi.h中提供了相应的数据结构。
文件头结构体:
typedef struct tagBITMAPFILEHEADER { WORD bfType;//位图文件的类型,必须为BM(1-2字节) DWORD bfSize;//位图文件的大小,以字节为单位(3-6字节,低位在前) WORD bfReserved1;//位图文件保留字,必须为0(7-8字节) WORD bfReserved2;//位图文件保留字,必须为0(9-10字节) DWORD bfOffBits;//位图数据的起始位置,以相对于位图(11-14字节,低位在前) //文件头的偏移量表示,以字节为单位 }BITMAPFILEHEADER;
信息头结构体:
typedef struct tagBITMAPINFOHEADER{ DWORD biSize;//本结构所占用字节数(15-18字节) LONG biWidth;//位图的宽度,以像素为单位(19-22字节) LONG biHeight;//位图的高度,以像素为单位(23-26字节) WORD biPlanes;//目标设备的级别,必须为1(27-28字节) WORD biBitCount;//每个像素所需的位数,必须是1(双色),(29-30字节) //4(16色),8(256色)16(高彩色)或24(真彩色)之一 DWORD biCompression;//位图压缩类型,必须是0(不压缩),(31-34字节) //1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一 DWORD biSizeImage;//位图的大小(其中包含了为了补齐行数是4的倍数而添加的空字节),以字节为单位(35-38字节) LONG biXPelsPerMeter;//位图水平分辨率,每米像素数(39-42字节) LONG biYPelsPerMeter;//位图垂直分辨率,每米像素数(43-46字节) DWORD biClrUsed;//位图实际使用的颜色表中的颜色数(47-50字节) DWORD biClrImportant;//位图显示过程中重要的颜色数(51-54字节) }BITMAPINFOHEADER;
全部实例代码:
/* * bmptest.c * * Created on: 2014-10-27 * Author: HZY */ #include <stdio.h> #include "GL/freeglut.h" static BYTE* buffer = NULL; static BITMAPINFOHEADER infoHeader; //BGR转RGB:对于每个点,第一字节和第三字节交换 void bgrToRgb(BYTE* buffer, int size) { int i = 0; int j = 0; BYTE temp = 0; int blueIdx = 0; int rowBytes = size / infoHeader.biHeight; for (i = 0; i < infoHeader.biHeight; i++) { for (j = 0; j < infoHeader.biWidth; j++) { blueIdx = i * rowBytes + j * 3; temp = buffer[blueIdx]; buffer[blueIdx] = buffer[blueIdx + 2]; buffer[blueIdx + 2] = temp; } } } //获取每一行所用的字节数,需要凑足4的倍数 int getRowBytes(int width){ //刚好是4的倍数 if((width * 3) % 4 == 0){ return width * 3; }else{ return ((width * 3) / 4 + 1) * 4; } } void printFileHeader(BITMAPFILEHEADER* h) { printf("$fileHeader: offbits[%ld], size[%ld], type[%d]\n", h->bfOffBits, h->bfSize, h->bfType); } void printInfoHeader(BITMAPINFOHEADER* h) { printf("$infoHeader: size[%ld], width[%ld], height[%ld], planes[%d]\n\t" "bitcount[%d], compression[%ld], sizeImage[%ld]\n\t" "XpixPerM[%ld], YpixPerM[%ld], colors[%ld], impColors[%ld]\n", h->biSize, h->biWidth, h->biHeight, h->biPlanes, h->biBitCount, h->biCompression, h->biSizeImage, h->biXPelsPerMeter, h->biYPelsPerMeter, h->biClrUsed, h->biClrImportant); } void parseBmp() { FILE* fp = NULL; BITMAPFILEHEADER fileHeader; int realBytes = 0; //打开文件 fp = fopen("test.bmp", "rb"); if (fp == NULL) { printf("file open error!\n"); exit(EXIT_FAILURE); } //读取文件头 fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, fp); printFileHeader(&fileHeader); //读取信息头 fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, fp); printInfoHeader(&infoHeader); //只处理24位非压缩位图 switch (infoHeader.biBitCount) { case 24: realBytes = infoHeader.biWidth * infoHeader.biHeight * 3; printf("image realBytes[%d]\n", realBytes); //一些图片编辑软件得到的biSizeImage为0, //这样的图片手动计算biSizeImage if (infoHeader.biSizeImage < realBytes) { infoHeader.biSizeImage = getRowBytes(infoHeader.biWidth) * infoHeader.biHeight; printf("Calculated biSizeImage[%ld]\n", infoHeader.biSizeImage); } //获取堆空间 buffer = malloc(infoHeader.biSizeImage); //读数据到内存 fread(buffer, infoHeader.biSizeImage, 1, fp); //bmp中保存的是BGR,转成RGB,方便显示 bgrToRgb(buffer, infoHeader.biSizeImage); break; default: printf("not 24 bit bitmap!\n"); fclose(fp); exit(EXIT_FAILURE); break; } fclose(fp); } //opengl显示图片 void myDisplay(){ glClear(GL_COLOR_BUFFER_BIT); glDrawPixels(infoHeader.biWidth, infoHeader.biHeight, GL_RGB, GL_UNSIGNED_BYTE, buffer); glFlush(); } int main(int c, char** v){ parseBmp(); glutInit(&c, v) ; glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE); glutInitWindowPosition(100, 100); glutInitWindowSize(infoHeader.biWidth, infoHeader.biHeight); glutCreateWindow("hello bmp"); glutDisplayFunc(&myDisplay); glutMainLoop(); free(buffer); return 0; }
效果如图:
显示图片采用opengl来渲染,使用了freeglut:
工程是用eclipse中cdt使用mingw编译:
全部代码在附件中。
相关推荐
- **文件读取**:熟练掌握使用C++读取文件,特别是BMP格式文件的技巧。 - **图像数据结构**:理解BMP文件结构,包括文件头、信息头和像素数据。 - **动态数据管理**:合理使用指针和动态内存分配,避免内存泄漏。 - ...
标题中的“BMP转pcb工具”指的是一个能够将位图图像(BMP格式)转换成PCB设计文件的软件。在电子设计领域,PCB(Printed Circuit Board,印制电路板)是承载电子元器件并连接它们的实体平台,而BMP是一种常见的图像...
在这个"bmp简单验证码识别"项目中,我们主要关注的是如何处理和解析BMP格式的图像,以识别其中包含的字符。以下是这个话题涉及的主要知识点: 1. BMP格式:BMP是位图图像文件的一种格式,它存储未经压缩的像素数据...
DICOM医学图像文件格式解析与应用研究 WINDOWS环境下DICOM医学图像显示方法的初步研究 标准医学DICOM图像的转换实现 基于DICOM的数据组织及医学图像序列提取方法研究 用二叉树实现DICOM医学图像的编码 树型结构DICOM...
首先,需要解析BMP文件头来获取图像的大小和格式信息;然后,将像素数据按行加载到内存中,可能需要进行数据格式转换,比如从RGB转换为灰度;最后,可以使用嵌入式处理器的硬件加速功能(如DMA)提高处理效率。 5. ...
DICOM(Digital Imaging and Communications in Medicine)是一种广泛应用于医疗成像领域的标准,用于存储、传输和显示医学图像。以下是从标题“用C读取DICOM文件”和描述“读取DICOM文件的程序(纯C编写的),大家...
"图片转PCB小工具",即bmp2pcb,提供了一个简单易用的解决方案,使得设计师能够快速将BMP格式的图片转化为PCB设计文件。本文将深入探讨这个工具的特性和使用方法,以及其在实际设计中的应用。 一、bmp2pcb简介 bmp...
7. **安全分析**:对于可能包含恶意代码的EXE文件,MultiExtractor可以帮助用户进行初步的安全检查,通过提取和查看其中的资源,以便发现潜在的威胁。 使用MultiExtractor,用户不仅可以探索EXE文件的内部结构,还...
1. 文件头标识:每种多媒体文件格式都有独特的文件头,通过读取文件的前几个字节,可以初步识别文件类型。 2. MIME类型:在互联网传输中,MIME类型是识别文件类型的重要方式,如audio/mpeg对应MP3,video/mp4对应...
1. **文件格式解析**:BMP文件由文件头、信息头和图像数据三部分组成。文件头包含文件的基本信息,如文件大小、创建日期等;信息头则详细描述了图像的属性,如宽度、高度、色彩深度等;图像数据则按照特定的顺序存储...
然而,对于地震数据的深度分析和交换,BMP格式并不理想,因为其体积大且不包含地震数据的元信息。这就是SEGY格式的用途所在。 SEGY(标准地震数据交换格式)是地震数据的标准存储格式,它不仅包含了地震记录,还...
- **`readBMP.c`程序**:这是一个用于读取BMP文件的示例程序,通过阅读和理解这个程序的代码逻辑,学生可以学习到如何解析BMP文件,并为进一步的信息隐藏操作打下基础。 总之,本实验旨在让学生通过实践操作深入...
本文将详细解析如何在J2EE环境中实现这一功能,主要分为两个部分:前端JavaScript控制的图片预览和后端Java处理的文件上传。 一、前端JavaScript控制的图片预览 1. 预览功能: 在HTML页面中,我们通常使用`...
- 脚本并未对文件内容进行验证,也没有对文件名进行严格的格式化检查,这导致可以上传包含恶意代码的文件。 - 此外,脚本也未能正确处理文件上传失败的情况,比如当上传的文件不是图片文件时。 5. **利用上传漏洞...
在Delphi编程环境中,处理图像是一项常见的任务,包括读取、显示、编辑和保存各种图像格式。本知识点将深入探讨如何使用Delphi获取图片类型,特别是GIF、JPG(JPEG)、ICO和BMP这些常见格式。Delphi提供了丰富的图形...
如果你不使用特定库,可以自行解析常见的图像格式,如BMP或JPEG。 2. **预处理**:可能需要将图像转换为灰度,因为Sobel算子通常应用于单通道图像。此外,确保图像数据在合适的范围内,例如0-255。 3. **应用Sobel...
1. **快速浏览**:ACDSee支持多种图片格式,如JPEG、PNG、GIF、BMP、TIFF等,能够快速打开并流畅显示大量图片,无需等待预览,极大地提高了工作效率。 2. **图像管理**:ACDSee提供了强大的图片分类和管理功能。...