#include "StdAfx.h"
#include "IMGCommon.h"
#include <strsafe.h>

#include "CharEncoding.h"

#ifdef _DEBUG  
#define new DEBUG_NEW  
#endif 

const ColorMatrix _ClrMatrix = 
{
	1.0, 0.0, 0.0, 0.0, 0.0, 
	0.0, 1.0, 0.0, 0.0, 0.0, 
	0.0, 0.0, 0.3, 0.0, 0.0, 
	0.0, 0.0, 0.0, 1.0, 0.0, 
	0.0, 0.0, 0.0, 0.0, 1.0, 
};

ULONG_PTR IMGCommon::m_gdiplusToken;

IMGCommon::IMGCommon(void)
{
	GdiplusStartupInput gdiplusStartupInput;
	GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
}

IMGCommon::~IMGCommon(void)
{
	Gdiplus::GdiplusShutdown(m_gdiplusToken);
}

	/************************************************************************/
	/*  函数：IsValidpath[3/20/2016 IT];
	/*  描述：判断一个路径是否是本地可以盘符或可用的网络路径;
	/*  参数：;
	/*  	[IN] strPath：要判断的路径;
	/*  返回：盘符或网络路径有效返回TRUE;
	/*  注意：;
	/*  示例：;
	/*
	/*  修改：;
	/*  日期：;
	/*  内容：;
	/************************************************************************/
	BOOL IMGCommon::IsValidpath(IN CONST TString &strPath)
	{
		// 文件表现形式有三种:
		// 1.本地形式: C:\myfolder\you
		// 2.共享形式: \\192.168.1.112\myfolder\\you
		if (strPath.size() < 2) return FALSE;

		// 含":"为本地路径;
		if (strPath[1] == _T(':'))
		{
			DWORD dwDiskType = 0;
			dwDiskType = GetDriveType(strPath.substr(0, 3).c_str());
			switch (dwDiskType)
			{
			case DRIVE_UNKNOWN:			// 未知驱动盘符;
			case DRIVE_NO_ROOT_DIR:		// 没有根目录;
				//case DRIVE_REMOVABLE:		// 移动存储设备盘符;
				// case DRIVE_FIXED:		// 硬盘;
			case DRIVE_CDROM:			// CD盘符;
			case DRIVE_RAMDISK:			// ;
				return FALSE;
				break;
			}
		}
		else if (strPath.substr(0, 2).find(_T("\\\\")) != TString::npos)
		{
			// 共享路径;
			TString strtmp = strPath.substr(2);
			int n = strPath.substr(2).find(_T("\\"));
			if (n == TString::npos)
				return FALSE;

			strtmp = strPath.substr(0, n + 2);

			// 需要判断网络路径可用否;
			DWORD dwRet = 0;
			NETRESOURCE nr;
			memset(&nr, 0, sizeof(nr));
			nr.dwScope = RESOURCE_CONNECTED;
			nr.dwType = RESOURCETYPE_ANY;
			nr.dwDisplayType = RESOURCEDISPLAYTYPE_GENERIC;
			nr.dwUsage = RESOURCEUSAGE_CONNECTABLE;

#ifndef UNICODE
			nr.lpRemoteName = (LPSTR)strtmp.c_str();
#else
			nr.lpRemoteName = (LPWSTR)(strtmp.c_str());
#endif
			dwRet = WNetAddConnection2(&nr, NULL, NULL, CONNECT_UPDATE_PROFILE);
			if (dwRet == ERROR_BAD_NETPATH)// 无效的网络路径,表示没有这个网络地址;
				return FALSE;
			else if (dwRet == ERROR_LOGON_FAILURE)// 登陆这个网络路径失败,因为当前用户名和密码错误; 没有权限;
				return FALSE;
		}

		return TRUE;
	}

void IMGCommon::Splitpath(IN CONST TCHAR *path, IN TCHAR * drive, IN size_t driveNumberOfElements, IN TCHAR * dir, IN size_t dirNumberOfElements, IN CONST int &nTimes)
	{
		int i = 0;
		int npoint = 0;	// '.'
		int nsprit = 0; // '\\'
		int ncolon = 0; // ':'
		int ntimes = 0;
		int nlen = _tcslen(path);
		while (nlen > i++)
		{
			if (path[i] == _T(':') && !ncolon )
			{
				ncolon = i;
			}
			else if (path[i] == _T('\\'))
			{
				if ( ncolon )
				{// 本地目录;
					if ( i == ncolon+1 )
						continue;

					nsprit = i;
					ntimes++;
					if (nTimes == ntimes) break;
				}
				else
				{// 网络路径;
					if ( i == 0 || i == 1 )
						continue;

					nsprit = i;
					ntimes++;
					if (nTimes == ntimes-1) break;
				}
			}
		}

		memcpy_s(drive, driveNumberOfElements*sizeof(TCHAR), path, (ncolon + 1)*sizeof(TCHAR));
		memcpy_s(dir, dirNumberOfElements*sizeof(TCHAR), &path[ncolon + 1], (nsprit - ncolon)*sizeof(TCHAR));
	}

	/************************************************************************/
	/*  函数：CreateDirectoryEx,多字节版本，支持UNICODE[9/13/2016 IT];
	/*  描述：创建目录及子目录文件夹;
	/*  参数：;
	/*  	[IN] lpDestDirectory：目录,必须是"E:\lyfzdb\数据\"格式,目录最后必须有"\",否则最后一个子目录无法创建！建议使用系统_tsplitpath来分隔目录,这样会保存最后一个"\"斜杠;
	/*  返回：成功创建返回TRUE;
	/*  注意：;
	/*  示例：;
	/*
	/*  修改：;
	/*  日期：;
	/*  内容：;
	/************************************************************************/
	BOOL IMGCommon::CreateDirectoryEx(IN LPCTSTR lpNewDirectory)
	{
		// 判断路径有效性 ;
		if (!lpNewDirectory || !IsValidpath(lpNewDirectory)) return FALSE;

		BOOL bExists = FALSE;
		TCHAR szNewFileName[_MAX_PATH] = { 0 };
		TCHAR szDrive[_MAX_DRIVE] = { 0 };
		TCHAR szDir[_MAX_DIR] = { 0 };
		TCHAR szFna[_MAX_FNAME] = { 0 };
		TCHAR szExt[_MAX_EXT] = { 0 };

		TCHAR szNewDirectory[_MAX_PATH] = { 0 };
		if (lpNewDirectory[_tcslen(lpNewDirectory) - 1] != _T('\\'))
			StringCchPrintf(szNewDirectory, _MAX_PATH, _T("%s\\"), lpNewDirectory);
		else
			StringCchPrintf(szNewDirectory, _MAX_PATH, _T("%s"), lpNewDirectory);

		int nIndex = 0;
		do
		{
			bExists = PathFileExists(szNewDirectory);
			if (!bExists)
			{

				memset(szDrive, 0, _MAX_DRIVE*sizeof(TCHAR));
				memset(szDir, 0, _MAX_DIR*sizeof(TCHAR));
				memset(szFna, 0, _MAX_FNAME*sizeof(TCHAR));
				memset(szExt, 0, _MAX_EXT*sizeof(TCHAR));

				Splitpath(szNewDirectory, szDrive, _MAX_DRIVE, szDir, _MAX_DIR, ++nIndex);
				StringCchPrintf(szNewFileName, _MAX_PATH, _T("%s%s"), szDrive, szDir);
				if (!CreateDirectory(szNewFileName, NULL))
				{
					DWORD dwError = GetLastError();				
					switch (dwError)
					{
					case ERROR_PATH_NOT_FOUND:		// 路径未找到,上一层目录未创建导致该错误;
					case ERROR_ACCESS_DENIED:		// 没有权限访问;
					case ERROR_BAD_NET_NAME:		// 错误的网络名称;
						//case ERROR_BAD_PATHNAME: // 
						//WriteTextLog(_T("创建目录失败：%s"), GetErrorInfo(dwError));
						return FALSE;
						break;
					case ERROR_ALREADY_EXISTS:		// 文件存在,不需要创建;
						break;
					default:
						//WriteTextLog(_T("创建目录失败：%s"), GetErrorInfo(dwError));
						break;
					}
				}
			}
		} while (!bExists);

		return TRUE;
	}

//////////////////////////////////////////////////////////////////////////
BOOL IMGCommon::LoadImgFromFile(IN Image** pImg, LPCTSTR lpPath)
{
	if ( !PathFileExists(lpPath) )
		return FALSE;

	if ( *pImg )
		delete *pImg;

	*pImg  = NULL;

#ifdef UNICODE
	*pImg = Image::FromFile(lpPath);
#else
	BSTR strtmp = _bstr_t(lpPath);
	*pImg = Image::FromFile(strtmp);
	SysFreeString(strtmp);
#endif

	return (*pImg ? TRUE : FALSE);
}

BOOL IMGCommon::LoadImgFromBuffer(IN Image** pImg, IN BYTE* pBuffer, IN CONST INT& nBufLen)
{
	if ( pBuffer == NULL )
		return FALSE;

	if ( *pImg )
		delete *pImg;

	*pImg  = NULL;
	HGLOBAL hMemery = GlobalAlloc(GMEM_MOVEABLE, nBufLen);
	if ( hMemery == NULL )
		return FALSE;

	BYTE *pMem = (BYTE*)GlobalLock(hMemery);
	memcpy(pMem, pBuffer, nBufLen);

	IStream *pstream = NULL;
	CreateStreamOnHGlobal(hMemery, TRUE, &pstream);
	*pImg = Image::FromStream(pstream);
	GlobalUnlock(hMemery);
	pstream->Release();

	return (*pImg ? TRUE : FALSE);
}

// 先以只读方式从文件中读取二进制流出来，可以做到不独占文件;
BOOL IMGCommon::LoadImgFromBuffer(IN Image** pImg, LPCTSTR lpPath)
{
	if ( !PathFileExists(lpPath) )
		return FALSE;

	if ( *pImg )
		delete *pImg;
	*pImg  = NULL;
	
	CFile fp;
	CFileException e;
	BOOL bRet = FALSE;
	if ( fp.Open(lpPath, CFile::modeRead, &e))
	{
		DWORD dwLength = (DWORD)fp.GetLength();
		BYTE *pData = new BYTE[dwLength];
		
		fp.Read(pData,dwLength);
		fp.Close();

		bRet = LoadImgFromBuffer(pImg, pData, dwLength);

		if( pData )
			delete []pData;
	}

	return bRet;
}

/************************************************************************/
/*  函数：LoadImgFromResource[9/21/2016 IT];
/*  描述：从资源中加载;
/*  参数：;
/*  	[IN] ：;
/*  	[OUT] ：;
/*  	[IN/OUT] ：;
/*  返回：void;
/*  注意：;
/*  示例：;
/*
/*  修改：;
/*  日期：;
/*  内容：;
/************************************************************************/
Image* IMGCommon::LoadImgFromResource(IN HMODULE hModule, IN LPCTSTR lpName, IN LPCTSTR lpType)
{
	HGLOBAL	hGlobal = NULL;
	HRSRC	hSource = NULL;
	LPVOID  lpBuffer = NULL;
	DWORD   dwSize = 0;
	// 1.定位我们的自定义资源，这里因为我们是从本模块定位资源，所以将句柄简单地置为NULL即可
	hSource = FindResource(hModule, lpName, lpType);
	if (hSource == NULL)
	{
		_tprintf(_T("载入资源失败:%s"), lpName);
		return NULL;
	}

	// 2.获取资源的大小;
	dwSize = (UINT)SizeofResource(NULL, hSource);

	// 3.加载资源;
	hGlobal = LoadResource(NULL, hSource);
	if (hGlobal == NULL)
	{
		_tprintf(_T("载入资源失败:%s"), lpName);
		return NULL;
	}

	// 4.锁定资源,获取buffer;
	lpBuffer = LockResource(hGlobal);
	if (lpBuffer == NULL)
	{
		_tprintf(_T("载入资源失败:%s"), lpName);
		return NULL;;
	}

	// lpFileFullName需要先判断文件是否存在??不需要;
	Image *pImg = NULL;
	LoadImgFromBuffer(&pImg, (BYTE*)lpBuffer, dwSize);

	UnlockResource(hGlobal);
	FreeResource(hGlobal);

	return pImg;
}

BOOL IMGCommon::GetOrientation(IN Image *pImg)
{
	if (pImg == NULL) return FALSE;

	UINT totalBufferSize;
	UINT numProperties;
	pImg->GetPropertySize(&totalBufferSize, &numProperties);
	// Allocate the buffer that will receive the property items.
	PropertyItem* pAllItems = (PropertyItem*)malloc(totalBufferSize);
	// Fill the buffer.
	pImg->GetAllPropertyItems(totalBufferSize, numProperties, pAllItems);
	// Print the id data member of each property item.
	for (UINT j = 0; j < numProperties; ++j)
	{
		if (PropertyTagOrientation == pAllItems[j].id)
		{
			short* ptrLong = (short*)(pAllItems[j].value);
			int ret = (int)*ptrLong;
			free(pAllItems);
			return ret;
		}
	}
	free(pAllItems);

	return TRUE;
}


/************************************************************************/
/*
	函数:GetEncoderClsid
	描述:获取GDI+支持的图像格式编码器种类,以及所有种类编码器信息;
	参数:
		IN:  format 要获取的图像格式;
		OUT: pClsid 返回符合条件的图像编码器信息;
	返回:成功返回编码器索引,否则返回-1;
*/
/************************************************************************/
int IMGCommon::GetEncoderClsid(IN CONST WCHAR* format, OUT CLSID* pClsid)
{
	// GDI+支持的图像编码器数量;
	UINT  numEncoders = 0;
	// GDI+所有图像格式编码器详细信息所需要的空间大小;
	UINT  nSize = 0;

	ImageCodecInfo* pImageCodecInfo = NULL;

	// 2.获取GDI+支持的所有图像格式编码器详细信息所需要的空间大小;
	GetImageEncodersSize(&numEncoders, &nSize);
	if (nSize == 0)
		return -1;

	//3.为ImageCodecInfo数组分配足额空间;
	pImageCodecInfo = (ImageCodecInfo*)(malloc(nSize));
	if (pImageCodecInfo == NULL)
		return -1;

	//4.获取所有的图像编码器信息;
	GetImageEncoders(numEncoders, nSize, pImageCodecInfo);

	//5.查找符合的图像编码器的Clsid;
	for (UINT i = 0; i < numEncoders; ++i)
	{
		if (wcscmp(pImageCodecInfo[i].MimeType, format) == 0)
		{
			*pClsid = pImageCodecInfo[i].Clsid;
			free(pImageCodecInfo);
			return i;  // Success
		}
	}

	//6.释放步骤3分配的内存;
	free(pImageCodecInfo);

	return -1;
}

/************************************************************************/
/*
	函数:SaveImg2newfile
	描述:将Image对象另存为其他格式的文件;
	参数:
		IN:  pImg		GDI+ Image对象指针,需要保存的图像对象;
		IN:	 lpnewfile	其他格式的新文件名(jpg,bmp,png,jpeg);
		IN:  uQuality	另存为新文件时的图像质量值;
	返回:

	注意:Image::Save 若文件存在,会覆盖存在的文件;
*/
/************************************************************************/
BOOL IMGCommon::SaveImg2newfile(IN Image* pImg, IN CString strNewfile, IN ULONG uQuality)
{
	if (pImg == NULL) return FALSE;

	// 需要判断路径是否存在,不存在创建目录;
	int nIndex = strNewfile.ReverseFind(_T('\\'));
	if (nIndex == -1)
		return FALSE;

	if (!PathFileExists(strNewfile.Left(nIndex)))
	{
		// 如果文件夹不存在,创建;
#if 0
		CreateDirectoryEx(strNewfile.Left(nIndex));
#else
		SHCreateDirectoryEx(NULL, strNewfile.Left(nIndex), NULL);
#endif
	}

	nIndex = strNewfile.ReverseFind(_T('.'));
	if (nIndex == -1)
		return FALSE;

	Status stat = GenericError;
	CLSID encoderClsid = { 0 };
	BSTR newfile = strNewfile.AllocSysString();

	strNewfile = strNewfile.Mid(nIndex + 1);
	if (strNewfile.CompareNoCase(_T("bmp")) == 0)
	{
		GetEncoderClsid(L"image/bmp", &encoderClsid);
		stat = pImg->Save(newfile, &encoderClsid, NULL);
	}
	else if (strNewfile.CompareNoCase(_T("png")) == 0)
	{
		GetEncoderClsid(L"image/png", &encoderClsid);
		stat = pImg->Save(newfile, &encoderClsid, NULL);
	}
	else// if ( strNewfile.CompareNoCase(_T("jpeg")) == 0 )
	{
		GetEncoderClsid(L"image/jpeg", &encoderClsid);

		EncoderParameters encoderParameters;
		encoderParameters.Count = 1;
		encoderParameters.Parameter[0].Guid = EncoderQuality;
		encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
		encoderParameters.Parameter[0].NumberOfValues = 1;
		// Save the image as a JPEG with quality level 100.
		encoderParameters.Parameter[0].Value = &uQuality;
		stat = pImg->Save(newfile, &encoderClsid, &encoderParameters);
	}

	SysFreeString(newfile);

	return stat == Ok ? TRUE : FALSE;
}

BOOL IMGCommon::SaveImg2newfile(IN Image* pImg, IN TString strNewfile, IN ULONG uQuality)
{
	if (pImg == NULL) return FALSE;

	// 需要判断路径是否存在,不存在创建目录;
	int nIndex = strNewfile.find_last_of(_T('\\'));
	if (nIndex == TString::npos)
		return FALSE;

	if (!PathFileExists(strNewfile.substr(0, nIndex).c_str()))
	{
		// 如果文件夹不存在,创建;
#if 0
		CreateDirectoryEx(strNewfile.substr(0, nIndex).c_str());
#else
		SHCreateDirectoryEx(NULL, strNewfile.substr(0, nIndex).c_str(), NULL);
#endif
	}

	nIndex = strNewfile.find_last_of(_T('.'));
	if (nIndex == TString::npos)
		return FALSE;

	Status stat = GenericError;
	CLSID encoderClsid = { 0 };
	BSTR newfile = _bstr_t(strNewfile.c_str());

	strNewfile = strNewfile.substr(nIndex + 1);
	if (strNewfile.find(_T("bmp")) == 0)
	{
		GetEncoderClsid(L"image/bmp", &encoderClsid);
		stat = pImg->Save(newfile, &encoderClsid, NULL);
	}
	else if (strNewfile.find(_T("png")) == 0)
	{
		GetEncoderClsid(L"image/png", &encoderClsid);
		stat = pImg->Save(newfile, &encoderClsid, NULL);
	}
	else// if ( strNewfile.CompareNoCase(_T("jpeg")) == 0 )
	{
		GetEncoderClsid(L"image/jpeg", &encoderClsid);

		EncoderParameters encoderParameters;
		encoderParameters.Count = 1;
		encoderParameters.Parameter[0].Guid = EncoderQuality;
		encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
		encoderParameters.Parameter[0].NumberOfValues = 1;
		// Save the image as a JPEG with quality level 100.
		encoderParameters.Parameter[0].Value = &uQuality;
		stat = pImg->Save(newfile, &encoderClsid, &encoderParameters);
	}

	SysFreeString(newfile);

	return stat == Ok ? TRUE : FALSE;
}

/************************************************************************/
/*
	函数:ZoomImg
	描述:缩放到指定大小的区域中,返回缩放后的尺寸;
	参数:
		IN:		Imgrc			图像的大小;
		IN:		dwDisplayPix	图像要显示的区域的大小;
		OUT:	dwZoomPix		图像在显示区域内缩放后的尺寸;
	返回:

	注意:dwZoomPix的尺寸必须在dwDisplayPix内;
*/
/************************************************************************/
int IMGCommon::ZoomImg(IN CRect &Imgrc, IN CONST DWORD &dwDisplayPix, OUT DWORD &dwZoomPix)
{
	double fDisplayWidth = GET_XPIX(dwDisplayPix);
	double fDisplayHeight = GET_YPIX(dwDisplayPix);

	// 显示区域长宽比;
	double fDisplayAspectRatio = fDisplayWidth / fDisplayHeight;

	// 图片长宽比;
	double fImgAspectRatio = ((double)Imgrc.Width()) / ((double)Imgrc.Height());

	double fZoomWidth;
	double fZoomHeight;

	if (fDisplayAspectRatio > fImgAspectRatio)
	{
		fZoomWidth = fDisplayHeight*fImgAspectRatio;
		fZoomHeight = fDisplayHeight;
	}
	else
	{
		fZoomWidth = fDisplayWidth;
		fZoomHeight = fDisplayWidth / fImgAspectRatio;
	}

	dwZoomPix = SET_PIX((int)fZoomWidth, (int)fZoomHeight);

	//////////////////////////////////////////////////////////////////////////
	int nRetval = 0;
	if ((fDisplayWidth == Imgrc.Width()) && (fDisplayHeight == Imgrc.Height()))
	{
		nRetval = ZoomNull;
	}
	else if ((fDisplayWidth > Imgrc.Width()) && (fDisplayHeight > Imgrc.Height()))
	{
		nRetval = ZoomOut;
	}
	else
	{
		nRetval = ZoomIn;
	}

	return nRetval;
}

int IMGCommon::ZoomImg(IN CONST DWORD &dwImgPix, IN CONST DWORD &dwDisplayPix, OUT DWORD &dwZoomPix)
{
	double fDisplayWidth = GET_XPIX(dwDisplayPix);
	double fDisplayHeight = GET_YPIX(dwDisplayPix);

	// 显示区域长宽比;
	double fDisplayAspectRatio = fDisplayWidth / fDisplayHeight;

	// 图片长宽比;
	double fImgAspectRatio = ((double)GET_XPIX(dwImgPix)) / ((double)GET_YPIX(dwImgPix));

	double fZoomWidth;
	double fZoomHeight;

	if (fDisplayAspectRatio > fImgAspectRatio)
	{
		fZoomWidth = fDisplayHeight*fImgAspectRatio;
		fZoomHeight = fDisplayHeight;
	}
	else
	{
		fZoomWidth = fDisplayWidth;
		fZoomHeight = fDisplayWidth / fImgAspectRatio;
	}

	dwZoomPix = SET_PIX((int)fZoomWidth, (int)fZoomHeight);

	//////////////////////////////////////////////////////////////////////////
	int nRetval = 0;
	if ((fDisplayWidth == GET_XPIX(dwImgPix)) && (fDisplayHeight == GET_YPIX(dwImgPix)))
	{
		nRetval = ZoomNull;
	}
	else if ((fDisplayWidth > GET_XPIX(dwImgPix)) && (fDisplayHeight > GET_YPIX(dwImgPix)))
	{
		nRetval = ZoomOut;
	}
	else
	{
		nRetval = ZoomIn;
	}

	return nRetval;
}

/************************************************************************/
/*
	函数:ImgThumbnail
	描述:生成高质量的图像缩略图;
	参数:
	返回:

	注意:为了健壮性,strNewfile的路径可以在函数内再次判断是否有效,防止在函数外没有进行经判断;
*/
/************************************************************************/
BOOL IMGCommon::ImgThumbnail(IN Image* pImg, IN CONST DWORD &dwDisplayPix, IN CString strNewfile, IN ULONG uQuality)
{
	if (pImg == NULL) return FALSE;

	DWORD dwZoomPix;
	int retval = ZoomImg(SET_PIX(pImg->GetWidth(), pImg->GetHeight()), dwDisplayPix, dwZoomPix);
	if (retval == ZoomOut)
	{
		return FALSE;
	}
	else if (retval == ZoomNull)
	{
		return SaveImg2newfile(pImg, strNewfile, uQuality);
	}

	// 绘制缩略图;
	Bitmap bitmap(GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
	Graphics *graphic = Graphics::FromImage(&bitmap);
	graphic->Clear(Color(255, 255, 255, 255));

	// 设置缩放或旋转图片时的算法（图片质量）;
	graphic->SetInterpolationMode(InterpolationModeHighQualityBicubic);
	// 设置渲染图形对象的质量;
	graphic->SetSmoothingMode(SmoothingModeHighQuality);//SmoothingModeHighSpeed
	// 设置图形对象的像素偏移模式;
	graphic->SetPixelOffsetMode(PixelOffsetModeHighQuality);
	// 设置图形对象的合成模式;
	graphic->SetCompositingMode(CompositingModeSourceOver);
	// 设置图形对象的合成质量;
	graphic->SetCompositingQuality(CompositingQualityHighQuality);
	// 设置图形对象的文本渲染模式;
	graphic->SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);
	graphic->DrawImage(pImg, 0, 0, GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));

	delete graphic;

	// 生成缩略图;
	return SaveImg2newfile(&bitmap, strNewfile, uQuality);
}

BOOL IMGCommon::ImgThumbnail(IN LPCTSTR lpImgpath, IN CONST DWORD &dwDisplayPix, IN CString strNewfile, IN ULONG uQuality)
{
	if (!PathFileExists(lpImgpath))
		return FALSE;

#ifdef UNICODE
	Image Img(lpImgpath);
#else
	BSTR strtmp = _bstr_t(lpImgpath);
	Image Img(strtmp);
	SysFreeString(strtmp);
#endif

	DWORD dwZoomPix;
	int retval = ZoomImg(SET_PIX(Img.GetWidth(), Img.GetHeight()), dwDisplayPix, dwZoomPix);
	if (retval == ZoomOut)
	{
		return FALSE;
	}
	else if (retval == ZoomNull)
	{
		return SaveImg2newfile(&Img, strNewfile, uQuality);
	}

	// 绘制缩略图;
	Bitmap bitmap(GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
	Graphics *graphic = Graphics::FromImage(&bitmap);
	graphic->Clear(Color(255, 255, 255, 255));

	// 设置缩放或旋转图片时的算法（图片质量）;
	graphic->SetInterpolationMode(InterpolationModeHighQualityBicubic);
	// 设置渲染图形对象的质量;
	graphic->SetSmoothingMode(SmoothingModeHighQuality);//SmoothingModeHighSpeed
	// 设置图形对象的像素偏移模式;
	graphic->SetPixelOffsetMode(PixelOffsetModeHighQuality);
	// 设置图形对象的合成模式;
	graphic->SetCompositingMode(CompositingModeSourceOver);
	// 设置图形对象的合成质量;
	graphic->SetCompositingQuality(CompositingQualityHighQuality);
	// 设置图形对象的文本渲染模式;
	graphic->SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);
	Status st = graphic->DrawImage(&Img, 0, 0, GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
	if ( st != Ok  )
	{
		delete graphic;
		return FALSE;
	}

	delete graphic;
	// 生成缩略图;
	return SaveImg2newfile(&bitmap, strNewfile, uQuality);
}

BOOL IMGCommon::ImgThumbnail(IN CONST TString &strImgpath, IN CONST DWORD &dwDisplayPix, IN TString strNewfile, IN ULONG uQuality)
{
	if (!PathFileExists(strImgpath.c_str()))
	{
		SetLastError(GetLastError());
		return FALSE;
	}

#ifdef UNICODE
	BSTR strtmp = _bstr_t(strImgpath.c_str());
	Image Img(strtmp);
	SysFreeString(strtmp);
	//Image Img(strImgpath);
#else
	BSTR strtmp = _bstr_t(strImgpath.c_str());
	Image Img(strtmp);
	SysFreeString(strtmp);
#endif

	DWORD dwZoomPix;
	int retval = ZoomImg(SET_PIX(Img.GetWidth(), Img.GetHeight()), dwDisplayPix, dwZoomPix);
	if (retval == ZoomOut)
	{
		return FALSE;
	}
	else if (retval == ZoomNull)
	{
		return SaveImg2newfile(&Img, strNewfile, uQuality);
	}

	// 绘制缩略图;
	Bitmap bitmap(GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
	Graphics *graphic = Graphics::FromImage(&bitmap);
	graphic->Clear(Color(255, 255, 255, 255));

	// 设置缩放或旋转图片时的算法（图片质量）;
	graphic->SetInterpolationMode(InterpolationModeHighQualityBicubic);
	// 设置渲染图形对象的质量;
	graphic->SetSmoothingMode(SmoothingModeHighQuality);//SmoothingModeHighSpeed
	// 设置图形对象的像素偏移模式;
	graphic->SetPixelOffsetMode(PixelOffsetModeHighQuality);
	// 设置图形对象的合成模式;
	graphic->SetCompositingMode(CompositingModeSourceOver);
	// 设置图形对象的合成质量;
	graphic->SetCompositingQuality(CompositingQualityHighQuality);
	// 设置图形对象的文本渲染模式;
	graphic->SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);
	Status st = graphic->DrawImage(&Img, 0, 0, GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
	if ( st != Ok  )
	{
		delete graphic;
		return FALSE;
	}

	delete graphic;
	// 生成缩略图;
	return SaveImg2newfile(&bitmap, strNewfile, uQuality);
}

BOOL IMGCommon::SimpleImgThumbnail(IN LPCTSTR lpImgpath, IN CONST DWORD &dwDisplayPix, IN CString strNewfile, IN ULONG uQuality)
{
	if (!PathFileExists(lpImgpath))
		return FALSE;

	DWORD dwZoomPix;
	Image *pImg = NULL;
	LoadImgFromFile(&pImg, lpImgpath);
	if ( pImg == NULL )
	{
		return FALSE;
	}

	int retval = ZoomImg(SET_PIX(pImg->GetWidth(), pImg->GetHeight()), dwDisplayPix, dwZoomPix);
	if (retval == ZoomOut)
	{
		if (pImg) delete pImg;
		
		return FALSE;
	}
	else if (retval == ZoomNull)
	{
		BOOL bRet = SaveImg2newfile(pImg, strNewfile, uQuality);
		if (pImg) delete pImg;

		return bRet;
	}

	Image *pThumbnailImg = pImg->GetThumbnailImage(GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
	if (pThumbnailImg)
	{
		// 提高缩略图质量;
		Graphics graphic(pThumbnailImg);
		graphic.DrawImage(pImg, 0, 0, pThumbnailImg->GetWidth(), pThumbnailImg->GetHeight());
		INT nRientation = GetOrientation(pImg);
		if ( nRientation == 8 )
		{
			pThumbnailImg->RotateFlip(Rotate270FlipNone);
		}
		else if (nRientation == 6)
		{
			pThumbnailImg->RotateFlip(Rotate90FlipNone);
		}
		SaveImg2newfile(pThumbnailImg, strNewfile, uQuality);
	}
	else
	{
		if (pImg) delete pImg;
		return FALSE;
	}

	if (pImg) delete pImg;
	if (pThumbnailImg) delete pThumbnailImg;

	return TRUE;
}

Image* IMGCommon::AppendImgWatermark(IN Image* pImg, IN Image* pWatemarkImg)
{
	if ( pImg == NULL || pWatemarkImg == NULL )
		return NULL;

	// Status st = GenericError;
	// 创建图像显示属性对象;
	ImageAttributes ImgAttr;
	// 创建新位图;
	Bitmap *pBitmap = ::new Bitmap(pImg->GetWidth(), pImg->GetHeight(), PixelFormat32bppPARGB);
	// 创建水印图显示位置;
	RectF layWatemarkRect(10.0, 10.0, pWatemarkImg->GetWidth(), pWatemarkImg->GetHeight());
	// 创建画布对象;
	Graphics *grap = Graphics::FromImage(pBitmap);
	// 绘制画布底色;
	if ( Ok != grap->Clear(Color(255,255,255,255)) )
		goto clear;
	// 设置图片显示质量;
	if ( Ok != grap->SetSmoothingMode(SmoothingModeAntiAlias) )
		goto clear;
	// 设置文本质量;
	if ( Ok != grap->SetTextRenderingHint(TextRenderingHintAntiAlias))
		goto clear;
	// 在画布上画原始图片;
	if ( Ok != grap->DrawImage(pImg, 0, 0, pImg->GetWidth(), pImg->GetHeight()) )
		goto clear;

	// 设置透明颜色为水印图片四角底色，水印图显示为圆角;
	if ( Ok != ImgAttr.SetColorKey(0xFF00FF00, 0xFF00FF00, ColorAdjustTypeBitmap))
		goto clear;
	// 设置水印图片透明底为0.3;
	if ( Ok != ImgAttr.SetColorMatrix(&_ClrMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap) )
		goto clear;
	// 在画布左上角画水印;
	if ( Ok != grap->DrawImage(pWatemarkImg, layWatemarkRect, 0, 0, pWatemarkImg->GetWidth(), pWatemarkImg->GetHeight(), UnitPixel, &ImgAttr) )
		goto clear;

	if ( grap )
		delete grap;

	return pBitmap;

clear:
	if ( grap )
		delete grap;

	if ( pBitmap )
		delete pBitmap;

	return NULL;
}

Image* IMGCommon::AppendImgWatermark(IN Image* pImg, IN LPCTSTR lpWatemarkImgpath)
{
	if ( !PathFileExists(lpWatemarkImgpath) || pImg == NULL )
		return FALSE;

#ifdef UNICODE
	Image *pWatemarkImg = Image::FromFile(lpWatemarkImgpath);
#else
	BSTR str = _bstr_t(lpWatemarkImgpath);
	Image* pWatemarkImg = Image::FromFile(str);
	SysFreeString(str);
#endif

	if ( pImg == NULL )
		return NULL;

	//Status st = GenericError;
	// 创建图像显示属性对象;
	ImageAttributes ImgAttr;
	// 创建新位图;
	Bitmap *pBitmap = ::new Bitmap(pImg->GetWidth(), pImg->GetHeight(), PixelFormat32bppPARGB);
	// 创建水印图显示位置;
	RectF layWatemarkRect(10.0, 10.0, pWatemarkImg->GetWidth(), pWatemarkImg->GetHeight());
	// 创建画布对象;
	Graphics *grap = Graphics::FromImage(pBitmap);
	// 绘制画布底色;
	if ( Ok != grap->Clear(Color(255,255,255,255)) )
		goto clear;
	// 设置图片显示质量;
	if ( Ok != grap->SetSmoothingMode(SmoothingModeAntiAlias) )
		goto clear;
	// 设置文本质量;
	if ( Ok != grap->SetTextRenderingHint(TextRenderingHintAntiAlias))
		goto clear;
	// 在画布上画原始图片;
	if ( Ok != grap->DrawImage(pImg, 0, 0, pImg->GetWidth(), pImg->GetHeight()) )
		goto clear;

	// 设置透明颜色为水印图片四角底色，水印图显示为圆角;
	if ( Ok != ImgAttr.SetColorKey(0xFF00FF00, 0xFF00FF00, ColorAdjustTypeBitmap))
		goto clear;
	// 设置水印图片透明底为0.3;
	if ( Ok != ImgAttr.SetColorMatrix(&_ClrMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap) )
		goto clear;
	// 在画布左上角画水印;
	if ( Ok != grap->DrawImage(pWatemarkImg, layWatemarkRect, 0, 0, pWatemarkImg->GetWidth(), pWatemarkImg->GetHeight(), UnitPixel, &ImgAttr) )
		goto clear;

	if ( grap )
		delete grap;

	return pBitmap;

clear:
	if ( grap )
		delete grap;

	if ( pBitmap )
		delete pBitmap;

	if ( pWatemarkImg )
		delete pWatemarkImg;

	return NULL;
}

Image* IMGCommon::AppendImgWatermark(IN LPCTSTR lpImgpath, IN Image* pWatemarkImg)
{
	if ( !PathFileExists(lpImgpath) || pWatemarkImg == NULL )
		return FALSE;

#ifdef UNICODE
	Image *pImg = Image::FromFile(lpImgpath);
#else
	BSTR str = _bstr_t(lpImgpath);
	Image* pImg = Image::FromFile(str);
	SysFreeString(str);
#endif

	if ( pImg == NULL )
		return NULL;

	//Status st = GenericError;
	// 创建图像显示属性对象;
	ImageAttributes ImgAttr;
	// 创建新位图;
	Bitmap *pBitmap = ::new Bitmap(pImg->GetWidth(), pImg->GetHeight(), PixelFormat32bppPARGB);
	// 创建水印图显示位置;
	RectF layWatemarkRect(10.0, 10.0, pWatemarkImg->GetWidth(), pWatemarkImg->GetHeight());
	// 创建画布对象;
	Graphics *grap = Graphics::FromImage(pBitmap);
	// 绘制画布底色;
	if ( Ok != grap->Clear(Color(255,255,255,255)) )
		goto clear;
	// 设置图片显示质量;
	if ( Ok != grap->SetSmoothingMode(SmoothingModeAntiAlias) )
		goto clear;
	// 设置文本质量;
	if ( Ok != grap->SetTextRenderingHint(TextRenderingHintAntiAlias))
		goto clear;
	// 在画布上画原始图片;
	if ( Ok != grap->DrawImage(pImg, 0, 0, pImg->GetWidth(), pImg->GetHeight()) )
		goto clear;

	// 设置透明颜色为水印图片四角底色，水印图显示为圆角;
	if ( Ok != ImgAttr.SetColorKey(0xFF00FF00, 0xFF00FF00, ColorAdjustTypeBitmap))
		goto clear;
	// 设置水印图片透明底为0.3;
	if ( Ok != ImgAttr.SetColorMatrix(&_ClrMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap) )
		goto clear;
	// 在画布左上角画水印;
	if ( Ok != grap->DrawImage(pWatemarkImg, layWatemarkRect, 0, 0, pWatemarkImg->GetWidth(), pWatemarkImg->GetHeight(), UnitPixel, &ImgAttr) )
		goto clear;

	if ( grap )
		delete grap;

	return pBitmap;

clear:
	if ( grap )
		delete grap;

	if ( pBitmap )
		delete pBitmap;

	if ( pImg )
		delete pImg;

	return NULL;
}

Image* IMGCommon::AppendImgWatermark(IN LPCTSTR lpImgpath, IN LPCTSTR lpWatemarkImgpath)
{
	if ( !PathFileExists(lpImgpath) || !PathFileExists(lpWatemarkImgpath) )
		return FALSE;

#ifdef UNICODE
	Image *pImg = Image::FromFile(lpImgpath);
	Image *pWatemarkImg = Image::FromFile(lpWatemarkImgpath);
#else
	BSTR str = _bstr_t(lpImgpath);
	Image* pImg = Image::FromFile(str);
	SysFreeString(str);

	BSTR str2 = _bstr_t(lpWatemarkImgpath);
	Image* pWatemarkImg = Image::FromFile(str2);
	SysFreeString(str2);
#endif

	if ( pImg == NULL || pWatemarkImg == NULL )
		return NULL;

	//Status st = GenericError;
	// 创建图像显示属性对象;
	ImageAttributes ImgAttr;
	// 创建新位图;
	Bitmap *pBitmap = ::new Bitmap(pImg->GetWidth(), pImg->GetHeight(), PixelFormat32bppPARGB);
	// 创建水印图显示位置;
	RectF layWatemarkRect(10.0, 10.0, pWatemarkImg->GetWidth(), pWatemarkImg->GetHeight());
	// 创建画布对象;
	Graphics *grap = Graphics::FromImage(pBitmap);
	// 绘制画布底色;
	if ( Ok != grap->Clear(Color(255,255,255,255)) )
		goto clear;
	// 设置图片显示质量;
	if ( Ok != grap->SetSmoothingMode(SmoothingModeAntiAlias) )
		goto clear;
	// 设置文本质量;
	if ( Ok != grap->SetTextRenderingHint(TextRenderingHintAntiAlias))
		goto clear;
	// 在画布上画原始图片;
	if ( Ok != grap->DrawImage(pImg, 0, 0, pImg->GetWidth(), pImg->GetHeight()) )
		goto clear;

	// 设置透明颜色为水印图片四角底色，水印图显示为圆角;
	if ( Ok != ImgAttr.SetColorKey(0xFF00FF00, 0xFF00FF00, ColorAdjustTypeBitmap))
		goto clear;
	// 设置水印图片透明底为0.3;
	if ( Ok != ImgAttr.SetColorMatrix(&_ClrMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap) )
		goto clear;
	// 在画布左上角画水印;
	if ( Ok != grap->DrawImage(pWatemarkImg, layWatemarkRect, 0, 0, pWatemarkImg->GetWidth(), pWatemarkImg->GetHeight(), UnitPixel, &ImgAttr) )
		goto clear;

	if ( grap )
		delete grap;

	return pBitmap;

clear:
	if ( grap )
		delete grap;

	if ( pBitmap )
		delete pBitmap;

	if ( pImg )
		delete pImg;

	if ( pWatemarkImg )
		delete pWatemarkImg;

	return NULL;
}

BOOL IMGCommon::AppendImgWatermark(IN Image* pImg, IN Image* pWatemarkImg, IN LPCTSTR lpSaveImgpath)
{
	Image* pSaveImg = AppendImgWatermark(pImg, pWatemarkImg);
	if ( pSaveImg == NULL )
		return FALSE;

	// 创建新的目录;
	CString strImgs = lpSaveImgpath;
	INT nIndex = strImgs.ReverseFind(_T('\\'));
	if ( nIndex != -1 )
	{
		strImgs = strImgs.Mid(0,nIndex+1);
		if ( !PathFileExists(strImgs) )
		{
#if 0
			if ( CreateDirectoryEx(strImgs) )
#else
			if (SHCreateDirectoryEx(NULL, strImgs, NULL))
#endif
			{
				if (SaveImg2newfile(pSaveImg, (CString)lpSaveImgpath, 100))
				{
					if ( pSaveImg )
						delete pSaveImg;
					pSaveImg = NULL;

					return TRUE;
				}

				return FALSE;
			}
		}
	}

	return FALSE;
}

BOOL IMGCommon::AppendImgWatermark(IN LPCTSTR lpImgpath, IN LPCTSTR lpWatemarkImgpath, IN LPCTSTR lpSaveImgpath)
{
	Image *pSaveImg = AppendImgWatermark(lpImgpath, lpWatemarkImgpath);
	if ( pSaveImg == NULL)
		return FALSE;

	// 创建新的目录;
	CString strImgs = lpSaveImgpath;
	INT nIndex = strImgs.ReverseFind(_T('\\'));
	if ( nIndex != -1 )
	{
		strImgs = strImgs.Mid(0,nIndex+1);
		if ( !PathFileExists(strImgs) )
		{
#if 0
			if (CreateDirectoryEx(strImgs))
#else
			if (SHCreateDirectoryEx(NULL, strImgs, NULL))
#endif
			{
				if (SaveImg2newfile(pSaveImg, (CString)lpSaveImgpath, 100))
				{
					if ( pSaveImg )
						delete pSaveImg;
					pSaveImg = NULL;

					return TRUE;
				}

				return FALSE;
			}
		}
	}

	return FALSE;
}

Image* IMGCommon::AppendWordWatermark(IN Image* pImg, IN LPCTSTR lpWatemarkString)
{
	if ( pImg == NULL || lpWatemarkString == NULL || lpWatemarkString[0] == _T('\0'))
		return NULL;

#ifndef UNICODE
	WCHAR* pText = CharEncoding::ASCII2UNICODE(lpWatemarkString);
#endif

	// 创建新位图;
	Bitmap *pBitmap = ::new Bitmap(pImg->GetWidth(), pImg->GetHeight(), PixelFormat32bppPARGB);
	// 创建字体;
	FontFamily ffly(L"宋体");
	Gdiplus::Font ft(&ffly, 24, FontStyleRegular, UnitPixel);
	// 创建画刷;
	SolidBrush brush(0x99000000);
	// 创建文本格式;
	StringFormat sf;
	sf.SetAlignment(StringAlignmentCenter);	// 水平居中;
	// 创建水印文本显示位置;
	RectF layWatemarkRect(pImg->GetWidth(), pImg->GetHeight() - 25, 0.0, 0.0);	// 文字阴影;
	RectF layWatemarkRect2(pImg->GetWidth(), pImg->GetHeight() - 26, 0.0, 0.0);		// 文字原体;
	// 创建画布对象;
	Graphics *grap = Graphics::FromImage(pBitmap);
	// 绘制画布底色;
	if ( Ok != grap->Clear(Color(255,255,255,255)) )
		goto clear;
	// 设置图片显示质量;
	if ( Ok != grap->SetSmoothingMode(SmoothingModeAntiAlias) )
		goto clear;
	// 设置文本质量;
	if ( Ok != grap->SetTextRenderingHint(TextRenderingHintAntiAlias))
		goto clear;
	// 在画布上画原始图片;
	if ( Ok != grap->DrawImage(pImg, 0, 0, pImg->GetWidth(), pImg->GetHeight()) )
		goto clear;

	// 画水印阴影;
#ifdef UNICODE
	if ( Ok != grap->DrawString(lpWatemarkString, wcslen(lpWatemarkString), &ft, layWatemarkRect, &sf, &brush) )
#else
	if ( Ok != grap->DrawString(pText, wcslen(pText), &ft, layWatemarkRect, &sf, &brush) )
#endif
		goto clear;
	// 画水印文本;
	brush.SetColor(0x99ffffff);
#ifdef UNICODE
	if ( Ok != grap->DrawString(lpWatemarkString, wcslen(lpWatemarkString), &ft, layWatemarkRect2, &sf, &brush) )
#else
	if ( Ok != grap->DrawString(pText, wcslen(pText), &ft, layWatemarkRect, &sf, &brush) )
#endif
		goto clear;

	if ( grap )
		delete grap;

	return pBitmap;

clear:
	if ( grap )
		delete grap;

	if ( pBitmap )
		delete pBitmap;

	if ( pImg )
		delete pImg;

#ifndef UNICODE
	if (pText)
		delete []pText;
#endif

	return NULL;
}

Image* IMGCommon::AppendWordWatermark(IN LPCTSTR lpImgpath, IN LPCTSTR lpWatemarkString)
{
	if ( !PathFileExists(lpImgpath) || lpWatemarkString == NULL || lpWatemarkString[0] == _T('\0'))
		return NULL;

#ifdef UNICODE
	Image *pImg = Image::FromFile(lpImgpath);
#else
	BSTR str = _bstr_t(lpImgpath);
	Image* pImg = Image::FromFile(str);
	SysFreeString(str);
#endif

#ifndef UNICODE
	WCHAR* pText = CharEncoding::ASCII2UNICODE(lpWatemarkString);
#endif

	// 创建新位图;
	Bitmap *pBitmap = ::new Bitmap(pImg->GetWidth(), pImg->GetHeight(), PixelFormat32bppPARGB);
	// 创建字体;
	FontFamily ffly(L"宋体");
	Gdiplus::Font ft(&ffly, 24, FontStyleRegular, UnitPixel);
	// 创建画刷;
	SolidBrush brush(0x99000000);
	// 创建文本格式;
	StringFormat sf;
	sf.SetAlignment(StringAlignmentCenter);	// 水平居中;
	// 创建水印文本显示位置;
	RectF layWatemarkRect(pImg->GetWidth(), pImg->GetHeight() - 25, 0.0, 0.0);	// 文字阴影;
	RectF layWatemarkRect2(pImg->GetWidth(), pImg->GetHeight() - 26, 0.0, 0.0);		// 文字原体;
	// 创建画布对象;
	Graphics *grap = Graphics::FromImage(pBitmap);
	// 绘制画布底色;
	if ( Ok != grap->Clear(Color(255,255,255,255)) )
		goto clear;
	// 设置图片显示质量;
	if ( Ok != grap->SetSmoothingMode(SmoothingModeAntiAlias) )
		goto clear;
	// 设置文本质量;
	if ( Ok != grap->SetTextRenderingHint(TextRenderingHintAntiAlias))
		goto clear;
	// 在画布上画原始图片;
	if ( Ok != grap->DrawImage(pImg, 0, 0, pImg->GetWidth(), pImg->GetHeight()) )
		goto clear;

	// 画水印阴影;
#ifdef UNICODE
	if ( Ok != grap->DrawString(lpWatemarkString, wcslen(lpWatemarkString), &ft, layWatemarkRect, &sf, &brush) )
#else
	if ( Ok != grap->DrawString(pText, wcslen(pText), &ft, layWatemarkRect, &sf, &brush) )
#endif
		goto clear;
	// 画水印文本;
	brush.SetColor(0x99ffffff);
#ifdef UNICODE
	if ( Ok != grap->DrawString(lpWatemarkString, wcslen(lpWatemarkString), &ft, layWatemarkRect2, &sf, &brush) )
#else
	if ( Ok != grap->DrawString(pText, wcslen(pText), &ft, layWatemarkRect, &sf, &brush) )
#endif
		goto clear;

	if ( grap )
		delete grap;

	return pBitmap;

clear:
	if ( grap )
		delete grap;

	if ( pBitmap )
		delete pBitmap;

	if ( pImg )
		delete pImg;

#ifndef UNICODE
	if (pText)
		delete []pText;
#endif

	return NULL;
}

BOOL IMGCommon::SaveBitmap(IN CDC *pDC, IN CBitmap* pBitmap, IN CONST INT& nBitdepth, IN const INT& nWidth, IN const INT& nHeight, IN LPCTSTR lpSavepath)
{
	// 计算出位图大小 =  （（宽 * 位宽 + 31）/ 32）* 4 * 高;
	DWORD dwBmpSize = ((nWidth*nBitdepth + 31) / 32) * 4 * nHeight;

	HANDLE hFile = CreateFile(lpSavepath, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		//WriteLog(_T("二维码位图创建失败"));
		return FALSE;
	}

	HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE | SEC_COMMIT, 0, 
		sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2 + dwBmpSize, NULL);
	LPBYTE lpbyMapView = (LPBYTE)MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, 0);

	ZeroMemory(lpbyMapView, sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2 + dwBmpSize);

	//结构体地址割付;

	LPBITMAPFILEHEADER pbfh = (LPBITMAPFILEHEADER)lpbyMapView;
	LPBITMAPINFO       pbmi = (LPBITMAPINFO)(lpbyMapView + sizeof(BITMAPFILEHEADER));
	LPVOID             pbdt = lpbyMapView + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2;

	// BITMAPFILEHEADER
	//pbfh->bfType      = (WORD) (('M' << 8) | 'B'); // "BM"
	// BMP类型,与上面同值;
	pbfh->bfType      = 0x4D42;
	pbfh->bfSize      = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2 + dwBmpSize;	// 文件总长;
	pbfh->bfReserved1 = 0;
	pbfh->bfReserved2 = 0;
	pbfh->bfOffBits   = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2;	// 位图数据相对于文件头的偏移量;

	// LPBITMAPINFO->BITMAPINFOHEADER
	pbmi->bmiHeader.biSize			= sizeof(BITMAPINFOHEADER);
	pbmi->bmiHeader.biWidth			= nWidth;
	pbmi->bmiHeader.biHeight		= nHeight;
	pbmi->bmiHeader.biPlanes		= 1;
	pbmi->bmiHeader.biBitCount		= nBitdepth;			// 位深度 1;
	pbmi->bmiHeader.biCompression	= BI_RGB;
	pbmi->bmiHeader.biSizeImage		= dwBmpSize;
	pbmi->bmiHeader.biXPelsPerMeter = 3780;
	pbmi->bmiHeader.biYPelsPerMeter = 3780;
	pbmi->bmiHeader.biClrUsed		= 0;
	pbmi->bmiHeader.biClrImportant	= 0;

	// 放大到指定的像素宽高;
	CDC* pWorkDC = new CDC;
	pWorkDC->CreateCompatibleDC(NULL);

	CBitmap* pWorkBitmap = new CBitmap;
	pWorkBitmap->CreateBitmap(nWidth, nHeight, 1, 1, NULL);

	CBitmap* pOldBitmap = pWorkDC->SelectObject(pWorkBitmap);
	pWorkDC->StretchBlt(0, 0, nWidth, nHeight, pDC, 0, 0, nWidth, nHeight, SRCCOPY);

	GetDIBits(pWorkDC->m_hDC, (HBITMAP)*pWorkBitmap, 0, nHeight, pbdt, pbmi, DIB_RGB_COLORS);

	pWorkDC->SelectObject(pOldBitmap);
	delete pWorkBitmap;
	delete pWorkDC;

	UnmapViewOfFile(lpbyMapView);
	CloseHandle(hFileMapping);
	CloseHandle(hFile);

	return TRUE;
}

BOOL IMGCommon::SaveBitmap2(IN CDC *pDC, IN CBitmap* pBitmap, IN CONST INT& nBitdepth, IN const INT& nWidth, IN const INT& nHeight, IN LPCTSTR lpSavepath)
{
	DWORD dwPaletteSize = 0;	//调色板大小;
	DWORD dwbmdibitSize = 0;
	WORD  wbitsCount = 0;		//位图中每个像素所占字节数;
	if( nBitdepth <= 1 )
		wbitsCount = 1;
	if( nBitdepth <= 4 )
		wbitsCount = 4;
	if( nBitdepth <= 8 )
		wbitsCount = 8;
	if( nBitdepth <= 16 )
		wbitsCount = 16;
	if( nBitdepth <= 24 )
		wbitsCount = 24;
	else 
		wbitsCount = 32;

	if( wbitsCount <= 8 )
		dwPaletteSize = (1 << wbitsCount) * sizeof(RGBQUAD);

	// 计算出位图大小 =  （（宽 * 位宽 + 31）/ 32）* 4 * 高;
	DWORD dwBmpSize = ((nWidth*wbitsCount + 31) / 8) * nHeight;

	HANDLE hFile = CreateFile(lpSavepath, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		//WriteLog(_T("二维码位图创建失败"));
		return FALSE;
	}

	HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE | SEC_COMMIT, 0, 
		//sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2 + dwBmpSize, NULL);
		sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmpSize, NULL);
	LPBYTE lpbyMapView = (LPBYTE)MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, 0);

	//ZeroMemory(lpbyMapView, sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2 + dwBmpSize);
	ZeroMemory(lpbyMapView, sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmpSize);

	//结构体地址割付;

	LPBITMAPFILEHEADER pbfh = (LPBITMAPFILEHEADER)lpbyMapView;
	LPBITMAPINFO       pbmi = (LPBITMAPINFO)(lpbyMapView + sizeof(BITMAPFILEHEADER));
	LPVOID             pbdt = lpbyMapView + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmpSize;

	// BITMAPFILEHEADER
	//pbfh->bfType      = (WORD) (('M' << 8) | 'B'); // "BM"
	// BMP类型,与上面同值;
	pbfh->bfType      = 0x4D42;
	pbfh->bfSize      = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmpSize;	// 文件总长;
	pbfh->bfReserved1 = 0;
	pbfh->bfReserved2 = 0;
	pbfh->bfOffBits   = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize;	// 位图数据相对于文件头的偏移量;

	// LPBITMAPINFO->BITMAPINFOHEADER
	pbmi->bmiHeader.biSize			= sizeof(BITMAPINFOHEADER);
	pbmi->bmiHeader.biWidth			= nWidth;
	pbmi->bmiHeader.biHeight		= nHeight;
	pbmi->bmiHeader.biPlanes		= 1;
	pbmi->bmiHeader.biBitCount		= wbitsCount;			// 位深度 1;
	pbmi->bmiHeader.biCompression	= BI_RGB;
	pbmi->bmiHeader.biSizeImage		= dwBmpSize;
	pbmi->bmiHeader.biXPelsPerMeter = 3780;
	pbmi->bmiHeader.biYPelsPerMeter = 3780;
	pbmi->bmiHeader.biClrUsed		= 0;
	pbmi->bmiHeader.biClrImportant	= 0;

	// 放大到指定的像素宽高;
	CDC* pWorkDC = new CDC;
	pWorkDC->CreateCompatibleDC(NULL);

	CBitmap* pWorkBitmap = new CBitmap;
	pWorkBitmap->CreateBitmap(nWidth, nHeight, 1, 1, NULL);

	CBitmap* pOldBitmap = pWorkDC->SelectObject(pWorkBitmap);
	pWorkDC->StretchBlt(0, 0, nWidth, nHeight, pDC, 0, 0, nWidth, nHeight, SRCCOPY);

	GetDIBits(pWorkDC->m_hDC, (HBITMAP)*pWorkBitmap, 0, nHeight, pbdt, pbmi, DIB_RGB_COLORS);

	pWorkDC->SelectObject(pOldBitmap);
	delete pWorkBitmap;
	delete pWorkDC;

	UnmapViewOfFile(lpbyMapView);
	CloseHandle(hFileMapping);
	CloseHandle(hFile);

	return TRUE;
}

void IMGCommon::DrawString(IN CDC* pdc, IN CONST INT& nFontSize, IN LPCTSTR lpFontName, IN LPCTSTR lpString, IN OUT CRect &rcString)
{
	if ( !pdc || !lpString )
		return;

	LOGFONT log;
	// 设置字体字号;
	log.lfHeight = -MulDiv(nFontSize ? nFontSize : 9, GetDeviceCaps(pdc->GetSafeHdc(), LOGPIXELSY), 72);
	log.lfWidth = 0;
	log.lfEscapement = 0;   
	log.lfOrientation = 0;   
	log.lfWeight = FW_REGULAR;   
	log.lfItalic =  false;
	log.lfUnderline = false;   
	log.lfStrikeOut = 0;   
	log.lfCharSet = ANSI_CHARSET;
	log.lfOutPrecision = OUT_DEFAULT_PRECIS;   
	log.lfClipPrecision = CLIP_DEFAULT_PRECIS;   
	log.lfQuality = DEFAULT_QUALITY;
	log.lfPitchAndFamily = DEFAULT_PITCH || FF_ROMAN;  
	// 设置字体名称;
	_tcscpy_s(log.lfFaceName, (lpFontName && (lpFontName[0] != _T('\0'))) ? lpFontName : _T("Arial"));

	CFont cf;
	cf.CreateFontIndirect(&log);
	CFont *oldf = pdc->SelectObject(&cf);

	SIZE Size;
	GetTextExtentPoint32(pdc->GetSafeHdc(), lpString, _tcslen(lpString), &Size);
	rcString.SetRect(rcString.left, rcString.top, Size.cx + rcString.left, Size.cy + rcString.top);
	pdc->TextOut(rcString.left, rcString.top, lpString);
}
