?? dib.cpp
字號(hào):
// Dib.cpp: implementation of the CDib class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "direction2.h"
#include "Dib.h"
#include <io.h>
#include <errno.h>
#include <math.h>
#include <direct.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CDib::CDib()
{
m_hDib=NULL; //為圖句柄
m_bIsImageMap=FALSE; //是否設(shè)計(jì)地圖范圍
m_dScale=0.0; //原始圖的比例 遲
m_x1=m_y1=0.0;
m_x2=m_y2=0.0; //圖的范圍
}
CDib::~CDib()
{
if(m_hDib != NULL)
{
//釋放內(nèi)存
::GlobalFree((HGLOBAL) m_hDib);
m_hDib=NULL;
}
if(m_Pal.GetSafeHandle())
{
m_Pal.DeleteObject();
}
}
//Dib 文件頭標(biāo)志(字符串“BM”,寫DIB實(shí)用到該常數(shù))
#define DIB_HEADER_MAKER ((WORD) ('m'<<8) | 'B')
///////該函數(shù)主要用來繪制DIB對(duì)象。其中調(diào)用了StretchDIBits()或者
//SetDIBitsToDive()來繪制DIB 。輸出的設(shè)備有參數(shù)hDC指定;繪制的矩形區(qū)域
//有參數(shù)lpDIBRect指定
/**************/
BOOL CDib::PaintDIB(HDC hDC,LPRECT lpDCRect,LPRECT lpDIBRect)
{
LPTSTR lpDIBHdr; //BITMAPINFOHEADE指針
LPTSTR lpDIBBits; //DIB像素指針
BOOL bSuccess= FALSE; //成功標(biāo)志
HPALETTE hPal=NULL; //DIB調(diào)色板
HPALETTE hOldPal=NULL; //以前的調(diào)色板
//判斷DIB對(duì)象是否為空
if(m_hDib == NULL)
{
//返回
return FALSE;
}
//鎖定DIB
lpDIBHdr = (LPTSTR) :: GlobalLock((HGLOBAL) m_hDib);
//找到DIB圖像像素起始位置
lpDIBBits= FindDIBBits(lpDIBHdr);
//獲取DIB調(diào)色板,并選中它
if(m_Pal.m_hObject != NULL)
{
hPal = (HPALETTE) m_Pal.m_hObject;
//選中調(diào)色板
hOldPal=::SelectPalette(hDC,hPal,TRUE);
}
///設(shè)計(jì)顯示模式
::SetStretchBltMode(hDC,COLORONCOLOR);
//判斷是調(diào)用StretchDIBits()還是 SetDIBitsToDevice()來繪制DIB對(duì)象
if((RECTWIDTH(lpDCRect) == RECTWIDTH(lpDIBRect)) && (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))
{
//原始大小,不用拉伸。
bSuccess=::SetDIBitsToDevice(hDC,lpDCRect->left,lpDCRect->top,RECTWIDTH(lpDCRect),RECTHEIGHT(lpDCRect),lpDIBRect->left,(int)DIBHeight(lpDIBHdr) - lpDIBRect->top - RECTHEIGHT(lpDIBRect),0,(WORD)DIBHeight(lpDIBHdr),lpDIBBits,LPBITMAPINFO(lpDIBHdr),DIB_RGB_COLORS);
}
else
{
bSuccess = ::StretchDIBits(hDC,lpDCRect->left,lpDCRect->top,RECTWIDTH(lpDCRect),RECTHEIGHT(lpDCRect),lpDIBRect->left,lpDIBRect->top,RECTWIDTH(lpDIBRect),RECTHEIGHT(lpDIBRect),lpDIBBits,(LPBITMAPINFO)lpDIBHdr,DIB_RGB_COLORS,SRCCOPY);
}
// 解除鎖定
::GlobalUnlock((HGLOBAL) m_hDib);
//恢復(fù)以前的調(diào)色板
if(hOldPal != NULL)
{
::SelectPalette(hDC,hOldPal,TRUE);
}
//返回
return bSuccess;
}
BOOL CDib::CreateDIBPalette(HDIB hDIB)
{
//指向邏輯調(diào)色板的指針
LPLOGPALETTE lpPal;
//邏輯調(diào)色板句柄
HANDLE hLogPal;
//調(diào)色板句柄
HPALETTE hPal = NULL;
//循環(huán)變量
int i;
//顏色表中的顏色數(shù)
WORD wNumColors;
//指向DIB的指針
LPTSTR lpbi;
//指向BITMAPINFO結(jié)構(gòu)的指針
LPBITMAPINFO lpbmi;
LPBITMAPCOREINFO lpbmc;
BOOL bWinStyleDIB;
BOOL bResult = TRUE;
if (hDIB==NULL)
{
return FALSE;
}
///鎖定DIB
lpbi = (LPTSTR) ::GlobalLock((HGLOBAL) hDIB);
lpbmi = (LPBITMAPINFO) lpbi;
lpbmc= (LPBITMAPCOREINFO) lpbi;
wNumColors = DIBNumColors(lpbi);
if(wNumColors != 0)
{
hLogPal = ::GlobalAlloc(GHND,sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*wNumColors);
if(hLogPal == 0)
{
::GlobalUnlock((HGLOBAL) hDIB);
return FALSE;
}
lpPal = (LPLOGPALETTE) ::GlobalLock((HGLOBAL) hLogPal);
lpPal->palVersion = PALVERSION;
lpPal->palNumEntries = (WORD)wNumColors;
bWinStyleDIB = IS_WIN30_DIB(lpbi);
for(i=0;i<(int)wNumColors;i++)
{
if (bWinStyleDIB)
{
lpPal->palPalEntry[i].peRed=lpbmi->bmiColors[i].rgbRed;
lpPal->palPalEntry[i].peGreen=lpbmi->bmiColors[i].rgbGreen;
lpPal->palPalEntry[i].peBlue=lpbmi->bmiColors[i].rgbBlue;
lpPal->palPalEntry[i].peFlags=0;
}
else
{
lpPal->palPalEntry[i].peRed=lpbmc->bmciColors[i].rgbtRed;
lpPal->palPalEntry[i].peGreen=lpbmc->bmciColors[i].rgbtGreen;
lpPal->palPalEntry[i].peBlue=lpbmc->bmciColors[i].rgbtBlue;
lpPal->palPalEntry[i].peFlags=0;
}
}
bResult = m_Pal.CreatePalette(lpPal);
::GlobalUnlock((HGLOBAL) hLogPal);
::GlobalFree((HGLOBAL) hLogPal);
}
::GlobalUnlock((HGLOBAL) hDIB);
//
return bResult;
}
/////////說明:該函數(shù)計(jì)算DIB中圖像的起始位置,并返回指向它 的指針
LPTSTR CDib::FindDIBBits(LPTSTR lpbi)
{
return (lpbi + *(LPDWORD)lpbi + PaletteSize(lpbi));
}
///該函數(shù)返回DIB中的圖像的寬度。對(duì)于Windows 3.0 DIB 返BITMAPINFOHEADE
///中的biWidth值,對(duì)于其他返回BITMAPCOREHEADE中的bcWidth值。
LONG CDib::DIBWidth(LPTSTR lpDIB)
{
//指向BITMAPINFO結(jié)構(gòu)的指針(win30)
LPBITMAPINFOHEADER lpbmi;
//指向BITMAPCOREHEADER的指針
LPBITMAPCOREHEADER lpbmc;
//獲取指針
lpbmi = (LPBITMAPINFOHEADER) lpDIB ;
lpbmc = (LPBITMAPCOREHEADER) lpDIB;
//返回DIB中圖像的寬度
if(IS_WIN30_DIB(lpDIB))
{
//對(duì)于Windows3,0DIB,返回lpbmi-〉biWidth
return lpbmi->biWidth;
}
else
{
//對(duì)于其他各式的DIB,返回lpbmc-〉bcWidth
return (LONG)lpbmc->bcWidth;
}
}
///說明:該函數(shù)返回DIB中的圖像的高度。對(duì)Window 3.0 DIB 返回BITMAPINFOHEADE
//中的biHeight的值;對(duì)于其他返回BITMAPCOREHEADE中的bcHeight的值
LONG CDib::DIBHeight(LPTSTR lpDIB)
{
//指向BITMAPINFO結(jié)構(gòu)的指針(win30)
LPBITMAPINFOHEADER lpbmi;
//指向BITMAPCOREHEADER的指針
LPBITMAPCOREHEADER lpbmc;
//獲取指針
lpbmi = (LPBITMAPINFOHEADER) lpDIB ;
lpbmc = (LPBITMAPCOREHEADER) lpDIB;
//返回DIB中圖像的寬度
if(IS_WIN30_DIB(lpDIB))
{
//對(duì)于Windows3,0DIB,返回lpbmi-〉biWidth
return lpbmi->biHeight;
}
else
{
//對(duì)于其他各式的DIB,返回lpbmc-〉bcWidth
return (LONG)lpbmc->bcHeight;
}
}
long CDib::GetWidth()
{
if(m_hDib == NULL)
return 0;
//鎖定DIB
LPTSTR lpDIB = (LPTSTR) ::GlobalLock((HGLOBAL) m_hDib);
//得到DIB寬度
long dwWidth = DIBWidth(lpDIB);
::GlobalUnlock((HGLOBAL) m_hDib);
return dwWidth;
}
///獲得圖像高度
long CDib::GetHeight()
{
if(m_hDib == NULL)
return 0;
//鎖定DIB
LPTSTR lpDIB = (LPTSTR) ::GlobalLock((HGLOBAL) m_hDib);
//得到DIB寬度
long dwHeight = DIBHeight(lpDIB);
::GlobalUnlock((HGLOBAL) m_hDib);
return dwHeight;
}
///說明該函數(shù)返回DIB中調(diào)色板的大小。對(duì)于Windows3.0 DIB,返回顏色數(shù)*RGBQUAD
//大小,對(duì)于其他返回顏色數(shù)目*RGBTRPKE的大小。
WORD CDib::PaletteSize(LPTSTR lpbi)
{
//計(jì)算DIB中調(diào)色板的大小
if(IS_WIN30_DIB (lpbi))
{
return (WORD) (DIBNumColors(lpbi) * sizeof(RGBQUAD));
}
else
{
return (WORD) (DIBNumColors(lpbi) * sizeof(RGBTRIPLE));
}
}
/////說明該函數(shù)返回DIB中調(diào)色板的顏色的總數(shù)。對(duì)于但色位圖,返回2,
//對(duì)于16色位圖,返回16,對(duì)于256色位圖,返回256,對(duì)于真彩色位圖(24位)沒有調(diào)色板,返回0。
WORD CDib::DIBNumColors(LPTSTR lpbi)
{
WORD wBitCount;
if(IS_WIN30_DIB(lpbi))
{
DWORD dwClrUsed;
dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed;
if(dwClrUsed !=0)
{
return (WORD)dwClrUsed;
}
}
//讀出像素的為數(shù)
if(IS_WIN30_DIB(lpbi))
{
wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
}
else
{
wBitCount = ((LPBITMAPCOREHEADER) lpbi)->bcBitCount;
}
///按照像素的為數(shù)計(jì)算顏色的數(shù)目
switch(wBitCount)
{
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
return 0;
}
}
////////該函數(shù)返回DIBBitsCount
WORD CDib::DIBBitsCount(LPTSTR lpbi)
{
WORD wBitCount;
if(IS_WIN30_DIB(lpbi))
{
wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;
}
else
{
wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
}
return wBitCount;
}
////////說明該函數(shù)復(fù)制制定的內(nèi)存區(qū)域,返回復(fù)制后的新內(nèi)存區(qū)域,出錯(cuò)時(shí)返回0。
HGLOBAL CDib::CopyHandle(HGLOBAL h)
{
if(h==NULL)
return NULL;
///獲取指定內(nèi)存的大小
DWORD dwLen=::GlobalSize((HGLOBAL) h);
///分配新的內(nèi)存空間
HGLOBAL hCopy = ::GlobalAlloc(GHND,dwLen);
//判斷分配是否成功
if(hCopy !=NULL)
{
// 鎖定
void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);
void* lp = ::GlobalLock((HGLOBAL) h);
//復(fù)制
memcpy(lpCopy,lp,dwLen);
//解除鎖定
::GlobalUnlock(hCopy);
::GlobalUnlock(h);
}
return hCopy;
}
//保存當(dāng)前位圖
BOOL CDib::SaveDIB(LPCTSTR lpszDibName)
{
HDIB hDib = m_hDib;
CFile file;
if(!file.Open(lpszDibName,CFile::modeCreate|CFile::modeReadWrite))
{
//打開文件失敗
MessageBox(NULL,_T("建立文件失敗"),_T("錯(cuò)誤"), MB_OK);
return FALSE;
}
//Bitmap文件頭
BITMAPFILEHEADER bmfHdr;
//指向BITMAPINFOHEADE的指針
LPBITMAPINFOHEADER lpBI;
//DIB大小
DWORD dwDIBSize;
if(hDib == NULL)
{
//如果DIB為空,返回FALSE
file.Close();
return FALSE;
}
//讀取BITMAPINFO 的結(jié)構(gòu),并鎖定
lpBI = (LPBITMAPINFOHEADER) ::GlobalLock((HGLOBAL) hDib);
if(lpBI == NULL)
{
//為空,返回FALSE
file.Close();
return FALSE;
}
//判斷是否是WIN3.0DIB
if(!IS_WIN30_DIB(lpBI))
{
//不支持其他類型的DIB保存
//解除鎖定
::GlobalUnlock((HGLOBAL) hDib);
file.Close();
///返回FALSE
return FALSE;
}
//填充文件頭
//文件類型“BM”
bmfHdr.bfType = DIB_HEADER_MAKER;
//計(jì)算DIB大小時(shí),最簡(jiǎn)單的方法是調(diào)用GlobalSize()函數(shù),但是全局內(nèi)存大小
//并不真正是DIB的大小,他總是多幾個(gè)字節(jié),這樣就需要計(jì)算一下DIB的真實(shí)的大小
//文件頭大小加顏色表大小
dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPTSTR) lpBI);
//計(jì)算圖像的大小
if((lpBI->biCompression == BI_RLE8)||(lpBI->biCompression== BI_RLE4))
{
//對(duì)RLE位圖,沒法計(jì)算大小,只能信任biSizeIMAGE內(nèi)的值
dwDIBSize += lpBI->biSizeImage;
}
else
{
//像素的大小
DWORD dwBmBitsSize;
//大小為Width*Height
dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD) lpBI->biBitCount))* lpBI->biHeight;
//計(jì)算出DIB真正的大小
dwDIBSize+=dwBmBitsSize;
//更新biSizeImage(很多BMP文件頭中biSizeImage的值是錯(cuò)誤的)
lpBI->biSizeImage = dwBmBitsSize;
}
//計(jì)算文件大小:DIB
bmfHdr.bfReserved1 = 0;
bmfHdr.bfReserved2 = 0;
bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + lpBI->biSize+PaletteSize((LPTSTR) lpBI);
// 嘗試寫文件
TRY
{
//寫文件頭
file.Write((LPTSTR) &bmfHdr,sizeof(BITMAPFILEHEADER));
file.WriteHuge(lpBI,dwDIBSize);
}
CATCH (CFileException,e)
{
::GlobalUnlock((HGLOBAL) hDib);
THROW_LAST();
}
END_CATCH
//
::GlobalUnlock((HGLOBAL) hDib);
file.Close();
return TRUE;
}
////說明該函數(shù)將指定的文件中的DIB對(duì)象讀到指定的內(nèi)存區(qū)域中
//BITMAPFILEHEADE外的內(nèi)容都將被讀入內(nèi)存
BOOL CDib::ReadDIBFile(LPCTSTR lpszDibName)
{
CFile file;
DWORD dwBitsSize, dwFileSize;
HDIB hDIB;
LPTSTR pDIB;
BITMAPFILEHEADER bmfHeader;
if(m_hDib != NULL)
{
//釋放 內(nèi)存
::GlobalFree((HGLOBAL) m_hDib);
m_hDib = NULL;
}
if(m_Pal.GetSafeHandle())
{
m_Pal.DeleteObject();
}
//打開文件
if(!file.Open(lpszDibName,CFile::modeRead))
{
MessageBox(NULL,_T("打開文件失敗"),_T("錯(cuò)誤"),MB_OK);
return FALSE;
}
dwFileSize = file.GetLength();
if(file.Read((LPTSTR)&bmfHeader,sizeof(bmfHeader))!=sizeof(bmfHeader))
{
file.Close();
return FALSE;
}
if(bmfHeader.bfType != DIB_HEADER_MAKER)
{
file.Close();
return FALSE;
}
dwBitsSize= bmfHeader.bfSize- sizeof(BITMAPFILEHEADER);
hDIB = (HDIB)::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT,dwBitsSize);
if(hDIB == 0)
{
file.Close();
return FALSE;
}
pDIB = (LPTSTR)::GlobalLock((HGLOBAL) hDIB);
if(file.ReadHuge(pDIB,dwBitsSize-sizeof(BITMAPFILEHEADER)) !=dwBitsSize - sizeof(BITMAPFILEHEADER))
{
file.Close();
::GlobalUnlock((HGLOBAL) hDIB);
::GlobalFree((HGLOBAL) hDIB);
return FALSE;
}
////讀地圖坐標(biāo)
if(dwFileSize != bmfHeader.bfSize)
{
file.Seek(-long(sizeof(float)*5),CFile::end);
file.Read(&m_x1,sizeof(float));
file.Read(&m_y1,sizeof(float));
file.Read(&m_x2,sizeof(float));
file.Read(&m_y2,sizeof(float));
file.Read(&m_dScale,sizeof(float));
m_bIsImageMap = TRUE;
}
file.Close();
::GlobalUnlock((HGLOBAL) hDIB);
m_hDib = hDIB;
if(!CreateDIBPalette(hDIB))
return FALSE;
return TRUE;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -