#include "StdAfx.h" #include "IMGCommon.h" #include "IMGkernelGlobal.h" #include #include "StringProcess.h" 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); } /************************************************************************/ /* 函数:IsCorrectExt[6/1/2016 IT]; /* 描述:扩展名是否正确; /* 参数:; /* [IN] fext:要判断的扩展名; /* [OUT] lpMistakenExt:返回错误的扩展名; /* 返回:扩展名错误返回-1、扩展名为*.*返回0、扩展符合要求返回1; /* 注意:; /* 示例:; /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ INT IMGCommon::IsCorrectExt( IN const TString &fext, OUT TString* lpMistakenExt /* = NULL */ ) { if (fext.size() == 0) { IMGkernelGlobal::WriteTextLog(_T("要查找的扩展名字符空!")); return -1; } if (fext.find(_T("*.*")) != TString::npos) { IMGkernelGlobal::WriteTextLog(_T("要查找的扩展名为\"*.*\"")); return 0; } TString ext = IMGkernelGlobal::lowercase(fext); if (ext[ext.length() - 1] != _T('|')) ext.append(_T("|")); INT bRet = 1; CONST TString sCorrectExt = _T("*.jpg|*.jpeg|*.png|*.bmp|*.cr2|*.nef|*.raw|*.ra2|*.ofr|*.pef|*.sr2"); int nIndex = 0; do { nIndex = ext.find(_T('|')); if (nIndex != TString::npos) { if (sCorrectExt.find(ext.substr(0, nIndex)) == TString::npos) { if (lpMistakenExt) *lpMistakenExt = ext.substr(0, nIndex); bRet = -1; break; } ext = ext.substr(nIndex + 1); } } while (ext.find(_T('|')) != TString::npos); return bRet; } /************************************************************************/ /* 函数:ExtMerge[6/1/2016 IT]; /* 描述:合并扩展名; /* 参数:; /* [IN] ext1:要合并的扩展名1; /* [IN] ext2:要合并的扩展名2; /* [OUT] merge:合并后的扩展名; /* 返回:只合并合法的扩展名,若两扩展名都非法,返回FALSE; /* 注意:; /* 示例:; /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ BOOL IMGCommon::ExtMerge(IN CONST TString& ext1, IN CONST TString& ext2, OUT TString &merge) // 合并扩展名; { // 1.判断扩展名1合法性; INT nRet = IsCorrectExt(ext1); if ( nRet == -1 ) { nRet = IsCorrectExt(ext2); if ( nRet == -1) return FALSE; merge = ext2; return TRUE; } if (nRet == 0) { merge = _T("*.*"); return TRUE; } merge = ext1; // 2.判断扩展名2合法性; nRet = IsCorrectExt(ext2); if (nRet != 1) return TRUE; // 3.合并2扩展名; if (merge[merge.length() - 1] != _T('|')) merge.append(_T("|")); merge.append(ext2); return TRUE; } /************************************************************************/ /* 函数:GetFileName[6/1/2016 IT]; /* 描述:根据参数,获取参数中的文件名; /* 参数:; /* [IN] strfile:要获取文件名的全路径名; /* 返回:获取成功返回文件名,否则返回空; /* 注意:; /* 示例:; /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ CString IMGCommon::GetFileName(IN CONST CString& strfile) { CString name = _T(""); int nIndex = strfile.ReverseFind(_T('\\')); if (nIndex == -1) return _T(""); name = strfile.Mid(nIndex + 1); nIndex = name.ReverseFind(_T('.')); if (nIndex == -1) return _T(""); name = name.Mid(0, nIndex); return name; } /************************************************************************/ /* 函数:GetFilteringImg[6/1/2016 IT]; /* 描述:过滤掉扩展名不符合要求的文件名; /* 参数:; /* [IN] AryImgs:要被过滤的文件名数组; /* [IN] lpCopyExt:要保留的文件的扩展名; /* [IN] bPickoutThumbnail:是否剔除缩略图; /* 返回:void; /* 注意:; /* 示例:; /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ void IMGCommon::GetFilteringImg(IN CStringArray &AryImgs, IN LPCTSTR lpCopyExt, IN BOOL bPickoutThumbnail /*= TRUE*/) { if (AryImgs.GetSize() == 0 || lpCopyExt == NULL) return; // 获取复制扩展名; int nIndex = 0; TString strtmp; TString strCopyExt(lpCopyExt); if (strCopyExt.find(_T("*.*")) != TString::npos) return; strCopyExt.append(_T("|")); STR_VEC vtCopyExt; // 将所有扩展名解析到数组里; do { nIndex = strCopyExt.find(_T('|')); if (nIndex != TString::npos) { strtmp = strCopyExt.substr(0, nIndex); strCopyExt = strCopyExt.substr(nIndex + 1); if (strtmp.compare(_T("*.*"))) vtCopyExt.push_back(strtmp.substr(1)); } } while (strCopyExt.find(_T('|')) != TString::npos); // 过滤非复制扩展名的文件,同时去掉缩略图,保留指定复制扩展名的文件; for (int i = AryImgs.GetSize() - 1; i >= 0; i--) { BOOL bExsit = FALSE; for (STR_VEC::iterator itExt = vtCopyExt.begin(); itExt != vtCopyExt.end(); itExt++) { if (AryImgs.ElementAt(i).MakeLower().Find(itExt->c_str()) != -1) { bExsit = TRUE; break; } } if (!bExsit) { AryImgs.RemoveAt(i); continue; } if (bPickoutThumbnail) {// 这里应该去除"s"和"m"开头的缩略图;// 但新的做法是在订单里创建缩略图子文件夹;// 总而言之,都要去掉缩略图; nIndex = AryImgs.ElementAt(i).ReverseFind(_T('\\')); if (nIndex != -1) { strtmp = AryImgs.ElementAt(i).Mid(nIndex + 1); if (strtmp[0] == _T('s') || strtmp[0] == _T('m')) { AryImgs.RemoveAt(i); continue; } } } } } /************************************************************************/ /* 函数:GetFilteringImg[6/1/2016 IT]; /* 描述:过滤掉扩展名不符合要求的文件名; /* 参数:; /* [IN] vtImgs:要被过滤的文件名数组; /* [IN] lpCopyExt:要保留的文件的扩展名; /* [IN] bPickoutThumbnail:是否剔除缩略图; /* 返回:void; /* 注意:; /* 示例:; /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ void IMGCommon::GetFilteringImg(IN STR_VEC &vtImgs, IN LPCTSTR lpCopyExt, IN BOOL bPickoutThumbnail /*= TRUE*/) { if (vtImgs.size() == 0 || lpCopyExt == NULL) return; // 获取复制扩展名; int nIndex = 0; TString strtmp; TString strCopyExt(lpCopyExt); if (strCopyExt.find(_T("*.*")) != TString::npos) return; strCopyExt.append(_T("|")); STR_VEC vtCopyExt; // 将所有扩展名解析到数组里; do { nIndex = strCopyExt.find(_T('|')); if (nIndex != TString::npos) { strtmp = strCopyExt.substr(0, nIndex); strCopyExt = strCopyExt.substr(nIndex + 1); if (strtmp.compare(_T("*.*"))) vtCopyExt.push_back(strtmp); } } while (strCopyExt.find(_T('|')) != TString::npos); // 过滤非复制扩展名的文件,同时去掉缩略图,保留指定复制扩展名的文件; for (STR_VEC::iterator it = vtImgs.begin(); it != vtImgs.end();) { BOOL bExsit = FALSE; for (STR_VEC::iterator itExt = vtCopyExt.begin(); itExt != vtCopyExt.end(); itExt++) { if (IMGkernelGlobal::match(itExt->c_str(), it->c_str())) { bExsit = TRUE; break; } } if (!bExsit) { it = vtImgs.erase(it); continue; } if (bPickoutThumbnail) {// 这里应该去除"s"和"m"开头的缩略图;// 但新的做法是在订单里创建缩略图子文件夹;// 总而言之,都要去掉缩略图; nIndex = it->find_last_of(_T('\\')); if (nIndex != TString::npos) { strtmp = it->substr(nIndex + 1); if (strtmp[0] == _T('s') || strtmp[0] == _T('m')) { it = vtImgs.erase(it); continue; } } } it++; } } /************************************************************************/ /* 函数:SubgroupExt[6/1/2016 IT]; /* 描述:将指定的扩展名文件分离出来; /* 参数:; /* [IN] vtAllImgs:源,要被分离指定扩展名的文件路径数组; /* [IN] lpSubgroupExt:要分离出来的扩展名; /* [OUT] AryImgs:返回分离出来的文件路径数组; /* 返回:void; /* 注意:; /* 示例:; /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ void IMGCommon::SubgroupExt(IN STR_VEC &vtAllImgs, IN LPCTSTR lpSubgroupExt, OUT CStringArray &AryImgs) { if (vtAllImgs.size() == 0 || lpSubgroupExt == NULL) return; // 获取复制扩展名; int nIndex = 0; TString strtmp; TString strSubgroupExt(lpSubgroupExt); if (strSubgroupExt.find(_T("*.*")) != TString::npos) { for (STR_VEC::iterator it = vtAllImgs.begin(); it != vtAllImgs.end(); it++) AryImgs.Add(CString(it->c_str())); return; } strSubgroupExt.append(_T("|")); STR_VEC vtSubgroupExt; // 将所有扩展名解析到数组里; do { nIndex = strSubgroupExt.find(_T('|')); if (nIndex != TString::npos) { strtmp = strSubgroupExt.substr(0, nIndex); strSubgroupExt = strSubgroupExt.substr(nIndex + 1); if (strtmp.compare(_T("*.*"))) vtSubgroupExt.push_back(strtmp); } } while (strSubgroupExt.find(_T('|')) != TString::npos); // 过滤非复制扩展名的文件,同时去掉缩略图,保留指定复制扩展名的文件; for (STR_VEC::iterator it = vtAllImgs.begin(); it != vtAllImgs.end(); it++) { BOOL bExsit = FALSE; for (STR_VEC::iterator itExt = vtSubgroupExt.begin(); itExt != vtSubgroupExt.end(); itExt++) { if (IMGkernelGlobal::match(itExt->c_str(), it->c_str())) { #if 1// 这里应该去除"s"和"m"开头的缩略图;// 但新的做法是在订单里创建缩略图子文件夹;// 总而言之,都要去掉缩略图; nIndex = it->find_last_of(_T('\\')); if (nIndex != TString::npos) { strtmp = it->substr(nIndex + 1); if (strtmp[0] == _T('s') || strtmp[0] == _T('m')) { continue; } } #endif AryImgs.Add(CString(it->c_str())); break; } } } } void IMGCommon::SubgroupExt(IN STR_VEC &vtAllImgs, IN LPCTSTR lpSubgroupExt, IN STR_VEC &vtImgs) { if (vtAllImgs.size() == 0 || lpSubgroupExt == NULL) return; // 获取复制扩展名; int nIndex = 0; TString strtmp; TString strSubgroupExt(lpSubgroupExt); if (strSubgroupExt.find(_T("*.*")) != TString::npos) { for (STR_VEC::iterator it = vtAllImgs.begin(); it != vtAllImgs.end(); it++) vtImgs.push_back(*it); return; } strSubgroupExt.append(_T("|")); STR_VEC vtSubgroupExt; // 将所有扩展名解析到数组里; do { nIndex = strSubgroupExt.find(_T('|')); if (nIndex != TString::npos) { strtmp = strSubgroupExt.substr(0, nIndex); strSubgroupExt = strSubgroupExt.substr(nIndex + 1); if (strtmp.compare(_T("*.*"))) vtSubgroupExt.push_back(strtmp); } } while (strSubgroupExt.find(_T('|')) != TString::npos); // 过滤非复制扩展名的文件,同时去掉缩略图,保留指定复制扩展名的文件; for (STR_VEC::iterator it = vtAllImgs.begin(); it != vtAllImgs.end(); it++) { BOOL bExsit = FALSE; for (STR_VEC::iterator itExt = vtSubgroupExt.begin(); itExt != vtSubgroupExt.end(); itExt++) { if (IMGkernelGlobal::match(itExt->c_str(), it->c_str())) { #if 1// 这里应该去除"s"和"m"开头的缩略图;// 但新的做法是在订单里创建缩略图子文件夹;// 总而言之,都要去掉缩略图; nIndex = it->find_last_of(_T('\\')); if (nIndex != TString::npos) { strtmp = it->substr(nIndex + 1); if (strtmp[0] == _T('s') || strtmp[0] == _T('m')) { continue; } } #endif vtImgs.push_back(*it); break; } } } } ////////////////////////////////////////////////////////////////////////// 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, TRUE); 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; return LoadImgFromFile(pImg, lpPath); 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::LoadImgFromFile(IN Bitmap** pImg, LPCTSTR lpPath) { if ( !PathFileExists(lpPath) ) return FALSE; if ( *pImg ) delete *pImg; *pImg = NULL; #ifdef UNICODE *pImg = Bitmap::FromFile(lpPath); #else BSTR strtmp = _bstr_t(lpPath); *pImg = Bitmap::FromFile(strtmp); SysFreeString(strtmp); #endif return TRUE; } BOOL IMGCommon::LoadImgFromBuffer(IN Bitmap** 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 = Bitmap::FromStream(pstream); GlobalUnlock(hMemery); pstream->Release(); return TRUE; } */ ////////////////////////////////////////////////////////////////////////// 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))) { // 如果文件夹不存在,创建; SHCreateDirectoryEx(NULL, strNewfile.Left(nIndex), NULL); } 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())) { // 如果文件夹不存在,创建; SHCreateDirectoryEx(NULL, strNewfile.substr(0, nIndex).c_str(), NULL); } 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) { IMGkernelGlobal::WriteTextLog(_T("复制时放大图像,退出复制!")); 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) { IMGkernelGlobal::WriteTextLog(_T("复制时放大图像,退出复制!")); 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) { IMGkernelGlobal::WriteTextLog(_T("复制时放大图像,退出复制!")); 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) { IMGkernelGlobal::WriteTextLog(_T("复制时放大图像,退出复制!")); 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; } void IMGCommon::CopyWithExt(IN CONST TString& strfile, IN TString& strChange, IN STR_VEC& vtExts, IN BOOL bFailIfExists) { // 复制其他扩展名的相片; INT nIndex = 0; for (STR_VEC::iterator it = vtExts.begin(); it != vtExts.end(); it++) { TString strWithExt = IMGkernelGlobal::lowercase(strfile.c_str()); if (strWithExt.find(it->c_str()) != TString::npos) // 不复制本扩展名; continue; nIndex = strfile.find_last_of(_T('.')); if (nIndex != TString::npos) { //strWithExt.replace(nIndex,itExt->size(),itExt->c_str()); //strtmp.replace(strtmp.find_last_of(_T('.')), itExt->size(), itExt->c_str()); strWithExt.replace(nIndex, strfile.length() - nIndex, it->c_str()); nIndex = strChange.find_last_of(_T('.')); if ( nIndex != TString::npos ) { strChange.replace(nIndex, strChange.length() - nIndex, it->c_str()); if (!PathFileExists(strWithExt.c_str())) continue; if (!CopyFile(strWithExt.c_str(), strChange.c_str(), bFailIfExists)) { // 返回复制错误信息; //m_richlog.SetSel(-1, -1); //m_richlog.ReplaceSel( _T("复制相片时出错\r") ); } } } } } BOOL IMGCommon::CopyFileEx(IN TString& strExistFile, IN OUT TString& strNewFile, IN CONST DWORD& dwZoomPix, IN CONST INT& nCopyType) { if ( nCopyType == COPY_FAIL_IF_EXISTS ) {// 文件存在,不覆盖; if ( PathFileExists(strNewFile.c_str()) ) return TRUE; } else if ( nCopyType == COPY_OTHER_NAME_IF_EXISTS ) {// 文件存在,重命名; 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 }; StringCchPrintf(szNewFileName, _MAX_PATH, _T("%s"), strNewFile.c_str()); _tsplitpath_s(szNewFileName, szDrive, szDir, szFna, szExt); int nIndex = 1; //判断指定文件夹下某个文件是否存在 while (PathFileExists(szNewFileName)) { // 当副本很多时,这里会很慢,如 "001 (100).jpg",那么就要循环100次才生成"001 (101).jpg"; StringCchPrintf(szNewFileName, _MAX_PATH, _T("%s%s%s (%d)%s"), szDrive, szDir, szFna, nIndex++, szExt); } // 赋值返回; strNewFile = szNewFileName; } // 默认文件存在,直接覆盖; if ( PathFileExists(strNewFile.substr(0, strNewFile.find_last_of(_T('\\'))).c_str()) == FALSE ) { SHCreateDirectoryEx(NULL, strNewFile.substr(0, strNewFile.find_last_of(_T('\\'))).c_str(), NULL); } return ImgThumbnail(strExistFile.c_str(), dwZoomPix, strNewFile.c_str(), 100); } TString IMGCommon::CopyImage( IN TString &strSourceImg, IN LPCTSTR lpDestDirectory, IN CONST DWORD& dwZoomPix, IN CONST INT& nCopyType, IN CString strPerImgGoods, IN BOOL bGoodsWithName, IN LPCTSTR lpSeparator, IN BOOL bKeepbackWard, IN CONST INT &nLayers ) { // 判断源文件是否存在; if ( !PathFileExists(strSourceImg.c_str()) || !lpDestDirectory ) { IMGkernelGlobal::WriteTextLog(_T("%s-%s:参数无效"), __FILE__, __FUNCTION__); // 如果可以,使用SetLastError设置自定义的错误码和描述符;再通过GetLastError返回自定义的结果; return _T(""); } if ( !PathFileExists(lpDestDirectory) ) {// 目标路径不存在,创建; INT nRet = SHCreateDirectoryEx(NULL, lpDestDirectory, NULL); if ( ERROR_SUCCESS != nRet && ERROR_ALREADY_EXISTS != nRet) { IMGkernelGlobal::WriteTextLog(_T("创建目录失败,请确认是否有权限或路径名有效")); return _T(""); } } // 分隔出需要的文件夹层(即需要套系文件夹名或景点名); INT nIndex = 0; TString strSeparator; TString strNewImg = lpDestDirectory; if ( strNewImg[strNewImg.size() - 1] == _T('\\') ) { strNewImg = strNewImg.substr(0, strNewImg.size() - 1); } ////////////////////////////////////////////////////////////////////////// if ( lpSeparator == NULL ) { nIndex = strSourceImg.find_last_of(_T('\\')); if ( nIndex == TString::npos ) { IMGkernelGlobal::WriteTextLog(_T("未找到分层符")); return _T(""); } strSeparator = strSourceImg.substr(nIndex); } else { strSeparator = lpSeparator; strSeparator = IMGkernelGlobal::lowercase(strSeparator); nIndex = strSourceImg.find(strSeparator); if ( nIndex == TString::npos ) { IMGkernelGlobal::WriteTextLog(_T("未找到该分隔符")); return _T(""); } if ( bKeepbackWard ) {// 向后保留; strSeparator = strSourceImg.substr(nIndex + _tcslen(lpSeparator)); if ( strSeparator[0] != _T('\\') ) {// 如果截断后,还属于上层文件夹,继续截断; nIndex = strSeparator.find_first_of(_T('\\')); if ( nIndex != TString::npos ) { strSeparator = strSeparator.substr(nIndex+1); } else {// 如果没有找到文件夹分层符,返回空; IMGkernelGlobal::WriteTextLog(_T("无法找到文件夹分层符")); return _T(""); } } else { strSeparator = strSeparator.substr(1); } // 按层截取指定的文件夹名称; INT nCurLayer = nLayers; if ( nCurLayer != 0 ) { do{ nIndex = strSeparator.find_first_of(_T('\\')); if ( nIndex != TString::npos ) { strNewImg.append(_T("\\")); strNewImg.append(strSeparator.substr(0,nIndex)); strSeparator = strSeparator.substr(nIndex+1); nCurLayer--; } else { break; } }while(nCurLayer); } if( nCurLayer != 0 ) {// 不等于0,没找到相应的层; IMGkernelGlobal::WriteTextLog(_T("没有找到相应层数文件夹")); return _T(""); } else { nIndex = strSeparator.find_last_of(_T('\\')); if ( nIndex != TString::npos ) { strSeparator = strSeparator.substr(nIndex); } #if 0 nIndex = strSeparator.find_last_of(_T('.')); if ( nIndex != TString::npos ) { strNewImg.append(_T("\\")); strNewImg.append(strSeparator.substr(0,nIndex)); // 扩展名; strSeparator = strSeparator.substr(nIndex); } #endif } } else {// 向前保留; strSeparator = strSourceImg.substr(0, nIndex); if ( strSeparator[strSeparator.size() - 1] != _T('\\') ) { nIndex = strSeparator.find_last_of(_T('\\')); if ( nIndex != TString::npos ) { strSeparator = strSeparator.substr(0, nIndex); } else {// 如果没有找到文件夹分层符,返回空; IMGkernelGlobal::WriteTextLog(_T("无法找到文件夹分层符")); return _T(""); } } else { strSeparator = strSourceImg.substr(0,strSeparator.size()-1); } // 按层截取指定的文件夹名称; INT nCurLayer = nLayers; if ( nCurLayer != 0 ) { do{ nIndex = strSeparator.find_last_of(_T('\\')); if ( nIndex != TString::npos ) { strNewImg.append(strSeparator.substr(nIndex)); strSeparator = strSeparator.substr(0,nIndex); nCurLayer--; } else { break; } }while(nCurLayer); } if ( nCurLayer != 0 ) {// 不等于0,没找到相应的层; IMGkernelGlobal::WriteTextLog(_T("没有找到相应层数文件夹")); return _T(""); } else { nIndex = strSourceImg.find_last_of(_T('\\')); if ( nIndex != TString::npos ) { strSeparator = strSourceImg.substr(nIndex+1); #if 0 nIndex = strSeparator.find_last_of(_T('.')); if ( nIndex != TString::npos ) { strNewImg.append(_T("\\")); strNewImg.append(strSeparator.substr(0,nIndex)); // 扩展名; strSeparator = strSeparator.substr(nIndex); } #endif } } } } ////////////////////////////////////////////////////////////////////////// // strNewImg + [] + strSeparator = 新文件名; // 处理strPerImgGoods与新文件名的合并; if ( bGoodsWithName ) { nIndex = strSeparator.find_last_of(_T('.')); if ( nIndex != TString::npos ) { strNewImg.append(_T("\\")); strNewImg.append(strSeparator.substr(0,nIndex)); // 扩展名; strSeparator = strSeparator.substr(nIndex); } strNewImg.append(_T("(")); strNewImg.append(strPerImgGoods.GetString()); strNewImg.append(_T(")")); strNewImg.append(strSeparator); if ( dwZoomPix == INVALID_COPY_PIX ) { if ( !IMGkernelGlobal::CopyFileEx(strSourceImg, strNewImg, nCopyType) ) { IMGkernelGlobal::WriteTextLog(_T("复制时出错")); return _T(""); } } else { if ( !CopyFileEx(strSourceImg, strNewImg, dwZoomPix, nCopyType) ) { IMGkernelGlobal::WriteTextLog(_T("复制时出错")); return _T(""); } } } else {// 分目录; CString strGoods; TString strtemp; strPerImgGoods += _T(";"); do { nIndex = strPerImgGoods.Find(_T(";")); if ( nIndex != -1 ) { strGoods = strPerImgGoods.Left(nIndex); strPerImgGoods = strPerImgGoods.Mid(nIndex+1); strtemp = strNewImg; strtemp.append(_T("\\")); strtemp.append(strGoods.GetString()); nIndex = strSeparator.find_last_of(_T('.')); if ( nIndex != TString::npos ) { strtemp.append(_T("\\")); strtemp.append(strSeparator.substr(0,nIndex)); } strtemp.append(strSeparator.substr(nIndex)); if ( dwZoomPix == INVALID_COPY_PIX ) { if ( !IMGkernelGlobal::CopyFileEx(strSourceImg, strtemp, nCopyType) ) { IMGkernelGlobal::WriteTextLog(_T("复制文件时出错")); continue; } } else { if ( !CopyFileEx(strSourceImg, strtemp, dwZoomPix, nCopyType)) { IMGkernelGlobal::WriteTextLog(_T("复制文件时出错")); continue; } } } } while ( strPerImgGoods.Find(_T(";")) != -1 ); } return strNewImg; } /************************************************************************/ /* 函数:CopyImageEx[3/6/2016 IT]; /* 描述:; /* 参数:; /* [IN] :; /* [OUT] :; /* [IN/OUT] :; /* 返回:void; /* 注意:; /* 示例:; /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ BOOL IMGCommon::CopyImageEx( IN TString &strSourceImg, IN LPCTSTR lpDestDirectory, IN CONST DWORD& dwZoomPix, IN CONST INT& nCopyType, IN STR_VEC& vtWithExt, IN CString strPerImgGoods, IN BOOL bGoodsWithName, IN LPCTSTR lpCustomInfo, IN LPCTSTR lpSeparator, IN BOOL bKeepbackWard, IN CONST INT &nLayers ) { // 判断源文件是否存在; if ( !PathFileExists(strSourceImg.c_str()) || !lpDestDirectory || strPerImgGoods.IsEmpty()) { IMGkernelGlobal::WriteTextLog(_T("%s-%s:参数无效"), __FILE__, __FUNCTION__); // 如果可以,使用SetLastError设置自定义的错误码和描述符;再通过GetLastError返回自定义的结果; return FALSE; } if ( !PathFileExists(lpDestDirectory) ) {// 目标路径不存在,创建; INT nRet = SHCreateDirectoryEx(NULL, lpDestDirectory, NULL) ; if ( ERROR_SUCCESS != nRet && ERROR_ALREADY_EXISTS != nRet ) { IMGkernelGlobal::WriteTextLog(_T("创建目录失败,请确认是否有权限或路径名有效")); return FALSE; } } // 分隔出需要的文件夹层(即需要套系文件夹名或景点名); INT nIndex = 0; TString strSeparator; TString strNewImg = lpDestDirectory; if ( strNewImg[strNewImg.size() - 1] == _T('\\') ) { strNewImg = strNewImg.substr(0, strNewImg.size() - 1); } ////////////////////////////////////////////////////////////////////////// if ( lpSeparator == NULL ) { #ifdef _THE_TEST_ IMGkernelGlobal::WriteTextLog(_T("分隔符为空~")); #endif nIndex = strSourceImg.find_last_of(_T('\\')); if ( nIndex == TString::npos ) { IMGkernelGlobal::WriteTextLog(_T("未找到分层符")); return FALSE; } strSeparator = strSourceImg.substr(nIndex); } else { #ifdef _THE_TEST_ IMGkernelGlobal::WriteTextLog(_T("分隔符:")); IMGkernelGlobal::WriteTextLog(lpSeparator); if (nLayers == 1) IMGkernelGlobal::WriteTextLog(_T("1层")); else IMGkernelGlobal::WriteTextLog(_T("0层")); #endif strSeparator = lpSeparator; strSeparator = IMGkernelGlobal::lowercase(strSeparator); nIndex = strSourceImg.find(strSeparator); if ( nIndex == TString::npos ) { IMGkernelGlobal::WriteTextLog(_T("未找到该分隔符")); return FALSE; } if ( bKeepbackWard ) {// 向后保留; strSeparator = strSourceImg.substr(nIndex + _tcslen(lpSeparator)); #if _THE_TEST_ IMGkernelGlobal::WriteTextLog(_T("向后保留:")); IMGkernelGlobal::WriteTextLog(strSeparator.c_str()); #endif if ( strSeparator[0] != _T('\\') ) {// 如果截断后,还属于上层文件夹,继续截断; nIndex = strSeparator.find_first_of(_T('\\')); if ( nIndex != TString::npos ) { strSeparator = strSeparator.substr(nIndex+1); } else {// 如果没有找到文件夹分层符,返回空; IMGkernelGlobal::WriteTextLog(_T("无法找到文件夹分层符")); return FALSE; } } else { strSeparator = strSeparator.substr(1); } // 按层截取指定的文件夹名称; INT nCurLayer = nLayers; if ( nCurLayer != 0 ) { if (nCurLayer == -1 ) nCurLayer = 65536; do{ nIndex = strSeparator.find_first_of(_T('\\')); if ( nIndex != TString::npos ) { strNewImg.append(_T("\\")); strNewImg.append(strSeparator.substr(0,nIndex)); strSeparator = strSeparator.substr(nIndex+1); nCurLayer--; } else { if ( nLayers == 1 ) nCurLayer--; break; } }while(nCurLayer); } if( nCurLayer != 0 ) {// 不等于0,没找到相应的层; #ifdef _THE_TEST_ IMGkernelGlobal::WriteTextLog(_T("分隔符=:")); IMGkernelGlobal::WriteTextLog(strSeparator.c_str()); IMGkernelGlobal::WriteTextLog(strNewImg.c_str()); #endif IMGkernelGlobal::WriteTextLog(_T("没有找到相应层数文件夹.1.")); return FALSE; } else { nIndex = strSeparator.find_last_of(_T('\\')); if ( nIndex != TString::npos ) { strSeparator = strSeparator.substr(nIndex); } } } else {// 向前保留; strSeparator = strSourceImg.substr(0, nIndex); if ( strSeparator[strSeparator.size() - 1] != _T('\\') ) { nIndex = strSeparator.find_last_of(_T('\\')); if ( nIndex != TString::npos ) { strSeparator = strSeparator.substr(0, nIndex); } else {// 如果没有找到文件夹分层符,返回空; IMGkernelGlobal::WriteTextLog(_T("无法找到文件夹分层符.2.")); return FALSE; } } else { strSeparator = strSourceImg.substr(0,strSeparator.size()-1); } // 按层截取指定的文件夹名称; INT nCurLayer = nLayers; if ( nCurLayer != 0 ) { do{ nIndex = strSeparator.find_last_of(_T('\\')); if ( nIndex != TString::npos ) { strNewImg.append(strSeparator.substr(nIndex)); strSeparator = strSeparator.substr(0,nIndex); nCurLayer--; } else { break; } }while(nCurLayer); } if ( nCurLayer != 0 ) {// 不等于0,没找到相应的层; IMGkernelGlobal::WriteTextLog(_T("没有找到相应层数文件夹.3.")); return FALSE; } else { nIndex = strSourceImg.find_last_of(_T('\\')); if ( nIndex != TString::npos ) { strSeparator = strSourceImg.substr(nIndex+1); } } } } ////////////////////////////////////////////////////////////////////////// // strNewImg + [] + strSeparator = 新文件名; // 处理strPerImgGoods与新文件名的合并; if ( bGoodsWithName ) { nIndex = strSeparator.find_last_of(_T('.')); if ( nIndex != TString::npos ) { strNewImg.append(_T("\\")); strNewImg.append(strSeparator.substr(0,nIndex)); // 扩展名; strSeparator = strSeparator.substr(nIndex); } strNewImg.append(_T("(")); if ( lpCustomInfo && lpCustomInfo[0] != _T('\0') ) { strNewImg.append(lpCustomInfo); strNewImg.append(_T(",")); } strNewImg.append(strPerImgGoods.GetString()); strNewImg.append(_T(")")); strNewImg.append(strSeparator); if ( dwZoomPix == INVALID_COPY_PIX ) { if ( !IMGkernelGlobal::CopyFileEx(strSourceImg, strNewImg, nCopyType) ) { IMGkernelGlobal::WriteTextLog(_T("复制时出错")); return FALSE; } CopyWithExt(strSourceImg, strNewImg, vtWithExt, FALSE); } else { if ( !CopyFileEx(strSourceImg, strNewImg, dwZoomPix, nCopyType) ) { IMGkernelGlobal::WriteTextLog(_T("复制时出错")); return FALSE; } CopyWithExt(strSourceImg, strNewImg, vtWithExt, FALSE); } } else {// 分目录; CString strGoods; TString strtemp; strPerImgGoods += _T(";"); do { nIndex = strPerImgGoods.Find(_T(";")); if ( nIndex != -1 ) { strGoods = strPerImgGoods.Left(nIndex); strPerImgGoods = strPerImgGoods.Mid(nIndex+1); strtemp = strNewImg; strtemp.append(_T("\\")); strtemp.append(strGoods.GetString()); nIndex = strSeparator.find_last_of(_T('.')); if ( nIndex != TString::npos ) { strtemp.append(_T("\\")); strtemp.append(strSeparator.substr(0,nIndex)); } strtemp.append(strSeparator.substr(nIndex)); if ( dwZoomPix == INVALID_COPY_PIX ) { if ( !IMGkernelGlobal::CopyFileEx(strSourceImg, strtemp, nCopyType) ) { IMGkernelGlobal::WriteTextLog(_T("复制文件时出错")); continue; } CopyWithExt(strSourceImg, strtemp, vtWithExt, FALSE); } else { if ( !CopyFileEx(strSourceImg, strtemp, dwZoomPix, nCopyType)) { IMGkernelGlobal::WriteTextLog(_T("复制文件时出错")); continue; } CopyWithExt(strSourceImg, strtemp, vtWithExt, FALSE); } } } while ( strPerImgGoods.Find(_T(";")) != -1 ); } return TRUE; } /************************************************************************/ /* 函数:ExportCropImageToFile 描述:导出裁剪相片; 参数: strSourceImg 源相片文件路径; strSaveDirectory 保存裁剪后的文件目录; nExportType 裁剪的操作类型; strCropInfo 裁剪信息(保存在[dindan].[size]字段中, 格式如:"225:5X7,1440,900,88,0,1352,900;", 内容如:相片名|裁剪方案|原片宽|原片高|裁剪left|裁剪top|裁剪bottom|裁剪rigth); lpSeparator 截取strSourceImg的分隔符; bKeepbackWard TRUE向后截取分隔符字符串,FALSE向前截取分隔符字符串; nLayers 返回: 注意: 示例: */ /************************************************************************/ BOOL IMGCommon::ExportCropImageToFile(IN CONST TString& strSourceImg, IN LPCTSTR lpSaveDirectory, IN CONST INT& nExportType, IN CString strCropInfo, IN LPCTSTR lpSeparator, IN BOOL bKeepbackWard, IN CONST INT &nLayers) { // 判断参数有效性; if ( !PathFileExists(strSourceImg.c_str()) ) { IMGkernelGlobal::WriteTextLog(_T("源相片文件无效")); return FALSE; } if ( !PathFileExists(lpSaveDirectory) ) { INT nRet = SHCreateDirectoryEx(NULL, lpSaveDirectory, NULL); if ( ERROR_SUCCESS != nRet && ERROR_ALREADY_EXISTS != nRet ) { IMGkernelGlobal::WriteTextLog(_T("生成目录失败")); return FALSE; } } // 分隔出需要的文件夹层(即需要套系文件夹名或景点名); INT nIndex = 0; TString strSeparator; TString strNewImg = lpSaveDirectory; if ( strNewImg[strNewImg.size() - 1] == _T('\\') ) { strNewImg = strNewImg.substr(0, strNewImg.size() - 1); } ////////////////////////////////////////////////////////////////////////// if ( lpSeparator == NULL ) { nIndex = strSourceImg.find_last_of(_T('\\')); if ( nIndex == TString::npos ) { IMGkernelGlobal::WriteTextLog(_T("未找到分层符")); return FALSE; } strSeparator = strSourceImg.substr(nIndex); } else { strSeparator = lpSeparator; strSeparator = IMGkernelGlobal::lowercase(strSeparator); nIndex = strSourceImg.find(strSeparator); if ( nIndex == TString::npos ) { IMGkernelGlobal::WriteTextLog(_T("未找到该分隔符")); return FALSE; } if ( bKeepbackWard ) {// 向后保留; strSeparator = strSourceImg.substr(nIndex + _tcslen(lpSeparator)); if ( strSeparator[0] != _T('\\') ) {// 如果截断后,还属于上层文件夹,继续截断; nIndex = strSeparator.find_first_of(_T('\\')); if ( nIndex != TString::npos ) { strSeparator = strSeparator.substr(nIndex+1); } else {// 如果没有找到文件夹分层符,返回空; IMGkernelGlobal::WriteTextLog(_T("无法找到文件夹分层符")); return FALSE; } } else { strSeparator = strSeparator.substr(1); } // 按层截取指定的文件夹名称; INT nCurLayer = nLayers; if ( nCurLayer != 0 ) { do{ nIndex = strSeparator.find_first_of(_T('\\')); if ( nIndex != TString::npos ) { strNewImg.append(_T("\\")); strNewImg.append(strSeparator.substr(0,nIndex)); strSeparator = strSeparator.substr(nIndex+1); nCurLayer--; } else { break; } }while(nCurLayer); } if( nCurLayer != 0 ) {// 不等于0,没找到相应的层; IMGkernelGlobal::WriteTextLog(_T("没有找到相应层数文件夹")); return FALSE; } else { nIndex = strSeparator.find_last_of(_T('\\')); if ( nIndex != TString::npos ) { strSeparator = strSeparator.substr(nIndex); } } } else {// 向前保留; strSeparator = strSourceImg.substr(0, nIndex); if ( strSeparator[strSeparator.size() - 1] != _T('\\') ) { nIndex = strSeparator.find_last_of(_T('\\')); if ( nIndex != TString::npos ) { strSeparator = strSeparator.substr(0, nIndex); } else {// 如果没有找到文件夹分层符,返回空; IMGkernelGlobal::WriteTextLog(_T("无法找到文件夹分层符")); return FALSE; } } else { strSeparator = strSourceImg.substr(0,strSeparator.size()-1); } // 按层截取指定的文件夹名称; INT nCurLayer = nLayers; if ( nCurLayer != 0 ) { do{ nIndex = strSeparator.find_last_of(_T('\\')); if ( nIndex != TString::npos ) { strNewImg.append(strSeparator.substr(nIndex)); strSeparator = strSeparator.substr(0,nIndex); nCurLayer--; } else { break; } }while(nCurLayer); } if ( nCurLayer != 0 ) {// 不等于0,没找到相应的层; IMGkernelGlobal::WriteTextLog(_T("没有找到相应层数文件夹")); return FALSE; } else { nIndex = strSourceImg.find_last_of(_T('\\')); if ( nIndex != TString::npos ) { strSeparator = strSourceImg.substr(nIndex+1); } } } } // 获取与源同名的裁剪信息; TString strName = IMGkernelGlobal::getfilename(strSourceImg); if ( strName.size() == 0 ) { IMGkernelGlobal::WriteTextLog(_T("获取文件名错误")); return FALSE; } CString strTemp = _T(""); do { // 225:5X7,1440,900,88,0,1352,900; nIndex = strCropInfo.Find(_T(';')); if ( nIndex != -1 ) { strTemp = strCropInfo.Left(nIndex); strCropInfo = strCropInfo.Mid(nIndex + 1); nIndex = strTemp.Find(_T(':')); if ( nIndex != -1 ) { if ( strTemp.Left(nIndex).CompareNoCase(strName.c_str()) == 0 ) {// 获取同名裁剪信息; AnalysisCropInfo(strName, strSourceImg, strNewImg.c_str(), strTemp); } } } } while (nIndex != -1); return TRUE; } BOOL IMGCommon::AnalysisCropInfo(IN TString &strName, IN CONST TString& strSourceImg, IN LPCTSTR lpSaveDirectory, IN CString strCropInfo) { CRect rcCrop; INT nIndex = 0; CString strCropScheme = _T(""); nIndex = strCropInfo.Find(_T(',')); strCropScheme = strCropInfo.Left(nIndex); // 裁剪方案; strCropInfo.Delete(0, nIndex + 1); // 裁剪方案; nIndex = strCropScheme.Find(_T(":")); if ( nIndex != -1 ) { strCropScheme = strCropScheme.Mid(nIndex+1); } // 裁剪缩放显示时的相片宽; nIndex = strCropInfo.Find(_T(',')); LONG SrcImageWid = _ttol(strCropInfo.Left(nIndex)); strCropInfo.Delete(0, nIndex + 1); // 裁剪缩放显示时的相片高; nIndex = strCropInfo.Find(_T(',')); LONG SrcImageHei = _ttol(strCropInfo.Left(nIndex)); strCropInfo.Delete(0, nIndex + 1); // 缩略显示时被裁剪的left坐标值; nIndex = strCropInfo.Find(_T(',')); rcCrop.left = _ttol(strCropInfo.Left(nIndex)); strCropInfo.Delete(0, nIndex + 1); // 缩略显示时被裁剪的top坐标值; nIndex = strCropInfo.Find(_T(',')); rcCrop.top = _ttol(strCropInfo.Left(nIndex)); strCropInfo.Delete(0, nIndex + 1); // 缩略显示时被裁剪的right坐标值; nIndex = strCropInfo.Find(_T(',')); rcCrop.right = _ttol(strCropInfo.Left(nIndex)); strCropInfo.Delete(0, nIndex + 1); // 缩略显示时被裁剪的bottom坐标值; rcCrop.bottom = _ttol(strCropInfo); Image *pImgCrop = NULL; if ( !LoadImgFromBuffer(&pImgCrop, strSourceImg.c_str()) || pImgCrop == NULL ) { IMGkernelGlobal::WriteTextLog(_T("加载相片失败")); return FALSE; } if ( pImgCrop->GetWidth() == 0 ) { IMGkernelGlobal::WriteTextLog(_T("相片宽为0,存在未知错误")); return FALSE; } // 旋转原图Image对象,使之正放; INT nOrientation = GetOrientation(pImgCrop); if ( nOrientation == 8 ) { pImgCrop->RotateFlip(Rotate270FlipNone); } else if ( nOrientation == 6 ) { pImgCrop->RotateFlip(Rotate90FlipNone); } // 计算出选片时缩略图与原图的缩放比例; FLOAT fscal = 1.0; fscal *= (float)pImgCrop->GetWidth() / (float)SrcImageWid; // 缩略的裁剪位置*缩略比例=原片裁剪位置; rcCrop.left *= fscal; rcCrop.right *= fscal; rcCrop.top *= fscal; rcCrop.bottom *= fscal; TString strSaveDirectory = lpSaveDirectory; if (strSaveDirectory[strSaveDirectory.length() - 1] != _T('\\')) strSaveDirectory.append(_T("\\")); strSaveDirectory.append(_T("裁剪结果")); strSaveDirectory.append(_T("\\")); strSaveDirectory.append(strName); strSaveDirectory.append(_T(":")); strSaveDirectory.append(strCropScheme.GetString()); strSaveDirectory.append(_T(".jpg")); Bitmap bp(rcCrop.Width(), rcCrop.Height()); Graphics *graphic = Graphics::FromImage(&bp); 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(pImgCrop, RectF(0, 0, rcCrop.Width(), rcCrop.Height()), rcCrop.left, rcCrop.top, rcCrop.Width(), rcCrop.Height(), UnitPixel); if (pImgCrop) delete pImgCrop; if ( graphic) delete graphic; return SaveImg2newfile(&bp, strSaveDirectory, 100); } BOOL IMGCommon::CropImgToFile(IN CONST TString& strImgpath, IN TString& strCropFile, IN CRect& rcCrop) { if ( !PathFileExists(strImgpath.c_str()) ) { return FALSE; } Image *pImgCrop = NULL; if ( !LoadImgFromBuffer(&pImgCrop, strImgpath.c_str()) || pImgCrop == NULL ) { IMGkernelGlobal::WriteTextLog(_T("加载相片失败")); return FALSE; } if ( pImgCrop->GetWidth() == 0 ) { IMGkernelGlobal::WriteTextLog(_T("相片宽为0,存在未知错误")); return FALSE; } INT nOrientation = GetOrientation(pImgCrop); if ( nOrientation == 8 ) { pImgCrop->RotateFlip(Rotate270FlipNone); } else if ( nOrientation == 6 ) { pImgCrop->RotateFlip(Rotate90FlipNone); } Bitmap bp(rcCrop.Width(), rcCrop.Height()); Graphics *graphic = Graphics::FromImage(&bp); 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(pImgCrop, RectF(0, 0, rcCrop.Width(), rcCrop.Height()), rcCrop.left, rcCrop.top, rcCrop.Width(), rcCrop.Height(), UnitPixel); delete pImgCrop; delete graphic; return SaveImg2newfile(&bp, strCropFile, 100); } 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) ) { INT nRet = SHCreateDirectoryEx(NULL, strImgs, NULL); if ( ERROR_SUCCESS == nRet || ERROR_ALREADY_EXISTS == nRet ) { 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) ) { INT nRet = SHCreateDirectoryEx(NULL, strImgs, NULL); if ( ERROR_SUCCESS == nRet || ERROR_ALREADY_EXISTS == nRet ) { 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 = StringProcess::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 = StringProcess::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; } /************************************************************************/ /* 函数:SaveBitmapEx[10/17/2016 IT]; /* 描述:将CDC上的位图保存成文件; /* 参数:; /* [IN] :; /* [OUT] :; /* [IN/OUT] :; /* 返回:void; /* 注意:位图大小 = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 调色板大小(16、24、32位深的调色板大小为0) + 位图数据大小; /* 示例:; /* /* 修改:; /* 日期:; /* 内容:; /************************************************************************/ BOOL IMGCommon::SaveBitmapEx(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 dwBmBitsSize = 0; // 位图中像素字节大小; DWORD dwDIBSize = 0; // 位图文件大小; WORD wBitsCount = 0; // 当前显示分辨率下每个像素所占字节数; if( nBitdepth <= 1 ) wBitsCount = 1; else if( nBitdepth <= 4 ) wBitsCount = 4; else if( nBitdepth <= 8 ) wBitsCount = 8; else if( nBitdepth <= 16 ) wBitsCount = 16; else if( nBitdepth <= 24 ) wBitsCount = 24; else wBitsCount = 32; // 计算出调色板大小; if( wBitsCount <= 8 ) dwPaletteSize = (1 << wBitsCount) * sizeof(RGBQUAD); // 计算出位图数据大小 = ((宽 * 位宽 + 31)/ 32)* 4 * 高; dwBmBitsSize = ((nWidth*wBitsCount + 31) / 8) * nHeight; // 计算出位图文件大小; dwDIBSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmBitsSize; ////////////////////////////////////////////////////////////////////////// // 根据新位图来创建位图文件; HANDLE hFile = CreateFile(lpSavepath, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { return FALSE; } HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE | SEC_COMMIT, 0, dwDIBSize, NULL); LPBYTE lpbyMapView = (LPBYTE)MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, 0); ZeroMemory(lpbyMapView, dwDIBSize); //结构体地址割付; LPBITMAPFILEHEADER pbfh = (LPBITMAPFILEHEADER)lpbyMapView; LPBITMAPINFO pbmi = (LPBITMAPINFO)(lpbyMapView + sizeof(BITMAPFILEHEADER)); LPVOID pbdt = lpbyMapView + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize; // BITMAPFILEHEADER // pbfh->bfType = (WORD) (('M' << 8) | 'B'); // "BM" // BMP类型,与上面同值; pbfh->bfType = 0x4D42; pbfh->bfSize = dwDIBSize; // 文件总长; pbfh->bfReserved1 = 0; pbfh->bfReserved2 = 0; pbfh->bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + (DWORD)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; // 位深度; pbmi->bmiHeader.biCompression = BI_RGB; pbmi->bmiHeader.biSizeImage = dwBmBitsSize; // 位图数据大小; 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->GetSafeHdc(), (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); } HICON IMGCommon::GetFileIcon(IN const CString& strFilePath, IN BOOL bLarge) { SHFILEINFO SHFI; ZeroMemory(&SHFI, sizeof(SHFI)); DWORD_PTR ret = ::SHGetFileInfo(strFilePath, 0, &SHFI, sizeof(SHFI), SHGFI_ICON | (bLarge ? SHGFI_LARGEICON : SHGFI_SMALLICON)); if (ret != 0) { return SHFI.hIcon; } return NULL; }