C++语言基础 例程 案例:bmp文件格式剖析

贺老师的教学链接  本课讲解

附:二进制文件查看器及示例bmp文件 http://pan.baidu.com/s/1dDjf5uD

用程序读出BMP文件信息

//readbmp.h
#ifndef READBMP_H_INCLUDED
#define READBMP_H_INCLUDED

typedef unsigned char BYTE;
typedef unsigned short int UINT;
typedef short int WORD;
typedef int DWORD;
typedef long LONG;

typedef struct tagBITMAPFILEHEADER
{
    UINT bfType; /*说明文件的类型*/
    DWORD bfSize; /*说明文件的大小*/
    UINT bfReserved1; /*保留,设置为0 */
    UINT bfReserved2; /*保留,设置为0*/
    DWORD bfOffBits; /*到图像数据的偏移量*/
} BITMAPFILEHEADER;

typedef struct tagBITMAPINFOHEADER
{
    DWORD biSize; /*BITMAPINFOHEADER结构所需要的字节数*/
    LONG biWidth; /*图像的宽度,以像素为单位*/
    LONG biHeight; /*图像的高度,以像素为单位*/
    WORD biPlanes; /*为目标设备说明位面数,其值设置为1*/
    WORD biBitCount; /*位数/像素*/
    DWORD biCompression; /*图像数据压缩的类型:不压缩,或4/8位RLE */
    DWORD biSizeImage; /*图像的大小,以字节为单位。*/
    LONG biXPelsPerMeter; /*水平分辨率,用像素/米表示*/
    LONG biYPelsPerMeter; /*垂直分辨率,用像素/米表示*/
    DWORD biClrUsed; /*位图使用的彩色表中的颜色索引数:2/16/256/224*/
    DWORD biClrImportant; /*对图像显示有重要影响的颜色索引的数目,如果是0,表示都重要*/
} BITMAPINFOHEADER;

typedef struct tagRGBQUAD   /* rgbq */
{
    BYTE rgbBlue; /*指定蓝色强度*/
    BYTE rgbGreen; /*指定绿色强度*/
    BYTE rgbRed; /*指定红色强度*/
    BYTE rgbReserved; /*保留,设置为0 */
} RGBQUAD;

typedef struct tagBITMAPINFO
{
    BITMAPINFOHEADER bmiHeader; // 位图信息头
    RGBQUAD bmiColors[16]; // 颜色表
} BITMAPINFO;

//像素信息
typedef unsigned char IMAGEDATA;

#endif // READBMP_H_INCLUDED

//main.cpp
#include "readbmp.h"
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <iostream>
#include <fstream>
using namespace std;

//变量定义
BITMAPFILEHEADER bmpHeader;   //文件头
BITMAPINFOHEADER bmpInfoHeader;     //文件信息头
RGBQUAD *colorTable; //彩色表
IMAGEDATA *bmpData;

int main()
{
    char bmpFileName[80]="bmp16bit.bmp";//bmp文件名
    ifstream bmpFile(bmpFileName, ios::in|ios::binary);
    if(!bmpFile)
    {
        cerr<<"open error!"<<endl;
        exit(1);//退出程序
    }
    /* 读出位图头 */
    //由于“内存对齐问题(这部分为14字节),无法一次性读入所有信息,此处逐个取出成员
    bmpFile.read((char*)&bmpHeader.bfType, sizeof(bmpHeader.bfType));
    bmpFile.read((char*)&bmpHeader.bfSize, sizeof(bmpHeader.bfSize));
    bmpFile.read((char*)&bmpHeader.bfReserved1, sizeof(bmpHeader.bfReserved1));
    bmpFile.read((char*)&bmpHeader.bfReserved1, sizeof(bmpHeader.bfReserved2));
    bmpFile.read((char*)&bmpHeader.bfOffBits, sizeof(bmpHeader.bfOffBits));
    /* 显示位图头 */
    if(0x4d42!=bmpHeader.bfType)  //前两个字符BM,其ASCII码合成0x4d42,应该是固定的
    {
        cerr<<"not a bmp file!"<<endl;
        exit(1);
    }
    cout<<"位图文件头:"<<endl;
    cout<<"文件类型: BM"<<endl;
    cout<<"文件大小:"<<hex<<bmpHeader.bfSize<<endl;  //hex:用16进制输出
    cout<<"保留字_1:"<<bmpHeader.bfReserved1<<endl;
    cout<<"保留字_2:"<<bmpHeader.bfReserved2<<endl;
    cout<<"实际位图数据的偏移字节数:"<<hex<<bmpHeader.bfOffBits<<endl<<endl;

    /* 读出位图信息 */
    bmpFile.read((char*)&bmpInfoHeader, sizeof(bmpInfoHeader));
    /* 显示位图信息 */
    cout<<"位图信息头:"<<endl;
    cout<<"结构体的长度:"<<bmpInfoHeader.biSize<<endl;
    cout<<"位图宽:"<<bmpInfoHeader.biWidth<<endl;
    cout<<"位图高:"<<bmpInfoHeader.biHeight<<endl;
    cout<<"biPlanes平面数:"<<bmpInfoHeader.biPlanes<<endl;
    cout<<"biBitCount采用颜色位数:"<<bmpInfoHeader.biBitCount<<endl;
    cout<<"压缩方式:"<<bmpInfoHeader.biCompression<<endl;
    cout<<"biSizeImage实际位图数据占用的字节数:"<<bmpInfoHeader.biSizeImage<<endl;
    cout<<"X方向分辨率:"<<bmpInfoHeader.biXPelsPerMeter<<endl;
    cout<<"Y方向分辨率:"<<bmpInfoHeader.biYPelsPerMeter<<endl;
    cout<<"使用的颜色数:"<<bmpInfoHeader.biClrUsed<<endl;
    cout<<"重要颜色数:"<<bmpInfoHeader.biClrImportant<<endl<<endl;

    /*biClrUsed指定本图象实际用到的颜色数,如果该值为零,则用到的颜色数为2^biBitCount*/
    int colorNum = bmpInfoHeader.biClrUsed;
    if(0==colorNum)
    {
        colorNum = pow(2, bmpInfoHeader.biBitCount);
    }
    colorTable = new RGBQUAD[colorNum];

    /* 读取彩色表并显示  */
    cout<<"所用颜色(R:G:B)"<<endl;
    int i;
    for(i=0; i<colorNum; i++)
    {
        bmpFile.read((char*)&colorTable[i].rgbBlue, 1);
        bmpFile.read((char*)&colorTable[i].rgbGreen, 1);
        bmpFile.read((char*)&colorTable[i].rgbRed, 1);
        bmpFile.read((char*)&colorTable[i].rgbReserved, 1);
        cout<<dec<<"["<<i<<"]="<<hex<<int(colorTable[i].rgbRed);
        cout<<":"<<int(colorTable[i].rgbGreen);
        cout<<":"<<int(colorTable[i].rgbBlue)<<endl;
    }
    cout<<endl;

    /*读取像素信息*/
    bmpData = new unsigned char[bmpInfoHeader.biSizeImage];
    bmpFile.read((char*)bmpData, bmpInfoHeader.biSizeImage);

    /显示像素信息:下面的显示只提取了数据。BMP中的像素信息是从右上到左上存储,在显示图像时还需要要做处理*/
    /*牵涉到每像素几位-bmpInfoHeader.biBitCount-的问题,下面的代码,有点小绕*/
    int w, h;
    cout<<"下面是像素信息:"<<endl;
    for(h=0; h<bmpInfoHeader.biHeight; ++h)
    {
        cout<<"["<<setw(2)<<h<<"]: ";
        for(w=0; w < bmpInfoHeader.biSizeImage / bmpInfoHeader.biHeight; ++w)
        {
            cout<<setw(2)<<int(*(bmpData+h*bmpInfoHeader.biHeight*bmpInfoHeader.biBitCount/8+w))<<" ";
        }
        cout<<endl;
    }
    /*本程序只读出了位图信息,要显示出来,需要调用输出设备的功能了,此处略过*/
    delete[] bmpData;
    delete[] colorTable;
    return 0;
}
时间: 2024-07-30 08:49:08

C++语言基础 例程 案例:bmp文件格式剖析的相关文章

C++语言基础 例程 案例:MyVector类的设计

贺老师的教学链接  本课讲解 //MyVector类的设计 #include <iostream> using namespace std; class MyVector //定义向量类 { public: MyVector(int m); //构造函数,共有m个元素的向量,元素值预置为0 MyVector(const MyVector &v); //复制构造函数 ~MyVector(); //析构函数:释放动态数组所占用的存储空间 friend istream &operat

C++语言基础 例程 案例:Time类的设计

贺老师的教学链接  本课讲解 #include <iostream> using namespace std; class CTime { private: unsigned short int hour; // 时 unsigned short int minute; // 分 unsigned short int second; // 秒 public: CTime(int h=0,int m=0,int s=0); void setTime(int h,int m,int s); //输

C++语言基础 例程 案例:一个接口,多种方法

贺老师的教学链接  本课讲解 用指针输出几何体 #include <iostream> using namespace std; class Point { public: Point(double x=0,double y=0); friend ostream & operator<<(ostream &,const Point &); protected: double x,y; }; Point::Point(double a,double b):x(

C++语言基础 例程 二进制文件应用案例

贺老师的教学链接  本课讲解 系统升级第一步:转换现有数据格式(附:数据文件点击打开链接) #include <iostream> #include <fstream> #include <cstdlib> using namespace std; typedef struct { int NO; char name[8]; int chinese; int math; int english; int Comprehensive; int total; } Stude

C++语言基础 例程 重载单目运算符

贺老师的教学链接  本课讲解 示例1:分数类对象的相反数 class CFraction { private: int nume; // 分子 int deno; // 分母 public: CFraction(int nu=0,int de=1):nume(nu),deno(de) {} CFraction operator-(const CFraction &c); //两个分数相减,结果要化简 CFraction operator-(); //取反一目运算 }; // 分数相减 CFrac

C++语言基础 例程 虚析构函数

贺老师的教学链接  本课讲解 问题的由来 #include <iostream> using namespace std; class Point { public: Point( ) { } ~Point() { cout<<"executing Point destructor"<<endl; } }; class Circle:public Point { public: Circle( ) { } ~Circle( ) { cout<&

C++语言基础 例程 应用系统开发:银行储蓄系统

贺老师的教学链接  本课讲解 说明:(1)下面的代码,只演示了利用链表作为存储结构的可选处理方法,本讲提到的其他方面的拓展,请感兴趣做下去的同学自行使用相关技术组合起来,形成一个完整的系统.(2)运行程序,登录用户名和密码,请阅读程序,从程序中找出.建议建立多文件项目,将代码拷贝到IDE中看.(3)本程序由我的2011级学生刘镇参加企业组织的实训中完成,原文在:点击打开链接 Record.h #ifndef HEADER_RECORD //条件编译 #define HEADER_RECORD #

C++语言基础 例程 C++中的输入和输出

贺老师的教学链接 程序将自行识别符号 #include <iostream> using namespace std; int main() { int a,b; char op; cin>>a>>op>>b cout<<"result: "<<'\n'; cout<<"a: "<<a<<'\n'; cout<<"b: "<

C++语言基础 例程 重载流插入运算符和流提取运算符

贺老师的教学链接  本课讲解 重载流插入运算符"<<" #include <iostream> using namespace std; class Complex { public: Complex( ) { real=0; imag=0; } Complex(double r,double i) { real=r; imag=i; } Complex operator + (Complex &c2); //运算符"+"重载为成员函