📄 dib.cpp
字号:
// 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; //是否设计地图范围
m_dScale=0.0; //原始图的比例 迟
m_x1=m_y1=0.0;
m_x2=m_y2=0.0; //图的范围
}
CDib::~CDib()
{
if(m_hDib != NULL)
{
//释放内存
::GlobalFree((HGLOBAL) m_hDib);
m_hDib=NULL;
}
if(m_Pal.GetSafeHandle())
{
m_Pal.DeleteObject();
}
}
//Dib 文件头标志(字符串“BM”,写DIB实用到该常数)
#define DIB_HEADER_MAKER ((WORD) ('m'<<8) | 'B')
///////该函数主要用来绘制DIB对象。其中调用了StretchDIBits()或者
//SetDIBitsToDive()来绘制DIB 。输出的设备有参数hDC指定;绘制的矩形区域
//有参数lpDIBRect指定
/**************/
BOOL CDib::PaintDIB(HDC hDC,LPRECT lpDCRect,LPRECT lpDIBRect)
{
LPTSTR lpDIBHdr; //BITMAPINFOHEADE指针
LPTSTR lpDIBBits; //DIB像素指针
BOOL bSuccess= FALSE; //成功标志
HPALETTE hPal=NULL; //DIB调色板
HPALETTE hOldPal=NULL; //以前的调色板
//判断DIB对象是否为空
if(m_hDib == NULL)
{
//返回
return FALSE;
}
//锁定DIB
lpDIBHdr = (LPTSTR) :: GlobalLock((HGLOBAL) m_hDib);
//找到DIB图像像素起始位置
lpDIBBits= FindDIBBits(lpDIBHdr);
//获取DIB调色板,并选中它
if(m_Pal.m_hObject != NULL)
{
hPal = (HPALETTE) m_Pal.m_hObject;
//选中调色板
hOldPal=::SelectPalette(hDC,hPal,TRUE);
}
///设计显示模式
::SetStretchBltMode(hDC,COLORONCOLOR);
//判断是调用StretchDIBits()还是 SetDIBitsToDevice()来绘制DIB对象
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);
//恢复以前的调色板
if(hOldPal != NULL)
{
::SelectPalette(hDC,hOldPal,TRUE);
}
//返回
return bSuccess;
}
BOOL CDib::CreateDIBPalette(HDIB hDIB)
{
//指向逻辑调色板的指针
LPLOGPALETTE lpPal;
//逻辑调色板句柄
HANDLE hLogPal;
//调色板句柄
HPALETTE hPal = NULL;
//循环变量
int i;
//颜色表中的颜色数
WORD wNumColors;
//指向DIB的指针
LPTSTR lpbi;
//指向BITMAPINFO结构的指针
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;
}
/////////说明:该函数计算DIB中图像的起始位置,并返回指向它 的指针
LPTSTR CDib::FindDIBBits(LPTSTR lpbi)
{
return (lpbi + *(LPDWORD)lpbi + PaletteSize(lpbi));
}
///该函数返回DIB中的图像的宽度。对于Windows 3.0 DIB 返BITMAPINFOHEADE
///中的biWidth值,对于其他返回BITMAPCOREHEADE中的bcWidth值。
LONG CDib::DIBWidth(LPTSTR lpDIB)
{
//指向BITMAPINFO结构的指针(win30)
LPBITMAPINFOHEADER lpbmi;
//指向BITMAPCOREHEADER的指针
LPBITMAPCOREHEADER lpbmc;
//获取指针
lpbmi = (LPBITMAPINFOHEADER) lpDIB ;
lpbmc = (LPBITMAPCOREHEADER) lpDIB;
//返回DIB中图像的宽度
if(IS_WIN30_DIB(lpDIB))
{
//对于Windows3,0DIB,返回lpbmi-〉biWidth
return lpbmi->biWidth;
}
else
{
//对于其他各式的DIB,返回lpbmc-〉bcWidth
return (LONG)lpbmc->bcWidth;
}
}
///说明:该函数返回DIB中的图像的高度。对Window 3.0 DIB 返回BITMAPINFOHEADE
//中的biHeight的值;对于其他返回BITMAPCOREHEADE中的bcHeight的值
LONG CDib::DIBHeight(LPTSTR lpDIB)
{
//指向BITMAPINFO结构的指针(win30)
LPBITMAPINFOHEADER lpbmi;
//指向BITMAPCOREHEADER的指针
LPBITMAPCOREHEADER lpbmc;
//获取指针
lpbmi = (LPBITMAPINFOHEADER) lpDIB ;
lpbmc = (LPBITMAPCOREHEADER) lpDIB;
//返回DIB中图像的宽度
if(IS_WIN30_DIB(lpDIB))
{
//对于Windows3,0DIB,返回lpbmi-〉biWidth
return lpbmi->biHeight;
}
else
{
//对于其他各式的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;
}
///说明该函数返回DIB中调色板的大小。对于Windows3.0 DIB,返回颜色数*RGBQUAD
//大小,对于其他返回颜色数目*RGBTRPKE的大小。
WORD CDib::PaletteSize(LPTSTR lpbi)
{
//计算DIB中调色板的大小
if(IS_WIN30_DIB (lpbi))
{
return (WORD) (DIBNumColors(lpbi) * sizeof(RGBQUAD));
}
else
{
return (WORD) (DIBNumColors(lpbi) * sizeof(RGBTRIPLE));
}
}
/////说明该函数返回DIB中调色板的颜色的总数。对于但色位图,返回2,
//对于16色位图,返回16,对于256色位图,返回256,对于真彩色位图(24位)没有调色板,返回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;
}
}
//读出像素的为数
if(IS_WIN30_DIB(lpbi))
{
wBitCount = ((LPBITMAPINFOHEADER)lpbi)->biBitCount;
}
else
{
wBitCount = ((LPBITMAPCOREHEADER) lpbi)->bcBitCount;
}
///按照像素的为数计算颜色的数目
switch(wBitCount)
{
case 1:
return 2;
case 4:
return 16;
case 8:
return 256;
default:
return 0;
}
}
////////该函数返回DIBBitsCount
WORD CDib::DIBBitsCount(LPTSTR lpbi)
{
WORD wBitCount;
if(IS_WIN30_DIB(lpbi))
{
wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;
}
else
{
wBitCount = ((LPBITMAPCOREHEADER)lpbi)->bcBitCount;
}
return wBitCount;
}
////////说明该函数复制制定的内存区域,返回复制后的新内存区域,出错时返回0。
HGLOBAL CDib::CopyHandle(HGLOBAL h)
{
if(h==NULL)
return NULL;
///获取指定内存的大小
DWORD dwLen=::GlobalSize((HGLOBAL) h);
///分配新的内存空间
HGLOBAL hCopy = ::GlobalAlloc(GHND,dwLen);
//判断分配是否成功
if(hCopy !=NULL)
{
// 锁定
void* lpCopy = ::GlobalLock((HGLOBAL) hCopy);
void* lp = ::GlobalLock((HGLOBAL) h);
//复制
memcpy(lpCopy,lp,dwLen);
//解除锁定
::GlobalUnlock(hCopy);
::GlobalUnlock(h);
}
return hCopy;
}
//保存当前位图
BOOL CDib::SaveDIB(LPCTSTR lpszDibName)
{
HDIB hDib = m_hDib;
CFile file;
if(!file.Open(lpszDibName,CFile::modeCreate|CFile::modeReadWrite))
{
//打开文件失败
MessageBox(NULL,_T("建立文件失败"),_T("错误"), MB_OK);
return FALSE;
}
//Bitmap文件头
BITMAPFILEHEADER bmfHdr;
//指向BITMAPINFOHEADE的指针
LPBITMAPINFOHEADER lpBI;
//DIB大小
DWORD dwDIBSize;
if(hDib == NULL)
{
//如果DIB为空,返回FALSE
file.Close();
return FALSE;
}
//读取BITMAPINFO 的结构,并锁定
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;
//计算DIB大小时,最简单的方法是调用GlobalSize()函数,但是全局内存大小
//并不真正是DIB的大小,他总是多几个字节,这样就需要计算一下DIB的真实的大小
//文件头大小加颜色表大小
dwDIBSize = *(LPDWORD)lpBI + PaletteSize((LPTSTR) lpBI);
//计算图像的大小
if((lpBI->biCompression == BI_RLE8)||(lpBI->biCompression== BI_RLE4))
{
//对RLE位图,没法计算大小,只能信任biSizeIMAGE内的值
dwDIBSize += lpBI->biSizeImage;
}
else
{
//像素的大小
DWORD dwBmBitsSize;
//大小为Width*Height
dwBmBitsSize = WIDTHBYTES((lpBI->biWidth)*((DWORD) lpBI->biBitCount))* lpBI->biHeight;
//计算出DIB真正的大小
dwDIBSize+=dwBmBitsSize;
//更新biSizeImage(很多BMP文件头中biSizeImage的值是错误的)
lpBI->biSizeImage = dwBmBitsSize;
}
//计算文件大小: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;
}
////说明该函数将指定的文件中的DIB对象读到指定的内存区域中
//BITMAPFILEHEADE外的内容都将被读入内存
BOOL CDib::ReadDIBFile(LPCTSTR lpszDibName)
{
CFile file;
DWORD dwBitsSize, dwFileSize;
HDIB hDIB;
LPTSTR pDIB;
BITMAPFILEHEADER bmfHeader;
if(m_hDib != NULL)
{
//释放 内存
::GlobalFree((HGLOBAL) m_hDib);
m_hDib = NULL;
}
if(m_Pal.GetSafeHandle())
{
m_Pal.DeleteObject();
}
//打开文件
if(!file.Open(lpszDibName,CFile::modeRead))
{
MessageBox(NULL,_T("打开文件失败"),_T("错误"),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;
}
////读地图坐标
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -