`
hzy3774
  • 浏览: 992986 次
  • 性别: Icon_minigender_1
  • 来自: 珠海
社区版块
存档分类
最新评论

BMP格式文件初步解析和显示

 
阅读更多

    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编译:

 

全部代码在附件中。

  • 大小: 210.7 KB
分享到:
评论

相关推荐

    VC++实现bmp位图打开和显示.

    - **文件读取**:熟练掌握使用C++读取文件,特别是BMP格式文件的技巧。 - **图像数据结构**:理解BMP文件结构,包括文件头、信息头和像素数据。 - **动态数据管理**:合理使用指针和动态内存分配,避免内存泄漏。 - ...

    BMP转pcb工具

    标题中的“BMP转pcb工具”指的是一个能够将位图图像(BMP格式)转换成PCB设计文件的软件。在电子设计领域,PCB(Printed Circuit Board,印制电路板)是承载电子元器件并连接它们的实体平台,而BMP是一种常见的图像...

    bmp简单验证码识别

    在这个"bmp简单验证码识别"项目中,我们主要关注的是如何处理和解析BMP格式的图像,以识别其中包含的字符。以下是这个话题涉及的主要知识点: 1. BMP格式:BMP是位图图像文件的一种格式,它存储未经压缩的像素数据...

    DICOM图像相关文档

    DICOM医学图像文件格式解析与应用研究 WINDOWS环境下DICOM医学图像显示方法的初步研究 标准医学DICOM图像的转换实现 基于DICOM的数据组织及医学图像序列提取方法研究 用二叉树实现DICOM医学图像的编码 树型结构DICOM...

    CCS3.3读取bmp图像进行处理

    首先,需要解析BMP文件头来获取图像的大小和格式信息;然后,将像素数据按行加载到内存中,可能需要进行数据格式转换,比如从RGB转换为灰度;最后,可以使用嵌入式处理器的硬件加速功能(如DMA)提高处理效率。 5. ...

    用C读取DICOM文件

    DICOM(Digital Imaging and Communications in Medicine)是一种广泛应用于医疗成像领域的标准,用于存储、传输和显示医学图像。以下是从标题“用C读取DICOM文件”和描述“读取DICOM文件的程序(纯C编写的),大家...

    图片转PCB小工具

    "图片转PCB小工具",即bmp2pcb,提供了一个简单易用的解决方案,使得设计师能够快速将BMP格式的图片转化为PCB设计文件。本文将深入探讨这个工具的特性和使用方法,以及其在实际设计中的应用。 一、bmp2pcb简介 bmp...

    EXE文件提取器

    7. **安全分析**:对于可能包含恶意代码的EXE文件,MultiExtractor可以帮助用户进行初步的安全检查,通过提取和查看其中的资源,以便发现潜在的威胁。 使用MultiExtractor,用户不仅可以探索EXE文件的内部结构,还...

    行业分类-设备装置-多媒体文件的识别方法、装置.zip

    1. 文件头标识:每种多媒体文件格式都有独特的文件头,通过读取文件的前几个字节,可以初步识别文件类型。 2. MIME类型:在互联网传输中,MIME类型是识别文件类型的重要方式,如audio/mpeg对应MP3,video/mp4对应...

    数字图像处理BMPViewer.rar

    1. **文件格式解析**:BMP文件由文件头、信息头和图像数据三部分组成。文件头包含文件的基本信息,如文件大小、创建日期等;信息头则详细描述了图像的属性,如宽度、高度、色彩深度等;图像数据则按照特定的顺序存储...

    由地震剖面图像格式生成segy地震数据的M程序image2segy.rar

    然而,对于地震数据的深度分析和交换,BMP格式并不理想,因为其体积大且不包含地震数据的元信息。这就是SEGY格式的用途所在。 SEGY(标准地震数据交换格式)是地震数据的标准存储格式,它不仅包含了地震记录,还...

    信息隐藏算法和设计

    - **`readBMP.c`程序**:这是一个用于读取BMP文件的示例程序,通过阅读和理解这个程序的代码逻辑,学生可以学习到如何解析BMP文件,并为进一步的信息隐藏操作打下基础。 总之,本实验旨在让学生通过实践操作深入...

    j2ee里图片上传及预览的实现

    本文将详细解析如何在J2EE环境中实现这一功能,主要分为两个部分:前端JavaScript控制的图片预览和后端Java处理的文件上传。 一、前端JavaScript控制的图片预览 1. 预览功能: 在HTML页面中,我们通常使用`...

    PHPweb渗透小记.docx

    - 脚本并未对文件内容进行验证,也没有对文件名进行严格的格式化检查,这导致可以上传包含恶意代码的文件。 - 此外,脚本也未能正确处理文件上传失败的情况,比如当上传的文件不是图片文件时。 5. **利用上传漏洞...

    Delphi获取图片类型

    在Delphi编程环境中,处理图像是一项常见的任务,包括读取、显示、编辑和保存各种图像格式。本知识点将深入探讨如何使用Delphi获取图片类型,特别是GIF、JPG(JPEG)、ICO和BMP这些常见格式。Delphi提供了丰富的图形...

    边缘检测--图像处理-C语言

    如果你不使用特定库,可以自行解析常见的图像格式,如BMP或JPEG。 2. **预处理**:可能需要将图像转换为灰度,因为Sobel算子通常应用于单通道图像。此外,确保图像数据在合适的范围内,例如0-255。 3. **应用Sobel...

    ACDSee看图软件

    1. **快速浏览**:ACDSee支持多种图片格式,如JPEG、PNG、GIF、BMP、TIFF等,能够快速打开并流畅显示大量图片,无需等待预览,极大地提高了工作效率。 2. **图像管理**:ACDSee提供了强大的图片分类和管理功能。...

Global site tag (gtag.js) - Google Analytics