?? cdib.cpp
字號:
//cdib.cpp
#include "StdAfx.h"
#include "cdib.h"
IMPLEMENT_SERIAL(CDib,CObject,0);
/***********************************************************
* \函數名稱:
* CDib()
* \輸入參數:
* 無
* \返回值:
* 無
* \說明:
* 構造函數
*************************************************************
*/
CDib::CDib()
{
m_hFile = NULL;
m_hBitmap = NULL;
m_hPalette = NULL;
m_nBmihAlloc = m_nImageAlloc = noAlloc;
Empty();
}
/***********************************************************
* \函數名稱:
* CDib()
* \輸入參數:
* CSize size -位圖尺寸
* int nBitCount -像素位數
* \返回值:
* 無
* \說明:
* 構造函數
* 根據給定尺寸和像素位數構造CDib對象,并對信息頭和調色板分配內存
* 但并沒有給位圖數據分配內存
************************************************************
*/
CDib::CDib(CSize size,int nBitCount)
{
m_hFile = NULL;
m_hBitmap = NULL;
m_hPalette = NULL;
m_nBmihAlloc = m_nImageAlloc = noAlloc;
Empty();
ComputePaletteSize(nBitCount); //根據像素位數計算調色板尺寸
//分配DIB信息頭和調色板的內存
m_lpBMIH = (LPBITMAPINFOHEADER)new char[sizeof(BITMAPINFOHEADER)
+ sizeof(RGBQUAD) * m_nColorTableEntries];
m_nBmihAlloc = crtAlloc; //設置信息頭內存分配狀態
//設置信息頭中的信息
m_lpBMIH->biSize = sizeof(BITMAPINFOHEADER);
m_lpBMIH->biWidth = size.cx;
m_lpBMIH->biHeight = size.cy;
m_lpBMIH->biPlanes = 1;
m_lpBMIH->biBitCount = nBitCount;
m_lpBMIH->biCompression = BI_RGB;
m_lpBMIH->biSizeImage = 0;
m_lpBMIH->biXPelsPerMeter = 0;
m_lpBMIH->biYPelsPerMeter = 0;
m_lpBMIH->biClrUsed = m_nColorTableEntries;
m_lpBMIH->biClrImportant = m_nColorTableEntries;
ComputeMetrics(); //計算圖像數據內存的大小,并設置DIB的調色板的指針
//將此DIB的調色板初始化為0
memset(m_lpvColorTable,0,sizeof(RGBQUAD) * m_nColorTableEntries);
//暫時不分配圖像數據內存
m_lpImage = NULL;
}
/***********************************************************
* \函數名稱:
* ~CDib()
* \輸入參數:
* 無
* \返回值:
* 無
* \說明:
* 析構函數,并釋放所有分配的DIB內存
************************************************************
*/
CDib::~CDib()
{
Empty();
}
/***********************************************************
* \函數名稱:
* Read()
* \輸入參數:
* CFile* pFile -指向CFile對象的指針
* \返回值:
* BOOL -如果成功,則返回TRUE
* \說明:
* 該函數從一個文件讀入CDib對象,該文件必須成功打開。
* 如果該文件是BMP,讀取工作從文件頭開始;如果是一個文檔,讀取工作則從當前文件指針處開始
************************************************************
*/
BOOL CDib::Read(CFile* pFile)
{
Empty(); //釋放已經分配的內存
//臨時存放信息的變量
int nCount,nSize;
BITMAPFILEHEADER bmfh;
//進行讀操作
try
{
//讀取文件頭
nCount = pFile->Read((LPVOID)&bmfh,sizeof(BITMAPFILEHEADER));
if(nCount!=sizeof(BITMAPFILEHEADER)){
throw new CException;
}
//如果文件類型部位"BM",則返回并進行相應錯誤處理
if(bmfh.bfType!=0x4d42){
throw new CException;
}
//計算信息頭加上調色板的大小,并分配內存
nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
m_lpBMIH = (LPBITMAPINFOHEADER)new char[nSize];
m_nBmihAlloc=m_nImageAlloc=crtAlloc;
//讀取信息頭和調色板
nCount = pFile->Read(m_lpBMIH,nSize);
//計算圖像數據大小并設置調色板指針
ComputeMetrics();
//計算調色板的表項數
ComputePaletteSize(m_lpBMIH->biBitCount);
//如果DIB存在調色板,則創建一個Windows調色板
MakePalette();
//分配圖像數據內存,并從文件中讀取圖像數據
m_lpImage = (LPBYTE)new char[m_dwSizeImage];
nCount = pFile->Read(m_lpImage,m_dwSizeImage);
}
//錯誤處理
catch(CException* pe)
{
AfxMessageBox("Read error");
pe->Delete();
return FALSE;
}
//返回
return TRUE;
}
/***********************************************************
* \函數名稱:
* ReadSection()
* \輸入參數:
* CFile* pFile -指向CFile對象的指針,對應的磁盤文件中包含DIB
* CDC* pDC -設備上下文指針
* \返回值:
* BOOL -如果成功,則返回TRUE
* \說明:
* 該函數從BMP文件中讀取信息頭,調用CreateDIBSection來分配圖像內存,然后將圖像從該文件
* 讀入剛分配的內存。如果你想從磁盤讀取一個DIB,然后通過調用GDI函數編輯它的話,
* 可以使用該函數。你可以用Write或CopyToMapFile將DIB寫回到磁盤
************************************************************
*/
BOOL CDib::ReadSection(CFile* pFile,CDC* pDC/* = NULL*/)
{
Empty(); //釋放已經分配的內存
//臨時存放信息的變量
int nCount,nSize;
BITMAPFILEHEADER bmfh;
//進行讀操作
try
{
//讀取文件頭
nCount = pFile->Read((LPVOID)&bmfh,sizeof(BITMAPFILEHEADER));
if(nCount!=sizeof(BITMAPFILEHEADER)){
throw new CException;
}
//如果文件類型部位"BM",則返回并進行相應錯誤處理
if(bmfh.bfType!=0x4d42){
throw new CException;
}
//計算信息頭加上調色板的大小,并分配內存
nSize = bmfh.bfOffBits - sizeof(BITMAPFILEHEADER);
m_lpBMIH = (LPBITMAPINFOHEADER)new char[nSize];
m_nBmihAlloc=crtAlloc;
m_nImageAlloc=noAlloc;
//讀取信息頭和調色板
nCount = pFile->Read(m_lpBMIH,nSize);
//如果圖像為壓縮格式,則不進行后續處理
if(m_lpBMIH->biCompression!=BI_RGB){
throw new CException;
}
//計算圖像數據大小并設置調色板指針
ComputeMetrics();
//計算調色板的表項數
ComputePaletteSize(m_lpBMIH->biBitCount);
//如果DIB存在調色板,則創建一個Windows調色板
MakePalette();
//將CDib對象的邏輯調色板選人設備上下文
UsePalette(pDC);
//創建一個DIB段,并分配圖像內存
m_hBitmap = ::CreateDIBSection(pDC->GetSafeHdc(),(LPBITMAPINFO)m_lpBMIH,
DIB_RGB_COLORS,(LPVOID*)&m_lpImage,NULL,0);
ASSERT(m_lpImage!=NULL);
//從文件中讀取圖像數據
nCount = pFile->Read(m_lpImage,m_dwSizeImage);
}
//錯誤處理
catch(CException* pe)
{
AfxMessageBox("Read error");
pe->Delete();
return FALSE;
}
//返回
return TRUE;
}
/***********************************************************
* \函數名稱:
* Write()
* \輸入參數:
* CFile* pFile -指向CFile對象的指針
* \返回值:
* BOOL -如果成功,則返回TRUE
* \說明:
* 該函數把DIB從CDib對象寫進文件,該文件必須成功打開或者創建
************************************************************
*/
BOOL CDib::Write(CFile* pFile)
{
BITMAPFILEHEADER bmfh;
//設置文件頭中文件類型為"BM"
bmfh.bfType = 0x4d42;
//計算信息頭和調色板的大小尺寸
int nSizeHdr = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * m_nColorTableEntries;
//設置文件頭信息
bmfh.bfSize = sizeof(BITMAPFILEHEADER) + nSizeHdr + m_dwSizeImage;
bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+
sizeof(RGBQUAD) * m_nColorTableEntries;
//進行寫操作
try{
pFile->Write((LPVOID)&bmfh,sizeof(BITMAPFILEHEADER));
pFile->Write((LPVOID)m_lpBMIH,nSizeHdr);
pFile->Write((LPVOID)m_lpImage,m_dwSizeImage);
}
//錯誤處理
catch(CException* pe){
pe->Delete();
AfxMessageBox("write error");
return FALSE;
}
//返回
return TRUE;
}
/***********************************************************
* \函數名稱:
* Serialize()
* \輸入參數:
* CArchive& ar -指向應用程序歸檔對象
* \返回值:
* 無
* \說明:
* 該函數進行串行化過程,將CDib數據進行讀入或寫出
************************************************************
*/
void CDib::Serialize(CArchive& ar)
{
DWORD dwPos;
//獲得此歸檔文件的CFile對象指針
dwPos = ar.GetFile()->GetPosition();
TRACE("CDib::Serialize--pos = %d\n",dwPos);
//從歸檔文件緩沖區中沖掉未寫入數據
ar.Flush();
//重新獲得此歸檔文件的CFile對象指針
dwPos = ar.GetFile()->GetPosition();
TRACE("CDib::Serialize--pos = %d\n",dwPos);
//確定歸檔文件是否被存儲,是則進行存儲
if(ar.IsStoring()){
Write(ar.GetFile());
}
//否則進行加載
else{
Read(ar.GetFile());
}
}
/***********************************************************
* \函數名稱:
* GetDibSaveDim()
* \輸入參數:
* 無
* \返回值:
* CSize -DIB實際存儲的高度和寬度
* \說明:
* 該函數用來得到dib的實際存儲寬度(DWORD對齊)
************************************************************
*/
CSize CDib::GetDibSaveDim()
{
CSize sizeSaveDim;
sizeSaveDim.cx = (m_lpBMIH->biWidth * m_lpBMIH->biBitCount + 31)/32*4;
sizeSaveDim.cy = m_lpBMIH->biHeight;
return sizeSaveDim;
}
/***********************************************************
* \函數名稱:
* GetDimensions()
* \輸入參數:
* 無
* \返回值:
* CSize -DIB的高度和寬度
* \說明:
* 該函數返回以像素表示的dib的寬度和高度
************************************************************
*/
CSize CDib::GetDimensions()
{
if(m_lpBMIH == NULL) return CSize(0,0);
return CSize((int)m_lpBMIH->biWidth,(int)m_lpBMIH->biHeight);
}
/***********************************************************
* \函數名稱:
* GetPixel()
* \輸入參數:
* int x -像素在X軸的坐標
* int y -像素在Y軸的坐標
* \返回值:
* RGBQUAD -返回DIB在該點真實的顏色
* \說明:
* 該函數得到DIB圖像在該點真實的顏色
************************************************************
*/
RGBQUAD CDib::GetPixel(int x, int y)
{
RGBQUAD cColor;
//CPalette* pPaletteTemp;
switch(m_lpBMIH->biBitCount)
{
case 1:
if(1<<(7-x%8)&*(LPBYTE)(m_lpImage + GetPixelOffset(x,y)))
{
cColor.rgbBlue = 255;
cColor.rgbGreen = 255;
cColor.rgbRed = 255;
cColor.rgbReserved =0;
}
else
{
cColor.rgbBlue = 0;
cColor.rgbGreen = 0;
cColor.rgbRed = 0;
cColor.rgbReserved = 0;
}
break;
case 4:
{
int nIndex = (*(LPBYTE)(m_lpImage + GetPixelOffset(x,y))&
(x%2?0x0f:0xf0))>>(x%2?0:4);
LPRGBQUAD pDibQuad = (LPRGBQUAD)(m_lpvColorTable) + nIndex;
cColor.rgbBlue = pDibQuad->rgbBlue;
cColor.rgbGreen = pDibQuad->rgbGreen;
cColor.rgbRed = pDibQuad->rgbRed;
cColor.rgbReserved = 0;
}
break;
case 8:
{
int nIndex = *(BYTE*)(m_lpImage + GetPixelOffset(x,y));
LPRGBQUAD pDibQuad = (LPRGBQUAD)(m_lpvColorTable) + nIndex;
cColor.rgbBlue = pDibQuad->rgbBlue;
cColor.rgbGreen = pDibQuad->rgbGreen;
cColor.rgbRed = pDibQuad->rgbRed;
cColor.rgbReserved = 0;
}
break;
default:
int nIndex = *(BYTE*)(m_lpImage + GetPixelOffset(x,y));
cColor.rgbBlue = m_lpImage[nIndex];
cColor.rgbGreen = m_lpImage[nIndex+1];
cColor.rgbRed = m_lpImage[nIndex+2];
cColor.rgbReserved = 0;
break;
}
return cColor;
}
/***********************************************************
* \函數名稱:
* GetPixelOffset()
* \輸入參數:
* int x -像素在X軸的坐標
* int y -像素在Y軸的坐標
* \返回值:
* int -返回像素在圖像數據塊中的真實地址
* \說明:
* 由于DIB結構中對圖像數據排列的方式從下到上,從左到右的,所以需要轉換
************************************************************
*/
LONG CDib::GetPixelOffset(int x, int y)
{
CSize sizeSaveDim;
sizeSaveDim =GetDibSaveDim();
LONG lOffset = (LONG)(sizeSaveDim.cy - y - 1) * sizeSaveDim.cx +
x/(8/m_lpBMIH->biBitCount);
return lOffset;
}
/***********************************************************
* \函數名稱:
* PaletteSize()
* \輸入參數:
* 無
* \返回值:
* DWORD -返回調色板的尺寸
* \說明:
* 該函數計算調色板所需的尺寸
************************************************************
*/
WORD CDib::PaletteSize()
{
//臨時變量
WORD NumColors;
LPBITMAPINFOHEADER lpbi = m_lpBMIH;
//如果biClrUsed為零,且圖像像素位數<8,則計算調色板用到的表項數
NumColors = ((lpbi)->biClrUsed == 0&&(lpbi)->biBitCount<=8
?(int)(1<<(int)(lpbi)->biBitCount):(int)(lpbi)->biClrUsed);
//根據顏色表表示的字節數計算調色板的尺寸
if(lpbi->biSize == sizeof(BITMAPCOREHEADER))
return NumColors * sizeof(RGBTRIPLE);
else
return NumColors * sizeof(RGBQUAD);
}
/***********************************************************
* \函數名稱:
* IsEmpty()
* \輸入參數:
* 無
* \返回值:
* BOOL -如果為空,則返回TRUE
* \說明:
* 判斷信息頭和圖像數據是否為空
************************************************************
*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -