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.

1776 lines
58 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORPORATION, 1998
  4. *
  5. * TITLE: GPHELPER.CPP
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: ShaunIv
  10. *
  11. * DATE: 10/11/1999
  12. *
  13. * DESCRIPTION: Encapsulation of common GDI plus operationss
  14. *
  15. *******************************************************************************/
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. #include "gphelper.h"
  19. #include <wiadebug.h>
  20. #include <psutil.h>
  21. using namespace Gdiplus;
  22. CGdiPlusHelper::CGdiPlusHelper(void)
  23. : m_pImageEncoderInfo(NULL),
  24. m_nImageEncoderCount(0),
  25. m_pImageDecoderInfo(NULL),
  26. m_nImageDecoderCount(0)
  27. {
  28. Initialize();
  29. }
  30. CGdiPlusHelper::~CGdiPlusHelper(void)
  31. {
  32. Destroy();
  33. }
  34. HRESULT CGdiPlusHelper::Initialize(void)
  35. {
  36. WIA_PUSHFUNCTION(TEXT("CGdiPlusHelper::Initialize"));
  37. //
  38. // Get the installed encoders
  39. //
  40. UINT cbCodecs = 0;
  41. HRESULT hr = GDISTATUS_TO_HRESULT(GetImageEncodersSize( &m_nImageEncoderCount, &cbCodecs ));
  42. if (SUCCEEDED(hr))
  43. {
  44. if (cbCodecs)
  45. {
  46. m_pImageEncoderInfo = static_cast<ImageCodecInfo*>(LocalAlloc(LPTR,cbCodecs));
  47. if (m_pImageEncoderInfo)
  48. {
  49. hr = GDISTATUS_TO_HRESULT(GetImageEncoders( m_nImageEncoderCount, cbCodecs, m_pImageEncoderInfo ));
  50. if (FAILED(hr))
  51. {
  52. WIA_PRINTHRESULT((hr,TEXT("GetImageEncoders failed")));
  53. }
  54. }
  55. else
  56. {
  57. hr = HRESULT_FROM_WIN32(GetLastError());
  58. WIA_PRINTHRESULT((hr,TEXT("LocalAlloc failed")));
  59. }
  60. }
  61. else
  62. {
  63. hr = E_INVALIDARG;
  64. WIA_PRINTHRESULT((hr,TEXT("GetImageEncodersSize succeeded, but cbCodecs was 0")));
  65. }
  66. }
  67. else
  68. {
  69. WIA_PRINTHRESULT((hr,TEXT("GetImageEncodersSize failed")));
  70. }
  71. //
  72. // Get the installed decoders
  73. //
  74. if (SUCCEEDED(hr))
  75. {
  76. cbCodecs = 0;
  77. hr = GDISTATUS_TO_HRESULT(GetImageDecodersSize( &m_nImageDecoderCount, &cbCodecs ));
  78. if (SUCCEEDED(hr))
  79. {
  80. if (cbCodecs)
  81. {
  82. m_pImageDecoderInfo = static_cast<ImageCodecInfo*>(LocalAlloc(LPTR,cbCodecs));
  83. if (m_pImageDecoderInfo)
  84. {
  85. hr = GDISTATUS_TO_HRESULT(GetImageDecoders( m_nImageDecoderCount, cbCodecs, m_pImageDecoderInfo ));
  86. if (FAILED(hr))
  87. {
  88. WIA_PRINTHRESULT((hr,TEXT("GetImageDecoders failed")));
  89. }
  90. }
  91. else
  92. {
  93. hr = HRESULT_FROM_WIN32(GetLastError());
  94. WIA_PRINTHRESULT((hr,TEXT("LocalAlloc failed")));
  95. }
  96. }
  97. else
  98. {
  99. hr = E_INVALIDARG;
  100. WIA_PRINTHRESULT((hr,TEXT("GetImageDecodersSize succeeded, but cbCodecs was 0")));
  101. }
  102. }
  103. else
  104. {
  105. WIA_PRINTHRESULT((hr,TEXT("GetImageDecodersSize failed")));
  106. }
  107. }
  108. //
  109. // If there was a problem, make sure there are no half-initialized things laying around
  110. //
  111. if (!SUCCEEDED(hr))
  112. {
  113. Destroy();
  114. }
  115. return hr;
  116. }
  117. void CGdiPlusHelper::Destroy(void)
  118. {
  119. #if defined(GDIPLUSHELPER_EXPLICIT_INITIALIZATION)
  120. //
  121. // Shut down GDI+
  122. //
  123. if (m_bGdiplusInitialized)
  124. {
  125. }
  126. #endif
  127. //
  128. // Free the lists of Encoders and Decoders
  129. //
  130. if (m_pImageEncoderInfo)
  131. {
  132. LocalFree(m_pImageEncoderInfo);
  133. m_pImageEncoderInfo = NULL;
  134. }
  135. m_nImageEncoderCount = 0;
  136. if (m_pImageDecoderInfo)
  137. {
  138. LocalFree(m_pImageDecoderInfo);
  139. m_pImageDecoderInfo = NULL;
  140. }
  141. m_nImageDecoderCount = 0;
  142. }
  143. bool CGdiPlusHelper::IsValid(void) const
  144. {
  145. //
  146. // Make sure we've been completely created
  147. //
  148. #if defined(GDIPLUSHELPER_EXPLICIT_INITIALIZATION)
  149. return(m_bGdiplusInitialized && m_pImageEncoderInfo && m_nImageEncoderCount && m_pImageDecoderInfo && m_nImageDecoderCount);
  150. #else
  151. return(m_pImageEncoderInfo && m_nImageEncoderCount && m_pImageDecoderInfo && m_nImageDecoderCount);
  152. #endif
  153. }
  154. HRESULT CGdiPlusHelper::GetClsidOfEncoder( const GUID &guidFormatId, CLSID &clsidFormat ) const
  155. {
  156. //
  157. // Given an image format, find the clsid for the output type
  158. //
  159. if (IsValid())
  160. {
  161. for (UINT i=0;i<m_nImageEncoderCount;i++)
  162. {
  163. if (m_pImageEncoderInfo[i].FormatID == guidFormatId)
  164. {
  165. clsidFormat = m_pImageEncoderInfo[i].Clsid;
  166. return S_OK;
  167. }
  168. }
  169. }
  170. return E_FAIL;
  171. }
  172. HRESULT CGdiPlusHelper::GetClsidOfDecoder( const GUID &guidFormatId, CLSID &clsidFormat ) const
  173. {
  174. //
  175. // Given an image format, find the clsid for the output type
  176. //
  177. if (IsValid())
  178. {
  179. for (UINT i=0;i<m_nImageDecoderCount;i++)
  180. {
  181. if (m_pImageDecoderInfo[i].FormatID == guidFormatId)
  182. {
  183. clsidFormat = m_pImageDecoderInfo[i].Clsid;
  184. return S_OK;
  185. }
  186. }
  187. }
  188. return E_FAIL;
  189. }
  190. HRESULT CGdiPlusHelper::Convert( LPCWSTR pszInputFilename, LPCWSTR pszOutputFilename, const CLSID &guidOutputFormat ) const
  191. {
  192. WIA_PUSH_FUNCTION((TEXT("CGdiPlusHelper::Convert( %ws, %ws )"), pszInputFilename, pszOutputFilename ));
  193. WIA_PRINTGUID((guidOutputFormat,TEXT("guidOutputFormat")));
  194. HRESULT hr;
  195. if (IsValid())
  196. {
  197. //
  198. // Open the source image
  199. //
  200. Image SourceImage(pszInputFilename);
  201. //
  202. // Make sure it was valid
  203. //
  204. hr = GDISTATUS_TO_HRESULT(SourceImage.GetLastStatus());
  205. if (SUCCEEDED(hr))
  206. {
  207. //
  208. // Get the correct encoder
  209. //
  210. CLSID clsidEncoder;
  211. hr = GetClsidOfEncoder( guidOutputFormat, clsidEncoder );
  212. if (SUCCEEDED(hr))
  213. {
  214. //
  215. // Save the image
  216. //
  217. hr = GDISTATUS_TO_HRESULT(SourceImage.Save( pszOutputFilename, &clsidEncoder, NULL ));
  218. if (FAILED(hr))
  219. {
  220. WIA_PRINTHRESULT((hr,TEXT("GetLastError() after Save()")));
  221. }
  222. }
  223. else
  224. {
  225. WIA_PRINTHRESULT((hr,TEXT("GetClsidOfEncoder() failed")));
  226. }
  227. }
  228. else
  229. {
  230. WIA_PRINTHRESULT((hr,TEXT("SourceImage.GetLastStatus() failed")));
  231. }
  232. }
  233. else
  234. {
  235. WIA_ERROR((TEXT("IsValid() returned false")));
  236. hr = E_FAIL;
  237. }
  238. return hr;
  239. }
  240. HRESULT CGdiPlusHelper::Rotate( LPCWSTR pszInputFilename, LPCWSTR pszOutputFilename, int nRotationAngle, const CLSID &guidOutputFormat ) const
  241. {
  242. WIA_PUSH_FUNCTION((TEXT("CGdiPlusHelper::Rotate( %ws, %ws, %d )"), pszInputFilename, pszOutputFilename, nRotationAngle ));
  243. HRESULT hr = E_FAIL;
  244. if (IsValid())
  245. {
  246. //
  247. // Open the source image
  248. //
  249. Image SourceImage(pszInputFilename);
  250. //
  251. // Make sure it was valid
  252. //
  253. hr = GDISTATUS_TO_HRESULT(SourceImage.GetLastStatus());
  254. if (SUCCEEDED(hr))
  255. {
  256. //
  257. // Figure out what the output format should be. If it is IID_NULL, change it to the same format as the input format
  258. //
  259. GUID OutputFormat = guidOutputFormat;
  260. if (OutputFormat == IID_NULL)
  261. {
  262. //
  263. // Find the input format
  264. //
  265. hr = GDISTATUS_TO_HRESULT(SourceImage.GetRawFormat(&OutputFormat));
  266. if (FAILED(hr))
  267. {
  268. WIA_PRINTHRESULT((hr,TEXT("SourceImage.GetRawFormat() failed")));
  269. }
  270. }
  271. if (SUCCEEDED(hr))
  272. {
  273. //
  274. // Get the encoder for this format
  275. //
  276. CLSID clsidEncoder;
  277. hr = GetClsidOfEncoder( OutputFormat, clsidEncoder );
  278. if (SUCCEEDED(hr))
  279. {
  280. //
  281. // Lossless rotation for JPEGs...
  282. //
  283. if (ImageFormatJPEG == OutputFormat && (SourceImage.GetWidth() % 8 == 0) && (SourceImage.GetHeight() % 8 == 0))
  284. {
  285. WIA_TRACE((TEXT("Performing lossless rotation")));
  286. LONG nTransform = 0;
  287. //
  288. // Which transform should we use?
  289. //
  290. switch (nRotationAngle % 360)
  291. {
  292. case 90:
  293. case -270:
  294. nTransform = EncoderValueTransformRotate90;
  295. break;
  296. case 180:
  297. case -180:
  298. nTransform = EncoderValueTransformRotate180;
  299. break;
  300. case 270:
  301. case -90:
  302. nTransform = EncoderValueTransformRotate270;
  303. break;
  304. }
  305. //
  306. // If the transform is zero, an invalid rotation angle was specified
  307. //
  308. if (nTransform)
  309. {
  310. //
  311. // Fill out the EncoderParameters for lossless JPEG rotation
  312. //
  313. EncoderParameters EncoderParams = {0};
  314. EncoderParams.Parameter[0].Guid = Gdiplus::EncoderTransformation;
  315. EncoderParams.Parameter[0].Type = EncoderParameterValueTypeLong;
  316. EncoderParams.Parameter[0].NumberOfValues = 1;
  317. EncoderParams.Parameter[0].Value = &nTransform;
  318. EncoderParams.Count = 1;
  319. //
  320. // Save the image to the target file
  321. //
  322. hr = GDISTATUS_TO_HRESULT(SourceImage.Save( pszOutputFilename, &clsidEncoder, &EncoderParams ));
  323. }
  324. else
  325. {
  326. hr = E_FAIL;
  327. }
  328. }
  329. //
  330. // Non-JPEG rotation, or rotation of JPEG files with non-standard sizes
  331. //
  332. else
  333. {
  334. WIA_TRACE((TEXT("Performing normal rotation")));
  335. //
  336. // Figure out which rotation flag to use
  337. //
  338. RotateFlipType rotateFlipType = RotateNoneFlipNone;
  339. switch (nRotationAngle % 360)
  340. {
  341. case 90:
  342. case -270:
  343. rotateFlipType = Rotate90FlipNone;
  344. break;
  345. case 180:
  346. case -180:
  347. rotateFlipType = Rotate180FlipNone;
  348. break;
  349. case 270:
  350. case -90:
  351. rotateFlipType = Rotate270FlipNone;
  352. break;
  353. }
  354. //
  355. // Make sure we have a valid rotation angle
  356. //
  357. if (rotateFlipType)
  358. {
  359. //
  360. // Rotate the image
  361. //
  362. hr = GDISTATUS_TO_HRESULT(SourceImage.RotateFlip(rotateFlipType));
  363. if (SUCCEEDED(hr))
  364. {
  365. //
  366. // Save the image
  367. //
  368. hr = GDISTATUS_TO_HRESULT(SourceImage.Save( pszOutputFilename, &clsidEncoder, NULL ));
  369. }
  370. }
  371. else
  372. {
  373. WIA_ERROR((TEXT("Invalid rotation specified (%d)"), nRotationAngle));
  374. hr = E_FAIL;
  375. }
  376. } // End else if non JPEG
  377. }
  378. else
  379. {
  380. WIA_PRINTHRESULT((hr,TEXT("GetClsidOfEncoder failed")));
  381. }
  382. }
  383. }
  384. else
  385. {
  386. WIA_PRINTHRESULT((hr,TEXT("SourceImage.GetLastStatus()")));
  387. }
  388. }
  389. else
  390. {
  391. WIA_ERROR((TEXT("IsValid() returned false")));
  392. hr = E_FAIL;
  393. }
  394. WIA_PRINTHRESULT((hr,TEXT("Returning")));
  395. return hr;
  396. }
  397. HRESULT CGdiPlusHelper::Rotate( HBITMAP hSourceBitmap, HBITMAP &hTargetBitmap, int nRotationAngle ) const
  398. {
  399. //
  400. // Initialize the result to NULL
  401. //
  402. hTargetBitmap = NULL;
  403. //
  404. // Assume failure
  405. //
  406. HRESULT hr = E_FAIL;
  407. //
  408. // Make sure we are in a valid state
  409. //
  410. if (IsValid())
  411. {
  412. //
  413. // Make sure we have a valid source bitmap
  414. //
  415. if (hSourceBitmap)
  416. {
  417. //
  418. // If we are rotating by 0 degrees, just copy the image
  419. //
  420. if (!nRotationAngle)
  421. {
  422. hTargetBitmap = reinterpret_cast<HBITMAP>(CopyImage( hSourceBitmap, IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION ));
  423. if (hTargetBitmap)
  424. {
  425. hr = S_OK;
  426. }
  427. else
  428. {
  429. hr = HRESULT_FROM_WIN32(GetLastError());
  430. WIA_PRINTHRESULT((hr,TEXT("CopyImage failed")));
  431. }
  432. }
  433. else
  434. {
  435. //
  436. // Create the source bitmap. No palette required, we assume it will always be a 24bit DIB.
  437. //
  438. Bitmap SourceBitmap( hSourceBitmap, NULL );
  439. hr = GDISTATUS_TO_HRESULT(SourceBitmap.GetLastStatus());
  440. if (SUCCEEDED(hr))
  441. {
  442. //
  443. // Get the image width and height
  444. //
  445. UINT nSourceWidth = SourceBitmap.GetWidth();
  446. UINT nSourceHeight = SourceBitmap.GetHeight();
  447. //
  448. // Make sure the width and height are non-zero
  449. //
  450. if (nSourceWidth && nSourceHeight)
  451. {
  452. //
  453. // Assume the target width and height are zero, so we can detect invalid rotation angles
  454. //
  455. UINT nTargetWidth = 0;
  456. UINT nTargetHeight = 0;
  457. RotateFlipType rotateFlipType = RotateNoneFlipNone;
  458. //
  459. // Find the transformation matrix for this rotation
  460. //
  461. switch (nRotationAngle % 360)
  462. {
  463. case -270:
  464. case 90:
  465. rotateFlipType = Rotate90FlipNone;
  466. nTargetWidth = nSourceHeight;
  467. nTargetHeight = nSourceWidth;
  468. break;
  469. case -180:
  470. case 180:
  471. rotateFlipType = Rotate180FlipNone;
  472. nTargetWidth = nSourceWidth;
  473. nTargetHeight = nSourceHeight;
  474. break;
  475. case -90:
  476. case 270:
  477. rotateFlipType = Rotate270FlipNone;
  478. nTargetWidth = nSourceHeight;
  479. nTargetHeight = nSourceWidth;
  480. break;
  481. }
  482. //
  483. // If either of these are zero, that means an invalid rotation was supplied
  484. //
  485. if (nTargetWidth && nTargetHeight)
  486. {
  487. //
  488. // Rotate the image
  489. //
  490. hr = GDISTATUS_TO_HRESULT(SourceBitmap.RotateFlip(rotateFlipType));
  491. if (SUCCEEDED(hr))
  492. {
  493. //
  494. // Create the target bitmap and make sure it succeeded
  495. //
  496. Bitmap TargetBitmap( nTargetWidth, nTargetHeight );
  497. hr = GDISTATUS_TO_HRESULT(TargetBitmap.GetLastStatus());
  498. if (SUCCEEDED(hr))
  499. {
  500. //
  501. // Get a graphics to render to
  502. //
  503. Graphics *pGraphics = Graphics::FromImage(&TargetBitmap);
  504. if (pGraphics)
  505. {
  506. //
  507. // Make sure it is valid
  508. //
  509. hr = GDISTATUS_TO_HRESULT(pGraphics->GetLastStatus());
  510. if (SUCCEEDED(hr))
  511. {
  512. //
  513. // Draw image rotated to the graphics
  514. //
  515. hr = GDISTATUS_TO_HRESULT(pGraphics->DrawImage(&SourceBitmap,0,0));
  516. if (SUCCEEDED(hr))
  517. {
  518. //
  519. // Get the HBITMAP
  520. //
  521. hr = GDISTATUS_TO_HRESULT(TargetBitmap.GetHBITMAP( Color::Black, &hTargetBitmap ));
  522. if (SUCCEEDED(hr))
  523. {
  524. if (!hTargetBitmap)
  525. {
  526. WIA_ERROR((TEXT("hTargetBitmap was NULL")));
  527. hr = E_FAIL;
  528. }
  529. }
  530. }
  531. }
  532. //
  533. // Clean up our dynamically allocated graphics
  534. //
  535. delete pGraphics;
  536. }
  537. else
  538. {
  539. WIA_ERROR((TEXT("pGraphics was NULL")));
  540. hr = E_FAIL;
  541. }
  542. }
  543. else
  544. {
  545. WIA_PRINTHRESULT((hr,TEXT("TargetBitmap.GetLastStatus() failed")));
  546. }
  547. }
  548. else
  549. {
  550. WIA_PRINTHRESULT((hr,TEXT("SourceBitmap.RotateFlip() failed")));
  551. }
  552. }
  553. else
  554. {
  555. WIA_ERROR((TEXT("Invalid Target Bitmap Dimensions")));
  556. hr = E_FAIL;
  557. }
  558. }
  559. else
  560. {
  561. WIA_ERROR((TEXT("Invalid Source Bitmap Dimensions")));
  562. hr = E_FAIL;
  563. }
  564. }
  565. else
  566. {
  567. WIA_PRINTHRESULT((hr,TEXT("SourceBitmap.GetLastStatus() failed")));
  568. }
  569. } // end else if nRotationAngle != 0
  570. }
  571. else
  572. {
  573. WIA_ERROR((TEXT("hSourceBitmap was NULL")));
  574. hr = E_INVALIDARG;
  575. }
  576. }
  577. else
  578. {
  579. WIA_ERROR((TEXT("IsValid() failed")));
  580. }
  581. WIA_PRINTHRESULT((hr,TEXT("Returning")));
  582. return hr;
  583. }
  584. HRESULT CGdiPlusHelper::LoadAndScale( HBITMAP &hTargetBitmap, IStream *pStream, UINT nMaxWidth, UINT nMaxHeight, bool bStretchSmallImages )
  585. {
  586. HRESULT hr = E_FAIL;
  587. hTargetBitmap = NULL;
  588. //
  589. // Make sure we have a valid filename
  590. //
  591. if (pStream)
  592. {
  593. Bitmap SourceBitmap( pStream );
  594. hr = GDISTATUS_TO_HRESULT(SourceBitmap.GetLastStatus());
  595. if (SUCCEEDED(hr))
  596. {
  597. //
  598. // Get the image width and height
  599. //
  600. UINT nSourceWidth = SourceBitmap.GetWidth();
  601. UINT nSourceHeight = SourceBitmap.GetHeight();
  602. //
  603. // Make sure the width and height are non-zero
  604. //
  605. if (nSourceWidth && nSourceHeight)
  606. {
  607. //
  608. //
  609. // Assume the source dimensions are fine
  610. //
  611. UINT nTargetWidth = nSourceWidth;
  612. UINT nTargetHeight = nSourceHeight;
  613. //
  614. // If the height or the width exceed the allowed maximum, scale it down, or if we are allowing stretching
  615. //
  616. if (nMaxWidth > 0 && nMaxHeight > 0)
  617. {
  618. if ((nTargetWidth > nMaxWidth) || (nTargetHeight > nMaxHeight) || bStretchSmallImages)
  619. {
  620. SIZE sizeDesiredImageSize = PrintScanUtil::ScalePreserveAspectRatio( nMaxWidth, nMaxHeight, nTargetWidth, nTargetHeight );
  621. nTargetWidth = sizeDesiredImageSize.cx;
  622. nTargetHeight = sizeDesiredImageSize.cy;
  623. }
  624. }
  625. //
  626. // Make sure we have valid sizes
  627. //
  628. if (nTargetWidth && nTargetHeight)
  629. {
  630. //
  631. // Create the target bitmap and make sure it succeeded
  632. //
  633. Bitmap TargetBitmap( nTargetWidth, nTargetHeight );
  634. hr = GDISTATUS_TO_HRESULT(TargetBitmap.GetLastStatus());
  635. if (SUCCEEDED(hr))
  636. {
  637. //
  638. // Get a graphics to render to
  639. //
  640. Graphics *pGraphics = Graphics::FromImage(&TargetBitmap);
  641. if (pGraphics)
  642. {
  643. //
  644. // Make sure it is valid
  645. //
  646. hr = GDISTATUS_TO_HRESULT(pGraphics->GetLastStatus());
  647. if (SUCCEEDED(hr))
  648. {
  649. //
  650. // Draw scaled image
  651. //
  652. hr = GDISTATUS_TO_HRESULT(pGraphics->DrawImage(&SourceBitmap, 0, 0, nTargetWidth, nTargetHeight));
  653. if (SUCCEEDED(hr))
  654. {
  655. //
  656. // Get an HBITMAP for this image
  657. //
  658. hr = GDISTATUS_TO_HRESULT(TargetBitmap.GetHBITMAP( Color::Black, &hTargetBitmap ));
  659. if (!hTargetBitmap)
  660. {
  661. WIA_ERROR((TEXT("hTargetBitmap was NULL")));
  662. hr = E_FAIL;
  663. }
  664. }
  665. else
  666. {
  667. WIA_PRINTHRESULT((hr,TEXT("pGraphics->DrawImage failed")));
  668. }
  669. }
  670. else
  671. {
  672. WIA_PRINTHRESULT((hr,TEXT("pGraphics->GetLastStatus() failed")));
  673. }
  674. //
  675. // Clean up our dynamically allocated graphics
  676. //
  677. delete pGraphics;
  678. }
  679. else
  680. {
  681. hr = E_FAIL;
  682. WIA_ERROR((TEXT("pGraphics was NULL")));
  683. }
  684. }
  685. else
  686. {
  687. WIA_PRINTHRESULT((hr,TEXT("TargetBitmap.GetLastStatus() is not OK")));
  688. }
  689. }
  690. else
  691. {
  692. WIA_ERROR((TEXT("Invalid Target Bitmap Dimensions (%d,%d)"), nTargetWidth, nTargetHeight));
  693. hr = E_FAIL;
  694. }
  695. }
  696. else
  697. {
  698. WIA_ERROR((TEXT("Invalid Source Bitmap Dimensions")));
  699. hr = E_FAIL;
  700. }
  701. }
  702. else
  703. {
  704. WIA_PRINTHRESULT((hr,TEXT("SourceBitmap.GetLastStatus() failed")));
  705. }
  706. }
  707. else
  708. {
  709. WIA_ERROR((TEXT("pStream was NULL")));
  710. hr = E_INVALIDARG;
  711. }
  712. return hr;
  713. }
  714. HRESULT CGdiPlusHelper::LoadAndScale( HBITMAP &hTargetBitmap, LPCTSTR pszFilename, UINT nMaxWidth, UINT nMaxHeight, bool bStretchSmallImages )
  715. {
  716. hTargetBitmap = NULL;
  717. HRESULT hr = E_FAIL;
  718. //
  719. // Make sure we have a valid filename
  720. //
  721. if (pszFilename && lstrlen(pszFilename))
  722. {
  723. Bitmap SourceBitmap( CSimpleStringConvert::WideString(CSimpleString(pszFilename) ) );
  724. hr = GDISTATUS_TO_HRESULT(SourceBitmap.GetLastStatus());
  725. if (SUCCEEDED(hr))
  726. {
  727. //
  728. // Get the image width and height
  729. //
  730. UINT nSourceWidth = SourceBitmap.GetWidth();
  731. UINT nSourceHeight = SourceBitmap.GetHeight();
  732. //
  733. // Make sure the width and height are non-zero
  734. //
  735. if (nSourceWidth && nSourceHeight)
  736. {
  737. //
  738. //
  739. // Assume the source dimensions are fine
  740. //
  741. UINT nTargetWidth = nSourceWidth;
  742. UINT nTargetHeight = nSourceHeight;
  743. //
  744. // If the height or the width exceed the allowed maximum, scale it down, or if we are allowing stretching
  745. //
  746. if (nMaxWidth > 0 && nMaxHeight > 0)
  747. {
  748. if ((nTargetWidth > nMaxWidth) || (nTargetHeight > nMaxHeight) || bStretchSmallImages)
  749. {
  750. SIZE sizeDesiredImageSize = PrintScanUtil::ScalePreserveAspectRatio( nMaxWidth, nMaxHeight, nTargetWidth, nTargetHeight );
  751. nTargetWidth = sizeDesiredImageSize.cx;
  752. nTargetHeight = sizeDesiredImageSize.cy;
  753. }
  754. }
  755. //
  756. // Make sure we have valid sizes
  757. //
  758. if (nTargetWidth && nTargetHeight)
  759. {
  760. //
  761. // Create the target bitmap and make sure it succeeded
  762. //
  763. Bitmap TargetBitmap( nTargetWidth, nTargetHeight );
  764. hr = GDISTATUS_TO_HRESULT(TargetBitmap.GetLastStatus());
  765. if (SUCCEEDED(hr))
  766. {
  767. //
  768. // Get a graphics to render to
  769. //
  770. Graphics *pGraphics = Graphics::FromImage(&TargetBitmap);
  771. if (pGraphics)
  772. {
  773. //
  774. // Make sure it is valid
  775. //
  776. hr = GDISTATUS_TO_HRESULT(pGraphics->GetLastStatus());
  777. if (SUCCEEDED(hr))
  778. {
  779. //
  780. // Draw scaled image
  781. //
  782. hr = GDISTATUS_TO_HRESULT(pGraphics->DrawImage(&SourceBitmap, 0, 0, nTargetWidth, nTargetHeight));
  783. if (SUCCEEDED(hr))
  784. {
  785. //
  786. // Get an HBITMAP for this image
  787. //
  788. hr = GDISTATUS_TO_HRESULT(TargetBitmap.GetHBITMAP( Color::Black, &hTargetBitmap ));
  789. if (SUCCEEDED(hr))
  790. {
  791. if (!hTargetBitmap)
  792. {
  793. hr = E_FAIL;
  794. }
  795. }
  796. else
  797. {
  798. WIA_ERROR((TEXT("TargetBitmap.GetHBITMAP failed")));
  799. }
  800. }
  801. else
  802. {
  803. WIA_ERROR((TEXT("pGraphics->DrawImage failed")));
  804. }
  805. }
  806. else
  807. {
  808. WIA_ERROR((TEXT("pGraphics->GetLastStatus() failed")));
  809. }
  810. //
  811. // Clean up our dynamically allocated graphics
  812. //
  813. delete pGraphics;
  814. }
  815. else
  816. {
  817. WIA_ERROR((TEXT("pGraphics was NULL")));
  818. hr = E_FAIL;
  819. }
  820. }
  821. else
  822. {
  823. WIA_PRINTHRESULT((hr,TEXT("TargetBitmap.GetLastStatus() is not OK")));
  824. }
  825. }
  826. else
  827. {
  828. WIA_ERROR((TEXT("Invalid Target Bitmap Dimensions (%d,%d)"), nTargetWidth, nTargetHeight));
  829. hr = E_FAIL;
  830. }
  831. }
  832. else
  833. {
  834. WIA_ERROR((TEXT("Invalid Source Bitmap Dimensions")));
  835. hr = E_FAIL;
  836. }
  837. }
  838. else
  839. {
  840. WIA_PRINTHRESULT((hr,TEXT("SourceBitmap.GetLastStatus() failed")));
  841. }
  842. }
  843. else
  844. {
  845. WIA_ERROR((TEXT("hSourceBitmap was NULL")));
  846. }
  847. return hr;
  848. }
  849. //
  850. // Construct a string like this: JPG;BMP;PNG with all supported extensions
  851. //
  852. HRESULT CGdiPlusHelper::ConstructCodecExtensionSearchStrings( CSimpleString &strExtensions, Gdiplus::ImageCodecInfo *pImageCodecInfo, UINT nImageCodecCount )
  853. {
  854. for (UINT i=0;i<nImageCodecCount;i++)
  855. {
  856. if (strExtensions.Length())
  857. {
  858. strExtensions += TEXT(";");
  859. }
  860. strExtensions += CSimpleStringConvert::NaturalString(CSimpleStringWide(pImageCodecInfo[i].FilenameExtension));
  861. }
  862. return (strExtensions.Length() ? S_OK : E_FAIL);
  863. }
  864. HRESULT CGdiPlusHelper::ConstructDecoderExtensionSearchStrings( CSimpleString &strExtensions )
  865. {
  866. return CGdiPlusHelper::ConstructCodecExtensionSearchStrings( strExtensions, m_pImageDecoderInfo, m_nImageDecoderCount );
  867. }
  868. HRESULT CGdiPlusHelper::ConstructEncoderExtensionSearchStrings( CSimpleString &strExtensions )
  869. {
  870. return CGdiPlusHelper::ConstructCodecExtensionSearchStrings( strExtensions, m_pImageEncoderInfo, m_nImageEncoderCount );
  871. }
  872. EncoderParameters *CGdiPlusHelper::AppendEncoderParameter( EncoderParameters *pEncoderParameters, const GUID &guidProp, ULONG nType, PVOID pVoid )
  873. {
  874. if (pEncoderParameters)
  875. {
  876. pEncoderParameters->Parameter[pEncoderParameters->Count].Guid = guidProp;
  877. pEncoderParameters->Parameter[pEncoderParameters->Count].Type = nType;
  878. pEncoderParameters->Parameter[pEncoderParameters->Count].NumberOfValues = 1;
  879. pEncoderParameters->Parameter[pEncoderParameters->Count].Value = pVoid;
  880. pEncoderParameters->Count++;
  881. }
  882. return pEncoderParameters;
  883. }
  884. HRESULT CGdiPlusHelper::SaveMultipleImagesAsMultiPage( const CSimpleDynamicArray<CSimpleStringWide> &Filenames, const CSimpleStringWide &strFilename, const GUID &guidOutputFormat )
  885. {
  886. //
  887. // Assume failure
  888. //
  889. HRESULT hr = E_FAIL;
  890. //
  891. // Parameters used in the encoder
  892. //
  893. ULONG nEncoderValueMultiFrame = EncoderValueMultiFrame;
  894. ULONG nEncoderValueFrameDimensionPage = EncoderValueFrameDimensionPage;
  895. ULONG nEncoderValueLastFrame = EncoderValueLastFrame;
  896. //
  897. // Make sure we have some files
  898. //
  899. if (Filenames.Size())
  900. {
  901. //
  902. // Get the encoder
  903. //
  904. CLSID clsidEncoder = IID_NULL;
  905. hr = GetClsidOfEncoder( guidOutputFormat, clsidEncoder );
  906. if (SUCCEEDED(hr))
  907. {
  908. //
  909. // Open the first image
  910. //
  911. Image SourceImage( Filenames[0] );
  912. hr = GDISTATUS_TO_HRESULT(SourceImage.GetLastStatus());
  913. if (SUCCEEDED(hr))
  914. {
  915. EncoderParameters encoderParameters = {0};
  916. if (Filenames.Size() > 1)
  917. {
  918. AppendEncoderParameter( &encoderParameters, EncoderSaveFlag, EncoderParameterValueTypeLong, &nEncoderValueMultiFrame );
  919. }
  920. //
  921. // Save the first page
  922. //
  923. hr = GDISTATUS_TO_HRESULT(SourceImage.Save( strFilename, &clsidEncoder, &encoderParameters ));
  924. if (SUCCEEDED(hr))
  925. {
  926. //
  927. // Save each additional page
  928. //
  929. for (int i=1;i<Filenames.Size() && SUCCEEDED(hr);i++)
  930. {
  931. //
  932. // Create the additional page
  933. //
  934. Image AdditionalPage(Filenames[i]);
  935. //
  936. // Make sure it succeeded
  937. //
  938. hr = GDISTATUS_TO_HRESULT(AdditionalPage.GetLastStatus());
  939. if (SUCCEEDED(hr))
  940. {
  941. //
  942. // Prepare the encoder parameters
  943. //
  944. EncoderParameters encoderParameters[2] = {0};
  945. AppendEncoderParameter( encoderParameters, EncoderSaveFlag, EncoderParameterValueTypeLong, &nEncoderValueFrameDimensionPage );
  946. //
  947. // If this is the last page, append the "last frame" parameter
  948. //
  949. if (i == Filenames.Size()-1)
  950. {
  951. AppendEncoderParameter( encoderParameters, EncoderSaveFlag, EncoderParameterValueTypeLong, &nEncoderValueLastFrame );
  952. }
  953. //
  954. // Try to add a page
  955. //
  956. hr = GDISTATUS_TO_HRESULT(SourceImage.SaveAdd( &AdditionalPage, encoderParameters ));
  957. if (FAILED(hr))
  958. {
  959. WIA_PRINTHRESULT((hr,TEXT("SourceImage.SaveAdd failed!")));
  960. }
  961. }
  962. else
  963. {
  964. WIA_PRINTHRESULT((hr,TEXT("AdditionalPage.GetLastStatus failed!")));
  965. }
  966. }
  967. }
  968. else
  969. {
  970. WIA_PRINTHRESULT((hr,TEXT("SourceImage.Save failed!")));
  971. }
  972. }
  973. else
  974. {
  975. WIA_PRINTHRESULT((hr,TEXT("SourceImage.GetLastStatus failed!")));
  976. }
  977. }
  978. else
  979. {
  980. WIA_PRINTHRESULT((hr,TEXT("GetClsidOfEncoder failed!")));
  981. }
  982. }
  983. else
  984. {
  985. WIA_ERROR((TEXT("Filenames.Size was 0!")));
  986. hr = E_INVALIDARG;
  987. }
  988. return hr;
  989. }
  990. static void CalculateBrightnessAndContrastParams( BYTE iBrightness, BYTE iContrast, float *scale, float *translate )
  991. {
  992. //
  993. // force values to be at least 1, to avoid undesired effects
  994. //
  995. if (iBrightness < 1)
  996. {
  997. iBrightness = 1;
  998. }
  999. if (iContrast < 1)
  1000. {
  1001. iContrast = 1;
  1002. }
  1003. //
  1004. // get current brightness as a percentage of full scale
  1005. //
  1006. float fBrightness = (float)( 100 - iBrightness ) / 100.0f;
  1007. if (fBrightness > 0.95f)
  1008. {
  1009. fBrightness = 0.95f; /* clamp */
  1010. }
  1011. //
  1012. // get current contrast as a percentage of full scale
  1013. //
  1014. float fContrast = (float) iContrast / 100.0f;
  1015. if (fContrast > 1.0f)
  1016. {
  1017. fContrast = 1.0; /* limit to 1.0 */
  1018. }
  1019. //
  1020. // convert contrast to a scale value
  1021. //
  1022. if (fContrast <= 0.5f)
  1023. {
  1024. *scale = fContrast / 0.5f; /* 0 -> 0, .5 -> 1.0 */
  1025. }
  1026. else
  1027. {
  1028. if (fContrast == 1.0f)
  1029. {
  1030. fContrast = 0.9999f;
  1031. }
  1032. *scale = 0.5f / (1.0f - fContrast); /* .5 -> 1.0, 1.0 -> inf */
  1033. }
  1034. *translate = 0.5f - *scale * fBrightness;
  1035. }
  1036. HRESULT CGdiPlusHelper::SetBrightnessAndContrast( HBITMAP hSourceBitmap, HBITMAP &hTargetBitmap, BYTE nBrightness, BYTE nContrast )
  1037. {
  1038. WIA_TRACE((TEXT("nBrightness: %d, nContrast: %d"), nBrightness, nContrast ));
  1039. //
  1040. // Initialize the result to NULL
  1041. //
  1042. hTargetBitmap = NULL;
  1043. //
  1044. // Assume failure
  1045. //
  1046. HRESULT hr = E_FAIL;
  1047. //
  1048. // Make sure we are in a valid state
  1049. //
  1050. if (IsValid())
  1051. {
  1052. //
  1053. // Make sure we have a valid source bitmap
  1054. //
  1055. if (hSourceBitmap)
  1056. {
  1057. //
  1058. // Create the source bitmap. No palette required, we assume it will always be a 24bit DIB.
  1059. //
  1060. Bitmap SourceBitmap( hSourceBitmap, NULL );
  1061. hr = GDISTATUS_TO_HRESULT(SourceBitmap.GetLastStatus());
  1062. if (SUCCEEDED(hr))
  1063. {
  1064. //
  1065. // Create the target bitmap and make sure it succeeded
  1066. //
  1067. Bitmap TargetBitmap( SourceBitmap.GetWidth(), SourceBitmap.GetHeight() );
  1068. hr = GDISTATUS_TO_HRESULT(TargetBitmap.GetLastStatus());
  1069. if (SUCCEEDED(hr))
  1070. {
  1071. //
  1072. // Get a graphics to render to
  1073. //
  1074. Graphics *pGraphics = Graphics::FromImage(&TargetBitmap);
  1075. if (pGraphics)
  1076. {
  1077. //
  1078. // Make sure it is valid
  1079. //
  1080. hr = GDISTATUS_TO_HRESULT(pGraphics->GetLastStatus());
  1081. if (SUCCEEDED(hr))
  1082. {
  1083. ImageAttributes imageAttributes;
  1084. //
  1085. // Calculate the values needed for the matrix
  1086. //
  1087. REAL scale = 0.0;
  1088. REAL trans = 0.0;
  1089. CalculateBrightnessAndContrastParams( nBrightness, nContrast, &scale, &trans );
  1090. //
  1091. // Prepare the matrix for brightness and contrast transforms
  1092. //
  1093. ColorMatrix brightnessAndContrast = {scale, 0, 0, 0, 0,
  1094. 0, scale, 0, 0, 0,
  1095. 0, 0, scale, 0, 0,
  1096. 0, 0, 0, 1, 0,
  1097. trans, trans, trans, 0, 1};
  1098. imageAttributes.SetColorMatrix(&brightnessAndContrast);
  1099. Rect rect( 0, 0, SourceBitmap.GetWidth(), SourceBitmap.GetHeight() );
  1100. //
  1101. // Draw the transformed image on the graphics
  1102. //
  1103. hr = GDISTATUS_TO_HRESULT(pGraphics->DrawImage(&SourceBitmap,rect,0,0,SourceBitmap.GetWidth(), SourceBitmap.GetHeight(),UnitPixel,&imageAttributes));
  1104. if (SUCCEEDED(hr))
  1105. {
  1106. //
  1107. // Get the HBITMAP
  1108. //
  1109. hr = GDISTATUS_TO_HRESULT(TargetBitmap.GetHBITMAP( Color::Black, &hTargetBitmap ));
  1110. if (SUCCEEDED(hr))
  1111. {
  1112. if (!hTargetBitmap)
  1113. {
  1114. WIA_ERROR((TEXT("hTargetBitmap was NULL")));
  1115. hr = E_FAIL;
  1116. }
  1117. }
  1118. else
  1119. {
  1120. WIA_PRINTHRESULT((hr,TEXT("Bitmap::GetHBITMAP failed")));
  1121. }
  1122. }
  1123. else
  1124. {
  1125. WIA_PRINTHRESULT((hr,TEXT("pGraphics->DrawImage failed")));
  1126. }
  1127. }
  1128. else
  1129. {
  1130. WIA_PRINTHRESULT((hr,TEXT("pGraphics->GetLastStatus() failed")));
  1131. }
  1132. //
  1133. // Clean up our dynamically allocated graphics
  1134. //
  1135. delete pGraphics;
  1136. }
  1137. else
  1138. {
  1139. WIA_ERROR((TEXT("pGraphics was NULL")));
  1140. hr = E_FAIL;
  1141. }
  1142. }
  1143. else
  1144. {
  1145. WIA_PRINTHRESULT((hr,TEXT("TargetBitmap.GetLastStatus() failed")));
  1146. }
  1147. }
  1148. else
  1149. {
  1150. WIA_PRINTHRESULT((hr,TEXT("SourceBitmap.GetLastStatus() failed")));
  1151. }
  1152. }
  1153. else
  1154. {
  1155. WIA_ERROR((TEXT("hSourceBitmap was NULL")));
  1156. hr = E_FAIL;
  1157. }
  1158. }
  1159. else
  1160. {
  1161. WIA_ERROR((TEXT("IsValid() returned false")));
  1162. hr = E_FAIL;
  1163. }
  1164. WIA_PRINTHRESULT((hr,TEXT("Returning")));
  1165. return hr;
  1166. }
  1167. HRESULT CGdiPlusHelper::SetThreshold( HBITMAP hSourceBitmap, HBITMAP &hTargetBitmap, BYTE nThreshold )
  1168. {
  1169. //
  1170. // Initialize the result to NULL
  1171. //
  1172. hTargetBitmap = NULL;
  1173. //
  1174. // Assume failure
  1175. //
  1176. HRESULT hr = E_FAIL;
  1177. //
  1178. // Make sure we are in a valid state
  1179. //
  1180. if (IsValid())
  1181. {
  1182. //
  1183. // Make sure we have a valid source bitmap
  1184. //
  1185. if (hSourceBitmap)
  1186. {
  1187. //
  1188. // Create the source bitmap. No palette required, we assume it will always be a 24bit DIB.
  1189. //
  1190. Bitmap SourceBitmap( hSourceBitmap, NULL );
  1191. hr = GDISTATUS_TO_HRESULT(SourceBitmap.GetLastStatus());
  1192. if (SUCCEEDED(hr))
  1193. {
  1194. //
  1195. // Create the target bitmap and make sure it succeeded
  1196. //
  1197. Bitmap TargetBitmap( SourceBitmap.GetWidth(), SourceBitmap.GetHeight() );
  1198. hr = GDISTATUS_TO_HRESULT(TargetBitmap.GetLastStatus());
  1199. if (SUCCEEDED(hr))
  1200. {
  1201. //
  1202. // Get a graphics to render to
  1203. //
  1204. Graphics *pGraphics = Graphics::FromImage(&TargetBitmap);
  1205. if (pGraphics)
  1206. {
  1207. //
  1208. // Make sure it is valid
  1209. //
  1210. hr = GDISTATUS_TO_HRESULT(pGraphics->GetLastStatus());
  1211. if (SUCCEEDED(hr))
  1212. {
  1213. ImageAttributes imageAttributes;
  1214. imageAttributes.SetThreshold(static_cast<double>(100-nThreshold)/100);
  1215. Rect rect( 0, 0, SourceBitmap.GetWidth(), SourceBitmap.GetHeight() );
  1216. //
  1217. // Draw image rotated to the graphics
  1218. //
  1219. hr = GDISTATUS_TO_HRESULT(pGraphics->DrawImage(&SourceBitmap,rect,0,0,SourceBitmap.GetWidth(), SourceBitmap.GetHeight(),UnitPixel,&imageAttributes));
  1220. if (SUCCEEDED(hr))
  1221. {
  1222. //
  1223. // Get the HBITMAP
  1224. //
  1225. hr = GDISTATUS_TO_HRESULT(TargetBitmap.GetHBITMAP( Color::Black, &hTargetBitmap ));
  1226. if (SUCCEEDED(hr))
  1227. {
  1228. if (!hTargetBitmap)
  1229. {
  1230. WIA_ERROR((TEXT("hTargetBitmap was NULL")));
  1231. hr = E_FAIL;
  1232. }
  1233. }
  1234. else
  1235. {
  1236. WIA_PRINTHRESULT((hr,TEXT("Bitmap::GetHBITMAP failed")));
  1237. }
  1238. }
  1239. else
  1240. {
  1241. WIA_PRINTHRESULT((hr,TEXT("pGraphics->DrawImage failed")));
  1242. }
  1243. }
  1244. else
  1245. {
  1246. WIA_PRINTHRESULT((hr,TEXT("pGraphics->GetLastStatus() failed")));
  1247. }
  1248. //
  1249. // Clean up our dynamically allocated graphics
  1250. //
  1251. delete pGraphics;
  1252. }
  1253. else
  1254. {
  1255. WIA_ERROR((TEXT("pGraphics was NULL")));
  1256. hr = E_FAIL;
  1257. }
  1258. }
  1259. }
  1260. else
  1261. {
  1262. WIA_PRINTHRESULT((hr,TEXT("SourceBitmap.GetLastStatus() failed")));
  1263. }
  1264. }
  1265. else
  1266. {
  1267. WIA_ERROR((TEXT("hSourceBitmap was NULL")));
  1268. hr = E_FAIL;
  1269. }
  1270. }
  1271. WIA_PRINTHRESULT((hr,TEXT("Returning")));
  1272. return hr;
  1273. }
  1274. CImageFileFormatVerifier::CImageFileFormatVerifierItem::CImageFileFormatVerifierItem(void)
  1275. : m_pSignature(NULL),
  1276. m_pMask(NULL),
  1277. m_nLength(0),
  1278. m_guidFormat(IID_NULL),
  1279. m_clsidDecoder(IID_NULL)
  1280. {
  1281. }
  1282. CImageFileFormatVerifier::CImageFileFormatVerifierItem::CImageFileFormatVerifierItem( const PBYTE pSignature, const PBYTE pMask, int nLength, const GUID &guidFormat, const CLSID &guidDecoder )
  1283. : m_pSignature(NULL),
  1284. m_pMask(NULL),
  1285. m_nLength(0),
  1286. m_guidFormat(IID_NULL),
  1287. m_clsidDecoder(IID_NULL)
  1288. {
  1289. Assign( pSignature, pMask, nLength, guidFormat, guidDecoder );
  1290. }
  1291. CImageFileFormatVerifier::CImageFileFormatVerifierItem::CImageFileFormatVerifierItem( const CImageFileFormatVerifierItem &other )
  1292. : m_pSignature(NULL),
  1293. m_pMask(NULL),
  1294. m_nLength(0),
  1295. m_guidFormat(IID_NULL),
  1296. m_clsidDecoder(IID_NULL)
  1297. {
  1298. Assign( other.Signature(), other.Mask(), other.Length(), other.Format(), other.Decoder() );
  1299. }
  1300. CImageFileFormatVerifier::CImageFileFormatVerifierItem &CImageFileFormatVerifier::CImageFileFormatVerifierItem::operator=( const CImageFileFormatVerifierItem &other )
  1301. {
  1302. if (this != &other)
  1303. {
  1304. return Assign( other.Signature(), other.Mask(), other.Length(), other.Format(), other.Decoder() );
  1305. }
  1306. else return *this;
  1307. }
  1308. CImageFileFormatVerifier::CImageFileFormatVerifierItem &CImageFileFormatVerifier::CImageFileFormatVerifierItem::Assign( const PBYTE pSignature, const PBYTE pMask, int nLength, const GUID &guidFormat, const CLSID &clsidDecoder )
  1309. {
  1310. Destroy();
  1311. bool bOK = false;
  1312. m_nLength = nLength;
  1313. m_guidFormat = guidFormat;
  1314. m_clsidDecoder = clsidDecoder;
  1315. if (nLength && pSignature && pMask)
  1316. {
  1317. m_pSignature = new BYTE[nLength];
  1318. m_pMask = new BYTE[nLength];
  1319. if (m_pSignature && m_pMask)
  1320. {
  1321. CopyMemory( m_pSignature, pSignature, nLength );
  1322. CopyMemory( m_pMask, pMask, nLength );
  1323. bOK = true;
  1324. }
  1325. }
  1326. if (!bOK)
  1327. Destroy();
  1328. return *this;
  1329. }
  1330. void CImageFileFormatVerifier::CImageFileFormatVerifierItem::Destroy(void)
  1331. {
  1332. if (m_pSignature)
  1333. delete[] m_pSignature;
  1334. m_pSignature = NULL;
  1335. if (m_pMask)
  1336. delete[] m_pMask;
  1337. m_pMask = NULL;
  1338. m_nLength = 0;
  1339. m_guidFormat = IID_NULL;
  1340. m_clsidDecoder = IID_NULL;
  1341. }
  1342. CImageFileFormatVerifier::CImageFileFormatVerifierItem::~CImageFileFormatVerifierItem(void)
  1343. {
  1344. Destroy();
  1345. }
  1346. PBYTE CImageFileFormatVerifier::CImageFileFormatVerifierItem::Signature(void) const
  1347. {
  1348. return m_pSignature;
  1349. }
  1350. PBYTE CImageFileFormatVerifier::CImageFileFormatVerifierItem::Mask(void) const
  1351. {
  1352. return m_pMask;
  1353. }
  1354. int CImageFileFormatVerifier::CImageFileFormatVerifierItem::Length(void) const
  1355. {
  1356. return m_nLength;
  1357. }
  1358. GUID CImageFileFormatVerifier::CImageFileFormatVerifierItem::Format(void) const
  1359. {
  1360. return m_guidFormat;
  1361. }
  1362. CLSID CImageFileFormatVerifier::CImageFileFormatVerifierItem::Decoder(void) const
  1363. {
  1364. return m_clsidDecoder;
  1365. }
  1366. bool CImageFileFormatVerifier::CImageFileFormatVerifierItem::Match( PBYTE pBytes, int nLen ) const
  1367. {
  1368. WIA_PUSH_FUNCTION((TEXT("CImageFileFormatVerifierItem::Match")));
  1369. WIA_PRINTGUID((m_clsidDecoder,TEXT("Decoder")));
  1370. if (nLen < Length())
  1371. {
  1372. return false;
  1373. }
  1374. for (int i=0;i<Length();i++)
  1375. {
  1376. if (false == ((pBytes[i] & m_pMask[i]) == m_pSignature[i]))
  1377. {
  1378. return false;
  1379. }
  1380. }
  1381. return true;
  1382. }
  1383. CImageFileFormatVerifier::CImageFileFormatVerifier(void)
  1384. : m_nMaxSignatureLength(0),
  1385. m_pSignatureBuffer(NULL)
  1386. {
  1387. //
  1388. // Get the decoder count and size of the decoder info array
  1389. //
  1390. UINT nImageDecoderCount = 0, cbCodecs = 0;
  1391. if (Gdiplus::Ok == Gdiplus::GetImageDecodersSize( &nImageDecoderCount, &cbCodecs ))
  1392. {
  1393. //
  1394. // Make sure we got good sizes back
  1395. //
  1396. if (cbCodecs && nImageDecoderCount)
  1397. {
  1398. //
  1399. // Allocate the array
  1400. //
  1401. Gdiplus::ImageCodecInfo *pImageDecoderInfo = static_cast<Gdiplus::ImageCodecInfo*>(LocalAlloc(LPTR,cbCodecs));
  1402. if (pImageDecoderInfo)
  1403. {
  1404. //
  1405. // Get the actual decoder info
  1406. //
  1407. if (Gdiplus::Ok == Gdiplus::GetImageDecoders( nImageDecoderCount, cbCodecs, pImageDecoderInfo ))
  1408. {
  1409. //
  1410. // Add each decoder to the format list
  1411. //
  1412. for (UINT i=0;i<nImageDecoderCount;i++)
  1413. {
  1414. //
  1415. // Add each signature to the format list
  1416. //
  1417. for (UINT j=0;j<pImageDecoderInfo[i].SigCount;j++)
  1418. {
  1419. #if defined(DBG)
  1420. CSimpleString strPattern;
  1421. CSimpleString strMask;
  1422. for (ULONG x=0;x<pImageDecoderInfo[i].SigSize;x++)
  1423. {
  1424. strPattern += CSimpleString().Format( TEXT("%02X"), ((const PBYTE)(pImageDecoderInfo[i].SigPattern+(j*pImageDecoderInfo[i].SigSize)))[x] );
  1425. strMask += CSimpleString().Format( TEXT("%02X"), ((const PBYTE)(pImageDecoderInfo[i].SigMask+(j*pImageDecoderInfo[i].SigSize)))[x] );
  1426. }
  1427. WIA_PRINTGUID((pImageDecoderInfo[i].FormatID,TEXT("FormatID")));
  1428. WIA_PRINTGUID((pImageDecoderInfo[i].Clsid,TEXT(" Clsid")));
  1429. WIA_TRACE((TEXT(" strPattern: %s, strMask: %s, SigSize: %d"), strPattern.String(), strMask.String(), pImageDecoderInfo[i].SigSize ));
  1430. #endif
  1431. 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 ) );
  1432. }
  1433. }
  1434. }
  1435. //
  1436. // Free the array
  1437. //
  1438. LocalFree(pImageDecoderInfo);
  1439. }
  1440. }
  1441. }
  1442. //
  1443. // Assume the max length is Zero
  1444. //
  1445. m_nMaxSignatureLength = 0;
  1446. //
  1447. // For each signature, check if it is greater in length than the maximum.
  1448. //
  1449. for (int i=0;i<m_FileFormatVerifierList.Size();i++)
  1450. {
  1451. //
  1452. // If it is the longest, save the length
  1453. //
  1454. if (m_FileFormatVerifierList[i].Length() > m_nMaxSignatureLength)
  1455. {
  1456. m_nMaxSignatureLength = m_FileFormatVerifierList[i].Length();
  1457. }
  1458. }
  1459. //
  1460. // If we have a valid max length, allocate a buffer to hold the file's data
  1461. //
  1462. if (m_nMaxSignatureLength)
  1463. {
  1464. m_pSignatureBuffer = new BYTE[m_nMaxSignatureLength];
  1465. }
  1466. //
  1467. // If anything failed, free everything
  1468. //
  1469. if (!IsValid())
  1470. {
  1471. Destroy();
  1472. }
  1473. }
  1474. void CImageFileFormatVerifier::Destroy(void)
  1475. {
  1476. //
  1477. // Free the file signature buffer
  1478. //
  1479. if (m_pSignatureBuffer)
  1480. {
  1481. delete[] m_pSignatureBuffer;
  1482. m_pSignatureBuffer = NULL;
  1483. }
  1484. m_nMaxSignatureLength = 0;
  1485. m_FileFormatVerifierList.Destroy();
  1486. }
  1487. bool CImageFileFormatVerifier::IsValid(void) const
  1488. {
  1489. return (m_pSignatureBuffer && m_nMaxSignatureLength && m_FileFormatVerifierList.Size());
  1490. }
  1491. CImageFileFormatVerifier::~CImageFileFormatVerifier(void)
  1492. {
  1493. Destroy();
  1494. }
  1495. GUID CImageFileFormatVerifier::GetImageType( IStream * pStream )
  1496. {
  1497. WIA_PUSH_FUNCTION((TEXT("CImageFileFormatVerifier::GetImageType( via IStream )")));
  1498. //
  1499. // Assume we will not find a match
  1500. //
  1501. GUID guidResult = IID_NULL;
  1502. //
  1503. // Make sure we have a valid IStream object...
  1504. //
  1505. if (pStream)
  1506. {
  1507. //
  1508. // Read the maximum signature length number of bytes
  1509. //
  1510. ULONG uBytesRead = 0;
  1511. HRESULT hr = pStream->Read( m_pSignatureBuffer, m_nMaxSignatureLength, &uBytesRead );
  1512. //
  1513. // Make sure we got some bytes
  1514. //
  1515. if (SUCCEEDED(hr) && uBytesRead)
  1516. {
  1517. //
  1518. // Go though the list and try to find a match
  1519. //
  1520. for (int i=0;i<m_FileFormatVerifierList.Size();i++)
  1521. {
  1522. //
  1523. // If we found a match, we are done
  1524. //
  1525. if (m_FileFormatVerifierList[i].Match(m_pSignatureBuffer,uBytesRead))
  1526. {
  1527. guidResult = m_FileFormatVerifierList[i].Format();
  1528. break;
  1529. }
  1530. }
  1531. }
  1532. else
  1533. {
  1534. WIA_ERROR((TEXT("pStream->Read() failed w/hr = 0x%x"),hr));
  1535. }
  1536. }
  1537. else
  1538. {
  1539. WIA_ERROR((TEXT("pStream was NULL")));
  1540. }
  1541. //
  1542. // This will contain IID_NULL if no matching image type was found
  1543. //
  1544. return guidResult;
  1545. }
  1546. bool CImageFileFormatVerifier::IsImageFile( LPCTSTR pszFilename )
  1547. {
  1548. WIA_PUSH_FUNCTION((TEXT("CImageFileFormatVerifier::IsImageFile(%s)"),pszFilename));
  1549. GUID guidImageType = IID_NULL;
  1550. //
  1551. // Get a stream object over the file...
  1552. //
  1553. IStream * pStream = NULL;
  1554. HRESULT hr = SHCreateStreamOnFile(pszFilename, STGM_READ | STGM_SHARE_DENY_WRITE, &pStream );
  1555. if (SUCCEEDED(hr) && pStream)
  1556. {
  1557. guidImageType = GetImageType(pStream);
  1558. }
  1559. if (pStream)
  1560. {
  1561. pStream->Release();
  1562. }
  1563. WIA_PRINTGUID((guidImageType,TEXT("guidImageType")));
  1564. //
  1565. // If the image type is IID_NULL, it isn't an image
  1566. //
  1567. return ((IID_NULL != guidImageType) != FALSE);
  1568. }
  1569. bool CImageFileFormatVerifier::IsSupportedImageFromStream( IStream * pStream, GUID * pGuidOfFormat )
  1570. {
  1571. WIA_PUSH_FUNCTION((TEXT("CImageFileFormatVerifier::IsSupportedImageFromStream()")));
  1572. GUID guidImageType = IID_NULL;
  1573. //
  1574. // Get an IStream pointer for this file...
  1575. //
  1576. if (pStream)
  1577. {
  1578. guidImageType = GetImageType(pStream);
  1579. }
  1580. WIA_PRINTGUID((guidImageType,TEXT("guidImageType")));
  1581. if (pGuidOfFormat)
  1582. {
  1583. *pGuidOfFormat = guidImageType;
  1584. }
  1585. //
  1586. // If the image type is IID_NULL, it isn't an image
  1587. //
  1588. return ((IID_NULL != guidImageType) != FALSE);
  1589. }
  1590. CGdiPlusInit::CGdiPlusInit()
  1591. : m_pGdiplusToken(NULL)
  1592. {
  1593. //
  1594. // Make sure GDI+ is initialized
  1595. //
  1596. GdiplusStartupInput StartupInput;
  1597. GdiplusStartup(&m_pGdiplusToken,&StartupInput,NULL);
  1598. }
  1599. CGdiPlusInit::~CGdiPlusInit()
  1600. {
  1601. GdiplusShutdown(m_pGdiplusToken);
  1602. }