⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dib.cpp

📁 数据结构求最短路径vc++ 实现手动作图
💻 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 + -