Leaked source code of windows server 2003
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.

248 lines
7.5 KiB

  1. #include "precomp.h"
  2. #pragma hdrstop
  3. #include "strsafe.h"
  4. CGdiPlusThumb::CGdiPlusThumb()
  5. {
  6. m_pImage = NULL;
  7. m_pImageFactory = NULL;
  8. m_szPath[0] = 0;
  9. }
  10. CGdiPlusThumb::~CGdiPlusThumb()
  11. {
  12. if (m_pImage)
  13. m_pImage->Release();
  14. if (m_pImageFactory)
  15. m_pImageFactory->Release();
  16. }
  17. STDMETHODIMP CGdiPlusThumb::GetLocation(LPWSTR pszPathBuffer, DWORD cch,
  18. DWORD * pdwPriority, const SIZE *prgSize,
  19. DWORD dwRecClrDepth, DWORD *pdwFlags)
  20. {
  21. HRESULT hr = E_UNEXPECTED;
  22. if (m_szPath[0])
  23. {
  24. hr = StringCchCopyW(pszPathBuffer, cch, m_szPath);
  25. if (SUCCEEDED(hr))
  26. {
  27. if (*pdwFlags & IEIFLAG_ASYNC)
  28. {
  29. hr = E_PENDING;
  30. // higher than normal priority, this task is relatively fast
  31. *pdwPriority = PRIORITY_EXTRACT_FAST;
  32. }
  33. m_rgSize = *prgSize;
  34. m_dwRecClrDepth = dwRecClrDepth;
  35. // We only work in non-paletted modes. Some of our extractors simply always use 24bbp, should we?
  36. if (m_dwRecClrDepth < 16)
  37. m_dwRecClrDepth = 16;
  38. m_fOrigSize = BOOLIFY(*pdwFlags & IEIFLAG_ORIGSIZE);
  39. m_fHighQuality = BOOLIFY(*pdwFlags & IEIFLAG_QUALITY);
  40. *pdwFlags = IEIFLAG_CACHE;
  41. }
  42. }
  43. return hr;
  44. }
  45. STDMETHODIMP CGdiPlusThumb::Extract(HBITMAP *phBmpThumbnail)
  46. {
  47. HRESULT hr = E_FAIL;
  48. // Do the GDI plus stuff here
  49. if (m_pImageFactory && m_pImage)
  50. {
  51. if (m_fHighQuality)
  52. {
  53. hr = m_pImage->Decode(SHIMGDEC_DEFAULT, 0, 0);
  54. }
  55. if (FAILED(hr))
  56. {
  57. hr = m_pImage->Decode(SHIMGDEC_THUMBNAIL, m_rgSize.cx, m_rgSize.cy);
  58. }
  59. if (SUCCEEDED(hr))
  60. {
  61. // Get the image's actual size, which might be less than the requested size since we asked for a thumbnail
  62. SIZE sizeImg;
  63. m_pImage->GetSize(&sizeImg);
  64. // we need to fill the background with the default color if we can't resize the bitmap
  65. // or if the image is transparent:
  66. m_fFillBackground = !m_fOrigSize || (m_pImage->IsTransparent() == S_OK);
  67. if (m_fOrigSize)
  68. {
  69. // if its too big, lets squish it, but try to
  70. // maintain the same aspect ratio. This is the same
  71. // sort of thing we do for the !m_fOrigSize case, except
  72. // here we want to do it here because we want to return
  73. // a correctly sized bitmap.
  74. if (sizeImg.cx != 0 && sizeImg.cy != 0 &&
  75. (sizeImg.cx > m_rgSize.cx || sizeImg.cy > m_rgSize.cy))
  76. {
  77. if (m_rgSize.cx * sizeImg.cy > m_rgSize.cy * sizeImg.cx)
  78. {
  79. m_rgSize.cx = MulDiv(m_rgSize.cy,sizeImg.cx,sizeImg.cy);
  80. }
  81. else
  82. {
  83. m_rgSize.cy = MulDiv(m_rgSize.cx,sizeImg.cy,sizeImg.cx);
  84. }
  85. }
  86. else
  87. {
  88. // Use the size if it was small enough and they wanted original size
  89. m_rgSize = sizeImg;
  90. }
  91. }
  92. hr = CreateDibFromBitmapImage( phBmpThumbnail );
  93. }
  94. }
  95. return SUCCEEDED(hr) ? S_OK : hr;
  96. }
  97. STDMETHODIMP CGdiPlusThumb::GetClassID(CLSID *pClassID)
  98. {
  99. *pClassID = CLSID_GdiThumbnailExtractor;
  100. return S_OK;
  101. }
  102. STDMETHODIMP CGdiPlusThumb::IsDirty()
  103. {
  104. return E_NOTIMPL;
  105. }
  106. STDMETHODIMP CGdiPlusThumb::Load(LPCOLESTR pszFileName, DWORD dwMode)
  107. {
  108. HRESULT hr;
  109. hr = StringCchCopyW(m_szPath, ARRAYSIZE(m_szPath), pszFileName );
  110. if (SUCCEEDED(hr))
  111. {
  112. // Call ImageFactory->CreateFromFile here. If Create from file failes then
  113. // return E_FAIL, otherwise return S_OK.
  114. ASSERT(NULL==m_pImageFactory);
  115. HRESULT hr = CoCreateInstance(CLSID_ShellImageDataFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellImageDataFactory, &m_pImageFactory));
  116. if (SUCCEEDED(hr))
  117. {
  118. hr = m_pImageFactory->CreateImageFromFile(m_szPath, &m_pImage);
  119. ASSERT((SUCCEEDED(hr) && m_pImage) || (FAILED(hr) && !m_pImage));
  120. }
  121. }
  122. return hr;
  123. }
  124. STDMETHODIMP CGdiPlusThumb::Save(LPCOLESTR pszFileName, BOOL fRemember)
  125. {
  126. return E_NOTIMPL;
  127. }
  128. STDMETHODIMP CGdiPlusThumb::SaveCompleted(LPCOLESTR pszFileName)
  129. {
  130. return E_NOTIMPL;
  131. }
  132. STDMETHODIMP CGdiPlusThumb::GetCurFile(LPOLESTR *ppszFileName)
  133. {
  134. return E_NOTIMPL;
  135. }
  136. HRESULT CGdiPlusThumb::CreateDibFromBitmapImage(HBITMAP * pbm)
  137. {
  138. HRESULT hr = E_FAIL;
  139. BITMAPINFO bmi = {0};
  140. void * pvBits;
  141. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  142. bmi.bmiHeader.biWidth = m_rgSize.cx;
  143. bmi.bmiHeader.biHeight = m_rgSize.cy;
  144. bmi.bmiHeader.biPlanes = 1;
  145. bmi.bmiHeader.biBitCount = (USHORT)m_dwRecClrDepth;
  146. bmi.bmiHeader.biCompression = BI_RGB;
  147. DWORD dwBPL = (((bmi.bmiHeader.biWidth * m_dwRecClrDepth) + 31) >> 3) & ~3;
  148. bmi.bmiHeader.biSizeImage = dwBPL * bmi.bmiHeader.biHeight;
  149. HDC hdc = GetDC(NULL);
  150. HBITMAP hbmp = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &pvBits, NULL, 0);
  151. if (hbmp)
  152. {
  153. HDC hMemDC = CreateCompatibleDC(hdc);
  154. if (hMemDC)
  155. {
  156. HBITMAP hbmOld = (HBITMAP)SelectObject(hMemDC, hbmp);
  157. RECT rc = {0, 0, m_rgSize.cx, m_rgSize.cy};
  158. if (m_fFillBackground)
  159. {
  160. FillRect(hMemDC, &rc, GetSysColorBrush(COLOR_WINDOW));
  161. }
  162. // if the m_fOrigSize flag isn't set then we need to return a bitmap that is the
  163. // requested size. In order to maintain aspect ratio that means we need to
  164. // center the thumbnail.
  165. if (!m_fOrigSize)
  166. {
  167. SIZE sizeImg;
  168. m_pImage->GetSize(&sizeImg);
  169. // if its too big, lets squish it, but try to
  170. // maintain the same aspect ratio. This is the same
  171. // sort of thing we did for the m_fOrigSize case, except
  172. // here we want to do it before centering.
  173. if (sizeImg.cx != 0 && sizeImg.cy != 0 &&
  174. (sizeImg.cx > m_rgSize.cx || sizeImg.cy > m_rgSize.cy))
  175. {
  176. if (m_rgSize.cx * sizeImg.cy > m_rgSize.cy * sizeImg.cx)
  177. {
  178. sizeImg.cx = MulDiv(m_rgSize.cy,sizeImg.cx,sizeImg.cy);
  179. sizeImg.cy = m_rgSize.cy;
  180. }
  181. else
  182. {
  183. sizeImg.cy = MulDiv(m_rgSize.cx,sizeImg.cy,sizeImg.cx);
  184. sizeImg.cx = m_rgSize.cx;
  185. }
  186. }
  187. rc.left = (m_rgSize.cx-sizeImg.cx)/2;
  188. rc.top = (m_rgSize.cy-sizeImg.cy)/2;
  189. rc.right = rc.left + sizeImg.cx;
  190. rc.bottom = rc.top + sizeImg.cy;
  191. }
  192. hr = m_pImage->Draw(hMemDC, &rc, NULL);
  193. SelectObject(hMemDC, hbmOld);
  194. DeleteDC(hMemDC);
  195. }
  196. }
  197. ReleaseDC(NULL, hdc);
  198. if (SUCCEEDED(hr))
  199. {
  200. *pbm = hbmp;
  201. }
  202. else if (hbmp)
  203. {
  204. DeleteObject(hbmp);
  205. }
  206. return hr;
  207. }