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.

1616 lines
31 KiB

  1. // CIMAGE.CPP
  2. // Implementation of CDIBImage and its kin
  3. #include <windows.h>
  4. #include <objbase.h>
  5. #include <shlobj.h>
  6. #include "wiadebug.h"
  7. #include "cunknown.h"
  8. #include <initguid.h>
  9. #include "util.h"
  10. #define DEFINE_GUIDS
  11. #include "cimage.h"
  12. STDMETHODIMP
  13. CDIBImage::QueryInterface (
  14. REFIID riid, LPVOID* ppvObject
  15. )
  16. {
  17. HRESULT hr;
  18. INTERFACES iface[] =
  19. {
  20. &IID_IBitmapImage, (IBitmapImage *) this,
  21. &IID_IPersistFile, (IPersistFile *) this,
  22. &IID_IDIBProperties, (IDIBProperties *) this,
  23. &IID_IImageProperties, (IImageProperties *) this,
  24. };
  25. //
  26. // Next, try the normal cases...
  27. //
  28. hr = HandleQueryInterface(riid, ppvObject, iface, ARRAYSIZE(iface));
  29. return hr;
  30. }
  31. STDMETHODIMP_(ULONG)
  32. CDIBImage::AddRef()
  33. {
  34. return CUnknown::HandleAddRef();
  35. }
  36. STDMETHODIMP_(ULONG)
  37. CDIBImage::Release()
  38. {
  39. return CUnknown::HandleRelease();
  40. }
  41. CDIBImage::CDIBImage() :
  42. m_hDIB(NULL),
  43. m_hBitmap(NULL),
  44. m_bDirty(FALSE),
  45. m_szFile(NULL),
  46. m_szDefaultExt (L"*.bmp")
  47. {
  48. }
  49. CDIBImage::~CDIBImage()
  50. {
  51. if (m_hDIB)
  52. {
  53. GlobalFree (m_hDIB);
  54. }
  55. if (m_hBitmap)
  56. {
  57. DeleteObject (m_hBitmap);
  58. }
  59. if (m_szFile)
  60. {
  61. delete [] m_szFile;
  62. }
  63. }
  64. /*++
  65. Name:
  66. CDIBImage::InternalCreate
  67. Description:
  68. Given a global memory DIB or an HBITMAP, init the
  69. object. Both a DIB and an HBITMAP are stored for quick
  70. access at the expense of increased memory use.
  71. Arguments:
  72. hDIB - global handle to a DIB
  73. hBmp - handle to a dibsection or compatible bitmap
  74. Return Value:
  75. S_OK on success, error code otherwise
  76. Notes:
  77. --*/
  78. HRESULT
  79. CDIBImage::InternalCreate (HANDLE hDIB, HBITMAP hBmp)
  80. {
  81. WIA_PUSHFUNCTION (TEXT("CDIBImage::InternalCreate"));
  82. HDC hdc = NULL;
  83. PBYTE pDIB = NULL;
  84. HRESULT hr = S_OK;
  85. if (!hDIB && !hBmp)
  86. {
  87. hr = E_INVALIDARG;
  88. goto exit_gracefully;// (hr, TEXT("NULL handles to InternalCreate"));
  89. }
  90. hdc = GetDC (NULL);
  91. if (m_hDIB)
  92. {
  93. GlobalFree (m_hDIB);
  94. }
  95. if (m_hBitmap)
  96. {
  97. DeleteObject (m_hBitmap);
  98. }
  99. if (hDIB)
  100. {
  101. m_hDIB = hDIB;
  102. }
  103. else
  104. {
  105. m_hDIB = Util::BitmapToDIB (hdc, hBmp);
  106. if (!m_hDIB)
  107. {
  108. hr = E_FAIL;
  109. goto exit_gracefully;
  110. }
  111. }
  112. if (hBmp)
  113. {
  114. m_hBitmap = hBmp;
  115. }
  116. else
  117. {
  118. pDIB = reinterpret_cast<PBYTE>(GlobalLock(m_hDIB));
  119. m_hBitmap = Util::DIBBufferToBMP (hdc, pDIB, FALSE);
  120. if (!m_hBitmap)
  121. {
  122. hr = E_FAIL;
  123. goto exit_gracefully;
  124. }
  125. }
  126. exit_gracefully:
  127. if (hdc)
  128. {
  129. ReleaseDC (NULL, hdc);
  130. }
  131. if (pDIB)
  132. {
  133. GlobalUnlock (m_hDIB);
  134. }
  135. return hr;
  136. }
  137. /*++
  138. Name:
  139. CDIBImage::CreateFromDataObject
  140. Description:
  141. Given an IDataObject pointer, retrieve an IBitmapImage interface
  142. for the data.
  143. Arguments:
  144. pdo - IDataObject interface
  145. Return Value:
  146. S_OK on success
  147. Notes:
  148. the pdo is not released by this function
  149. TODO: Add support for CF_BITMAP and other TYMED values
  150. --*/
  151. STDMETHODIMP
  152. CDIBImage::CreateFromDataObject (
  153. IDataObject *pdo
  154. )
  155. {
  156. FORMATETC fmt;
  157. STGMEDIUM stg;
  158. HRESULT hr = E_FAIL;
  159. WIA_PUSHFUNCTION(TEXT("CDIBImage::CreateFromDataObject"));
  160. if (!pdo)
  161. {
  162. goto exit_gracefully;// (hr, TEXT("NULL IDataObject passed to CreateFromDataObject"));
  163. }
  164. // Try with CF_DIB and TYMED_HGLOBAL only
  165. memset (&stg, 0, sizeof(stg));
  166. fmt.cfFormat = CF_DIB;
  167. fmt.ptd = NULL;
  168. fmt.dwAspect = DVASPECT_CONTENT;
  169. fmt.lindex = -1;
  170. fmt.tymed = TYMED_HGLOBAL;
  171. if (SUCCEEDED(hr=pdo->GetData(&fmt, &stg)))
  172. {
  173. hr = InternalCreate (stg.hGlobal, NULL);
  174. if (stg.pUnkForRelease)
  175. {
  176. stg.pUnkForRelease->Release();
  177. }
  178. else
  179. {
  180. GlobalFree (stg.hGlobal);
  181. }
  182. }
  183. exit_gracefully:
  184. return hr;
  185. }
  186. /*++
  187. Name:
  188. CDIBImage::CreateFromBitmap
  189. Description:
  190. Given an HBITMAP, init the object
  191. Arguments:
  192. hBitmap - dibsection or compatible bitmap
  193. Return Value:
  194. S_OK on success
  195. Notes:
  196. --*/
  197. STDMETHODIMP
  198. CDIBImage::CreateFromBitmap (
  199. HBITMAP hBitmap
  200. )
  201. {
  202. return InternalCreate (NULL, hBitmap);
  203. }
  204. /*++
  205. Name:
  206. CDIBImage::CreateFromDIB
  207. Description:
  208. Given a global memory DIB, init the object
  209. Arguments:
  210. hDIB - global DIB handle
  211. Return Value:
  212. S_OK on success
  213. Notes:
  214. --*/
  215. STDMETHODIMP
  216. CDIBImage::CreateFromDIB (
  217. HANDLE hDIB
  218. )
  219. {
  220. return InternalCreate (hDIB, NULL);
  221. }
  222. /*++
  223. Name:
  224. CDIBImage::Blt
  225. Description:
  226. Draw the image to the given DC
  227. Arguments:
  228. hdcDest- target DC
  229. prect - rectangle to fill in the DC
  230. xSrc - x coord to start in the image
  231. ySrc - y coord to start in the image
  232. dwRop - GDI ROP code
  233. Return Value:
  234. S_OK on success, E_FAIL if BitBlt fails
  235. Notes:
  236. --*/
  237. STDMETHODIMP
  238. CDIBImage::Blt (
  239. HDC hdcDest,
  240. LPRECT prect,
  241. INT xSrc,
  242. INT ySrc,
  243. DWORD dwRop
  244. )
  245. {
  246. WIA_PUSHFUNCTION(TEXT("CDIBImage::Blt"));
  247. HDC hdc = CreateCompatibleDC (hdcDest);
  248. HGDIOBJ hOld;
  249. BITMAP bm;
  250. HRESULT hr = S_OK;
  251. ZeroMemory (&bm, sizeof(bm));
  252. GetObject (m_hBitmap, sizeof(bm), &bm);
  253. if (hdc)
  254. {
  255. hOld = SelectObject (hdc, m_hBitmap);
  256. if (!::BitBlt (hdcDest,
  257. prect->left,
  258. prect->top,
  259. prect->right-prect->left,
  260. prect->bottom-prect->top,
  261. hdc,
  262. xSrc,
  263. ySrc,
  264. dwRop
  265. ))
  266. {
  267. hr = E_FAIL;
  268. }
  269. SelectObject (hdc, hOld);
  270. DeleteDC (hdc);
  271. }
  272. else
  273. {
  274. hr = E_OUTOFMEMORY;
  275. }
  276. return hr;
  277. }
  278. /*++
  279. Name:
  280. CDIBImage::Stretch
  281. Description:
  282. StretchBlt wrapper for the image
  283. Arguments:
  284. hdcDest - destination DC
  285. prcSrc - rectangle of the image to blt
  286. prcDest - rectangle of the DC to fill
  287. dwRop - GDI ROP code
  288. Return Value:
  289. S_OK on success, E_FAIL if StretchBlt fails
  290. Notes:
  291. --*/
  292. STDMETHODIMP
  293. CDIBImage::Stretch (
  294. HDC hdcDest,
  295. LPRECT prcSrc,
  296. LPRECT prcDest,
  297. DWORD dwRop
  298. )
  299. {
  300. WIA_PUSHFUNCTION(TEXT("CDIBImage::Stretch"));
  301. HRESULT hr = S_OK;
  302. if (!prcSrc || !prcDest)
  303. {
  304. hr = E_INVALIDARG;
  305. }
  306. else
  307. {
  308. HDC hdc = CreateCompatibleDC (hdcDest);
  309. HGDIOBJ hOld = NULL;
  310. if (hdc)
  311. {
  312. hOld = SelectObject (hdc, m_hBitmap);
  313. if (!::StretchBlt (hdcDest,
  314. prcDest->left,
  315. prcDest->top,
  316. prcDest->right-prcDest->left,
  317. prcDest->bottom-prcDest->top,
  318. hdc,
  319. prcSrc->left,
  320. prcSrc->top,
  321. prcSrc->right-prcSrc->left,
  322. prcSrc->bottom-prcDest->top,
  323. dwRop
  324. ))
  325. {
  326. hr = E_FAIL;
  327. }
  328. SelectObject (hdc, hOld);
  329. DeleteDC (hdc);
  330. }
  331. else
  332. {
  333. hr = E_OUTOFMEMORY;
  334. }
  335. }
  336. return hr;
  337. }
  338. /*++
  339. Name:
  340. CDIBImage::GetProperties
  341. Description:
  342. Retrieve an IImageProperties interface for the image
  343. Arguments:
  344. ppip - IImageProperties pointer to fill in
  345. Return Value:
  346. S_OK on success
  347. Notes:
  348. --*/
  349. STDMETHODIMP
  350. CDIBImage::GetProperties (
  351. IImageProperties **ppip
  352. )
  353. {
  354. if (!ppip)
  355. {
  356. return E_INVALIDARG;
  357. }
  358. return QueryInterface (IID_IImageProperties,
  359. reinterpret_cast<LPVOID *>(ppip));
  360. }
  361. /*++
  362. Name:
  363. CDIBImage::ConvertToDIB
  364. Description:
  365. Allocate a global DIB and fill it with the current image
  366. Arguments:
  367. phDIB - handle pointer to fill in
  368. Return Value:
  369. S_OK on success
  370. Notes:
  371. --*/
  372. STDMETHODIMP
  373. CDIBImage::ConvertToDIB (
  374. HANDLE *phDIB
  375. )
  376. {
  377. HANDLE hDIB;
  378. SIZE_T size;
  379. HRESULT hr = S_OK;
  380. PVOID pdib = NULL;
  381. PVOID pcopy = NULL;
  382. WIA_PUSHFUNCTION(TEXT("CDIBImage::ConvertToDIB"));
  383. if (!phDIB)
  384. {
  385. hr = E_INVALIDARG;
  386. goto exit_gracefully;// (hr, TEXT("NULL phDIB to ConvertToDIB"));
  387. }
  388. *phDIB = NULL;
  389. size = GlobalSize (m_hDIB);
  390. pdib = GlobalLock (m_hDIB);
  391. if (!pdib)
  392. {
  393. hr = E_OUTOFMEMORY;
  394. goto exit_gracefully;// (hr, TEXT("GlobalLock failed in ConvertToDIB"));
  395. }
  396. hDIB = GlobalAlloc (GHND, size);
  397. if (!hDIB)
  398. {
  399. hr = E_OUTOFMEMORY;
  400. goto exit_gracefully;// (hr, TEXT("GlobalAlloc failed in ConvertToDIB"));
  401. }
  402. pcopy = GlobalLock (hDIB);
  403. if (!pcopy)
  404. {
  405. GlobalFree (hDIB);
  406. hr = E_OUTOFMEMORY;
  407. goto exit_gracefully;// (hr, TEXT("GlobalLock failed in ConvertToDIB"));
  408. }
  409. memcpy (pcopy, pdib, size);
  410. exit_gracefully:
  411. if (phDIB && hDIB && pcopy)
  412. {
  413. GlobalUnlock (hDIB);
  414. *phDIB = hDIB;
  415. }
  416. if (pdib)
  417. {
  418. GlobalUnlock (m_hDIB);
  419. }
  420. return hr;
  421. }
  422. /*++
  423. Name:
  424. CDIBImage::CopyToClipboard
  425. Description:
  426. Put the image contents delimited by prect on the clipboard
  427. Arguments:
  428. prect - part of the image to copy
  429. Return Value:
  430. S_OK on success
  431. Notes:
  432. --*/
  433. STDMETHODIMP
  434. CDIBImage::CopyToClipboard (
  435. LPRECT prect
  436. )
  437. {
  438. WIA_PUSHFUNCTION(TEXT("CDIBImage::CopyToClipboard"));
  439. HRESULT hr = S_OK;
  440. OpenClipboard (NULL);
  441. EmptyClipboard();
  442. if (!prect)
  443. {
  444. //default to CF_DIB for whole image
  445. hr = SetClipboardData (CF_DIB, m_hDIB) ? S_OK:E_FAIL;
  446. }
  447. else
  448. {
  449. // Create an HBITMAP for the selected region
  450. HBITMAP hbmp = CropBitmap (m_hBitmap, prect);
  451. if (!hbmp)
  452. {
  453. hr = E_OUTOFMEMORY;
  454. goto exit_gracefully;// (hr, TEXT("CropBitmap failed in CopyToClipboard"));
  455. }
  456. hr = SetClipboardData (CF_BITMAP, hbmp) ? S_OK : E_FAIL;
  457. DeleteObject (hbmp);
  458. }
  459. exit_gracefully:
  460. CloseClipboard ();
  461. return hr;
  462. }
  463. /*++
  464. Name:
  465. CDIBImage::Rotate
  466. Description:
  467. Rotate the image around its center
  468. Arguments:
  469. nDegrees - amount to rotate
  470. Return Value:
  471. S_OK on success
  472. Notes:
  473. Currently only 90,180,270 degrees are supported
  474. --*/
  475. STDMETHODIMP
  476. CDIBImage::Rotate (
  477. INT nDegrees
  478. )
  479. {
  480. WIA_PUSHFUNCTION (TEXT("CDIBImage::Rotate"));
  481. HRESULT hr = S_OK;
  482. HBITMAP hNew;
  483. hNew = RotateBitmap (m_hBitmap, nDegrees);
  484. if (!hNew)
  485. {
  486. hr = E_FAIL;
  487. goto exit_gracefully;// (hr, TEXT("RotateBitmap failed in Rotate"));
  488. }
  489. else
  490. {
  491. m_bDirty = TRUE;
  492. InternalCreate (NULL, hNew);
  493. }
  494. exit_gracefully:
  495. return hr;
  496. }
  497. STDMETHODIMP
  498. CDIBImage::Crop (RECT *prcCrop,
  499. IBitmapImage **ppImage
  500. )
  501. {
  502. HBITMAP hBitmap;
  503. HRESULT hr = S_OK;
  504. CDIBImage *pObj;
  505. *ppImage = NULL;
  506. hBitmap = CropBitmap (m_hBitmap, prcCrop);
  507. if (hBitmap)
  508. {
  509. pObj = new CDIBImage ();
  510. if (pObj)
  511. {
  512. (pObj)->QueryInterface (IID_IBitmapImage,
  513. reinterpret_cast<PVOID*>(ppImage));
  514. (*ppImage)->CreateFromBitmap (hBitmap);
  515. pObj->Release();
  516. }
  517. DeleteObject (hBitmap);
  518. }
  519. else
  520. {
  521. hr = HRESULT_FROM_WIN32(GetLastError());
  522. }
  523. return hr;
  524. }
  525. ////////////////////////////////IImageProperties methods
  526. /*++
  527. Name:
  528. CDIBImage::GetSize
  529. Description:
  530. Returns the dimensions of the image
  531. Arguments:
  532. pSize - pointer to SIZE structure to fill
  533. Return Value:
  534. S_OK on success
  535. Notes:
  536. --*/
  537. STDMETHODIMP
  538. CDIBImage::GetSize (
  539. SIZE *pSize
  540. )
  541. {
  542. WIA_PUSHFUNCTION (TEXT("CDIBImage::GetSize"));
  543. BITMAP bm;
  544. if (!pSize)
  545. {
  546. return E_INVALIDARG;
  547. }
  548. ZeroMemory (&bm, sizeof(bm));
  549. GetObject (m_hBitmap, sizeof (bm), &bm);
  550. pSize->cx = bm.bmWidth;
  551. pSize->cy = bm.bmHeight;
  552. return S_OK;
  553. }
  554. /*++
  555. Name:
  556. CDIBImage::GetDepth
  557. Description:
  558. Return the bits per pixel of the image
  559. Arguments:
  560. pwBPP - pointer to value to fill in
  561. Return Value:
  562. S_OK on success
  563. Notes:
  564. --*/
  565. STDMETHODIMP
  566. CDIBImage::GetDepth (
  567. WORD *pwBPP
  568. )
  569. {
  570. WIA_PUSHFUNCTION (TEXT("CDIBImage::GetDepth"));
  571. BITMAP bm;
  572. if (!pwBPP)
  573. {
  574. return E_INVALIDARG;
  575. }
  576. if (GetObject (m_hBitmap, sizeof (bm), &bm) >= sizeof(bm))
  577. {
  578. *pwBPP = bm.bmBitsPixel;
  579. return S_OK;
  580. }
  581. return E_FAIL;
  582. }
  583. STDMETHODIMP
  584. CDIBImage::SetDepth (
  585. WORD wBPP
  586. )
  587. {
  588. return E_NOTIMPL;
  589. }
  590. STDMETHODIMP
  591. CDIBImage::GetAlpha (
  592. BYTE *pAlpha
  593. )
  594. {
  595. return E_NOTIMPL;
  596. }
  597. STDMETHODIMP
  598. CDIBImage::SetAlpha (
  599. BYTE Alpha
  600. )
  601. {
  602. return E_NOTIMPL;
  603. }
  604. STDMETHODIMP
  605. CDIBImage::GetAspectRatio(
  606. SIZE *pAspect
  607. )
  608. {
  609. return E_NOTIMPL;
  610. }
  611. STDMETHODIMP
  612. CDIBImage::SetAspectRatio(
  613. SIZE *pAspect
  614. )
  615. {
  616. return E_NOTIMPL;
  617. }
  618. //IDIBProperties methods
  619. /*++
  620. Name:
  621. CDIBImage::GetInfo
  622. Description:
  623. Construct a BITMAPINFO structure for the current image
  624. Arguments:
  625. ppbmi - pointer to BITMAPINFO pointer to allocate
  626. Return Value:
  627. S_OK on success
  628. Notes:
  629. --*/
  630. STDMETHODIMP
  631. CDIBImage::GetInfo(
  632. BITMAPINFO **ppbmi
  633. )
  634. {
  635. WIA_PUSHFUNCTION(TEXT("CDIBImage::GetInfo"));
  636. IMalloc *pMalloc = NULL;
  637. ULONG uSize;
  638. HRESULT hr = S_OK;
  639. BITMAPINFO *pDIB = NULL;
  640. hr = CoGetMalloc (1, &pMalloc);
  641. if (FAILED(hr))
  642. {
  643. goto exit_gracefully;// (hr, TEXT("SHGetMalloc in GetInfo"));
  644. }
  645. pDIB = reinterpret_cast<BITMAPINFO *>(GlobalLock (m_hDIB));
  646. if (!pDIB)
  647. {
  648. hr = E_OUTOFMEMORY;
  649. goto exit_gracefully;// (TEXT("GlobalLock failed in GetInfo"));
  650. }
  651. uSize = static_cast<LONG>(Util::GetBmiSize (pDIB));
  652. *ppbmi = reinterpret_cast<BITMAPINFO*>(pMalloc->Alloc (uSize));
  653. if (!*ppbmi)
  654. {
  655. hr = E_OUTOFMEMORY;
  656. goto exit_gracefully;// (hr, TEXT("IMalloc::Alloc"));
  657. }
  658. memcpy (*ppbmi, pDIB, uSize);
  659. exit_gracefully:
  660. if (pMalloc)
  661. {
  662. pMalloc->Release();
  663. }
  664. if (pDIB)
  665. {
  666. GlobalUnlock (m_hDIB);
  667. }
  668. return hr;
  669. }
  670. STDMETHODIMP
  671. CDIBImage::GetDIBSize(
  672. DWORD *pdwSize
  673. )
  674. {
  675. if (!pdwSize)
  676. {
  677. return E_POINTER;
  678. }
  679. *pdwSize = static_cast<DWORD>(GlobalSize(m_hDIB));
  680. return S_OK;
  681. }
  682. ////////////////////////////////// IPersistFile methods
  683. STDMETHODIMP
  684. CDIBImage::IsDirty(
  685. void
  686. )
  687. {
  688. return m_bDirty? S_OK:S_FALSE;
  689. }
  690. /*++
  691. Name:
  692. CDIBImage::Load
  693. Description:
  694. Init the image from an image file
  695. Arguments:
  696. pszFileName - path to the image file
  697. dwMode - storage mode to open with, currently ignored
  698. Return Value:
  699. S_OK on success
  700. Notes:
  701. --*/
  702. STDMETHODIMP
  703. CDIBImage::Load(
  704. LPCOLESTR pszFileName,
  705. DWORD dwMode
  706. )
  707. {
  708. HRESULT hr = S_OK;
  709. LPTSTR szDibFile = NULL;
  710. HBITMAP hBitmap;
  711. WIA_PUSHFUNCTION (TEXT("CDIBImage::Load"));
  712. if (!pszFileName || !*pszFileName)
  713. {
  714. hr = E_INVALIDARG;
  715. goto exit_gracefully;// (hr, TEXT("NULL filename to Load"));
  716. }
  717. if (m_szFile)
  718. {
  719. delete [] m_szFile;
  720. }
  721. m_szFile = new WCHAR[lstrlenW(pszFileName)+1];
  722. if (!m_szFile)
  723. {
  724. hr = E_OUTOFMEMORY;
  725. goto exit_gracefully;
  726. }
  727. wcscpy (m_szFile, pszFileName);
  728. #ifdef UNICODE
  729. szDibFile = m_szFile;
  730. #else
  731. INT len;
  732. len = WideCharToMultiByte (CP_ACP,
  733. 0,
  734. m_szFile,
  735. -1,
  736. szDibFile,
  737. 0,
  738. NULL,
  739. NULL);
  740. szDibFile = new CHAR[len+1];
  741. if (!szDibFile)
  742. {
  743. hr = E_OUTOFMEMORY;
  744. goto exit_gracefully;// (hr, TEXT("Unable to allocate file name in Load"));
  745. }
  746. WideCharToMultiByte (CP_ACP,
  747. 0,
  748. m_szFile,
  749. -1,
  750. szDibFile,
  751. len,
  752. NULL,
  753. NULL);
  754. #endif // UNICODE
  755. hBitmap = reinterpret_cast<HBITMAP>(LoadImage(NULL,
  756. szDibFile,
  757. IMAGE_BITMAP,
  758. 0,
  759. 0,
  760. LR_CREATEDIBSECTION|LR_LOADFROMFILE));
  761. hr = CreateFromBitmap (hBitmap);
  762. m_bDirty = FALSE;
  763. exit_gracefully:
  764. #ifndef UNICODE
  765. if (szDibFile)
  766. {
  767. delete [] szDibFile;
  768. }
  769. #endif //ndef UNICODE
  770. return hr;
  771. }
  772. STDMETHODIMP
  773. CDIBImage::GetClassID (
  774. CLSID *pClassID
  775. )
  776. {
  777. memcpy (pClassID, &CLSID_WIAImage, sizeof(CLSID));
  778. return S_OK;
  779. }
  780. /*++
  781. Name:
  782. CDIBImage::Save
  783. Description:
  784. Save the current image to file
  785. Arguments:
  786. pszFileName - file to save to. If NULL, use the current file name
  787. fRemember - whether to keep pszFileName as the new file name
  788. Return Value:
  789. S_OK on success
  790. Notes:
  791. --*/
  792. STDMETHODIMP
  793. CDIBImage::Save (
  794. LPCOLESTR pszFileName,
  795. BOOL fRemember
  796. )
  797. {
  798. HANDLE hFile;
  799. HRESULT hr = S_OK;
  800. LPTSTR pszDibFile = NULL;
  801. PBYTE pDibFile = NULL;
  802. PBITMAPINFOHEADER pDIB = NULL;
  803. PBYTE pBits;
  804. DWORD dw;
  805. WIA_PUSHFUNCTION(TEXT("CDIBImage::Save"));
  806. if (!*pszFileName)
  807. {
  808. hr = E_INVALIDARG;
  809. goto exit_gracefully;// (hr, TEXT("Empty filename to Save"));
  810. }
  811. if (fRemember && pszFileName)
  812. {
  813. if (m_szFile)
  814. {
  815. delete [] m_szFile;
  816. }
  817. m_szFile = new WCHAR[lstrlenW(pszFileName)+1];
  818. if (!m_szFile)
  819. {
  820. hr = E_OUTOFMEMORY;
  821. goto exit_gracefully;
  822. }
  823. lstrcpyW (m_szFile, pszFileName);
  824. }
  825. #ifdef UNICODE
  826. pszDibFile = const_cast<LPTSTR>(pszFileName);
  827. #else
  828. INT len;
  829. len = WideCharToMultiByte (CP_ACP,
  830. 0,
  831. pszFileName,
  832. -1,
  833. NULL,
  834. 0,
  835. NULL,
  836. NULL);
  837. pszDibFile = new CHAR[len+1];
  838. if (!pszDibFile)
  839. {
  840. hr = E_OUTOFMEMORY;
  841. goto exit_gracefully;// (hr, TEXT("Unable to allocate file name in Load"));
  842. }
  843. WideCharToMultiByte (CP_ACP,
  844. 0,
  845. pszFileName,
  846. -1,
  847. pszDibFile,
  848. len,
  849. NULL,
  850. NULL);
  851. #endif // UNICODE
  852. pDIB = reinterpret_cast<PBITMAPINFOHEADER>(GlobalLock (m_hDIB));
  853. pBits = reinterpret_cast<PBYTE>(pDIB) + Util::GetBmiSize(reinterpret_cast<PBITMAPINFO>(pDIB));
  854. pDibFile = Util::AllocDibFileFromBits (pBits,
  855. pDIB->biWidth,
  856. pDIB->biHeight,
  857. pDIB->biBitCount);
  858. if (!pDibFile)
  859. {
  860. hr = E_OUTOFMEMORY;
  861. goto exit_gracefully;// (hr, TEXT("AllocDibFileFromBits in Save"));
  862. }
  863. hFile = CreateFile (pszDibFile,
  864. GENERIC_WRITE,
  865. 0,
  866. NULL,
  867. CREATE_ALWAYS,
  868. FILE_ATTRIBUTE_NORMAL,
  869. NULL);
  870. if (INVALID_HANDLE_VALUE == hFile)
  871. {
  872. hr = E_FAIL;
  873. goto exit_gracefully;// (hr, TEXT("CreateFile in Save"));
  874. }
  875. WriteFile (hFile,
  876. pDibFile,
  877. reinterpret_cast<PBITMAPFILEHEADER>(pDibFile)->bfSize,
  878. &dw,
  879. NULL);
  880. CloseHandle (hFile);
  881. exit_gracefully:
  882. if (pDIB)
  883. {
  884. GlobalUnlock (m_hDIB);
  885. }
  886. if (pDibFile)
  887. {
  888. LocalFree (pDibFile);
  889. }
  890. #ifndef UNICODE
  891. if (pszDibFile)
  892. {
  893. delete [] pszDibFile;
  894. }
  895. #endif //ndef UNICODE
  896. return hr;
  897. }
  898. STDMETHODIMP
  899. CDIBImage::SaveCompleted (
  900. LPCOLESTR pszFileName
  901. )
  902. {
  903. return E_NOTIMPL;
  904. }
  905. /*++
  906. Name:
  907. CDIBImage::GetCurFile
  908. Description:
  909. Return the current file name of the image, or the
  910. preferred "file mask" for this kind of file.
  911. In this case the preferred mask is "*.bmp"
  912. Arguments:
  913. ppszFileName - pointer to string to fill in
  914. Return Value:
  915. S_OK on success
  916. Notes:
  917. --*/
  918. STDMETHODIMP
  919. CDIBImage::GetCurFile (
  920. LPOLESTR *ppszFileName
  921. )
  922. {
  923. HRESULT hr = S_OK;
  924. LPOLESTR szCur;
  925. IMalloc *pMalloc = NULL;
  926. WIA_PUSHFUNCTION(TEXT("CDIBImage::GetCurFile"));
  927. if (!ppszFileName)
  928. {
  929. hr = E_INVALIDARG;
  930. goto exit_gracefully;// (hr, TEXT("NULL out pointer to GetCurFile"));
  931. }
  932. if (!m_szFile)
  933. {
  934. szCur = const_cast<LPOLESTR>(m_szDefaultExt);
  935. }
  936. else
  937. {
  938. szCur = m_szFile;
  939. }
  940. hr = CoGetMalloc (1,&pMalloc);
  941. if (FAILED(hr))
  942. {
  943. goto exit_gracefully;// (hr, TEXT("CoGetMalloc in GetCurFile"));
  944. }
  945. *ppszFileName = reinterpret_cast<LPOLESTR>(pMalloc->Alloc((lstrlenW(szCur)+1)*sizeof(OLECHAR)));
  946. if (*ppszFileName)
  947. {
  948. lstrcpyW (*ppszFileName, szCur);
  949. }
  950. else
  951. {
  952. hr = E_OUTOFMEMORY;
  953. }
  954. exit_gracefully:
  955. if (pMalloc)
  956. {
  957. pMalloc->Release();
  958. }
  959. return hr;
  960. }
  961. // IDataObject methods
  962. STDMETHODIMP
  963. CDIBImage::GetData (
  964. FORMATETC *pformatetcIn,
  965. STGMEDIUM *pmedium
  966. )
  967. {
  968. return E_NOTIMPL;
  969. }
  970. STDMETHODIMP
  971. CDIBImage::GetDataHere (
  972. FORMATETC *pformatetc,
  973. STGMEDIUM *pmedium
  974. )
  975. {
  976. return E_NOTIMPL;
  977. }
  978. STDMETHODIMP
  979. CDIBImage::QueryGetData (
  980. FORMATETC *pformatetc
  981. )
  982. {
  983. return E_NOTIMPL;
  984. }
  985. STDMETHODIMP
  986. CDIBImage::GetCanonicalFormatEtc (
  987. FORMATETC *pformatectIn,
  988. FORMATETC *pformatetcOut
  989. )
  990. {
  991. return E_NOTIMPL;
  992. }
  993. STDMETHODIMP
  994. CDIBImage::SetData (
  995. FORMATETC *pformatetc,
  996. STGMEDIUM *pmedium,
  997. BOOL fRelease
  998. )
  999. {
  1000. return E_NOTIMPL;
  1001. }
  1002. STDMETHODIMP
  1003. CDIBImage::EnumFormatEtc (
  1004. DWORD dwDirection,
  1005. IEnumFORMATETC **ppenumFormatEtc
  1006. )
  1007. {
  1008. return E_NOTIMPL;
  1009. }
  1010. STDMETHODIMP
  1011. CDIBImage::DAdvise (
  1012. FORMATETC *pformatetc,
  1013. DWORD advf,
  1014. IAdviseSink *pAdvSink,
  1015. DWORD *pdwConnection
  1016. )
  1017. {
  1018. return E_NOTIMPL;
  1019. }
  1020. STDMETHODIMP
  1021. CDIBImage::DUnadvise (
  1022. DWORD dwConnection
  1023. )
  1024. {
  1025. return E_NOTIMPL;
  1026. }
  1027. STDMETHODIMP
  1028. CDIBImage::EnumDAdvise (
  1029. IEnumSTATDATA **ppenumAdvise
  1030. )
  1031. {
  1032. return E_NOTIMPL;
  1033. }
  1034. ///////////////////////////////////////////////////////////////////////////////
  1035. // Helper APIs
  1036. /*++
  1037. Name:
  1038. MakeNewDIBImage
  1039. Description:
  1040. Create an IBitmapImage interface for a CDIBImage object given an IDataObject
  1041. Arguments:
  1042. pdo - IDataObject pointer
  1043. pbiOut - IBitmapImage pointer to fill in
  1044. pfe - type of data to use
  1045. Return Value:
  1046. S_OK on success
  1047. Notes:
  1048. --*/
  1049. HRESULT MakeNewDIBImage (IDataObject *pdo, IBitmapImage **pbiOut, FORMATETC *pfe)
  1050. {
  1051. WIA_PUSHFUNCTION (TEXT("MakeNewDIBImage"));
  1052. CDIBImage *pDibImage = NULL;
  1053. IBitmapImage *pbi = NULL;
  1054. IPersistFile *ppf;
  1055. STGMEDIUM stg;
  1056. FORMATETC fmt;
  1057. HRESULT hr = S_OK;
  1058. *pbiOut = NULL;
  1059. pDibImage = new CDIBImage ();
  1060. if (!pDibImage)
  1061. {
  1062. hr = E_OUTOFMEMORY;
  1063. goto exit_gracefully;
  1064. }
  1065. if (FAILED(hr = pDibImage->QueryInterface (IID_IBitmapImage,
  1066. reinterpret_cast<LPVOID*>(&pbi)
  1067. )))
  1068. {
  1069. goto exit_gracefully;// (hr, TEXT("QueryInterface for IBitmapImage"));
  1070. }
  1071. if (pfe)
  1072. {
  1073. if (FAILED(hr = pdo->GetData (pfe, &stg)))
  1074. {
  1075. goto exit_gracefully;// (hr, TEXT("GetData in MakeNewDIBImage"));
  1076. }
  1077. switch (pfe->tymed)
  1078. {
  1079. case TYMED_HGLOBAL:
  1080. hr = pbi->CreateFromDIB (stg.hGlobal);
  1081. break;
  1082. case TYMED_GDI:
  1083. hr = pbi->CreateFromBitmap (stg.hBitmap);
  1084. break;
  1085. case TYMED_FILE:
  1086. hr = pbi->QueryInterface (IID_IPersistFile,
  1087. reinterpret_cast<LPVOID *>(&ppf)
  1088. );
  1089. if (SUCCEEDED(hr))
  1090. {
  1091. hr = ppf->Load (stg.lpszFileName, STGM_READ);
  1092. ppf->Release();
  1093. }
  1094. else
  1095. {
  1096. hr = DV_E_TYMED;
  1097. }
  1098. break;
  1099. default:
  1100. hr= DV_E_TYMED;
  1101. break;
  1102. }
  1103. }
  1104. else
  1105. {
  1106. // try HGLOBAL
  1107. fmt.cfFormat = CF_DIB;
  1108. fmt.tymed = TYMED_HGLOBAL;
  1109. fmt.lindex = -1;
  1110. fmt.dwAspect = DVASPECT_CONTENT;
  1111. fmt.ptd = NULL;
  1112. hr = MakeNewDIBImage (pdo, &pbi, &fmt);
  1113. }
  1114. exit_gracefully:
  1115. if (pDibImage)
  1116. {
  1117. pDibImage->Release ();
  1118. }
  1119. if (SUCCEEDED(hr))
  1120. {
  1121. *pbiOut = pbi;
  1122. }
  1123. else if (pbi)
  1124. {
  1125. pbi->Release();
  1126. }
  1127. return hr;
  1128. }
  1129. /*++
  1130. Name:
  1131. GetImageFromDataObject
  1132. Description:
  1133. Retrieve an IBitmapImage interface for an IDataObject
  1134. Arguments:
  1135. pdo - IDataObject pointer
  1136. pbi - IBitmapImage pointer to fill in
  1137. Return Value:
  1138. S_OK on success
  1139. Notes:
  1140. In the future, private formats in the IDataObject may allow this
  1141. function to return interfaces for other formats than DIB
  1142. --*/
  1143. HRESULT
  1144. GetImageFromDataObject (IN IDataObject *pdo, OUT IBitmapImage **pbi)
  1145. {
  1146. WIA_PUSHFUNCTION(TEXT("GetImageFromDataObject"));
  1147. IEnumFORMATETC *pEnum;
  1148. FORMATETC fe;
  1149. ULONG ul;
  1150. BOOL bMatch = FALSE;
  1151. HRESULT hr = S_OK;
  1152. if (SUCCEEDED(pdo->EnumFormatEtc (DATADIR_GET, &pEnum)))
  1153. {
  1154. while (S_OK == pEnum->Next (1, &fe,&ul))
  1155. {
  1156. switch (fe.cfFormat)
  1157. {
  1158. case CF_DIB:
  1159. case CF_BITMAP:
  1160. if (SUCCEEDED(hr= MakeNewDIBImage (pdo, pbi, &fe)))
  1161. {
  1162. bMatch = TRUE;
  1163. }
  1164. break;
  1165. default:
  1166. break;
  1167. }
  1168. }
  1169. if (!bMatch)
  1170. {
  1171. hr = E_FAIL;
  1172. }
  1173. pEnum->Release();
  1174. }
  1175. else
  1176. {
  1177. // just try DIBImage
  1178. hr = MakeNewDIBImage (pdo, pbi, NULL);
  1179. }
  1180. return hr;
  1181. }
  1182. #define MAKEPOINT(p,i,j) {(p).x = i;(p).y = j;}
  1183. HBITMAP RotateBitmap (HBITMAP hbm, UINT uAngle)
  1184. {
  1185. HDC hMemDCsrc = NULL;
  1186. HDC hMemDCdst = NULL;
  1187. HDC hdc = NULL;
  1188. HBITMAP hNewBm = NULL;
  1189. BITMAP bm;
  1190. LONG cx, cy;
  1191. POINT pts[3];
  1192. if (!hbm)
  1193. return NULL;
  1194. ZeroMemory (&bm, sizeof(bm));
  1195. GetObject (hbm, sizeof(BITMAP), (LPSTR)&bm);
  1196. switch (uAngle)
  1197. {
  1198. case 0:
  1199. case 360:
  1200. cx = bm.bmWidth;
  1201. cy = bm.bmHeight;
  1202. MAKEPOINT (pts[0], 0, 0)
  1203. MAKEPOINT (pts[1], bm.bmWidth, 0)
  1204. MAKEPOINT (pts[2], 0, bm.bmHeight)
  1205. break;
  1206. case 90:
  1207. cx = bm.bmHeight;
  1208. cy = bm.bmWidth;
  1209. MAKEPOINT(pts[0],bm.bmHeight,0)
  1210. MAKEPOINT(pts[1],bm.bmHeight,bm.bmWidth)
  1211. MAKEPOINT(pts[2],0,0)
  1212. break;
  1213. case 180:
  1214. cx = bm.bmWidth;
  1215. cy = bm.bmHeight;
  1216. MAKEPOINT(pts[0],bm.bmWidth, bm.bmHeight)
  1217. MAKEPOINT(pts[1],0,bm.bmHeight)
  1218. MAKEPOINT(pts[2],bm.bmWidth,0)
  1219. break;
  1220. case 270:
  1221. case -90:
  1222. cx = bm.bmHeight;
  1223. cy = bm.bmWidth;
  1224. MAKEPOINT(pts[0],0, bm.bmWidth)
  1225. MAKEPOINT(pts[1],0,0)
  1226. MAKEPOINT(pts[2],bm.bmHeight, bm.bmWidth)
  1227. break;
  1228. default:
  1229. return NULL;
  1230. WIA_TRACE((TEXT("RotateBitmap called with unsupported angle %d\n"), uAngle));
  1231. break;
  1232. }
  1233. hdc = GetDC (NULL);
  1234. if (hdc)
  1235. {
  1236. hMemDCsrc = CreateCompatibleDC (hdc);
  1237. hMemDCdst = CreateCompatibleDC (hdc);
  1238. }
  1239. if (hdc && hMemDCsrc && hMemDCdst)
  1240. {
  1241. hNewBm = CreateBitmap(cx, cy, bm.bmPlanes, bm.bmBitsPixel, NULL);
  1242. if (hNewBm)
  1243. {
  1244. SelectObject (hMemDCsrc, hbm);
  1245. SelectObject (hMemDCdst, hNewBm);
  1246. PlgBlt ( hMemDCdst,
  1247. pts,
  1248. hMemDCsrc,
  1249. 0,
  1250. 0,
  1251. bm.bmWidth,
  1252. bm.bmHeight,
  1253. NULL,
  1254. 0,0);
  1255. }
  1256. }
  1257. if (hdc)
  1258. ReleaseDC (NULL,hdc);
  1259. if (hMemDCsrc)
  1260. DeleteDC (hMemDCsrc);
  1261. if (hMemDCdst)
  1262. DeleteDC (hMemDCdst);
  1263. return hNewBm;
  1264. }
  1265. HBITMAP CropBitmap (
  1266. HBITMAP hbm,
  1267. PRECT prc)
  1268. {
  1269. HDC hMemDCsrc = NULL;
  1270. HDC hMemDCdst = NULL;
  1271. HDC hdc;
  1272. HBITMAP hNewBm = NULL;
  1273. BITMAP bm;
  1274. INT dx,dy;
  1275. if (!hbm)
  1276. return NULL;
  1277. hdc = GetDC (NULL);
  1278. if (hdc)
  1279. {
  1280. hMemDCsrc = CreateCompatibleDC (hdc);
  1281. hMemDCdst = CreateCompatibleDC (hdc);
  1282. }
  1283. if (hdc && hMemDCsrc && hMemDCdst)
  1284. {
  1285. ZeroMemory (&bm, sizeof(bm));
  1286. GetObject (hbm, sizeof(BITMAP), (LPSTR)&bm);
  1287. dx = prc->right - prc->left;
  1288. dy = prc->bottom - prc->top;
  1289. /*hNewBm = +++CreateBitmap - Not Recommended(use CreateDIBitmap)+++ (dx, dy, bm.bmPlanes, bm.bmBitsPixel, NULL);*/
  1290. hNewBm = CreateBitmap(dx, dy, bm.bmPlanes, bm.bmBitsPixel, NULL);
  1291. if (hNewBm)
  1292. {
  1293. SelectObject (hMemDCsrc, hbm);
  1294. SelectObject (hMemDCdst, hNewBm);
  1295. BitBlt (hMemDCdst,
  1296. 0,
  1297. 0,
  1298. dx,
  1299. dy,
  1300. hMemDCsrc,
  1301. prc->left,
  1302. prc->top,
  1303. SRCCOPY);
  1304. }
  1305. }
  1306. if (hdc)
  1307. ReleaseDC (NULL,hdc);
  1308. if (hMemDCsrc)
  1309. DeleteDC (hMemDCsrc);
  1310. if (hMemDCdst)
  1311. DeleteDC (hMemDCdst);
  1312. return hNewBm;
  1313. }