读取BMP格式数据

#pragma once
#include
class DigitalImage 
{
private:
    //指针数据类型,需要动态分配数据大小,并初始化数据
    char m_FileName[100];

    //文件头
    LPBITMAPFILEHEADER m_lpBitmapFileHender;

    //除位图文件头的所有数据
    LPBYTE m_lpNotFileHenderData;

    //文件信息头
    LPBITMAPINFOHEADER m_lpBitmapInfoHender;
    LPBITMAPINFO m_lpBitmapInfo;
    LPRGBQUAD m_lpRgbQuad;
    
    RGBQUAD* RgbArray;
    //图像数据
    LPBYTE m_lpBmpData;

public:
    DigitalImage(char m_FileName[100]);
    ~DigitalImage();

};

#include "DigitalImage.h"
#include
#include
using namespace std;

DigitalImage::DigitalImage(char m_FileName[100])
{
    CFile RdBmp;
    if (!RdBmp.Open(m_FileName, CFile::modeRead || CFile::shareDenyWrite))
        cout << "图像文件无法打开!" << endl;

    //申请文件头内存空间,用BYTE数组存储,方便解析,并初始化为零;
    m_lpBitmapFileHender = (LPBITMAPFILEHEADER) new BYTE[sizeof(BITMAPFILEHEADER)];
    memset(m_lpBitmapFileHender, 0, sizeof(BITMAPFILEHEADER));

    //读取文件头
    int FileHenderSize=RdBmp.Read(m_lpBitmapFileHender, sizeof(BITMAPFILEHEADER));
    if(FileHenderSize!= sizeof(BITMAPFILEHEADER))
        cout << "图像文件头读取错误!" << endl;

    //判断是否是位图图像
    if (m_lpBitmapFileHender->bfType == 0x4d42)//0x4d42=="BM",与是否是高字节在前还是低字节在前有关
    {
        //读取文件信息头,文件信息头结构本身大小不变,但是结构m_lpBitmapFileHender的成员变量所指示的某些数据的大小不一样,
        //因此,在分配文件文件信息头数据成员的大小是有所不同,即m_lpBitmapFileHender和m_lpBitmapInfoHender结构的大小是一定的,
        //但是其成员变量所指示的大小可能不同,读取后续数据需要计算,这无疑增加了小白的理解困难。

        DWORD FileSize = m_lpBitmapFileHender->bfSize;//指示了位图文件总的字节数;
        cout << "图像文件总字节数:" << FileSize << endl;
        
        //思考:根据文件头信息,此处如何计算文件信息头的大小呢?
        
        DWORD of = m_lpBitmapFileHender->bfOffBits;//指示了位图数据相对于文件头的偏移量
        //答案:我们知道,文件头包含bfOffBits成员,也知道了bmp文件的大小,则可以计算到位图数据的位置

    
        //思考:此处能直接读取文件信息头吗?


        //读取出文件头之后的所有数据,如何指定所读的大小?
        DWORD NotFileHenderSize = RdBmp.GetLength() - sizeof(BITMAPFILEHEADER);//GetLength()获取文件按字节计算的长度,而不是数量;
        
        //指定除文件头后数据的总大小,并分配,初始化
        m_lpNotFileHenderData = new BYTE[NotFileHenderSize];
        memset(m_lpNotFileHenderData, 0, NotFileHenderSize);

        RdBmp.Close();

        //此处难道是根据NotFileHenderSize这个中的数据来创建文件信息头,颜色表,位图像素数据的?

        //这两个有什么有吗,文件新消息头和颜色表组成了文件信息,下面这个知道其中一个不就行了吗?
        m_lpBitmapInfoHender =(LPBITMAPINFOHEADER) m_lpNotFileHenderData;//除文件头后的数据的开始处确实就是文件信息头的起始地址。
        m_lpBitmapInfo = (LPBITMAPINFO)m_lpNotFileHenderData; //除文件头后的数据的开始处确实就是文件信息头的起始地址。


        //m_lpBitmapInfoHender,m_lpBitmapInfo指针分配完了,如何初始化他们的成员变量呢?

        //先获取到颜色表的指针吧,跟着一步一步来,看吧........,怎么计算起始位置呢?

        
        m_lpRgbQuad = (LPRGBQUAD)(m_lpNotFileHenderData + m_lpBitmapInfoHender->biSize);


        //有些图片有颜色表,有些没有,是怎么区分的呢?有的话,如何创建颜色表呢?

        if (m_lpBitmapInfoHender->biClrUsed == 0)//图像实际使用的颜色数,为零就代表没有颜色了吗
            cout << "图像没有颜色表" << endl;
        else
        {
            //有颜色表的话,如何计算颜色表的长度呢?
            int size = (int)pow(2, m_lpBitmapInfoHender->biBitCount);//biBitCount 注意,
            RgbArray = new RGBQUAD[size];
            //如何初始化颜色数组?不是读取的吗?
            for (int i = 0; i < size; i++)
            {
                RgbArray[i].rgbRed = m_lpRgbQuad->rgbRed;
                RgbArray[i].rgbGreen = m_lpRgbQuad->rgbGreen;
                RgbArray[i].rgbBlue = m_lpRgbQuad->rgbBlue;
                RgbArray[i].rgbReserved = 0;//原来这个数据没有存储图像文件中,直接读的话会导致数据会乱吗?
                m_lpRgbQuad++;
            }

            //还需要计算颜色表的字节长度啊,用于定位像素位置,难道不是颜色数吗?no......
            DWORD RgbLen = size * sizeof(RGBQUAD);//我还以为是这样,size*4

            //像素数据指针,怎么计算
            m_lpBmpData = m_lpNotFileHenderData + m_lpBitmapInfoHender->biSize + sizeof(RgbArray);
            //m_lpBmpData = m_lpNotFileHenderData + sizeof(m_lpBitmapInfo);//可以这样吗
            //m_lpBmpData = m_lpNotFileHenderData + sizeof(BITMAPINFO);//这样可以吗?什么时候能这样?

        }
    }
    else
    {
        cout << "图像文件非BMP格式 !" << endl;
    }
}


DigitalImage::~DigitalImage()
{

    //文件头
    delete[] m_lpBitmapFileHender;

    //除位图文件头的所有数据
    delete[] m_lpNotFileHenderData;

    //文件信息头
     m_lpBitmapInfoHender=NULL;
     m_lpBitmapInfo=NULL;
     m_lpRgbQuad=NULL;

    delete[] RgbArray;
    //图像数据
}
 

你可能感兴趣的:(读取BMP格式数据)