Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

488 lines
16 KiB

  1. #include "precomp.h"
  2. #include "gphelper.h"
  3. #include "psutil.h"
  4. using namespace Gdiplus;
  5. CGdiPlusHelper::CGdiPlusHelper(void)
  6. : m_pImageEncoderInfo(NULL),
  7. m_nImageEncoderCount(0),
  8. m_pImageDecoderInfo(NULL),
  9. m_nImageDecoderCount(0)
  10. #if defined(GDIPLUSHELPER_EXPLICIT_INITIALIZATION)
  11. ,m_bGdiplusInitialized(false)
  12. ,m_pGdiplusToken(NULL)
  13. #endif
  14. {
  15. Initialize();
  16. }
  17. CGdiPlusHelper::~CGdiPlusHelper(void)
  18. {
  19. Destroy();
  20. }
  21. HRESULT CGdiPlusHelper::Initialize(void)
  22. {
  23. #if defined(GDIPLUSHELPER_EXPLICIT_INITIALIZATION)
  24. // Make sure GDI+ is initialized
  25. Gdiplus::GdiplusStartupInput StartupInput;
  26. m_bGdiplusInitialized = (Gdiplus::GdiplusStartup(&m_pGdiplusToken,&StartupInput,NULL) == Gdiplus::Ok);
  27. #endif
  28. // Get the installed encoders
  29. HRESULT hr = E_FAIL;
  30. UINT cbCodecs = 0;
  31. GetImageEncodersSize( &m_nImageEncoderCount, &cbCodecs );
  32. if (cbCodecs)
  33. {
  34. m_pImageEncoderInfo = static_cast<ImageCodecInfo*>(LocalAlloc(LPTR,cbCodecs));
  35. if (m_pImageEncoderInfo)
  36. {
  37. GpStatus Status = GetImageEncoders( m_nImageEncoderCount, cbCodecs, m_pImageEncoderInfo );
  38. if (Ok == Status)
  39. {
  40. for (UINT i=0;i<m_nImageEncoderCount;i++)
  41. {
  42. ////WIA_PRINTGUID((m_pImageEncoderInfo[i].Clsid,TEXT("m_pImageEncoderInfo[i].Clsid")));
  43. ////WIA_PRINTGUID((m_pImageEncoderInfo[i].FormatID,TEXT("m_pImageEncoderInfo[i].FormatID")));
  44. }
  45. hr = S_OK;
  46. }
  47. }
  48. }
  49. // Get the installed decoders
  50. cbCodecs = 0;
  51. GetImageDecodersSize( &m_nImageDecoderCount, &cbCodecs );
  52. if (cbCodecs)
  53. {
  54. m_pImageDecoderInfo = static_cast<ImageCodecInfo*>(LocalAlloc(LPTR,cbCodecs));
  55. if (m_pImageDecoderInfo)
  56. {
  57. GpStatus Status = GetImageDecoders( m_nImageDecoderCount, cbCodecs, m_pImageDecoderInfo );
  58. if (Ok == Status)
  59. {
  60. hr = S_OK;
  61. }
  62. }
  63. }
  64. // If there was a problem, make sure there are no half-initialized things laying around
  65. if (FAILED(hr))
  66. {
  67. Destroy();
  68. }
  69. return hr;
  70. }
  71. void CGdiPlusHelper::Destroy(void)
  72. {
  73. #if defined(GDIPLUSHELPER_EXPLICIT_INITIALIZATION)
  74. // Shut down GDI+
  75. if (m_bGdiplusInitialized)
  76. {
  77. Gdiplus::GdiplusShutdown(m_pGdiplusToken);
  78. m_bGdiplusInitialized = false;
  79. m_pGdiplusToken = NULL;
  80. }
  81. #endif
  82. // Free the lists of Encoders and Decoders
  83. if (m_pImageEncoderInfo)
  84. {
  85. LocalFree(m_pImageEncoderInfo);
  86. m_pImageEncoderInfo = NULL;
  87. }
  88. m_nImageEncoderCount = 0;
  89. if (m_pImageDecoderInfo)
  90. {
  91. LocalFree(m_pImageDecoderInfo);
  92. m_pImageDecoderInfo = NULL;
  93. }
  94. m_nImageDecoderCount = 0;
  95. }
  96. bool CGdiPlusHelper::IsValid(void) const
  97. {
  98. // Make sure we've been completely created
  99. #if defined(GDIPLUSHELPER_EXPLICIT_INITIALIZATION)
  100. return(m_bGdiplusInitialized && m_pImageEncoderInfo && m_nImageEncoderCount && m_pImageDecoderInfo && m_nImageDecoderCount);
  101. #else
  102. return(m_pImageEncoderInfo && m_nImageEncoderCount && m_pImageDecoderInfo && m_nImageDecoderCount);
  103. #endif
  104. }
  105. HRESULT CGdiPlusHelper::LoadAndScale( HBITMAP &hTargetBitmap, LPCTSTR pszFilename, UINT nMaxWidth, UINT nMaxHeight, bool bStretchSmallImages )
  106. {
  107. hTargetBitmap = NULL;
  108. // Make sure we have a valid filename
  109. if (pszFilename && lstrlen(pszFilename))
  110. {
  111. Bitmap SourceBitmap( CSimpleStringConvert::WideString(CSimpleString(pszFilename) ) );
  112. if (Ok == SourceBitmap.GetLastStatus())
  113. {
  114. // Get the image width and height
  115. UINT nSourceWidth = SourceBitmap.GetWidth();
  116. UINT nSourceHeight = SourceBitmap.GetHeight();
  117. // Make sure the width and height are non-zero
  118. if (nSourceWidth && nSourceHeight)
  119. {
  120. // Assume the source dimensions are fine
  121. UINT nTargetWidth = nSourceWidth;
  122. UINT nTargetHeight = nSourceHeight;
  123. // If the height or the width exceed the allowed maximum, scale it down, or if we are allowing stretching
  124. if ((nTargetWidth > nMaxWidth) || (nTargetHeight > nMaxHeight) || bStretchSmallImages)
  125. {
  126. SIZE sizeDesiredImageSize = PrintScanUtil::ScalePreserveAspectRatio( nMaxWidth, nMaxHeight, nTargetWidth, nTargetHeight );
  127. nTargetWidth = sizeDesiredImageSize.cx;
  128. nTargetHeight = sizeDesiredImageSize.cy;
  129. }
  130. // Make sure we have valid sizes
  131. if (nTargetWidth && nTargetHeight)
  132. {
  133. // Create the target bitmap and make sure it succeeded
  134. Bitmap TargetBitmap( nTargetWidth, nTargetHeight );
  135. if (Ok == TargetBitmap.GetLastStatus())
  136. {
  137. // Get a graphics to render to
  138. Graphics *pGraphics = Graphics::FromImage(&TargetBitmap);
  139. if (pGraphics)
  140. {
  141. // Make sure it is valid
  142. if (pGraphics->GetLastStatus() == Ok)
  143. {
  144. // Draw scaled image
  145. if (pGraphics->DrawImage(&SourceBitmap, 0, 0, nTargetWidth, nTargetHeight) == Ok)
  146. {
  147. // Get an HBITMAP for this image
  148. TargetBitmap.GetHBITMAP( Color::Black, &hTargetBitmap );
  149. }
  150. }
  151. // Clean up our dynamically allocated graphics
  152. delete pGraphics;
  153. }
  154. }
  155. }
  156. }
  157. }
  158. }
  159. return(hTargetBitmap ? S_OK : E_FAIL);
  160. }
  161. // Construct a string like this: JPG;BMP;PNG with all supported extensions
  162. HRESULT CGdiPlusHelper::ConstructCodecExtensionSearchStrings( CSimpleString &strExtensions, Gdiplus::ImageCodecInfo *pImageCodecInfo, UINT nImageCodecCount )
  163. {
  164. for (UINT i=0;i<nImageCodecCount;i++)
  165. {
  166. if (strExtensions.Length())
  167. {
  168. strExtensions += TEXT(";");
  169. }
  170. strExtensions += CSimpleStringConvert::NaturalString(CSimpleStringWide(pImageCodecInfo[i].FilenameExtension));
  171. }
  172. return (strExtensions.Length() ? S_OK : E_FAIL);
  173. }
  174. HRESULT CGdiPlusHelper::ConstructDecoderExtensionSearchStrings( CSimpleString &strExtensions )
  175. {
  176. return CGdiPlusHelper::ConstructCodecExtensionSearchStrings( strExtensions, m_pImageDecoderInfo, m_nImageDecoderCount );
  177. }
  178. HRESULT CGdiPlusHelper::ConstructEncoderExtensionSearchStrings( CSimpleString &strExtensions )
  179. {
  180. return CGdiPlusHelper::ConstructCodecExtensionSearchStrings( strExtensions, m_pImageEncoderInfo, m_nImageEncoderCount );
  181. }
  182. CImageFileFormatVerifier::CImageFileFormatVerifierItem::CImageFileFormatVerifierItem(void)
  183. : m_pSignature(NULL),
  184. m_pMask(NULL),
  185. m_nLength(0),
  186. m_guidFormat(IID_NULL),
  187. m_clsidDecoder(IID_NULL)
  188. {
  189. }
  190. CImageFileFormatVerifier::CImageFileFormatVerifierItem::CImageFileFormatVerifierItem( const PBYTE pSignature, const PBYTE pMask, int nLength, const GUID &guidFormat, const CLSID &guidDecoder )
  191. : m_pSignature(NULL),
  192. m_pMask(NULL),
  193. m_nLength(0),
  194. m_guidFormat(IID_NULL),
  195. m_clsidDecoder(IID_NULL)
  196. {
  197. Assign( pSignature, pMask, nLength, guidFormat, guidDecoder );
  198. }
  199. CImageFileFormatVerifier::CImageFileFormatVerifierItem::CImageFileFormatVerifierItem( const CImageFileFormatVerifierItem &other )
  200. : m_pSignature(NULL),
  201. m_pMask(NULL),
  202. m_nLength(0),
  203. m_guidFormat(IID_NULL),
  204. m_clsidDecoder(IID_NULL)
  205. {
  206. Assign( other.Signature(), other.Mask(), other.Length(), other.Format(), other.Decoder() );
  207. }
  208. CImageFileFormatVerifier::CImageFileFormatVerifierItem &CImageFileFormatVerifier::CImageFileFormatVerifierItem::operator=( const CImageFileFormatVerifierItem &other )
  209. {
  210. if (this != &other)
  211. {
  212. return Assign( other.Signature(), other.Mask(), other.Length(), other.Format(), other.Decoder() );
  213. }
  214. else return *this;
  215. }
  216. CImageFileFormatVerifier::CImageFileFormatVerifierItem &CImageFileFormatVerifier::CImageFileFormatVerifierItem::Assign( const PBYTE pSignature, const PBYTE pMask, int nLength, const GUID &guidFormat, const CLSID &clsidDecoder )
  217. {
  218. Destroy();
  219. bool bOK = false;
  220. m_nLength = nLength;
  221. m_guidFormat = guidFormat;
  222. m_clsidDecoder = clsidDecoder;
  223. if (nLength && pSignature && pMask)
  224. {
  225. m_pSignature = new BYTE[nLength];
  226. m_pMask = new BYTE[nLength];
  227. if (m_pSignature && m_pMask)
  228. {
  229. CopyMemory( m_pSignature, pSignature, nLength );
  230. CopyMemory( m_pMask, pMask, nLength );
  231. bOK = true;
  232. }
  233. }
  234. if (!bOK)
  235. {
  236. Destroy();
  237. }
  238. return *this;
  239. }
  240. void CImageFileFormatVerifier::CImageFileFormatVerifierItem::Destroy(void)
  241. {
  242. if (m_pSignature)
  243. {
  244. delete[] m_pSignature;
  245. m_pSignature = NULL;
  246. }
  247. if (m_pMask)
  248. {
  249. delete[] m_pMask;
  250. m_pMask;
  251. }
  252. m_nLength = 0;
  253. m_guidFormat = IID_NULL;
  254. m_clsidDecoder = IID_NULL;
  255. }
  256. CImageFileFormatVerifier::CImageFileFormatVerifierItem::~CImageFileFormatVerifierItem(void)
  257. {
  258. Destroy();
  259. }
  260. PBYTE CImageFileFormatVerifier::CImageFileFormatVerifierItem::Signature(void) const
  261. {
  262. return m_pSignature;
  263. }
  264. PBYTE CImageFileFormatVerifier::CImageFileFormatVerifierItem::Mask(void) const
  265. {
  266. return m_pMask;
  267. }
  268. int CImageFileFormatVerifier::CImageFileFormatVerifierItem::Length(void) const
  269. {
  270. return m_nLength;
  271. }
  272. GUID CImageFileFormatVerifier::CImageFileFormatVerifierItem::Format(void) const
  273. {
  274. return m_guidFormat;
  275. }
  276. CLSID CImageFileFormatVerifier::CImageFileFormatVerifierItem::Decoder(void) const
  277. {
  278. return m_clsidDecoder;
  279. }
  280. bool CImageFileFormatVerifier::CImageFileFormatVerifierItem::Match( PBYTE pBytes, int nLen ) const
  281. {
  282. if (nLen < Length())
  283. {
  284. return false;
  285. }
  286. for (int i=0;i<Length();i++)
  287. {
  288. if (false == ((pBytes[i] & m_pMask[i]) == m_pSignature[i]))
  289. {
  290. return false;
  291. }
  292. }
  293. return true;
  294. }
  295. CImageFileFormatVerifier::CImageFileFormatVerifier(void)
  296. : m_nMaxSignatureLength(0),
  297. m_pSignatureBuffer(NULL)
  298. {
  299. // Get the decoder count and size of the decoder info array
  300. UINT nImageDecoderCount = 0, cbCodecs = 0;
  301. if (Gdiplus::Ok == Gdiplus::GetImageDecodersSize( &nImageDecoderCount, &cbCodecs ))
  302. {
  303. // Make sure we got good sizes back
  304. if (cbCodecs && nImageDecoderCount)
  305. {
  306. // Allocate the array
  307. Gdiplus::ImageCodecInfo *pImageDecoderInfo = static_cast<Gdiplus::ImageCodecInfo*>(LocalAlloc(LPTR,cbCodecs));
  308. if (pImageDecoderInfo)
  309. {
  310. // Get the actual decoder info
  311. if (Gdiplus::Ok == Gdiplus::GetImageDecoders( nImageDecoderCount, cbCodecs, pImageDecoderInfo ))
  312. {
  313. // Add each decoder to the format list
  314. for (UINT i=0;i<nImageDecoderCount;i++)
  315. {
  316. // Add each signature to the format list
  317. for (UINT j=0;j<pImageDecoderInfo[i].SigCount;j++)
  318. {
  319. #if defined(DBG)
  320. CSimpleString strPattern;
  321. CSimpleString strMask;
  322. for (ULONG x=0;x<pImageDecoderInfo[i].SigSize;x++)
  323. {
  324. strPattern += CSimpleString().Format( TEXT("%02X"), ((const PBYTE)(pImageDecoderInfo[i].SigPattern+(j*pImageDecoderInfo[i].SigSize)))[x] );
  325. strMask += CSimpleString().Format( TEXT("%02X"), ((const PBYTE)(pImageDecoderInfo[i].SigMask+(j*pImageDecoderInfo[i].SigSize)))[x] );
  326. }
  327. //WIA_PRINTGUID((pImageDecoderInfo[i].FormatID,TEXT("FormatID")));
  328. //WIA_PRINTGUID((pImageDecoderInfo[i].Clsid,TEXT(" Clsid")));
  329. //WIA_TRACE((TEXT(" strPattern: %s, strMask: %s, SigSize: %d"), strPattern.String(), strMask.String(), pImageDecoderInfo[i].SigSize ));
  330. #endif
  331. m_FileFormatVerifierList.Append( CImageFileFormatVerifier::CImageFileFormatVerifierItem( (const PBYTE)(pImageDecoderInfo[i].SigPattern+(j*pImageDecoderInfo[i].SigSize)), (const PBYTE)(pImageDecoderInfo[i].SigMask+(j*pImageDecoderInfo[i].SigSize)), pImageDecoderInfo[i].SigSize, pImageDecoderInfo[i].FormatID, pImageDecoderInfo[i].Clsid ) );
  332. }
  333. }
  334. }
  335. // Free the array
  336. LocalFree(pImageDecoderInfo);
  337. }
  338. }
  339. }
  340. // Assume the max length is Zero
  341. m_nMaxSignatureLength = 0;
  342. // For each signature, check if it is greater in length than the maximum.
  343. for (int i=0;i<m_FileFormatVerifierList.Size();i++)
  344. {
  345. // If it is the longest, save the length
  346. if (m_FileFormatVerifierList[i].Length() > m_nMaxSignatureLength)
  347. {
  348. m_nMaxSignatureLength = m_FileFormatVerifierList[i].Length();
  349. }
  350. }
  351. // If we have a valid max length, allocate a buffer to hold the file's data
  352. if (m_nMaxSignatureLength)
  353. {
  354. m_pSignatureBuffer = new BYTE[m_nMaxSignatureLength];
  355. }
  356. // If anything failed, free everything
  357. if (!IsValid())
  358. {
  359. Destroy();
  360. }
  361. }
  362. void CImageFileFormatVerifier::Destroy(void)
  363. {
  364. // Free the file signature buffer
  365. if (m_pSignatureBuffer)
  366. {
  367. delete[] m_pSignatureBuffer;
  368. m_pSignatureBuffer = NULL;
  369. }
  370. m_nMaxSignatureLength = 0;
  371. m_FileFormatVerifierList.Destroy();
  372. }
  373. bool CImageFileFormatVerifier::IsValid(void) const
  374. {
  375. return (m_pSignatureBuffer && m_nMaxSignatureLength && m_FileFormatVerifierList.Size());
  376. }
  377. CImageFileFormatVerifier::~CImageFileFormatVerifier(void)
  378. {
  379. Destroy();
  380. }
  381. GUID CImageFileFormatVerifier::GetImageType( LPCTSTR pszFilename )
  382. {
  383. // Assume we will not find a match
  384. GUID guidResult = IID_NULL;
  385. // Open the file for reading
  386. HANDLE hFile = CreateFile( pszFilename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
  387. if (INVALID_HANDLE_VALUE != hFile)
  388. {
  389. // Read the maximum signature length number of bytes
  390. DWORD dwBytesRead = 0;
  391. if (ReadFile( hFile, m_pSignatureBuffer, m_nMaxSignatureLength, &dwBytesRead, NULL ))
  392. {
  393. // Make sure we got some bytes
  394. if (dwBytesRead)
  395. {
  396. // Go though the list and try to find a match
  397. for (int i=0;i<m_FileFormatVerifierList.Size();i++)
  398. {
  399. // If we found a match, we are done
  400. if (m_FileFormatVerifierList[i].Match(m_pSignatureBuffer,dwBytesRead))
  401. {
  402. guidResult = m_FileFormatVerifierList[i].Format();
  403. break;
  404. }
  405. }
  406. }
  407. }
  408. // Close the file
  409. CloseHandle(hFile);
  410. }
  411. // This will contain IID_NULL if no matching image type was found
  412. return guidResult;
  413. }
  414. bool CImageFileFormatVerifier::IsImageFile( LPCTSTR pszFilename )
  415. {
  416. //WIA_PUSH_FUNCTION((TEXT("CImageFileFormatVerifier::IsImageFile(%s)"),pszFilename));
  417. // Try to find the image type
  418. GUID guidImageType = GetImageType(pszFilename);
  419. //WIA_PRINTGUID((guidImageType,TEXT("guidImageType")));
  420. // If the image type is IID_NULL, it isn't an image
  421. return ((IID_NULL != guidImageType) != FALSE);
  422. }