IMGCommon.cpp 28 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111
  1. #include "StdAfx.h"
  2. #include "IMGCommon.h"
  3. #include <strsafe.h>
  4. #include <comutil.h>
  5. #pragma comment(lib, "comsuppw.lib")
  6. const ColorMatrix _ClrMatrix =
  7. {
  8. 1.0, 0.0, 0.0, 0.0, 0.0,
  9. 0.0, 1.0, 0.0, 0.0, 0.0,
  10. 0.0, 0.0, 0.3, 0.0, 0.0,
  11. 0.0, 0.0, 0.0, 1.0, 0.0,
  12. 0.0, 0.0, 0.0, 0.0, 1.0,
  13. };
  14. ULONG_PTR IMGCommon::m_gdiplusToken;
  15. IMGCommon::IMGCommon(void)
  16. {
  17. GdiplusStartupInput gdiplusStartupInput;
  18. GdiplusStartup(&m_gdiplusToken, &gdiplusStartupInput, NULL);
  19. }
  20. IMGCommon::~IMGCommon(void)
  21. {
  22. Gdiplus::GdiplusShutdown(m_gdiplusToken);
  23. }
  24. /************************************************************************/
  25. /* 函数:IsCorrectExt[6/1/2016 IT];
  26. /* 描述:扩展名是否正确;
  27. /* 参数:;
  28. /* [IN] fext:要判断的扩展名;
  29. /* [OUT] lpMistakenExt:返回错误的扩展名;
  30. /* 返回:扩展名错误返回-1、扩展名为*.*返回0、扩展符合要求返回1;
  31. /* 注意:;
  32. /* 示例:;
  33. /*
  34. /* 修改:;
  35. /* 日期:;
  36. /* 内容:;
  37. /************************************************************************/
  38. INT IMGCommon::IsCorrectExt( IN const TString &fext, OUT TString* lpMistakenExt /* = NULL */ )
  39. {
  40. if (fext.size() == 0)
  41. {
  42. WriteTextLog(_T("要查找的扩展名字符空!"));
  43. return -1;
  44. }
  45. if (fext.find(_T("*.*")) != TString::npos)
  46. {
  47. WriteTextLog(_T("要查找的扩展名为\"*.*\""));
  48. return 0;
  49. }
  50. TString ext = fext;
  51. if (ext[ext.length() - 1] != _T('|'))
  52. ext.append(_T("|"));
  53. INT bRet = 1;
  54. CONST TString sCorrectExt = _T("*.jpg|*.jpeg|*.png|*.bmp|*.cr2|*.nef|*.raw|*.ra2|*.ofr|*.pef|*.sr2");
  55. int nIndex = 0;
  56. do
  57. {
  58. nIndex = ext.find(_T('|'));
  59. if (nIndex != TString::npos)
  60. {
  61. if (sCorrectExt.find(ext.substr(0, nIndex)) == TString::npos)
  62. {
  63. if (lpMistakenExt)
  64. *lpMistakenExt = ext.substr(0, nIndex);
  65. bRet = -1;
  66. break;
  67. }
  68. ext = ext.substr(nIndex + 1);
  69. }
  70. } while (ext.find(_T('|')) != TString::npos);
  71. return bRet;
  72. }
  73. /************************************************************************/
  74. /* 函数:ExtMerge[6/1/2016 IT];
  75. /* 描述:合并扩展名;
  76. /* 参数:;
  77. /* [IN] ext1:要合并的扩展名1;
  78. /* [IN] ext2:要合并的扩展名2;
  79. /* [OUT] merge:合并后的扩展名;
  80. /* 返回:只合并合法的扩展名,若两扩展名都非法,返回FALSE;
  81. /* 注意:;
  82. /* 示例:;
  83. /*
  84. /* 修改:;
  85. /* 日期:;
  86. /* 内容:;
  87. /************************************************************************/
  88. BOOL IMGCommon::ExtMerge(IN CONST TString& ext1, IN CONST TString& ext2, OUT TString &merge) // 合并扩展名;
  89. {
  90. // 1.判断扩展名1合法性;
  91. INT nRet = IsCorrectExt(ext1);
  92. if ( nRet == -1 )
  93. {
  94. nRet = IsCorrectExt(ext2);
  95. if ( nRet == -1)
  96. return FALSE;
  97. merge = ext2;
  98. return TRUE;
  99. }
  100. if (nRet == 0)
  101. {
  102. merge = _T("*.*");
  103. return TRUE;
  104. }
  105. merge = ext1;
  106. // 2.判断扩展名2合法性;
  107. nRet = IsCorrectExt(ext2);
  108. if (nRet != 1) return TRUE;
  109. // 3.合并2扩展名;
  110. if (merge[merge.length() - 1] != _T('|'))
  111. merge.append(_T("|"));
  112. merge.append(ext2);
  113. return TRUE;
  114. }
  115. /************************************************************************/
  116. /* 函数:GetFileName[6/1/2016 IT];
  117. /* 描述:根据参数,获取参数中的文件名;
  118. /* 参数:;
  119. /* [IN] strfile:要获取文件名的全路径名;
  120. /* 返回:获取成功返回文件名,否则返回空;
  121. /* 注意:;
  122. /* 示例:;
  123. /*
  124. /* 修改:;
  125. /* 日期:;
  126. /* 内容:;
  127. /************************************************************************/
  128. CString IMGCommon::GetFileName(IN CONST CString& strfile)
  129. {
  130. CString name = _T("");
  131. int nIndex = strfile.ReverseFind(_T('\\'));
  132. if (nIndex == -1)
  133. return _T("");
  134. name = strfile.Mid(nIndex + 1);
  135. nIndex = name.ReverseFind(_T('.'));
  136. if (nIndex == -1)
  137. return _T("");
  138. name = name.Mid(0, nIndex);
  139. return name;
  140. }
  141. /************************************************************************/
  142. /* 函数:GetFilteringImg[6/1/2016 IT];
  143. /* 描述:过滤掉扩展名不符合要求的文件名;
  144. /* 参数:;
  145. /* [IN] AryImgs:要被过滤的文件名数组;
  146. /* [IN] lpCopyExt:要保留的文件的扩展名;
  147. /* [IN] bPickoutThumbnail:是否剔除缩略图;
  148. /* 返回:void;
  149. /* 注意:;
  150. /* 示例:;
  151. /*
  152. /* 修改:;
  153. /* 日期:;
  154. /* 内容:;
  155. /************************************************************************/
  156. void IMGCommon::GetFilteringImg(IN CStringArray &AryImgs, IN LPCTSTR lpCopyExt, IN BOOL bPickoutThumbnail /*= TRUE*/)
  157. {
  158. if (AryImgs.GetSize() == 0 || lpCopyExt == NULL) return;
  159. // 获取复制扩展名;
  160. int nIndex = 0;
  161. TString strtmp;
  162. TString strCopyExt(lpCopyExt);
  163. if (strCopyExt.find(_T("*.*")) != TString::npos) return;
  164. strCopyExt.append(_T("|"));
  165. STR_VEC vtCopyExt;
  166. // 将所有扩展名解析到数组里;
  167. do
  168. {
  169. nIndex = strCopyExt.find(_T('|'));
  170. if (nIndex != TString::npos)
  171. {
  172. strtmp = strCopyExt.substr(0, nIndex);
  173. strCopyExt = strCopyExt.substr(nIndex + 1);
  174. if (strtmp.compare(_T("*.*")))
  175. vtCopyExt.push_back(strtmp.substr(1));
  176. }
  177. } while (strCopyExt.find(_T('|')) != TString::npos);
  178. // 过滤非复制扩展名的文件,同时去掉缩略图,保留指定复制扩展名的文件;
  179. for (int i = AryImgs.GetSize() - 1; i >= 0; i--)
  180. {
  181. BOOL bExsit = FALSE;
  182. for (STR_VEC::iterator itExt = vtCopyExt.begin(); itExt != vtCopyExt.end(); itExt++)
  183. {
  184. if (AryImgs.ElementAt(i).MakeLower().Find(itExt->c_str()) != -1) {
  185. bExsit = TRUE;
  186. break;
  187. }
  188. }
  189. if (!bExsit) {
  190. AryImgs.RemoveAt(i);
  191. continue;
  192. }
  193. if (bPickoutThumbnail)
  194. {// 这里应该去除"s"和"m"开头的缩略图;// 但新的做法是在订单里创建缩略图子文件夹;// 总而言之,都要去掉缩略图;
  195. nIndex = AryImgs.ElementAt(i).ReverseFind(_T('\\'));
  196. if (nIndex != -1)
  197. {
  198. strtmp = AryImgs.ElementAt(i).Mid(nIndex + 1);
  199. if (strtmp[0] == _T('s') || strtmp[0] == _T('m')) {
  200. AryImgs.RemoveAt(i);
  201. continue;
  202. }
  203. }
  204. }
  205. }
  206. }
  207. /************************************************************************/
  208. /* 函数:GetFilteringImg[6/1/2016 IT];
  209. /* 描述:过滤掉扩展名不符合要求的文件名;
  210. /* 参数:;
  211. /* [IN] vtImgs:要被过滤的文件名数组;
  212. /* [IN] lpCopyExt:要保留的文件的扩展名;
  213. /* [IN] bPickoutThumbnail:是否剔除缩略图;
  214. /* 返回:void;
  215. /* 注意:;
  216. /* 示例:;
  217. /*
  218. /* 修改:;
  219. /* 日期:;
  220. /* 内容:;
  221. /************************************************************************/
  222. void IMGCommon::GetFilteringImg(IN STR_VEC &vtImgs, IN LPCTSTR lpCopyExt, IN BOOL bPickoutThumbnail /*= TRUE*/)
  223. {
  224. if (vtImgs.size() == 0 || lpCopyExt == NULL) return;
  225. // 获取复制扩展名;
  226. int nIndex = 0;
  227. TString strtmp;
  228. TString strCopyExt(lpCopyExt);
  229. if (strCopyExt.find(_T("*.*")) != TString::npos) return;
  230. strCopyExt.append(_T("|"));
  231. STR_VEC vtCopyExt;
  232. // 将所有扩展名解析到数组里;
  233. do
  234. {
  235. nIndex = strCopyExt.find(_T('|'));
  236. if (nIndex != TString::npos)
  237. {
  238. strtmp = strCopyExt.substr(0, nIndex);
  239. strCopyExt = strCopyExt.substr(nIndex + 1);
  240. if (strtmp.compare(_T("*.*")))
  241. vtCopyExt.push_back(strtmp);
  242. }
  243. } while (strCopyExt.find(_T('|')) != TString::npos);
  244. // 过滤非复制扩展名的文件,同时去掉缩略图,保留指定复制扩展名的文件;
  245. for (STR_VEC::iterator it = vtImgs.begin(); it != vtImgs.end();)
  246. {
  247. BOOL bExsit = FALSE;
  248. for (STR_VEC::iterator itExt = vtCopyExt.begin(); itExt != vtCopyExt.end(); itExt++)
  249. {
  250. if (match(itExt->c_str(), it->c_str())) {
  251. bExsit = TRUE;
  252. break;
  253. }
  254. }
  255. if (!bExsit) {
  256. it = vtImgs.erase(it);
  257. continue;
  258. }
  259. if (bPickoutThumbnail)
  260. {// 这里应该去除"s"和"m"开头的缩略图;// 但新的做法是在订单里创建缩略图子文件夹;// 总而言之,都要去掉缩略图;
  261. nIndex = it->find_last_of(_T('\\'));
  262. if (nIndex != TString::npos) {
  263. strtmp = it->substr(nIndex + 1);
  264. if (strtmp[0] == _T('s') || strtmp[0] == _T('m')) {
  265. it = vtImgs.erase(it);
  266. continue;
  267. }
  268. }
  269. }
  270. it++;
  271. }
  272. }
  273. /************************************************************************/
  274. /* 函数:SubgroupExt[6/1/2016 IT];
  275. /* 描述:将指定的扩展名文件分离出来;
  276. /* 参数:;
  277. /* [IN] vtAllImgs:源,要被分离指定扩展名的文件路径数组;
  278. /* [IN] lpSubgroupExt:要分离出来的扩展名;
  279. /* [OUT] AryImgs:返回分离出来的文件路径数组;
  280. /* 返回:void;
  281. /* 注意:;
  282. /* 示例:;
  283. /*
  284. /* 修改:;
  285. /* 日期:;
  286. /* 内容:;
  287. /************************************************************************/
  288. void IMGCommon::SubgroupExt(IN STR_VEC &vtAllImgs, IN LPCTSTR lpSubgroupExt, OUT CStringArray &AryImgs)
  289. {
  290. if (vtAllImgs.size() == 0 || lpSubgroupExt == NULL) return;
  291. // 获取复制扩展名;
  292. int nIndex = 0;
  293. TString strtmp;
  294. TString strSubgroupExt(lpSubgroupExt);
  295. if (strSubgroupExt.find(_T("*.*")) != TString::npos)
  296. {
  297. for (STR_VEC::iterator it = vtAllImgs.begin(); it != vtAllImgs.end(); it++)
  298. AryImgs.Add(CString(it->c_str()));
  299. return;
  300. }
  301. strSubgroupExt.append(_T("|"));
  302. STR_VEC vtSubgroupExt;
  303. // 将所有扩展名解析到数组里;
  304. do
  305. {
  306. nIndex = strSubgroupExt.find(_T('|'));
  307. if (nIndex != TString::npos)
  308. {
  309. strtmp = strSubgroupExt.substr(0, nIndex);
  310. strSubgroupExt = strSubgroupExt.substr(nIndex + 1);
  311. if (strtmp.compare(_T("*.*")))
  312. vtSubgroupExt.push_back(strtmp);
  313. }
  314. } while (strSubgroupExt.find(_T('|')) != TString::npos);
  315. // 过滤非复制扩展名的文件,同时去掉缩略图,保留指定复制扩展名的文件;
  316. for (STR_VEC::iterator it = vtAllImgs.begin(); it != vtAllImgs.end(); it++)
  317. {
  318. BOOL bExsit = FALSE;
  319. for (STR_VEC::iterator itExt = vtSubgroupExt.begin(); itExt != vtSubgroupExt.end(); itExt++)
  320. {
  321. if (match(itExt->c_str(), it->c_str()))
  322. {
  323. #if 1// 这里应该去除"s"和"m"开头的缩略图;// 但新的做法是在订单里创建缩略图子文件夹;// 总而言之,都要去掉缩略图;
  324. nIndex = it->find_last_of(_T('\\'));
  325. if (nIndex != TString::npos)
  326. {
  327. strtmp = it->substr(nIndex + 1);
  328. if (strtmp[0] == _T('s') || strtmp[0] == _T('m'))
  329. {
  330. continue;
  331. }
  332. }
  333. #endif
  334. AryImgs.Add(CString(it->c_str()));
  335. break;
  336. }
  337. }
  338. }
  339. }
  340. void IMGCommon::SubgroupExt(IN STR_VEC &vtAllImgs, IN LPCTSTR lpSubgroupExt, IN STR_VEC &vtImgs)
  341. {
  342. if (vtAllImgs.size() == 0 || lpSubgroupExt == NULL) return;
  343. // 获取复制扩展名;
  344. int nIndex = 0;
  345. TString strtmp;
  346. TString strSubgroupExt(lpSubgroupExt);
  347. if (strSubgroupExt.find(_T("*.*")) != TString::npos)
  348. {
  349. for (STR_VEC::iterator it = vtAllImgs.begin(); it != vtAllImgs.end(); it++)
  350. vtImgs.push_back(*it);
  351. return;
  352. }
  353. strSubgroupExt.append(_T("|"));
  354. STR_VEC vtSubgroupExt;
  355. // 将所有扩展名解析到数组里;
  356. do
  357. {
  358. nIndex = strSubgroupExt.find(_T('|'));
  359. if (nIndex != TString::npos)
  360. {
  361. strtmp = strSubgroupExt.substr(0, nIndex);
  362. strSubgroupExt = strSubgroupExt.substr(nIndex + 1);
  363. if (strtmp.compare(_T("*.*")))
  364. vtSubgroupExt.push_back(strtmp);
  365. }
  366. } while (strSubgroupExt.find(_T('|')) != TString::npos);
  367. // 过滤非复制扩展名的文件,同时去掉缩略图,保留指定复制扩展名的文件;
  368. for (STR_VEC::iterator it = vtAllImgs.begin(); it != vtAllImgs.end(); it++)
  369. {
  370. BOOL bExsit = FALSE;
  371. for (STR_VEC::iterator itExt = vtSubgroupExt.begin(); itExt != vtSubgroupExt.end(); itExt++)
  372. {
  373. if (match(itExt->c_str(), it->c_str())) {
  374. #if 1// 这里应该去除"s"和"m"开头的缩略图;// 但新的做法是在订单里创建缩略图子文件夹;// 总而言之,都要去掉缩略图;
  375. nIndex = it->find_last_of(_T('\\'));
  376. if (nIndex != TString::npos) {
  377. strtmp = it->substr(nIndex + 1);
  378. if (strtmp[0] == _T('s') || strtmp[0] == _T('m')) {
  379. continue;
  380. }
  381. }
  382. #endif
  383. vtImgs.push_back(*it);
  384. break;
  385. }
  386. }
  387. }
  388. }
  389. //////////////////////////////////////////////////////////////////////////
  390. BOOL IMGCommon::LoadImgFromFile(IN Image** pImg, LPCTSTR lpPath)
  391. {
  392. if ( !PathFileExists(lpPath) )
  393. return FALSE;
  394. if ( *pImg )
  395. delete *pImg;
  396. *pImg = NULL;
  397. #ifdef UNICODE
  398. *pImg = Image::FromFile(lpPath, g_useEmbeddedColorManagement);
  399. #else
  400. BSTR strtmp = _bstr_t(lpPath);
  401. *pImg = Image::FromFile(strtmp, g_useEmbeddedColorManagement);
  402. SysFreeString(strtmp);
  403. #endif
  404. return (*pImg ? TRUE : FALSE);
  405. }
  406. BOOL IMGCommon::LoadImgFromBuffer(IN Image** pImg, IN BYTE* pBuffer, IN CONST INT& nBufLen)
  407. {
  408. if ( pBuffer == NULL )
  409. return FALSE;
  410. if ( *pImg )
  411. delete *pImg;
  412. *pImg = NULL;
  413. HGLOBAL hMemery = GlobalAlloc(GMEM_MOVEABLE, nBufLen);
  414. if ( hMemery == NULL )
  415. return FALSE;
  416. BYTE *pMem = (BYTE*)GlobalLock(hMemery);
  417. memcpy(pMem, pBuffer, nBufLen);
  418. IStream *pstream = NULL;
  419. CreateStreamOnHGlobal(hMemery, TRUE, &pstream);
  420. *pImg = Image::FromStream(pstream, g_useEmbeddedColorManagement);
  421. GlobalUnlock(hMemery);
  422. pstream->Release();
  423. return (*pImg ? TRUE : FALSE);
  424. }
  425. // 先以只读方式从文件中读取二进制流出来,可以做到不独占文件;
  426. BOOL IMGCommon::LoadImgFromBuffer(IN Image** pImg, LPCTSTR lpPath)
  427. {
  428. if ( !PathFileExists(lpPath) )
  429. return FALSE;
  430. if ( *pImg )
  431. delete *pImg;
  432. *pImg = NULL;
  433. return LoadImgFromFile(pImg, lpPath);
  434. CFile fp;
  435. CFileException e;
  436. BOOL bRet = FALSE;
  437. if ( fp.Open(lpPath, CFile::modeRead, &e))
  438. {
  439. DWORD dwLength = (DWORD)fp.GetLength();
  440. BYTE *pData = new BYTE[dwLength];
  441. fp.Read(pData,dwLength);
  442. fp.Close();
  443. bRet = LoadImgFromBuffer(pImg, pData, dwLength);
  444. if( pData )
  445. delete []pData;
  446. }
  447. return bRet;
  448. }
  449. /************************************************************************/
  450. /* 函数:LoadImgFromResource[9/21/2016 IT];
  451. /* 描述:从资源中加载;
  452. /* 参数:;
  453. /* [IN] :;
  454. /* [OUT] :;
  455. /* [IN/OUT] :;
  456. /* 返回:void;
  457. /* 注意:;
  458. /* 示例:;
  459. /*
  460. /* 修改:;
  461. /* 日期:;
  462. /* 内容:;
  463. /************************************************************************/
  464. Image* IMGCommon::LoadImgFromResource(IN HMODULE hModule, IN LPCTSTR lpName, IN LPCTSTR lpType)
  465. {
  466. HGLOBAL hGlobal = NULL;
  467. HRSRC hSource = NULL;
  468. LPVOID lpBuffer = NULL;
  469. DWORD dwSize = 0;
  470. // 1.定位我们的自定义资源,这里因为我们是从本模块定位资源,所以将句柄简单地置为NULL即可
  471. hSource = FindResource(hModule, lpName, lpType);
  472. if (hSource == NULL)
  473. {
  474. _tprintf(_T("载入资源失败:%s"), lpName);
  475. return NULL;
  476. }
  477. // 2.获取资源的大小;
  478. dwSize = (UINT)SizeofResource(NULL, hSource);
  479. // 3.加载资源;
  480. hGlobal = LoadResource(NULL, hSource);
  481. if (hGlobal == NULL)
  482. {
  483. _tprintf(_T("载入资源失败:%s"), lpName);
  484. return NULL;
  485. }
  486. // 4.锁定资源,获取buffer;
  487. lpBuffer = LockResource(hGlobal);
  488. if (lpBuffer == NULL)
  489. {
  490. _tprintf(_T("载入资源失败:%s"), lpName);
  491. return NULL;
  492. }
  493. // lpFileFullName需要先判断文件是否存在??不需要;
  494. Image *pImg = NULL;
  495. LoadImgFromBuffer(&pImg, (BYTE*)lpBuffer, dwSize);
  496. UnlockResource(hGlobal);
  497. FreeResource(hGlobal);
  498. return pImg;
  499. }
  500. BOOL IMGCommon::GetOrientation(IN Image *pImg)
  501. {
  502. if (pImg == NULL) return FALSE;
  503. UINT totalBufferSize;
  504. UINT numProperties;
  505. pImg->GetPropertySize(&totalBufferSize, &numProperties);
  506. // Allocate the buffer that will receive the property items.
  507. PropertyItem* pAllItems = (PropertyItem*)malloc(totalBufferSize);
  508. // Fill the buffer.
  509. pImg->GetAllPropertyItems(totalBufferSize, numProperties, pAllItems);
  510. // Print the id data member of each property item.
  511. for (UINT j = 0; j < numProperties; ++j)
  512. {
  513. if (PropertyTagOrientation == pAllItems[j].id)
  514. {
  515. short* ptrLong = (short*)(pAllItems[j].value);
  516. int ret = (int)*ptrLong;
  517. free(pAllItems);
  518. return ret;
  519. }
  520. }
  521. free(pAllItems);
  522. return TRUE;
  523. }
  524. /************************************************************************/
  525. /*
  526. 函数:GetEncoderClsid
  527. 描述:获取GDI+支持的图像格式编码器种类,以及所有种类编码器信息;
  528. 参数:
  529. IN: format 要获取的图像格式;
  530. OUT: pClsid 返回符合条件的图像编码器信息;
  531. 返回:成功返回编码器索引,否则返回-1;
  532. */
  533. /************************************************************************/
  534. int IMGCommon::GetEncoderClsid(IN CONST WCHAR* format, OUT CLSID* pClsid)
  535. {
  536. // GDI+支持的图像编码器数量;
  537. UINT numEncoders = 0;
  538. // GDI+所有图像格式编码器详细信息所需要的空间大小;
  539. UINT nSize = 0;
  540. ImageCodecInfo* pImageCodecInfo = NULL;
  541. // 2.获取GDI+支持的所有图像格式编码器详细信息所需要的空间大小;
  542. GetImageEncodersSize(&numEncoders, &nSize);
  543. if (nSize == 0)
  544. return -1;
  545. //3.为ImageCodecInfo数组分配足额空间;
  546. pImageCodecInfo = (ImageCodecInfo*)(malloc(nSize));
  547. if (pImageCodecInfo == NULL)
  548. return -1;
  549. //4.获取所有的图像编码器信息;
  550. GetImageEncoders(numEncoders, nSize, pImageCodecInfo);
  551. //5.查找符合的图像编码器的Clsid;
  552. for (UINT i = 0; i < numEncoders; ++i)
  553. {
  554. if (wcscmp(pImageCodecInfo[i].MimeType, format) == 0)
  555. {
  556. *pClsid = pImageCodecInfo[i].Clsid;
  557. free(pImageCodecInfo);
  558. return i; // Success
  559. }
  560. }
  561. //6.释放步骤3分配的内存;
  562. free(pImageCodecInfo);
  563. return -1;
  564. }
  565. /************************************************************************/
  566. /*
  567. 函数:SaveImg2newfile
  568. 描述:将Image对象另存为其他格式的文件;
  569. 参数:
  570. IN: pImg GDI+ Image对象指针,需要保存的图像对象;
  571. IN: lpnewfile 其他格式的新文件名(jpg,bmp,png,jpeg);
  572. IN: uQuality 另存为新文件时的图像质量值;
  573. 返回:
  574. 注意:Image::Save 若文件存在,会覆盖存在的文件;
  575. */
  576. /************************************************************************/
  577. BOOL IMGCommon::SaveImg2newfile(IN Image* pImg, IN CString strNewfile, IN ULONG uQuality)
  578. {
  579. if (pImg == NULL) return FALSE;
  580. // 需要判断路径是否存在,不存在创建目录;
  581. int nIndex = strNewfile.ReverseFind(_T('\\'));
  582. if (nIndex == -1)
  583. return FALSE;
  584. if (!PathFileExists(strNewfile.Left(nIndex)))
  585. {
  586. // 如果文件夹不存在,创建;
  587. SHCreateDirectoryEx(NULL, strNewfile.Left(nIndex), NULL);
  588. }
  589. nIndex = strNewfile.ReverseFind(_T('.'));
  590. if (nIndex == -1)
  591. return FALSE;
  592. Status stat = GenericError;
  593. CLSID encoderClsid = { 0 };
  594. BSTR newfile = strNewfile.AllocSysString();
  595. strNewfile = strNewfile.Mid(nIndex + 1);
  596. if (strNewfile.CompareNoCase(_T("bmp")) == 0)
  597. {
  598. GetEncoderClsid(L"image/bmp", &encoderClsid);
  599. stat = pImg->Save(newfile, &encoderClsid, NULL);
  600. }
  601. else if (strNewfile.CompareNoCase(_T("png")) == 0)
  602. {
  603. GetEncoderClsid(L"image/png", &encoderClsid);
  604. stat = pImg->Save(newfile, &encoderClsid, NULL);
  605. }
  606. else// if ( strNewfile.CompareNoCase(_T("jpeg")) == 0 )
  607. {
  608. GetEncoderClsid(L"image/jpeg", &encoderClsid);
  609. EncoderParameters encoderParameters;
  610. encoderParameters.Count = 1;
  611. encoderParameters.Parameter[0].Guid = EncoderQuality;
  612. encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
  613. encoderParameters.Parameter[0].NumberOfValues = 1;
  614. // Save the image as a JPEG with quality level 100.
  615. encoderParameters.Parameter[0].Value = &uQuality;
  616. stat = pImg->Save(newfile, &encoderClsid, &encoderParameters);
  617. }
  618. SysFreeString(newfile);
  619. if ( stat != Ok)
  620. GetGdiPlusError(stat);
  621. return stat == Ok ? TRUE : FALSE;
  622. }
  623. BOOL IMGCommon::SaveImg2newfile(IN Image* pImg, IN TString strNewfile, IN ULONG uQuality)
  624. {
  625. if (pImg == NULL) return FALSE;
  626. // 需要判断路径是否存在,不存在创建目录;
  627. int nIndex = strNewfile.find_last_of(_T('\\'));
  628. if (nIndex == TString::npos)
  629. return FALSE;
  630. if (!PathFileExists(strNewfile.substr(0, nIndex).c_str()))
  631. {
  632. // 如果文件夹不存在,创建;
  633. SHCreateDirectoryEx(NULL, strNewfile.substr(0, nIndex).c_str(), NULL);
  634. }
  635. nIndex = strNewfile.find_last_of(_T('.'));
  636. if (nIndex == TString::npos)
  637. return FALSE;
  638. Status stat = GenericError;
  639. CLSID encoderClsid = { 0 };
  640. BSTR newfile = _bstr_t(strNewfile.c_str());
  641. strNewfile = strNewfile.substr(nIndex + 1);
  642. if (strNewfile.find(_T("bmp")) == 0)
  643. {
  644. GetEncoderClsid(L"image/bmp", &encoderClsid);
  645. stat = pImg->Save(newfile, &encoderClsid, NULL);
  646. }
  647. else if (strNewfile.find(_T("png")) == 0)
  648. {
  649. GetEncoderClsid(L"image/png", &encoderClsid);
  650. stat = pImg->Save(newfile, &encoderClsid, NULL);
  651. }
  652. else// if ( strNewfile.CompareNoCase(_T("jpeg")) == 0 )
  653. {
  654. GetEncoderClsid(L"image/jpeg", &encoderClsid);
  655. EncoderParameters encoderParameters;
  656. encoderParameters.Count = 1;
  657. encoderParameters.Parameter[0].Guid = EncoderQuality;
  658. encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
  659. encoderParameters.Parameter[0].NumberOfValues = 1;
  660. // Save the image as a JPEG with quality level 100.
  661. encoderParameters.Parameter[0].Value = &uQuality;
  662. stat = pImg->Save(newfile, &encoderClsid, &encoderParameters);
  663. }
  664. SysFreeString(newfile);
  665. if ( stat != Ok)
  666. GetGdiPlusError(stat);
  667. return stat == Ok ? TRUE : FALSE;
  668. }
  669. /************************************************************************/
  670. /*
  671. 函数:ZoomImg
  672. 描述:缩放到指定大小的区域中,返回缩放后的尺寸;
  673. 参数:
  674. IN: Imgrc 图像的大小;
  675. IN: dwDisplayPix 图像要显示的区域的大小;
  676. OUT: dwZoomPix 图像在显示区域内缩放后的尺寸;
  677. 返回:
  678. 注意:dwZoomPix的尺寸必须在dwDisplayPix内;
  679. */
  680. /************************************************************************/
  681. int IMGCommon::ZoomImg(IN CRect &Imgrc, IN CONST DWORD &dwDisplayPix, OUT DWORD &dwZoomPix)
  682. {
  683. double fDisplayWidth = GET_XPIX(dwDisplayPix);
  684. double fDisplayHeight = GET_YPIX(dwDisplayPix);
  685. // 显示区域长宽比;
  686. double fDisplayAspectRatio = fDisplayWidth / fDisplayHeight;
  687. // 图片长宽比;
  688. double fImgAspectRatio = ((double)Imgrc.Width()) / ((double)Imgrc.Height());
  689. double fZoomWidth;
  690. double fZoomHeight;
  691. if (fDisplayAspectRatio > fImgAspectRatio)
  692. {
  693. fZoomWidth = fDisplayHeight*fImgAspectRatio;
  694. fZoomHeight = fDisplayHeight;
  695. }
  696. else
  697. {
  698. fZoomWidth = fDisplayWidth;
  699. fZoomHeight = fDisplayWidth / fImgAspectRatio;
  700. }
  701. dwZoomPix = SET_PIX((int)fZoomWidth, (int)fZoomHeight);
  702. //////////////////////////////////////////////////////////////////////////
  703. int nRetval = 0;
  704. if ((fDisplayWidth == Imgrc.Width()) && (fDisplayHeight == Imgrc.Height()))
  705. {
  706. nRetval = ZoomNull;
  707. }
  708. else if ((fDisplayWidth > Imgrc.Width()) && (fDisplayHeight > Imgrc.Height()))
  709. {
  710. nRetval = ZoomOut;
  711. }
  712. else
  713. {
  714. nRetval = ZoomIn;
  715. }
  716. return nRetval;
  717. }
  718. int IMGCommon::ZoomImg(IN CONST DWORD &dwImgPix, IN CONST DWORD &dwDisplayPix, OUT DWORD &dwZoomPix)
  719. {
  720. double fDisplayWidth = GET_XPIX(dwDisplayPix);
  721. double fDisplayHeight = GET_YPIX(dwDisplayPix);
  722. // 显示区域长宽比;
  723. double fDisplayAspectRatio = fDisplayWidth / fDisplayHeight;
  724. // 图片长宽比;
  725. double fImgAspectRatio = ((double)GET_XPIX(dwImgPix)) / ((double)GET_YPIX(dwImgPix));
  726. double fZoomWidth;
  727. double fZoomHeight;
  728. if (fDisplayAspectRatio > fImgAspectRatio)
  729. {
  730. fZoomWidth = fDisplayHeight*fImgAspectRatio;
  731. fZoomHeight = fDisplayHeight;
  732. }
  733. else
  734. {
  735. fZoomWidth = fDisplayWidth;
  736. fZoomHeight = fDisplayWidth / fImgAspectRatio;
  737. }
  738. dwZoomPix = SET_PIX((int)fZoomWidth, (int)fZoomHeight);
  739. //////////////////////////////////////////////////////////////////////////
  740. int nRetval = 0;
  741. if ((fDisplayWidth == GET_XPIX(dwImgPix)) && (fDisplayHeight == GET_YPIX(dwImgPix)))
  742. {
  743. nRetval = ZoomNull;
  744. }
  745. else if ((fDisplayWidth > GET_XPIX(dwImgPix)) && (fDisplayHeight > GET_YPIX(dwImgPix)))
  746. {
  747. nRetval = ZoomOut;
  748. }
  749. else
  750. {
  751. nRetval = ZoomIn;
  752. }
  753. return nRetval;
  754. }
  755. /************************************************************************/
  756. /*
  757. 函数:ImgThumbnail
  758. 描述:生成高质量的图像缩略图;
  759. 参数:
  760. 返回:
  761. 注意:为了健壮性,strNewfile的路径可以在函数内再次判断是否有效,防止在函数外没有进行经判断;
  762. */
  763. /************************************************************************/
  764. BOOL IMGCommon::ImgThumbnail(IN Image* pImg, IN CONST DWORD &dwDisplayPix, IN CString strNewfile, IN ULONG uQuality)
  765. {
  766. if (pImg == NULL) return FALSE;
  767. DWORD dwZoomPix;
  768. int retval = ZoomImg(SET_PIX(pImg->GetWidth(), pImg->GetHeight()), dwDisplayPix, dwZoomPix);
  769. if (retval == ZoomOut)
  770. {
  771. WriteTextLog(_T("复制时放大图像,退出复制!"));
  772. return FALSE;
  773. }
  774. else if (retval == ZoomNull)
  775. {
  776. return SaveImg2newfile(pImg, strNewfile, uQuality);
  777. }
  778. // 绘制缩略图;
  779. Bitmap bitmap(GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
  780. Graphics *graphic = Graphics::FromImage(&bitmap);
  781. graphic->Clear(Color(255, 255, 255, 255));
  782. // 设置缩放或旋转图片时的算法(图片质量);
  783. graphic->SetInterpolationMode(InterpolationModeHighQualityBicubic);
  784. // 设置渲染图形对象的质量;
  785. graphic->SetSmoothingMode(SmoothingModeHighQuality);//SmoothingModeHighSpeed
  786. // 设置图形对象的像素偏移模式;
  787. graphic->SetPixelOffsetMode(PixelOffsetModeHighQuality);
  788. // 设置图形对象的合成模式;
  789. graphic->SetCompositingMode(CompositingModeSourceOver);
  790. // 设置图形对象的合成质量;
  791. graphic->SetCompositingQuality(CompositingQualityHighQuality);
  792. // 设置图形对象的文本渲染模式;
  793. graphic->SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);
  794. Status st = graphic->DrawImage(pImg, 0, 0, GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
  795. if ( st != Ok )
  796. {
  797. delete graphic;
  798. WriteTextLog("创建缩略图画板失败:%ld",st);
  799. GetGdiPlusError(st);
  800. return FALSE;
  801. }
  802. delete graphic;
  803. // 生成缩略图;
  804. return SaveImg2newfile(&bitmap, strNewfile, uQuality);
  805. }
  806. BOOL IMGCommon::ImgThumbnail(IN LPCTSTR lpImgpath, IN CONST DWORD &dwDisplayPix, IN CString strNewfile, IN ULONG uQuality)
  807. {
  808. if (!PathFileExists(lpImgpath))
  809. return FALSE;
  810. #ifdef UNICODE
  811. Image Img(lpImgpath);
  812. #else
  813. BSTR strtmp = _bstr_t(lpImgpath);
  814. Image Img(strtmp);
  815. SysFreeString(strtmp);
  816. #endif
  817. DWORD dwZoomPix;
  818. int retval = ZoomImg(SET_PIX(Img.GetWidth(), Img.GetHeight()), dwDisplayPix, dwZoomPix);
  819. if (retval == ZoomOut)
  820. {
  821. WriteTextLog(_T("复制时放大图像,退出复制!"));
  822. return FALSE;
  823. }
  824. else if (retval == ZoomNull)
  825. {
  826. return SaveImg2newfile(&Img, strNewfile, uQuality);
  827. }
  828. // 绘制缩略图;
  829. Bitmap bitmap(GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
  830. Graphics *graphic = Graphics::FromImage(&bitmap);
  831. graphic->Clear(Color(255, 255, 255, 255));
  832. // 设置缩放或旋转图片时的算法(图片质量);
  833. graphic->SetInterpolationMode(InterpolationModeHighQualityBicubic);
  834. // 设置渲染图形对象的质量;
  835. graphic->SetSmoothingMode(SmoothingModeHighQuality);//SmoothingModeHighSpeed
  836. // 设置图形对象的像素偏移模式;
  837. graphic->SetPixelOffsetMode(PixelOffsetModeHighQuality);
  838. // 设置图形对象的合成模式;
  839. graphic->SetCompositingMode(CompositingModeSourceOver);
  840. // 设置图形对象的合成质量;
  841. graphic->SetCompositingQuality(CompositingQualityHighQuality);
  842. // 设置图形对象的文本渲染模式;
  843. graphic->SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);
  844. Status st = graphic->DrawImage(&Img, 0, 0, GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
  845. if ( st != Ok )
  846. {
  847. delete graphic;
  848. WriteTextLog("创建缩略图画板失败:%ld",st);
  849. GetGdiPlusError(st);
  850. return FALSE;
  851. }
  852. delete graphic;
  853. // 生成缩略图;
  854. return SaveImg2newfile(&bitmap, strNewfile, uQuality);
  855. }
  856. BOOL IMGCommon::ImgThumbnail(IN CONST TString &strImgpath, IN CONST DWORD &dwDisplayPix, IN TString strNewfile, IN ULONG uQuality)
  857. {
  858. if (!PathFileExists(strImgpath.c_str()))
  859. {
  860. SetLastError(GetLastError());
  861. return FALSE;
  862. }
  863. #ifdef UNICODE
  864. BSTR strtmp = _bstr_t(strImgpath.c_str());
  865. Image Img(strtmp);
  866. SysFreeString(strtmp);
  867. //Image Img(strImgpath);
  868. #else
  869. BSTR strtmp = _bstr_t(strImgpath.c_str());
  870. Image Img(strtmp);
  871. SysFreeString(strtmp);
  872. #endif
  873. DWORD dwZoomPix;
  874. int retval = ZoomImg(SET_PIX(Img.GetWidth(), Img.GetHeight()), dwDisplayPix, dwZoomPix);
  875. if (retval == ZoomOut)
  876. {
  877. WriteTextLog(_T("复制时放大图像,退出复制!"));
  878. return FALSE;
  879. }
  880. else if (retval == ZoomNull)
  881. {
  882. return SaveImg2newfile(&Img, strNewfile, uQuality);
  883. }
  884. // 绘制缩略图;
  885. Bitmap bitmap(GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
  886. Graphics *graphic = Graphics::FromImage(&bitmap);
  887. graphic->Clear(Color(255, 255, 255, 255));
  888. // 设置缩放或旋转图片时的算法(图片质量);
  889. graphic->SetInterpolationMode(InterpolationModeHighQualityBicubic);
  890. // 设置渲染图形对象的质量;
  891. graphic->SetSmoothingMode(SmoothingModeHighQuality);//SmoothingModeHighSpeed
  892. // 设置图形对象的像素偏移模式;
  893. graphic->SetPixelOffsetMode(PixelOffsetModeHighQuality);
  894. // 设置图形对象的合成模式;
  895. graphic->SetCompositingMode(CompositingModeSourceOver);
  896. // 设置图形对象的合成质量;
  897. graphic->SetCompositingQuality(CompositingQualityHighQuality);
  898. // 设置图形对象的文本渲染模式;
  899. graphic->SetTextRenderingHint(TextRenderingHintAntiAliasGridFit);
  900. Status st = graphic->DrawImage(&Img, 0, 0, GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
  901. if ( st != Ok )
  902. {
  903. delete graphic;
  904. return FALSE;
  905. }
  906. delete graphic;
  907. // 生成缩略图;
  908. return SaveImg2newfile(&bitmap, strNewfile, uQuality);
  909. }
  910. BOOL IMGCommon::SimpleImgThumbnail(IN LPCTSTR lpImgpath, IN CONST DWORD &dwDisplayPix, IN CString strNewfile, IN ULONG uQuality)
  911. {
  912. if (!PathFileExists(lpImgpath))
  913. return FALSE;
  914. DWORD dwZoomPix;
  915. Image *pImg = NULL;
  916. LoadImgFromFile(&pImg, lpImgpath);
  917. if ( pImg == NULL )
  918. {
  919. return FALSE;
  920. }
  921. int retval = ZoomImg(SET_PIX(pImg->GetWidth(), pImg->GetHeight()), dwDisplayPix, dwZoomPix);
  922. if (retval == ZoomOut)
  923. {
  924. WriteTextLog(_T("复制时放大图像,退出复制!"));
  925. if (pImg) delete pImg;
  926. return FALSE;
  927. }
  928. else if (retval == ZoomNull)
  929. {
  930. BOOL bRet = SaveImg2newfile(pImg, strNewfile, uQuality);
  931. if (pImg) delete pImg;
  932. return bRet;
  933. }
  934. Image *pThumbnailImg = pImg->GetThumbnailImage(GET_XPIX(dwZoomPix), GET_YPIX(dwZoomPix));
  935. if (pThumbnailImg)
  936. {
  937. // 提高缩略图质量;
  938. Graphics graphic(pThumbnailImg);
  939. graphic.DrawImage(pImg, 0, 0, pThumbnailImg->GetWidth(), pThumbnailImg->GetHeight());
  940. INT nRientation = GetOrientation(pImg);
  941. if ( nRientation == 8 )
  942. {
  943. pThumbnailImg->RotateFlip(Rotate270FlipNone);
  944. }
  945. else if (nRientation == 6)
  946. {
  947. pThumbnailImg->RotateFlip(Rotate90FlipNone);
  948. }
  949. SaveImg2newfile(pThumbnailImg, strNewfile, uQuality);
  950. }
  951. else
  952. {
  953. if (pImg) delete pImg;
  954. return FALSE;
  955. }
  956. if (pImg) delete pImg;
  957. if (pThumbnailImg) delete pThumbnailImg;
  958. return TRUE;
  959. }