📄 dib.cpp
字号:
/////////////////////////////////////////////////////////////////////////////////
//
// Dib.cpp: implementation of the CDib class.
//
////////////////////////////////////////////////////////////////////////////////
// 版权所有(2002)
// Copyright(2002)
// 编写者: 向世明
// Author: Xiang Shiming
#include "stdafx.h"
#include "dib.h"
IMPLEMENT_DYNAMIC(CDib, CObject)
CDib::CDib()
{
Init();
}
CDib::CDib(const char* pszDibFileName)
{
Init();
LoadFile(pszDibFileName);
}
CDib::~CDib()
{
ClearMemory();
}
void CDib::ClearMemory()
{
if(m_hDIB != NULL)
::GlobalFree(m_hDIB);
m_hDIB = 0;
m_pDibData = NULL;
m_pszFileName = NULL;
m_pBitmapInfoHeader = NULL;
m_pBitmapInfo = NULL;
m_pRGBQuad = NULL;
m_pBitmapFileHeader = NULL;
}
#ifdef _DEBUG
void CDib::Dump(CDumpContext& dc) const
{
CObject::Dump(dc);
}
void CDib::AssertValid() const
{
CObject::AssertValid();
ASSERT(m_pszFileName != NULL);
ASSERT(m_hDIB != 0);
}
#endif
void CDib::Init()
{
m_pRGBQuad = NULL; //RGBQUAD 表项
m_pDibData = NULL; //位图像素数据
m_nWidth = 0; //宽度
m_nHeight = 0; //高度
m_nBitCount = 0; //每个像素占有的位数
m_nTotalColors = 0; //颜色总数
m_pBitmapFileHeader = NULL;
m_pBitmapInfoHeader = NULL;
m_pBitmapInfo = NULL;
m_hDIB = 0;
m_pszFileName = NULL;
}
void CDib::LoadFile(const char* pszDibFileName)
{
ASSERT(pszDibFileName);
//如果存在就释放内存
if(m_pBitmapInfo) ::GlobalFree(m_hDIB);
//再次初始化, 用于多次动态重用
Init();
m_pszFileName = (char*)pszDibFileName;
BITMAPFILEHEADER bitmapFileHeader;
CFile dibFile(pszDibFileName, CFile::modeRead);
try
{
//读入位图文件头信息
UINT nBFHsize = dibFile.Read((void*)&bitmapFileHeader, sizeof(BITMAPFILEHEADER));
if(nBFHsize != sizeof(BITMAPFILEHEADER))
{
m_bValid = FALSE;
return;
}
}
catch(CFileException* e)
{
e->Delete();
}
//如果为位图就进行下一步的处理
if (bitmapFileHeader.bfType == 0x4d42)
{
AfxGetApp()->BeginWaitCursor();
//文件长度
DWORD dwFileLength = dibFile.GetLength();
//位图信息及位图数据的大小(字节)
DWORD dwSize = dwFileLength - sizeof(BITMAPFILEHEADER);
//为Dib分配全局内存
m_hDIB = (HGLOBAL) ::GlobalAlloc(GMEM_MOVEABLE, dwSize);
if (m_hDIB == 0) m_bValid = FALSE;
//指向Dib实际像素数据的指针,
BYTE* pbyDib = (BYTE*)::GlobalLock(m_hDIB);
if (pbyDib == NULL) m_bValid = FALSE;
try
{
//读入内存
DWORD dwReadSize = dibFile.Read((void*)pbyDib, dwSize);
dibFile.Close();
if(dwReadSize != dwSize)
{
m_bValid = FALSE;
::GlobalUnlock(m_hDIB);
::GlobalFree(m_hDIB);
Init();
return;
}
}
catch(CFileException* e)
{
e->Delete();
}
//获取位图文件头指针和位图文件数据信息指针
m_pBitmapInfo = (BITMAPINFO*) pbyDib;
m_pBitmapInfoHeader = (BITMAPINFOHEADER*) pbyDib;
//宽度和高度
m_nWidth = m_pBitmapInfoHeader->biWidth;
m_nHeight = m_pBitmapInfoHeader->biHeight;
//每像素的颜色位数
m_nBitCount = (BYTE)m_pBitmapInfoHeader->biBitCount;
//颜色数
m_nTotalColors = GetColorNumber();
if (m_pBitmapInfoHeader->biClrUsed == 0)
m_pBitmapInfoHeader->biClrUsed = m_nTotalColors;
//指向位图颜色索引表项的指针, 如果没有颜色表项, 则该值为NULL
m_pRGBQuad = (RGBQUAD*)(pbyDib + m_pBitmapInfoHeader->biSize);
//颜色索引表的大小(字节)
DWORD dwColorTableSize = m_nTotalColors * sizeof(RGBQUAD);
//指向位图数据的指针
m_pDibData = pbyDib + m_pBitmapInfoHeader->biSize + dwColorTableSize;
//如果没有颜色索引表, 则该值为NULL
if (m_pRGBQuad == (RGBQUAD*)m_pDibData) m_pRGBQuad = NULL;
//位图的大小(面积像素单位)
m_pBitmapInfoHeader->biSizeImage = GetSize();
::GlobalUnlock(m_hDIB);
AfxGetApp()->EndWaitCursor();
m_bValid = TRUE;
}
else
{
AfxMessageBox("This is not a bitmap file!");
m_bValid = FALSE;
}
}
LONG CDib::GetWidth() const
{
return m_nWidth;
}
LONG CDib::GetHeight() const
{
return m_nHeight;
}
//获取数据缓冲区的大小
DWORD CDib::GetSize()
{
if (m_pBitmapInfoHeader->biSizeImage != 0)
return (m_pBitmapInfoHeader->biSizeImage);
else
return (DWORD)GetDibWidthBytes(m_nWidth, 24) * (DWORD)m_nHeight;
}
BYTE CDib::GetBitCount() const
{
return m_nBitCount;
}
UINT CDib::GetColorNumber() const
{
UINT nColors = 0;
if ((m_pBitmapInfoHeader->biClrUsed == 0) &&
(m_pBitmapInfoHeader->biBitCount < 9))
{
switch (m_pBitmapInfoHeader->biBitCount)
{
case 1: nColors = 2; break;
case 4: nColors = 16; break;
case 8: nColors = 256;break;
}
}
else
nColors = (UINT) m_pBitmapInfoHeader->biClrUsed;
return nColors;
}
char* CDib::GetFileName() const
{
return m_pszFileName;
}
BYTE* CDib::GetDibData() const
{
return m_pDibData;
}
RGBQUAD* CDib::GetRGBQuad() const
{
return m_pRGBQuad;
}
BITMAPINFO* CDib::GetBmpInfo() const
{
return m_pBitmapInfo;
}
BOOL CDib::IsValid() const
{
return m_bValid;
}
//每行的字节宽度
DWORD CDib::GetDibWidthBytes(int nWidth, BYTE byBitCount)
{
DWORD dwWidthBytes = (DWORD)nWidth; //8-bits
if(byBitCount == 1) dwWidthBytes = (nWidth + 7) / 8;
else if(byBitCount == 4) dwWidthBytes = (nWidth + 1) / 2;
else if(byBitCount == 24) dwWidthBytes = 3 * nWidth ;
while((dwWidthBytes & 3) != 0)dwWidthBytes++;
return dwWidthBytes;
}
//将所有格式的数据转换成DDB--24位数据, 存放于lpbyDdb24
//返回获取数据的总数.
DWORD CDib::GetDdbData24(LPBYTE lpbyDdb24)
{
ASSERT(lpbyDdb24);
//计算DIB位图中一行的字节量
DWORD dwDibWidthBytes = GetDibWidthBytes(m_nWidth, m_nBitCount);
//转换成24位DDB后每行的大小, 注意每行的字节数只需要是偶数即可
DWORD dwDdbWidthBytes = ((m_nWidth * 24 + 15) / 16) * 2;
if(m_nBitCount == 1)
{
//每行实际字节数, 8个像素对应一个字节.
LONG nLineBytes = (m_nWidth + 7) / 8;
BYTE abyBitMask[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
//DIB位图数据的行头
DWORD dwDibBaseIndex = (m_nHeight - 1) * dwDibWidthBytes;
//DDB 24位位图数据的行头
DWORD dwDdbBaseIndex = 0;
for(LONG i = 0;i < m_nHeight;i++)
{
//指向DIB行数据的指针
BYTE* pbyDibRaw = m_pDibData + dwDibBaseIndex;
//指向 DDB 24位位图的数据的指针
BYTE* pbyDdbRaw = lpbyDdb24 + dwDdbBaseIndex;
for(LONG j = 0;j < nLineBytes;j++)
{
//8个像素数据的索引值
BYTE byBit8 = *(pbyDibRaw++);
for(int n = 0; n < 8;n++)
{
BYTE byBitSingle = (byBit8 & abyBitMask[n]) >> (7 - n);
*(pbyDdbRaw++) = m_pRGBQuad[byBitSingle].rgbBlue; //蓝色
*(pbyDdbRaw++) = m_pRGBQuad[byBitSingle].rgbGreen; //绿色
*(pbyDdbRaw++) = m_pRGBQuad[byBitSingle].rgbRed; //红色
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -