#pragma once
#include<afx.h>
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<iostream>
#include<math.h>
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;
//图像数据
}