实验一 位图文件的读取与显示

合集下载
相关主题
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

实验一位图文件的读取与显示

一、实验背景

1 位图文件格式说明

位图文件格式由四部分组成,如图1所示,分别是位图文件头、位图信息头、调色板以及位图像素数据,其中调色板信息为可选信息,只有当每个像素的比特数小于或等于8(BITMAPINFOHEADER.biBitCount<=8)时才存在,即为一个颜色查找表。

需要注意的是,位图文件存储时为了提高内存访问的速度,每一行的字节数必须是4的倍数,即:如果一幅图像的宽度为253,每个像素用8bit表示,因此,该图像实际每行所占的存储空间数为253Byte,但为了与4对齐,存储时所用的存储空间为256Byte。具体而言,假设图像的宽度为w,每个像素用n比特表示,则图像每行像素所占的字节数为:

(w * n + 31)/32 * 4

图1 位图文件格式说明

2 位图文件读取

位图文件的读取包括两步:(1)根据第1节中的位图文件格式说明,对位图文件进行解析;(2)根据读取的内容创建可供显示的位图句柄。

(1)位图文件解析

//open file

FILE *fp = NULL;

fopen_s(&fp, strPath, _T("rb"));

if (fp == NULL)

{

CString str = _T("File not exist: " )+ strPath;

AfxMessageBox(str);

return NULL;

}

//bitmap file header

BITMAPFILEHEADER bmFileHeader;

fread(&bmFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);

if (bmFileHeader.bfType != 0x4d42)

{

AfxMessageBox(_T("file type is not bitmap"));

return NULL;

}

//bitmap info header

BITMAPINFO bmInfo;

BITMAPINFOHEADER &bmInfoHeader = bmInfo.bmiHeader;

fread(&bmInfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);

if (bmInfoHeader.biSize != sizeof(BITMAPINFOHEADER))

{

AfxMessageBox(_T("size of bitmap info header is inconsistent"));

return NULL;

}

//whether is compressed

if (bmInfoHeader.biCompression != BI_RGB)

{

AfxMessageBox(_T("File is compressed"));

return NULL;

}

int nPalettes = bmInfoHeader.biClrUsed;

if (nPalettes == 0 && bmInfoHeader.biBitCount <= 8)

nPalettes = 1 << bmInfoHeader.biBitCount;

if (bmFileHeader.bfOffBits != sizeof(BITMAPFILEHEADER) +

sizeof(BITMAPINFOHEADER) + nPalettes * sizeof(RGBQUAD))

{

AfxMessageBox(_T("off bits is inconsistent"));

return NULL;

}

//Palette

//RGBQUAD *pPalette = NULL;

byte *pBmInfo = NULL;

if (nPalettes > 0)

{

pBmInfo = new byte[sizeof(BITMAPINFOHEADER) + nPalettes *

sizeof(RGBQUAD)];

memcpy(pBmInfo, &bmInfoHeader, sizeof(BITMAPINFOHEADER));

byte *pPalette = pBmInfo + sizeof(BITMAPINFOHEADER);

fread(pPalette, sizeof(RGBQUAD), nPalettes, fp);

}

//line width

int nLineByte = (bmInfoHeader.biWidth * bmInfoHeader.biBitCount + 31) / 32 * 4;

//不直接使用bmInfoHeader.biSizeImage,因为图像不压缩时该字段可以为零

int nImageBytes = nLineByte * bmInfoHeader.biHeight;

//image data

byte *pContents = new byte[nImageBytes];

fread(pContents, nImageBytes, 1, fp);

(2)将读取的内容转换为Bitmap句柄

该步骤需使用系统函数CreateDIBitmap。CreateDIBitmap的函数说明如下:

HBITMAP CreateDIBitmap(HDC hdc, CONST BITMAPINFOHEADER *lpbmih, DWORD fdwlnit, CONST VOID *lpblnit, CONST BITMAPINFO *lpbmi, UINT fuUsage);

参数:

hdc:设备环境句柄。

lpbmih:指向位图信息头结构的指针,它可以是下列操作系统位图信息头之一:

Fdwlnit:位标识集。它指定系统如何对位图的位进行初始化。

CBM_INIT:如果设置了该标志,那么系统将使用lpblnit和lpbmi两个参数指向的数据来对位图中的位进行初始化。如果没有该标志,那么表示上述两个参数指向的数据无效。如果fdwlnit为0,那么系统不会对位图的位进行初始化。

lpblnit:该指针指向包含初始的位图数据的字节类型数组。数据格式与参数lpbmi指向的BITMAPINFO结构中的成员biBitCount有关。

lpbmi:指向BITMAPINFO结构的旨针。该结构描述了参数lpbmi指向的数组的维数和

相关文档
最新文档