IMGCommon.cpp 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558
  1. #include "StdAfx.h"
  2. #include "IMGCommon.h"
  3. #include <strsafe.h>
  4. #include "CharEncoding.h"
  5. #ifdef _DEBUG
  6. #define new DEBUG_NEW
  7. #endif
  8. const ColorMatrix _ClrMatrix =
  9. {
  10. 1.0, 0.0, 0.0, 0.0, 0.0,
  11. 0.0, 1.0, 0.0, 0.0, 0.0,
  12. 0.0, 0.0, 0.3, 0.0, 0.0,
  13. 0.0, 0.0, 0.0, 1.0, 0.0,
  14. 0.0, 0.0, 0.0, 0.0, 1.0,
  15. };
  16. ULONG_PTR IMGCommon::m_gdiplusToken;
  17. IMGCommon::IMGCommon(void)
  18. {
  19. GdiplusStartupInput gdiplusStartupInput;
  20. GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
  21. }
  22. IMGCommon::~IMGCommon(void)
  23. {
  24. Gdiplus::GdiplusShutdown(m_gdiplusToken);
  25. }
  26. /************************************************************************/
  27. /* 函数:IsValidpath[3/20/2016 IT];
  28. /* 描述:判断一个路径是否是本地可以盘符或可用的网络路径;
  29. /* 参数:;
  30. /* [IN] strPath:要判断的路径;
  31. /* 返回:盘符或网络路径有效返回TRUE;
  32. /* 注意:;
  33. /* 示例:;
  34. /*
  35. /* 修改:;
  36. /* 日期:;
  37. /* 内容:;
  38. /************************************************************************/
  39. BOOL IMGCommon::IsValidpath(IN CONST TString &strPath)
  40. {
  41. // 文件表现形式有三种:
  42. // 1.本地形式: C:\myfolder\you
  43. // 2.共享形式: \\192.168.1.112\myfolder\\you
  44. if (strPath.size() < 2) return FALSE;
  45. // 含":"为本地路径;
  46. if (strPath[1] == _T(':'))
  47. {
  48. DWORD dwDiskType = 0;
  49. dwDiskType = GetDriveType(strPath.substr(0, 3).c_str());
  50. switch (dwDiskType)
  51. {
  52. case DRIVE_UNKNOWN: // 未知驱动盘符;
  53. case DRIVE_NO_ROOT_DIR: // 没有根目录;
  54. //case DRIVE_REMOVABLE: // 移动存储设备盘符;
  55. // case DRIVE_FIXED: // 硬盘;
  56. case DRIVE_CDROM: // CD盘符;
  57. case DRIVE_RAMDISK: // ;
  58. return FALSE;
  59. break;
  60. }
  61. }
  62. else if (strPath.substr(0, 2).find(_T("\\\\")) != TString::npos)
  63. {
  64. // 共享路径;
  65. TString strtmp = strPath.substr(2);
  66. int n = strPath.substr(2).find(_T("\\"));
  67. if (n == TString::npos)
  68. return FALSE;
  69. strtmp = strPath.substr(0, n + 2);
  70. // 需要判断网络路径可用否;
  71. DWORD dwRet = 0;
  72. NETRESOURCE nr;
  73. memset(&nr, 0, sizeof(nr));
  74. nr.dwScope = RESOURCE_CONNECTED;
  75. nr.dwType = RESOURCETYPE_ANY;
  76. nr.dwDisplayType = RESOURCEDISPLAYTYPE_GENERIC;
  77. nr.dwUsage = RESOURCEUSAGE_CONNECTABLE;
  78. #ifndef UNICODE
  79. nr.lpRemoteName = (LPSTR)strtmp.c_str();
  80. #else
  81. nr.lpRemoteName = (LPWSTR)(strtmp.c_str());
  82. #endif
  83. dwRet = WNetAddConnection2(&nr, NULL, NULL, CONNECT_UPDATE_PROFILE);
  84. if (dwRet == ERROR_BAD_NETPATH)// 无效的网络路径,表示没有这个网络地址;
  85. return FALSE;
  86. else if (dwRet == ERROR_LOGON_FAILURE)// 登陆这个网络路径失败,因为当前用户名和密码错误; 没有权限;
  87. return FALSE;
  88. }
  89. return TRUE;
  90. }
  91. 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)
  92. {
  93. int i = 0;
  94. int npoint = 0; // '.'
  95. int nsprit = 0; // '\\'
  96. int ncolon = 0; // ':'
  97. int ntimes = 0;
  98. int nlen = _tcslen(path);
  99. while (nlen > i++)
  100. {
  101. if (path[i] == _T(':') && !ncolon )
  102. {
  103. ncolon = i;
  104. }
  105. else if (path[i] == _T('\\'))
  106. {
  107. if ( ncolon )
  108. {// 本地目录;
  109. if ( i == ncolon+1 )
  110. continue;
  111. nsprit = i;
  112. ntimes++;
  113. if (nTimes == ntimes) break;
  114. }
  115. else
  116. {// 网络路径;
  117. if ( i == 0 || i == 1 )
  118. continue;
  119. nsprit = i;
  120. ntimes++;
  121. if (nTimes == ntimes-1) break;
  122. }
  123. }
  124. }
  125. memcpy_s(drive, driveNumberOfElements*sizeof(TCHAR), path, (ncolon + 1)*sizeof(TCHAR));
  126. memcpy_s(dir, dirNumberOfElements*sizeof(TCHAR), &path[ncolon + 1], (nsprit - ncolon)*sizeof(TCHAR));
  127. }
  128. /************************************************************************/
  129. /* 函数:CreateDirectoryEx,多字节版本,支持UNICODE[9/13/2016 IT];
  130. /* 描述:创建目录及子目录文件夹;
  131. /* 参数:;
  132. /* [IN] lpDestDirectory:目录,必须是"E:\lyfzdb\数据\"格式,目录最后必须有"\",否则最后一个子目录无法创建!建议使用系统_tsplitpath来分隔目录,这样会保存最后一个"\"斜杠;
  133. /* 返回:成功创建返回TRUE;
  134. /* 注意:;
  135. /* 示例:;
  136. /*
  137. /* 修改:;
  138. /* 日期:;
  139. /* 内容:;
  140. /************************************************************************/
  141. BOOL IMGCommon::CreateDirectoryEx(IN LPCTSTR lpNewDirectory)
  142. {
  143. // 判断路径有效性 ;
  144. if (!lpNewDirectory || !IsValidpath(lpNewDirectory)) return FALSE;
  145. BOOL bExists = FALSE;
  146. TCHAR szNewFileName[_MAX_PATH] = { 0 };
  147. TCHAR szDrive[_MAX_DRIVE] = { 0 };
  148. TCHAR szDir[_MAX_DIR] = { 0 };
  149. TCHAR szFna[_MAX_FNAME] = { 0 };
  150. TCHAR szExt[_MAX_EXT] = { 0 };
  151. TCHAR szNewDirectory[_MAX_PATH] = { 0 };
  152. if (lpNewDirectory[_tcslen(lpNewDirectory) - 1] != _T('\\'))
  153. StringCchPrintf(szNewDirectory, _MAX_PATH, _T("%s\\"), lpNewDirectory);
  154. else
  155. StringCchPrintf(szNewDirectory, _MAX_PATH, _T("%s"), lpNewDirectory);
  156. int nIndex = 0;
  157. do
  158. {
  159. bExists = PathFileExists(szNewDirectory);
  160. if (!bExists)
  161. {
  162. memset(szDrive, 0, _MAX_DRIVE*sizeof(TCHAR));
  163. memset(szDir, 0, _MAX_DIR*sizeof(TCHAR));
  164. memset(szFna, 0, _MAX_FNAME*sizeof(TCHAR));
  165. memset(szExt, 0, _MAX_EXT*sizeof(TCHAR));
  166. Splitpath(szNewDirectory, szDrive, _MAX_DRIVE, szDir, _MAX_DIR, ++nIndex);
  167. StringCchPrintf(szNewFileName, _MAX_PATH, _T("%s%s"), szDrive, szDir);
  168. if (!CreateDirectory(szNewFileName, NULL))
  169. {
  170. DWORD dwError = GetLastError();
  171. switch (dwError)
  172. {
  173. case ERROR_PATH_NOT_FOUND: // 路径未找到,上一层目录未创建导致该错误;
  174. case ERROR_ACCESS_DENIED: // 没有权限访问;
  175. case ERROR_BAD_NET_NAME: // 错误的网络名称;
  176. //case ERROR_BAD_PATHNAME: //
  177. //WriteTextLog(_T("创建目录失败:%s"), GetErrorInfo(dwError));
  178. return FALSE;
  179. break;
  180. case ERROR_ALREADY_EXISTS: // 文件存在,不需要创建;
  181. break;
  182. default:
  183. //WriteTextLog(_T("创建目录失败:%s"), GetErrorInfo(dwError));
  184. break;
  185. }
  186. }
  187. }
  188. } while (!bExists);
  189. return TRUE;
  190. }
  191. //////////////////////////////////////////////////////////////////////////
  192. BOOL IMGCommon::LoadImgFromFile(IN Image** pImg, LPCTSTR lpPath)
  193. {
  194. if ( !PathFileExists(lpPath) )
  195. return FALSE;
  196. if ( *pImg )
  197. delete *pImg;
  198. *pImg = NULL;
  199. #ifdef UNICODE
  200. *pImg = Image::FromFile(lpPath);
  201. #else
  202. BSTR strtmp = _bstr_t(lpPath);
  203. *pImg = Image::FromFile(strtmp);
  204. SysFreeString(strtmp);
  205. #endif
  206. return (*pImg ? TRUE : FALSE);
  207. }
  208. BOOL IMGCommon::LoadImgFromBuffer(IN Image** pImg, IN BYTE* pBuffer, IN CONST INT& nBufLen)
  209. {
  210. if ( pBuffer == NULL )
  211. return FALSE;
  212. if ( *pImg )
  213. delete *pImg;
  214. *pImg = NULL;
  215. HGLOBAL hMemery = GlobalAlloc(GMEM_MOVEABLE, nBufLen);
  216. if ( hMemery == NULL )
  217. return FALSE;
  218. BYTE *pMem = (BYTE*)GlobalLock(hMemery);
  219. memcpy(pMem, pBuffer, nBufLen);
  220. IStream *pstream = NULL;
  221. CreateStreamOnHGlobal(hMemery, TRUE, &pstream);
  222. *pImg = Image::FromStream(pstream);
  223. GlobalUnlock(hMemery);
  224. pstream->Release();
  225. return (*pImg ? TRUE : FALSE);
  226. }
  227. // 先以只读方式从文件中读取二进制流出来,可以做到不独占文件;
  228. BOOL IMGCommon::LoadImgFromBuffer(IN Image** pImg, LPCTSTR lpPath)
  229. {
  230. if ( !PathFileExists(lpPath) )
  231. return FALSE;
  232. if ( *pImg )
  233. delete *pImg;
  234. *pImg = NULL;
  235. CFile fp;
  236. CFileException e;
  237. BOOL bRet = FALSE;
  238. if ( fp.Open(lpPath, CFile::modeRead, &e))
  239. {
  240. DWORD dwLength = (DWORD)fp.GetLength();
  241. BYTE *pData = new BYTE[dwLength];
  242. fp.Read(pData,dwLength);
  243. fp.Close();
  244. bRet = LoadImgFromBuffer(pImg, pData, dwLength);
  245. if( pData )
  246. delete []pData;
  247. }
  248. return bRet;
  249. }
  250. /************************************************************************/
  251. /* 函数:LoadImgFromResource[9/21/2016 IT];
  252. /* 描述:从资源中加载;
  253. /* 参数:;
  254. /* [IN] :;
  255. /* [OUT] :;
  256. /* [IN/OUT] :;
  257. /* 返回:void;
  258. /* 注意:;
  259. /* 示例:;
  260. /*
  261. /* 修改:;
  262. /* 日期:;
  263. /* 内容:;
  264. /************************************************************************/
  265. Image* IMGCommon::LoadImgFromResource(IN HMODULE hModule, IN LPCTSTR lpName, IN LPCTSTR lpType)
  266. {
  267. HGLOBAL hGlobal = NULL;
  268. HRSRC hSource = NULL;
  269. LPVOID lpBuffer = NULL;
  270. DWORD dwSize = 0;
  271. // 1.定位我们的自定义资源,这里因为我们是从本模块定位资源,所以将句柄简单地置为NULL即可
  272. hSource = FindResource(hModule, lpName, lpType);
  273. if (hSource == NULL)
  274. {
  275. _tprintf(_T("载入资源失败:%s"), lpName);
  276. return NULL;
  277. }
  278. // 2.获取资源的大小;
  279. dwSize = (UINT)SizeofResource(hModule, hSource);
  280. // 3.加载资源;
  281. hGlobal = LoadResource(hModule, hSource);
  282. if (hGlobal == NULL)
  283. {
  284. _tprintf(_T("载入资源失败:%s"), lpName);
  285. return NULL;
  286. }
  287. // 4.锁定资源,获取buffer;
  288. lpBuffer = LockResource(hGlobal);
  289. if (lpBuffer == NULL)
  290. {
  291. _tprintf(_T("载入资源失败:%s"), lpName);
  292. return NULL;;
  293. }
  294. // lpFileFullName需要先判断文件是否存在??不需要;
  295. Image *pImg = NULL;
  296. LoadImgFromBuffer(&pImg, (BYTE*)lpBuffer, dwSize);
  297. UnlockResource(hGlobal);
  298. FreeResource(hGlobal);
  299. return pImg;
  300. }
  301. BOOL IMGCommon::GetOrientation(IN Image *pImg)
  302. {
  303. if (pImg == NULL) return FALSE;
  304. UINT totalBufferSize;
  305. UINT numProperties;
  306. pImg->GetPropertySize(&totalBufferSize, &numProperties);
  307. // Allocate the buffer that will receive the property items.
  308. PropertyItem* pAllItems = (PropertyItem*)malloc(totalBufferSize);
  309. // Fill the buffer.
  310. pImg->GetAllPropertyItems(totalBufferSize, numProperties, pAllItems);
  311. // Print the id data member of each property item.
  312. for (UINT j = 0; j < numProperties; ++j)
  313. {
  314. if (PropertyTagOrientation == pAllItems[j].id)
  315. {
  316. short* ptrLong = (short*)(pAllItems[j].value);
  317. int ret = (int)*ptrLong;
  318. free(pAllItems);
  319. return ret;
  320. }
  321. }
  322. free(pAllItems);
  323. return TRUE;
  324. }
  325. /************************************************************************/
  326. /*
  327. 函数:GetEncoderClsid
  328. 描述:获取GDI+支持的图像格式编码器种类,以及所有种类编码器信息;
  329. 参数:
  330. IN: format 要获取的图像格式;
  331. OUT: pClsid 返回符合条件的图像编码器信息;
  332. 返回:成功返回编码器索引,否则返回-1;
  333. */
  334. /************************************************************************/
  335. int IMGCommon::GetEncoderClsid(IN CONST WCHAR* format, OUT CLSID* pClsid)
  336. {
  337. // GDI+支持的图像编码器数量;
  338. UINT numEncoders = 0;
  339. // GDI+所有图像格式编码器详细信息所需要的空间大小;
  340. UINT nSize = 0;
  341. ImageCodecInfo* pImageCodecInfo = NULL;
  342. // 2.获取GDI+支持的所有图像格式编码器详细信息所需要的空间大小;
  343. GetImageEncodersSize(&numEncoders, &nSize);
  344. if (nSize == 0)
  345. return -1;
  346. //3.为ImageCodecInfo数组分配足额空间;
  347. pImageCodecInfo = (ImageCodecInfo*)(malloc(nSize));
  348. if (pImageCodecInfo == NULL)
  349. return -1;
  350. //4.获取所有的图像编码器信息;
  351. GetImageEncoders(numEncoders, nSize, pImageCodecInfo);
  352. //5.查找符合的图像编码器的Clsid;
  353. for (UINT i = 0; i < numEncoders; ++i)
  354. {
  355. if (wcscmp(pImageCodecInfo[i].MimeType, format) == 0)
  356. {
  357. *pClsid = pImageCodecInfo[i].Clsid;
  358. free(pImageCodecInfo);
  359. return i; // Success
  360. }
  361. }
  362. //6.释放步骤3分配的内存;
  363. free(pImageCodecInfo);
  364. return -1;
  365. }
  366. /************************************************************************/
  367. /*
  368. 函数:SaveImg2newfile
  369. 描述:将Image对象另存为其他格式的文件;
  370. 参数:
  371. IN: pImg GDI+ Image对象指针,需要保存的图像对象;
  372. IN: lpnewfile 其他格式的新文件名(jpg,bmp,png,jpeg);
  373. IN: uQuality 另存为新文件时的图像质量值;
  374. 返回:
  375. 注意:Image::Save 若文件存在,会覆盖存在的文件;
  376. */
  377. /************************************************************************/
  378. BOOL IMGCommon::SaveImg2newfile(IN Image* pImg, IN CString strNewfile, IN ULONG uQuality)
  379. {
  380. if (pImg == NULL) return FALSE;
  381. // 需要判断路径是否存在,不存在创建目录;
  382. int nIndex = strNewfile.ReverseFind(_T('\\'));
  383. if (nIndex == -1)
  384. return FALSE;
  385. if (!PathFileExists(strNewfile.Left(nIndex)))
  386. {
  387. // 如果文件夹不存在,创建;
  388. #if 0
  389. CreateDirectoryEx(strNewfile.Left(nIndex));
  390. #else
  391. SHCreateDirectoryEx(NULL, strNewfile.Left(nIndex), NULL);
  392. #endif
  393. }
  394. nIndex = strNewfile.ReverseFind(_T('.'));
  395. if (nIndex == -1)
  396. return FALSE;
  397. Status stat = GenericError;
  398. CLSID encoderClsid = { 0 };
  399. BSTR newfile = strNewfile.AllocSysString();
  400. strNewfile = strNewfile.Mid(nIndex + 1);
  401. if (strNewfile.CompareNoCase(_T("bmp")) == 0)
  402. {
  403. GetEncoderClsid(L"image/bmp", &encoderClsid);
  404. stat = pImg->Save(newfile, &encoderClsid, NULL);
  405. }
  406. else if (strNewfile.CompareNoCase(_T("png")) == 0)
  407. {
  408. GetEncoderClsid(L"image/png", &encoderClsid);
  409. stat = pImg->Save(newfile, &encoderClsid, NULL);
  410. }
  411. else// if ( strNewfile.CompareNoCase(_T("jpeg")) == 0 )
  412. {
  413. GetEncoderClsid(L"image/jpeg", &encoderClsid);
  414. EncoderParameters encoderParameters;
  415. encoderParameters.Count = 1;
  416. encoderParameters.Parameter[0].Guid = EncoderQuality;
  417. encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
  418. encoderParameters.Parameter[0].NumberOfValues = 1;
  419. // Save the image as a JPEG with quality level 100.
  420. encoderParameters.Parameter[0].Value = &uQuality;
  421. stat = pImg->Save(newfile, &encoderClsid, &encoderParameters);
  422. }
  423. SysFreeString(newfile);
  424. return stat == Ok ? TRUE : FALSE;
  425. }
  426. BOOL IMGCommon::SaveImg2newfile(IN Image* pImg, IN TString strNewfile, IN ULONG uQuality)
  427. {
  428. if (pImg == NULL) return FALSE;
  429. // 需要判断路径是否存在,不存在创建目录;
  430. int nIndex = strNewfile.find_last_of(_T('\\'));
  431. if (nIndex == TString::npos)
  432. return FALSE;
  433. if (!PathFileExists(strNewfile.substr(0, nIndex).c_str()))
  434. {
  435. // 如果文件夹不存在,创建;
  436. #if 0
  437. CreateDirectoryEx(strNewfile.substr(0, nIndex).c_str());
  438. #else
  439. SHCreateDirectoryEx(NULL, strNewfile.substr(0, nIndex).c_str(), NULL);
  440. #endif
  441. }
  442. nIndex = strNewfile.find_last_of(_T('.'));
  443. if (nIndex == TString::npos)
  444. return FALSE;
  445. Status stat = GenericError;
  446. CLSID encoderClsid = { 0 };
  447. BSTR newfile = _bstr_t(strNewfile.c_str());
  448. strNewfile = strNewfile.substr(nIndex + 1);
  449. if (strNewfile.find(_T("bmp")) == 0)
  450. {
  451. GetEncoderClsid(L"image/bmp", &encoderClsid);
  452. stat = pImg->Save(newfile, &encoderClsid, NULL);
  453. }
  454. else if (strNewfile.find(_T("png")) == 0)
  455. {
  456. GetEncoderClsid(L"image/png", &encoderClsid);
  457. stat = pImg->Save(newfile, &encoderClsid, NULL);
  458. }
  459. else// if ( strNewfile.CompareNoCase(_T("jpeg")) == 0 )
  460. {
  461. GetEncoderClsid(L"image/jpeg", &encoderClsid);
  462. EncoderParameters encoderParameters;
  463. encoderParameters.Count = 1;
  464. encoderParameters.Parameter[0].Guid = EncoderQuality;
  465. encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
  466. encoderParameters.Parameter[0].NumberOfValues = 1;
  467. // Save the image as a JPEG with quality level 100.
  468. encoderParameters.Parameter[0].Value = &uQuality;
  469. stat = pImg->Save(newfile, &encoderClsid, &encoderParameters);
  470. }
  471. SysFreeString(newfile);
  472. return stat == Ok ? TRUE : FALSE;
  473. }
  474. /************************************************************************/
  475. /*
  476. 函数:ZoomImg
  477. 描述:缩放到指定大小的区域中,返回缩放后的尺寸;
  478. 参数:
  479. IN: Imgrc 图像的大小;
  480. IN: dwDisplayPix 图像要显示的区域的大小;
  481. OUT: dwZoomPix 图像在显示区域内缩放后的尺寸;
  482. 返回:
  483. 注意:dwZoomPix的尺寸必须在dwDisplayPix内;
  484. */
  485. /************************************************************************/
  486. int IMGCommon::ZoomImg(IN CRect &Imgrc, IN CONST DWORD &dwDisplayPix, OUT DWORD &dwZoomPix)
  487. {
  488. double fDisplayWidth = GET_XPIX(dwDisplayPix);
  489. double fDisplayHeight = GET_YPIX(dwDisplayPix);
  490. // 显示区域长宽比;
  491. double fDisplayAspectRatio = fDisplayWidth / fDisplayHeight;
  492. // 图片长宽比;
  493. double fImgAspectRatio = ((double)Imgrc.Width()) / ((double)Imgrc.Height());
  494. double fZoomWidth;
  495. double fZoomHeight;
  496. if (fDisplayAspectRatio > fImgAspectRatio)
  497. {
  498. fZoomWidth = fDisplayHeight*fImgAspectRatio;
  499. fZoomHeight = fDisplayHeight;
  500. }
  501. else
  502. {
  503. fZoomWidth = fDisplayWidth;
  504. fZoomHeight = fDisplayWidth / fImgAspectRatio;
  505. }
  506. dwZoomPix = SET_PIX((int)fZoomWidth, (int)fZoomHeight);
  507. //////////////////////////////////////////////////////////////////////////
  508. int nRetval = 0;
  509. if ((fDisplayWidth == Imgrc.Width()) && (fDisplayHeight == Imgrc.Height()))
  510. {
  511. nRetval = ZoomNull;
  512. }
  513. else if ((fDisplayWidth > Imgrc.Width()) && (fDisplayHeight > Imgrc.Height()))
  514. {
  515. nRetval = ZoomOut;
  516. }
  517. else
  518. {
  519. nRetval = ZoomIn;
  520. }
  521. return nRetval;
  522. }
  523. int IMGCommon::ZoomImg(IN CONST DWORD &dwImgPix, IN CONST DWORD &dwDisplayPix, OUT DWORD &dwZoomPix)
  524. {
  525. double fDisplayWidth = GET_XPIX(dwDisplayPix);
  526. double fDisplayHeight = GET_YPIX(dwDisplayPix);
  527. // 显示区域长宽比;
  528. double fDisplayAspectRatio = fDisplayWidth / fDisplayHeight;
  529. // 图片长宽比;
  530. double fImgAspectRatio = ((double)GET_XPIX(dwImgPix)) / ((double)GET_YPIX(dwImgPix));
  531. double fZoomWidth;
  532. double fZoomHeight;
  533. if (fDisplayAspectRatio > fImgAspectRatio)
  534. {
  535. fZoomWidth = fDisplayHeight*fImgAspectRatio;
  536. fZoomHeight = fDisplayHeight;
  537. }
  538. else
  539. {
  540. fZoomWidth = fDisplayWidth;
  541. fZoomHeight = fDisplayWidth / fImgAspectRatio;
  542. }
  543. dwZoomPix = SET_PIX((int)fZoomWidth, (int)fZoomHeight);
  544. //////////////////////////////////////////////////////////////////////////
  545. int nRetval = 0;
  546. if ((fDisplayWidth == GET_XPIX(dwImgPix)) && (fDisplayHeight == GET_YPIX(dwImgPix)))
  547. {
  548. nRetval = ZoomNull;
  549. }
  550. else if ((fDisplayWidth > GET_XPIX(dwImgPix)) && (fDisplayHeight > GET_YPIX(dwImgPix)))
  551. {
  552. nRetval = ZoomOut;
  553. }
  554. else
  555. {
  556. nRetval = ZoomIn;
  557. }
  558. return nRetval;
  559. }
  560. /************************************************************************/
  561. /*
  562. 函数:ImgThumbnail
  563. 描述:生成高质量的图像缩略图;
  564. 参数:
  565. 返回:
  566. 注意:为了健壮性,strNewfile的路径可以在函数内再次判断是否有效,防止在函数外没有进行经判断;
  567. */
  568. /************************************************************************/
  569. BOOL IMGCommon::ImgThumbnail(IN Image* pImg, IN CONST DWORD &dwDisplayPix, IN CString strNewfile, IN ULONG uQuality)
  570. {
  571. if (pImg == NULL) return FALSE;
  572. DWORD dwZoomPix;
  573. int retval = ZoomImg(SET_PIX(pImg->GetWidth(), pImg->GetHeight()), dwDisplayPix, dwZoomPix);
  574. if (retval == ZoomOut)
  575. {
  576. return FALSE;
  577. }
  578. else if (retval == ZoomNull)
  579. {
  580. return SaveImg2newfile(pImg, strNewfile, uQuality);
  581. }
  582. // 绘制缩略图;
  583. Bitmap bitmap(GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
  584. Graphics *graphic = Graphics::FromImage(&bitmap);
  585. graphic->Clear(Color(255, 255, 255, 255));
  586. // 设置缩放或旋转图片时的算法(图片质量);
  587. graphic->SetInterpolationMode(InterpolationModeHighQualityBicubic);
  588. // 设置渲染图形对象的质量;
  589. graphic->SetSmoothingMode(SmoothingModeHighQuality);//SmoothingModeHighSpeed
  590. // 设置图形对象的像素偏移模式;
  591. graphic->SetPixelOffsetMode(PixelOffsetModeHighQuality);
  592. // 设置图形对象的合成模式;
  593. graphic->SetCompositingMode(CompositingModeSourceOver);
  594. // 设置图形对象的合成质量;
  595. graphic->SetCompositingQuality(CompositingQualityHighQuality);
  596. // 设置图形对象的文本渲染模式;
  597. graphic->SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);
  598. graphic->DrawImage(pImg, 0, 0, GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
  599. delete graphic;
  600. // 生成缩略图;
  601. return SaveImg2newfile(&bitmap, strNewfile, uQuality);
  602. }
  603. BOOL IMGCommon::ImgThumbnail(IN LPCTSTR lpImgpath, IN CONST DWORD &dwDisplayPix, IN CString strNewfile, IN ULONG uQuality)
  604. {
  605. if (!PathFileExists(lpImgpath))
  606. return FALSE;
  607. #ifdef UNICODE
  608. Image Img(lpImgpath);
  609. #else
  610. BSTR strtmp = _bstr_t(lpImgpath);
  611. Image Img(strtmp);
  612. SysFreeString(strtmp);
  613. #endif
  614. DWORD dwZoomPix;
  615. int retval = ZoomImg(SET_PIX(Img.GetWidth(), Img.GetHeight()), dwDisplayPix, dwZoomPix);
  616. if (retval == ZoomOut)
  617. {
  618. return FALSE;
  619. }
  620. else if (retval == ZoomNull)
  621. {
  622. return SaveImg2newfile(&Img, strNewfile, uQuality);
  623. }
  624. // 绘制缩略图;
  625. Bitmap bitmap(GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
  626. Graphics *graphic = Graphics::FromImage(&bitmap);
  627. graphic->Clear(Color(255, 255, 255, 255));
  628. // 设置缩放或旋转图片时的算法(图片质量);
  629. graphic->SetInterpolationMode(InterpolationModeHighQualityBicubic);
  630. // 设置渲染图形对象的质量;
  631. graphic->SetSmoothingMode(SmoothingModeHighQuality);//SmoothingModeHighSpeed
  632. // 设置图形对象的像素偏移模式;
  633. graphic->SetPixelOffsetMode(PixelOffsetModeHighQuality);
  634. // 设置图形对象的合成模式;
  635. graphic->SetCompositingMode(CompositingModeSourceOver);
  636. // 设置图形对象的合成质量;
  637. graphic->SetCompositingQuality(CompositingQualityHighQuality);
  638. // 设置图形对象的文本渲染模式;
  639. graphic->SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);
  640. Status st = graphic->DrawImage(&Img, 0, 0, GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
  641. if ( st != Ok )
  642. {
  643. delete graphic;
  644. return FALSE;
  645. }
  646. delete graphic;
  647. // 生成缩略图;
  648. return SaveImg2newfile(&bitmap, strNewfile, uQuality);
  649. }
  650. BOOL IMGCommon::ImgThumbnail(IN CONST TString &strImgpath, IN CONST DWORD &dwDisplayPix, IN TString strNewfile, IN ULONG uQuality)
  651. {
  652. if (!PathFileExists(strImgpath.c_str()))
  653. {
  654. SetLastError(GetLastError());
  655. return FALSE;
  656. }
  657. #ifdef UNICODE
  658. BSTR strtmp = _bstr_t(strImgpath.c_str());
  659. Image Img(strtmp);
  660. SysFreeString(strtmp);
  661. //Image Img(strImgpath);
  662. #else
  663. BSTR strtmp = _bstr_t(strImgpath.c_str());
  664. Image Img(strtmp);
  665. SysFreeString(strtmp);
  666. #endif
  667. DWORD dwZoomPix;
  668. int retval = ZoomImg(SET_PIX(Img.GetWidth(), Img.GetHeight()), dwDisplayPix, dwZoomPix);
  669. if (retval == ZoomOut)
  670. {
  671. return FALSE;
  672. }
  673. else if (retval == ZoomNull)
  674. {
  675. return SaveImg2newfile(&Img, strNewfile, uQuality);
  676. }
  677. // 绘制缩略图;
  678. Bitmap bitmap(GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
  679. Graphics *graphic = Graphics::FromImage(&bitmap);
  680. graphic->Clear(Color(255, 255, 255, 255));
  681. // 设置缩放或旋转图片时的算法(图片质量);
  682. graphic->SetInterpolationMode(InterpolationModeHighQualityBicubic);
  683. // 设置渲染图形对象的质量;
  684. graphic->SetSmoothingMode(SmoothingModeHighQuality);//SmoothingModeHighSpeed
  685. // 设置图形对象的像素偏移模式;
  686. graphic->SetPixelOffsetMode(PixelOffsetModeHighQuality);
  687. // 设置图形对象的合成模式;
  688. graphic->SetCompositingMode(CompositingModeSourceOver);
  689. // 设置图形对象的合成质量;
  690. graphic->SetCompositingQuality(CompositingQualityHighQuality);
  691. // 设置图形对象的文本渲染模式;
  692. graphic->SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);
  693. Status st = graphic->DrawImage(&Img, 0, 0, GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
  694. if ( st != Ok )
  695. {
  696. delete graphic;
  697. return FALSE;
  698. }
  699. delete graphic;
  700. // 生成缩略图;
  701. return SaveImg2newfile(&bitmap, strNewfile, uQuality);
  702. }
  703. BOOL IMGCommon::SimpleImgThumbnail(IN LPCTSTR lpImgpath, IN CONST DWORD &dwDisplayPix, IN CString strNewfile, IN ULONG uQuality)
  704. {
  705. if (!PathFileExists(lpImgpath))
  706. return FALSE;
  707. DWORD dwZoomPix;
  708. Image *pImg = NULL;
  709. LoadImgFromFile(&pImg, lpImgpath);
  710. if ( pImg == NULL )
  711. {
  712. return FALSE;
  713. }
  714. int retval = ZoomImg(SET_PIX(pImg->GetWidth(), pImg->GetHeight()), dwDisplayPix, dwZoomPix);
  715. if (retval == ZoomOut)
  716. {
  717. if (pImg) delete pImg;
  718. return FALSE;
  719. }
  720. else if (retval == ZoomNull)
  721. {
  722. BOOL bRet = SaveImg2newfile(pImg, strNewfile, uQuality);
  723. if (pImg) delete pImg;
  724. return bRet;
  725. }
  726. Image *pThumbnailImg = pImg->GetThumbnailImage(GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
  727. if (pThumbnailImg)
  728. {
  729. // 提高缩略图质量;
  730. Graphics graphic(pThumbnailImg);
  731. graphic.DrawImage(pImg, 0, 0, pThumbnailImg->GetWidth(), pThumbnailImg->GetHeight());
  732. INT nRientation = GetOrientation(pImg);
  733. if ( nRientation == 8 )
  734. {
  735. pThumbnailImg->RotateFlip(Rotate270FlipNone);
  736. }
  737. else if (nRientation == 6)
  738. {
  739. pThumbnailImg->RotateFlip(Rotate90FlipNone);
  740. }
  741. SaveImg2newfile(pThumbnailImg, strNewfile, uQuality);
  742. }
  743. else
  744. {
  745. if (pImg) delete pImg;
  746. return FALSE;
  747. }
  748. if (pImg) delete pImg;
  749. if (pThumbnailImg) delete pThumbnailImg;
  750. return TRUE;
  751. }
  752. Image* IMGCommon::AppendImgWatermark(IN Image* pImg, IN Image* pWatemarkImg)
  753. {
  754. if ( pImg == NULL || pWatemarkImg == NULL )
  755. return NULL;
  756. // Status st = GenericError;
  757. // 创建图像显示属性对象;
  758. ImageAttributes ImgAttr;
  759. // 创建新位图;
  760. Bitmap *pBitmap = ::new Bitmap(pImg->GetWidth(), pImg->GetHeight(), PixelFormat32bppPARGB);
  761. // 创建水印图显示位置;
  762. RectF layWatemarkRect(10.0, 10.0, pWatemarkImg->GetWidth(), pWatemarkImg->GetHeight());
  763. // 创建画布对象;
  764. Graphics *grap = Graphics::FromImage(pBitmap);
  765. // 绘制画布底色;
  766. if ( Ok != grap->Clear(Color(255,255,255,255)) )
  767. goto clear;
  768. // 设置图片显示质量;
  769. if ( Ok != grap->SetSmoothingMode(SmoothingModeAntiAlias) )
  770. goto clear;
  771. // 设置文本质量;
  772. if ( Ok != grap->SetTextRenderingHint(TextRenderingHintAntiAlias))
  773. goto clear;
  774. // 在画布上画原始图片;
  775. if ( Ok != grap->DrawImage(pImg, 0, 0, pImg->GetWidth(), pImg->GetHeight()) )
  776. goto clear;
  777. // 设置透明颜色为水印图片四角底色,水印图显示为圆角;
  778. if ( Ok != ImgAttr.SetColorKey(0xFF00FF00, 0xFF00FF00, ColorAdjustTypeBitmap))
  779. goto clear;
  780. // 设置水印图片透明底为0.3;
  781. if ( Ok != ImgAttr.SetColorMatrix(&_ClrMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap) )
  782. goto clear;
  783. // 在画布左上角画水印;
  784. if ( Ok != grap->DrawImage(pWatemarkImg, layWatemarkRect, 0, 0, pWatemarkImg->GetWidth(), pWatemarkImg->GetHeight(), UnitPixel, &ImgAttr) )
  785. goto clear;
  786. if ( grap )
  787. delete grap;
  788. return pBitmap;
  789. clear:
  790. if ( grap )
  791. delete grap;
  792. if ( pBitmap )
  793. delete pBitmap;
  794. return NULL;
  795. }
  796. Image* IMGCommon::AppendImgWatermark(IN Image* pImg, IN LPCTSTR lpWatemarkImgpath)
  797. {
  798. if ( !PathFileExists(lpWatemarkImgpath) || pImg == NULL )
  799. return FALSE;
  800. #ifdef UNICODE
  801. Image *pWatemarkImg = Image::FromFile(lpWatemarkImgpath);
  802. #else
  803. BSTR str = _bstr_t(lpWatemarkImgpath);
  804. Image* pWatemarkImg = Image::FromFile(str);
  805. SysFreeString(str);
  806. #endif
  807. if ( pImg == NULL )
  808. return NULL;
  809. //Status st = GenericError;
  810. // 创建图像显示属性对象;
  811. ImageAttributes ImgAttr;
  812. // 创建新位图;
  813. Bitmap *pBitmap = ::new Bitmap(pImg->GetWidth(), pImg->GetHeight(), PixelFormat32bppPARGB);
  814. // 创建水印图显示位置;
  815. RectF layWatemarkRect(10.0, 10.0, pWatemarkImg->GetWidth(), pWatemarkImg->GetHeight());
  816. // 创建画布对象;
  817. Graphics *grap = Graphics::FromImage(pBitmap);
  818. // 绘制画布底色;
  819. if ( Ok != grap->Clear(Color(255,255,255,255)) )
  820. goto clear;
  821. // 设置图片显示质量;
  822. if ( Ok != grap->SetSmoothingMode(SmoothingModeAntiAlias) )
  823. goto clear;
  824. // 设置文本质量;
  825. if ( Ok != grap->SetTextRenderingHint(TextRenderingHintAntiAlias))
  826. goto clear;
  827. // 在画布上画原始图片;
  828. if ( Ok != grap->DrawImage(pImg, 0, 0, pImg->GetWidth(), pImg->GetHeight()) )
  829. goto clear;
  830. // 设置透明颜色为水印图片四角底色,水印图显示为圆角;
  831. if ( Ok != ImgAttr.SetColorKey(0xFF00FF00, 0xFF00FF00, ColorAdjustTypeBitmap))
  832. goto clear;
  833. // 设置水印图片透明底为0.3;
  834. if ( Ok != ImgAttr.SetColorMatrix(&_ClrMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap) )
  835. goto clear;
  836. // 在画布左上角画水印;
  837. if ( Ok != grap->DrawImage(pWatemarkImg, layWatemarkRect, 0, 0, pWatemarkImg->GetWidth(), pWatemarkImg->GetHeight(), UnitPixel, &ImgAttr) )
  838. goto clear;
  839. if ( grap )
  840. delete grap;
  841. return pBitmap;
  842. clear:
  843. if ( grap )
  844. delete grap;
  845. if ( pBitmap )
  846. delete pBitmap;
  847. if ( pWatemarkImg )
  848. delete pWatemarkImg;
  849. return NULL;
  850. }
  851. Image* IMGCommon::AppendImgWatermark(IN LPCTSTR lpImgpath, IN Image* pWatemarkImg)
  852. {
  853. if ( !PathFileExists(lpImgpath) || pWatemarkImg == NULL )
  854. return FALSE;
  855. #ifdef UNICODE
  856. Image *pImg = Image::FromFile(lpImgpath);
  857. #else
  858. BSTR str = _bstr_t(lpImgpath);
  859. Image* pImg = Image::FromFile(str);
  860. SysFreeString(str);
  861. #endif
  862. if ( pImg == NULL )
  863. return NULL;
  864. //Status st = GenericError;
  865. // 创建图像显示属性对象;
  866. ImageAttributes ImgAttr;
  867. // 创建新位图;
  868. Bitmap *pBitmap = ::new Bitmap(pImg->GetWidth(), pImg->GetHeight(), PixelFormat32bppPARGB);
  869. // 创建水印图显示位置;
  870. RectF layWatemarkRect(10.0, 10.0, pWatemarkImg->GetWidth(), pWatemarkImg->GetHeight());
  871. // 创建画布对象;
  872. Graphics *grap = Graphics::FromImage(pBitmap);
  873. // 绘制画布底色;
  874. if ( Ok != grap->Clear(Color(255,255,255,255)) )
  875. goto clear;
  876. // 设置图片显示质量;
  877. if ( Ok != grap->SetSmoothingMode(SmoothingModeAntiAlias) )
  878. goto clear;
  879. // 设置文本质量;
  880. if ( Ok != grap->SetTextRenderingHint(TextRenderingHintAntiAlias))
  881. goto clear;
  882. // 在画布上画原始图片;
  883. if ( Ok != grap->DrawImage(pImg, 0, 0, pImg->GetWidth(), pImg->GetHeight()) )
  884. goto clear;
  885. // 设置透明颜色为水印图片四角底色,水印图显示为圆角;
  886. if ( Ok != ImgAttr.SetColorKey(0xFF00FF00, 0xFF00FF00, ColorAdjustTypeBitmap))
  887. goto clear;
  888. // 设置水印图片透明底为0.3;
  889. if ( Ok != ImgAttr.SetColorMatrix(&_ClrMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap) )
  890. goto clear;
  891. // 在画布左上角画水印;
  892. if ( Ok != grap->DrawImage(pWatemarkImg, layWatemarkRect, 0, 0, pWatemarkImg->GetWidth(), pWatemarkImg->GetHeight(), UnitPixel, &ImgAttr) )
  893. goto clear;
  894. if ( grap )
  895. delete grap;
  896. return pBitmap;
  897. clear:
  898. if ( grap )
  899. delete grap;
  900. if ( pBitmap )
  901. delete pBitmap;
  902. if ( pImg )
  903. delete pImg;
  904. return NULL;
  905. }
  906. Image* IMGCommon::AppendImgWatermark(IN LPCTSTR lpImgpath, IN LPCTSTR lpWatemarkImgpath)
  907. {
  908. if ( !PathFileExists(lpImgpath) || !PathFileExists(lpWatemarkImgpath) )
  909. return FALSE;
  910. #ifdef UNICODE
  911. Image *pImg = Image::FromFile(lpImgpath);
  912. Image *pWatemarkImg = Image::FromFile(lpWatemarkImgpath);
  913. #else
  914. BSTR str = _bstr_t(lpImgpath);
  915. Image* pImg = Image::FromFile(str);
  916. SysFreeString(str);
  917. BSTR str2 = _bstr_t(lpWatemarkImgpath);
  918. Image* pWatemarkImg = Image::FromFile(str2);
  919. SysFreeString(str2);
  920. #endif
  921. if ( pImg == NULL || pWatemarkImg == NULL )
  922. return NULL;
  923. //Status st = GenericError;
  924. // 创建图像显示属性对象;
  925. ImageAttributes ImgAttr;
  926. // 创建新位图;
  927. Bitmap *pBitmap = ::new Bitmap(pImg->GetWidth(), pImg->GetHeight(), PixelFormat32bppPARGB);
  928. // 创建水印图显示位置;
  929. RectF layWatemarkRect(10.0, 10.0, pWatemarkImg->GetWidth(), pWatemarkImg->GetHeight());
  930. // 创建画布对象;
  931. Graphics *grap = Graphics::FromImage(pBitmap);
  932. // 绘制画布底色;
  933. if ( Ok != grap->Clear(Color(255,255,255,255)) )
  934. goto clear;
  935. // 设置图片显示质量;
  936. if ( Ok != grap->SetSmoothingMode(SmoothingModeAntiAlias) )
  937. goto clear;
  938. // 设置文本质量;
  939. if ( Ok != grap->SetTextRenderingHint(TextRenderingHintAntiAlias))
  940. goto clear;
  941. // 在画布上画原始图片;
  942. if ( Ok != grap->DrawImage(pImg, 0, 0, pImg->GetWidth(), pImg->GetHeight()) )
  943. goto clear;
  944. // 设置透明颜色为水印图片四角底色,水印图显示为圆角;
  945. if ( Ok != ImgAttr.SetColorKey(0xFF00FF00, 0xFF00FF00, ColorAdjustTypeBitmap))
  946. goto clear;
  947. // 设置水印图片透明底为0.3;
  948. if ( Ok != ImgAttr.SetColorMatrix(&_ClrMatrix, ColorMatrixFlagsDefault, ColorAdjustTypeBitmap) )
  949. goto clear;
  950. // 在画布左上角画水印;
  951. if ( Ok != grap->DrawImage(pWatemarkImg, layWatemarkRect, 0, 0, pWatemarkImg->GetWidth(), pWatemarkImg->GetHeight(), UnitPixel, &ImgAttr) )
  952. goto clear;
  953. if ( grap )
  954. delete grap;
  955. return pBitmap;
  956. clear:
  957. if ( grap )
  958. delete grap;
  959. if ( pBitmap )
  960. delete pBitmap;
  961. if ( pImg )
  962. delete pImg;
  963. if ( pWatemarkImg )
  964. delete pWatemarkImg;
  965. return NULL;
  966. }
  967. BOOL IMGCommon::AppendImgWatermark(IN Image* pImg, IN Image* pWatemarkImg, IN LPCTSTR lpSaveImgpath)
  968. {
  969. Image* pSaveImg = AppendImgWatermark(pImg, pWatemarkImg);
  970. if ( pSaveImg == NULL )
  971. return FALSE;
  972. // 创建新的目录;
  973. CString strImgs = lpSaveImgpath;
  974. INT nIndex = strImgs.ReverseFind(_T('\\'));
  975. if ( nIndex != -1 )
  976. {
  977. strImgs = strImgs.Mid(0,nIndex+1);
  978. if ( !PathFileExists(strImgs) )
  979. {
  980. #if 0
  981. if ( CreateDirectoryEx(strImgs) )
  982. #else
  983. if (SHCreateDirectoryEx(NULL, strImgs, NULL))
  984. #endif
  985. {
  986. if (SaveImg2newfile(pSaveImg, (CString)lpSaveImgpath, 100))
  987. {
  988. if ( pSaveImg )
  989. delete pSaveImg;
  990. pSaveImg = NULL;
  991. return TRUE;
  992. }
  993. return FALSE;
  994. }
  995. }
  996. }
  997. return FALSE;
  998. }
  999. BOOL IMGCommon::AppendImgWatermark(IN LPCTSTR lpImgpath, IN LPCTSTR lpWatemarkImgpath, IN LPCTSTR lpSaveImgpath)
  1000. {
  1001. Image *pSaveImg = AppendImgWatermark(lpImgpath, lpWatemarkImgpath);
  1002. if ( pSaveImg == NULL)
  1003. return FALSE;
  1004. // 创建新的目录;
  1005. CString strImgs = lpSaveImgpath;
  1006. INT nIndex = strImgs.ReverseFind(_T('\\'));
  1007. if ( nIndex != -1 )
  1008. {
  1009. strImgs = strImgs.Mid(0,nIndex+1);
  1010. if ( !PathFileExists(strImgs) )
  1011. {
  1012. #if 0
  1013. if (CreateDirectoryEx(strImgs))
  1014. #else
  1015. if (SHCreateDirectoryEx(NULL, strImgs, NULL))
  1016. #endif
  1017. {
  1018. if (SaveImg2newfile(pSaveImg, (CString)lpSaveImgpath, 100))
  1019. {
  1020. if ( pSaveImg )
  1021. delete pSaveImg;
  1022. pSaveImg = NULL;
  1023. return TRUE;
  1024. }
  1025. return FALSE;
  1026. }
  1027. }
  1028. }
  1029. return FALSE;
  1030. }
  1031. Image* IMGCommon::AppendWordWatermark(IN Image* pImg, IN LPCTSTR lpWatemarkString)
  1032. {
  1033. if ( pImg == NULL || lpWatemarkString == NULL || lpWatemarkString[0] == _T('\0'))
  1034. return NULL;
  1035. #ifndef UNICODE
  1036. WCHAR* pText = CharEncoding::ASCII2UNICODE(lpWatemarkString);
  1037. #endif
  1038. // 创建新位图;
  1039. Bitmap *pBitmap = ::new Bitmap(pImg->GetWidth(), pImg->GetHeight(), PixelFormat32bppPARGB);
  1040. // 创建字体;
  1041. FontFamily ffly(L"宋体");
  1042. Gdiplus::Font ft(&ffly, 24, FontStyleRegular, UnitPixel);
  1043. // 创建画刷;
  1044. SolidBrush brush(0x99000000);
  1045. // 创建文本格式;
  1046. StringFormat sf;
  1047. sf.SetAlignment(StringAlignmentCenter); // 水平居中;
  1048. // 创建水印文本显示位置;
  1049. RectF layWatemarkRect(pImg->GetWidth(), pImg->GetHeight() - 25, 0.0, 0.0); // 文字阴影;
  1050. RectF layWatemarkRect2(pImg->GetWidth(), pImg->GetHeight() - 26, 0.0, 0.0); // 文字原体;
  1051. // 创建画布对象;
  1052. Graphics *grap = Graphics::FromImage(pBitmap);
  1053. // 绘制画布底色;
  1054. if ( Ok != grap->Clear(Color(255,255,255,255)) )
  1055. goto clear;
  1056. // 设置图片显示质量;
  1057. if ( Ok != grap->SetSmoothingMode(SmoothingModeAntiAlias) )
  1058. goto clear;
  1059. // 设置文本质量;
  1060. if ( Ok != grap->SetTextRenderingHint(TextRenderingHintAntiAlias))
  1061. goto clear;
  1062. // 在画布上画原始图片;
  1063. if ( Ok != grap->DrawImage(pImg, 0, 0, pImg->GetWidth(), pImg->GetHeight()) )
  1064. goto clear;
  1065. // 画水印阴影;
  1066. #ifdef UNICODE
  1067. if ( Ok != grap->DrawString(lpWatemarkString, wcslen(lpWatemarkString), &ft, layWatemarkRect, &sf, &brush) )
  1068. #else
  1069. if ( Ok != grap->DrawString(pText, wcslen(pText), &ft, layWatemarkRect, &sf, &brush) )
  1070. #endif
  1071. goto clear;
  1072. // 画水印文本;
  1073. brush.SetColor(0x99ffffff);
  1074. #ifdef UNICODE
  1075. if ( Ok != grap->DrawString(lpWatemarkString, wcslen(lpWatemarkString), &ft, layWatemarkRect2, &sf, &brush) )
  1076. #else
  1077. if ( Ok != grap->DrawString(pText, wcslen(pText), &ft, layWatemarkRect, &sf, &brush) )
  1078. #endif
  1079. goto clear;
  1080. if ( grap )
  1081. delete grap;
  1082. return pBitmap;
  1083. clear:
  1084. if ( grap )
  1085. delete grap;
  1086. if ( pBitmap )
  1087. delete pBitmap;
  1088. if ( pImg )
  1089. delete pImg;
  1090. #ifndef UNICODE
  1091. if (pText)
  1092. delete []pText;
  1093. #endif
  1094. return NULL;
  1095. }
  1096. Image* IMGCommon::AppendWordWatermark(IN LPCTSTR lpImgpath, IN LPCTSTR lpWatemarkString)
  1097. {
  1098. if ( !PathFileExists(lpImgpath) || lpWatemarkString == NULL || lpWatemarkString[0] == _T('\0'))
  1099. return NULL;
  1100. #ifdef UNICODE
  1101. Image *pImg = Image::FromFile(lpImgpath);
  1102. #else
  1103. BSTR str = _bstr_t(lpImgpath);
  1104. Image* pImg = Image::FromFile(str);
  1105. SysFreeString(str);
  1106. #endif
  1107. #ifndef UNICODE
  1108. WCHAR* pText = CharEncoding::ASCII2UNICODE(lpWatemarkString);
  1109. #endif
  1110. // 创建新位图;
  1111. Bitmap *pBitmap = ::new Bitmap(pImg->GetWidth(), pImg->GetHeight(), PixelFormat32bppPARGB);
  1112. // 创建字体;
  1113. FontFamily ffly(L"宋体");
  1114. Gdiplus::Font ft(&ffly, 24, FontStyleRegular, UnitPixel);
  1115. // 创建画刷;
  1116. SolidBrush brush(0x99000000);
  1117. // 创建文本格式;
  1118. StringFormat sf;
  1119. sf.SetAlignment(StringAlignmentCenter); // 水平居中;
  1120. // 创建水印文本显示位置;
  1121. RectF layWatemarkRect(pImg->GetWidth(), pImg->GetHeight() - 25, 0.0, 0.0); // 文字阴影;
  1122. RectF layWatemarkRect2(pImg->GetWidth(), pImg->GetHeight() - 26, 0.0, 0.0); // 文字原体;
  1123. // 创建画布对象;
  1124. Graphics *grap = Graphics::FromImage(pBitmap);
  1125. // 绘制画布底色;
  1126. if ( Ok != grap->Clear(Color(255,255,255,255)) )
  1127. goto clear;
  1128. // 设置图片显示质量;
  1129. if ( Ok != grap->SetSmoothingMode(SmoothingModeAntiAlias) )
  1130. goto clear;
  1131. // 设置文本质量;
  1132. if ( Ok != grap->SetTextRenderingHint(TextRenderingHintAntiAlias))
  1133. goto clear;
  1134. // 在画布上画原始图片;
  1135. if ( Ok != grap->DrawImage(pImg, 0, 0, pImg->GetWidth(), pImg->GetHeight()) )
  1136. goto clear;
  1137. // 画水印阴影;
  1138. #ifdef UNICODE
  1139. if ( Ok != grap->DrawString(lpWatemarkString, wcslen(lpWatemarkString), &ft, layWatemarkRect, &sf, &brush) )
  1140. #else
  1141. if ( Ok != grap->DrawString(pText, wcslen(pText), &ft, layWatemarkRect, &sf, &brush) )
  1142. #endif
  1143. goto clear;
  1144. // 画水印文本;
  1145. brush.SetColor(0x99ffffff);
  1146. #ifdef UNICODE
  1147. if ( Ok != grap->DrawString(lpWatemarkString, wcslen(lpWatemarkString), &ft, layWatemarkRect2, &sf, &brush) )
  1148. #else
  1149. if ( Ok != grap->DrawString(pText, wcslen(pText), &ft, layWatemarkRect, &sf, &brush) )
  1150. #endif
  1151. goto clear;
  1152. if ( grap )
  1153. delete grap;
  1154. return pBitmap;
  1155. clear:
  1156. if ( grap )
  1157. delete grap;
  1158. if ( pBitmap )
  1159. delete pBitmap;
  1160. if ( pImg )
  1161. delete pImg;
  1162. #ifndef UNICODE
  1163. if (pText)
  1164. delete []pText;
  1165. #endif
  1166. return NULL;
  1167. }
  1168. BOOL IMGCommon::SaveBitmap(IN CDC *pDC, IN CBitmap* pBitmap, IN CONST INT& nBitdepth, IN const INT& nWidth, IN const INT& nHeight, IN LPCTSTR lpSavepath)
  1169. {
  1170. // 计算出位图大小 = ((宽 * 位宽 + 31)/ 32)* 4 * 高;
  1171. DWORD dwBmpSize = ((nWidth*nBitdepth + 31) / 32) * 4 * nHeight;
  1172. HANDLE hFile = CreateFile(lpSavepath, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  1173. if (hFile == INVALID_HANDLE_VALUE)
  1174. {
  1175. //WriteLog(_T("二维码位图创建失败"));
  1176. return FALSE;
  1177. }
  1178. HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE | SEC_COMMIT, 0,
  1179. sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2 + dwBmpSize, NULL);
  1180. LPBYTE lpbyMapView = (LPBYTE)MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, 0);
  1181. ZeroMemory(lpbyMapView, sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2 + dwBmpSize);
  1182. //结构体地址割付;
  1183. LPBITMAPFILEHEADER pbfh = (LPBITMAPFILEHEADER)lpbyMapView;
  1184. LPBITMAPINFO pbmi = (LPBITMAPINFO)(lpbyMapView + sizeof(BITMAPFILEHEADER));
  1185. LPVOID pbdt = lpbyMapView + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2;
  1186. // BITMAPFILEHEADER
  1187. //pbfh->bfType = (WORD) (('M' << 8) | 'B'); // "BM"
  1188. // BMP类型,与上面同值;
  1189. pbfh->bfType = 0x4D42;
  1190. pbfh->bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2 + dwBmpSize; // 文件总长;
  1191. pbfh->bfReserved1 = 0;
  1192. pbfh->bfReserved2 = 0;
  1193. pbfh->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2; // 位图数据相对于文件头的偏移量;
  1194. // LPBITMAPINFO->BITMAPINFOHEADER
  1195. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  1196. pbmi->bmiHeader.biWidth = nWidth;
  1197. pbmi->bmiHeader.biHeight = nHeight;
  1198. pbmi->bmiHeader.biPlanes = 1;
  1199. pbmi->bmiHeader.biBitCount = nBitdepth; // 位深度 1;
  1200. pbmi->bmiHeader.biCompression = BI_RGB;
  1201. pbmi->bmiHeader.biSizeImage = dwBmpSize;
  1202. pbmi->bmiHeader.biXPelsPerMeter = 3780;
  1203. pbmi->bmiHeader.biYPelsPerMeter = 3780;
  1204. pbmi->bmiHeader.biClrUsed = 0;
  1205. pbmi->bmiHeader.biClrImportant = 0;
  1206. // 放大到指定的像素宽高;
  1207. CDC* pWorkDC = new CDC;
  1208. pWorkDC->CreateCompatibleDC(NULL);
  1209. CBitmap* pWorkBitmap = new CBitmap;
  1210. pWorkBitmap->CreateBitmap(nWidth, nHeight, 1, 1, NULL);
  1211. CBitmap* pOldBitmap = pWorkDC->SelectObject(pWorkBitmap);
  1212. pWorkDC->StretchBlt(0, 0, nWidth, nHeight, pDC, 0, 0, nWidth, nHeight, SRCCOPY);
  1213. GetDIBits(pWorkDC->m_hDC, (HBITMAP)*pWorkBitmap, 0, nHeight, pbdt, pbmi, DIB_RGB_COLORS);
  1214. pWorkDC->SelectObject(pOldBitmap);
  1215. delete pWorkBitmap;
  1216. delete pWorkDC;
  1217. UnmapViewOfFile(lpbyMapView);
  1218. CloseHandle(hFileMapping);
  1219. CloseHandle(hFile);
  1220. return TRUE;
  1221. }
  1222. BOOL IMGCommon::SaveBitmap2(IN CDC *pDC, IN CBitmap* pBitmap, IN CONST INT& nBitdepth, IN const INT& nWidth, IN const INT& nHeight, IN LPCTSTR lpSavepath)
  1223. {
  1224. DWORD dwPaletteSize = 0; //调色板大小;
  1225. DWORD dwbmdibitSize = 0;
  1226. WORD wbitsCount = 0; //位图中每个像素所占字节数;
  1227. if( nBitdepth <= 1 )
  1228. wbitsCount = 1;
  1229. if( nBitdepth <= 4 )
  1230. wbitsCount = 4;
  1231. if( nBitdepth <= 8 )
  1232. wbitsCount = 8;
  1233. if( nBitdepth <= 16 )
  1234. wbitsCount = 16;
  1235. if( nBitdepth <= 24 )
  1236. wbitsCount = 24;
  1237. else
  1238. wbitsCount = 32;
  1239. if( wbitsCount <= 8 )
  1240. dwPaletteSize = (1 << wbitsCount) * sizeof(RGBQUAD);
  1241. // 计算出位图大小 = ((宽 * 位宽 + 31)/ 32)* 4 * 高;
  1242. DWORD dwBmpSize = ((nWidth*wbitsCount + 31) / 8) * nHeight;
  1243. HANDLE hFile = CreateFile(lpSavepath, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  1244. if (hFile == INVALID_HANDLE_VALUE)
  1245. {
  1246. //WriteLog(_T("二维码位图创建失败"));
  1247. return FALSE;
  1248. }
  1249. HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READWRITE | SEC_COMMIT, 0,
  1250. //sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2 + dwBmpSize, NULL);
  1251. sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmpSize, NULL);
  1252. LPBYTE lpbyMapView = (LPBYTE)MapViewOfFile(hFileMapping, FILE_MAP_WRITE, 0, 0, 0);
  1253. //ZeroMemory(lpbyMapView, sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 2 + dwBmpSize);
  1254. ZeroMemory(lpbyMapView, sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmpSize);
  1255. //结构体地址割付;
  1256. LPBITMAPFILEHEADER pbfh = (LPBITMAPFILEHEADER)lpbyMapView;
  1257. LPBITMAPINFO pbmi = (LPBITMAPINFO)(lpbyMapView + sizeof(BITMAPFILEHEADER));
  1258. LPVOID pbdt = lpbyMapView + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmpSize;
  1259. // BITMAPFILEHEADER
  1260. //pbfh->bfType = (WORD) (('M' << 8) | 'B'); // "BM"
  1261. // BMP类型,与上面同值;
  1262. pbfh->bfType = 0x4D42;
  1263. pbfh->bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize + dwBmpSize; // 文件总长;
  1264. pbfh->bfReserved1 = 0;
  1265. pbfh->bfReserved2 = 0;
  1266. pbfh->bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dwPaletteSize; // 位图数据相对于文件头的偏移量;
  1267. // LPBITMAPINFO->BITMAPINFOHEADER
  1268. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  1269. pbmi->bmiHeader.biWidth = nWidth;
  1270. pbmi->bmiHeader.biHeight = nHeight;
  1271. pbmi->bmiHeader.biPlanes = 1;
  1272. pbmi->bmiHeader.biBitCount = wbitsCount; // 位深度 1;
  1273. pbmi->bmiHeader.biCompression = BI_RGB;
  1274. pbmi->bmiHeader.biSizeImage = dwBmpSize;
  1275. pbmi->bmiHeader.biXPelsPerMeter = 3780;
  1276. pbmi->bmiHeader.biYPelsPerMeter = 3780;
  1277. pbmi->bmiHeader.biClrUsed = 0;
  1278. pbmi->bmiHeader.biClrImportant = 0;
  1279. // 放大到指定的像素宽高;
  1280. CDC* pWorkDC = new CDC;
  1281. pWorkDC->CreateCompatibleDC(NULL);
  1282. CBitmap* pWorkBitmap = new CBitmap;
  1283. pWorkBitmap->CreateBitmap(nWidth, nHeight, 1, 1, NULL);
  1284. CBitmap* pOldBitmap = pWorkDC->SelectObject(pWorkBitmap);
  1285. pWorkDC->StretchBlt(0, 0, nWidth, nHeight, pDC, 0, 0, nWidth, nHeight, SRCCOPY);
  1286. GetDIBits(pWorkDC->m_hDC, (HBITMAP)*pWorkBitmap, 0, nHeight, pbdt, pbmi, DIB_RGB_COLORS);
  1287. pWorkDC->SelectObject(pOldBitmap);
  1288. delete pWorkBitmap;
  1289. delete pWorkDC;
  1290. UnmapViewOfFile(lpbyMapView);
  1291. CloseHandle(hFileMapping);
  1292. CloseHandle(hFile);
  1293. return TRUE;
  1294. }
  1295. void IMGCommon::DrawString(IN CDC* pdc, IN CONST INT& nFontSize, IN LPCTSTR lpFontName, IN LPCTSTR lpString, IN OUT CRect &rcString)
  1296. {
  1297. if ( !pdc || !lpString )
  1298. return;
  1299. LOGFONT log;
  1300. // 设置字体字号;
  1301. log.lfHeight = -MulDiv(nFontSize ? nFontSize : 9, GetDeviceCaps(pdc->GetSafeHdc(), LOGPIXELSY), 72);
  1302. log.lfWidth = 0;
  1303. log.lfEscapement = 0;
  1304. log.lfOrientation = 0;
  1305. log.lfWeight = FW_REGULAR;
  1306. log.lfItalic = false;
  1307. log.lfUnderline = false;
  1308. log.lfStrikeOut = 0;
  1309. log.lfCharSet = ANSI_CHARSET;
  1310. log.lfOutPrecision = OUT_DEFAULT_PRECIS;
  1311. log.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  1312. log.lfQuality = DEFAULT_QUALITY;
  1313. log.lfPitchAndFamily = DEFAULT_PITCH || FF_ROMAN;
  1314. // 设置字体名称;
  1315. _tcscpy_s(log.lfFaceName, (lpFontName && (lpFontName[0] != _T('\0'))) ? lpFontName : _T("Arial"));
  1316. CFont cf;
  1317. cf.CreateFontIndirect(&log);
  1318. CFont *oldf = pdc->SelectObject(&cf);
  1319. SIZE Size;
  1320. GetTextExtentPoint32(pdc->GetSafeHdc(), lpString, _tcslen(lpString), &Size);
  1321. rcString.SetRect(rcString.left, rcString.top, Size.cx + rcString.left, Size.cy + rcString.top);
  1322. pdc->TextOut(rcString.left, rcString.top, lpString);
  1323. }