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.

283 lines
6.9 KiB

  1. /****************************************************************************
  2. *
  3. * (C) COPYRIGHT 2000, MICROSOFT CORP.
  4. *
  5. * FILE: gdipconv.cpp
  6. *
  7. * VERSION: 1.0
  8. *
  9. * DATE: 11/10/2000
  10. *
  11. * AUTHOR: Dave Parsons
  12. *
  13. * DESCRIPTION:
  14. * Helper functions for using GDI+ to convert image formats.
  15. *
  16. *****************************************************************************/
  17. #include "pch.h"
  18. using namespace Gdiplus;
  19. CWiauFormatConverter::CWiauFormatConverter() :
  20. m_Token(NULL),
  21. m_EncoderCount(0),
  22. m_pEncoderInfo(NULL)
  23. {
  24. memset(&m_guidCodecBmp, 0, sizeof(m_guidCodecBmp));
  25. }
  26. CWiauFormatConverter::~CWiauFormatConverter()
  27. {
  28. if (m_pEncoderInfo)
  29. {
  30. delete []m_pEncoderInfo;
  31. m_pEncoderInfo = NULL;
  32. }
  33. if (m_Token)
  34. {
  35. GdiplusShutdown(m_Token);
  36. m_Token = NULL;
  37. }
  38. }
  39. HRESULT CWiauFormatConverter::Init()
  40. {
  41. HRESULT hr = S_OK;
  42. GpStatus Status = Ok;
  43. //
  44. // Locals
  45. //
  46. GdiplusStartupInput gsi;
  47. ImageCodecInfo *pEncoderInfo = NULL;
  48. if (m_pEncoderInfo != NULL) {
  49. wiauDbgError("Init", "Init has already been called");
  50. goto Cleanup;
  51. }
  52. //
  53. // Start up GDI+
  54. //
  55. Status = GdiplusStartup(&m_Token, &gsi, NULL);
  56. if (Status != Ok)
  57. {
  58. wiauDbgError("Init", "GdiplusStartup failed");
  59. hr = E_FAIL;
  60. goto Cleanup;
  61. }
  62. UINT cbCodecs = 0;
  63. Status = GetImageEncodersSize(&m_EncoderCount, &cbCodecs);
  64. if (Status != Ok)
  65. {
  66. wiauDbgError("Init", "GetImageEncodersSize failed");
  67. hr = E_FAIL;
  68. goto Cleanup;
  69. }
  70. m_pEncoderInfo = new BYTE[cbCodecs];
  71. REQUIRE_ALLOC(m_pEncoderInfo, hr, "Init");
  72. pEncoderInfo = (ImageCodecInfo *) m_pEncoderInfo;
  73. Status = GetImageEncoders(m_EncoderCount, cbCodecs, pEncoderInfo);
  74. if (Ok != Status)
  75. {
  76. wiauDbgError("Init", "GetImageEncoders failed");
  77. hr = E_FAIL;
  78. goto Cleanup;
  79. }
  80. for (UINT count = 0; count < m_EncoderCount; count++)
  81. {
  82. if (pEncoderInfo[count].FormatID == ImageFormatBMP)
  83. {
  84. m_guidCodecBmp = pEncoderInfo[count].Clsid;
  85. break;
  86. }
  87. }
  88. Cleanup:
  89. if (FAILED(hr)) {
  90. if (m_pEncoderInfo)
  91. delete []m_pEncoderInfo;
  92. m_pEncoderInfo = NULL;
  93. }
  94. return hr;
  95. }
  96. BOOL CWiauFormatConverter::IsFormatSupported(const GUID *pguidFormat)
  97. {
  98. BOOL result = FALSE;
  99. ImageCodecInfo *pEncoderInfo = (ImageCodecInfo *) m_pEncoderInfo;
  100. for (UINT count = 0; count < m_EncoderCount; count++)
  101. {
  102. if (pEncoderInfo[count].FormatID == *pguidFormat)
  103. {
  104. result = TRUE;
  105. break;
  106. }
  107. }
  108. return result;
  109. }
  110. HRESULT CWiauFormatConverter::ConvertToBmp(BYTE *pSource, INT iSourceSize,
  111. BYTE **ppDest, INT *piDestSize,
  112. BMP_IMAGE_INFO *pBmpImageInfo, SKIP_AMOUNT iSkipAmt)
  113. {
  114. HRESULT hr = S_OK;
  115. //
  116. // Locals
  117. //
  118. GpStatus Status = Ok;
  119. CImageStream *pInStream = NULL;
  120. CImageStream *pOutStream = NULL;
  121. Image *pSourceImage = NULL;
  122. BYTE *pTempBuf = NULL;
  123. SizeF gdipSize;
  124. //
  125. // Check args
  126. //
  127. REQUIRE_ARGS(!pSource || !ppDest || !piDestSize || !pBmpImageInfo, hr, "ConvertToBmp");
  128. memset(pBmpImageInfo, 0, sizeof(BMP_IMAGE_INFO));
  129. //
  130. // Create a CImageStream from the source memory
  131. //
  132. pInStream = new CImageStream;
  133. REQUIRE_ALLOC(pInStream, hr, "ConvertToBmp");
  134. hr = pInStream->SetBuffer(pSource, iSourceSize);
  135. REQUIRE_SUCCESS(hr, "ConvertToBmp", "SetBuffer failed");
  136. //
  137. // Create a GDI+ Image object from the IStream
  138. //
  139. pSourceImage = new Image(pInStream);
  140. REQUIRE_ALLOC(pSourceImage, hr, "ConvertToBmp");
  141. if (pSourceImage->GetLastStatus() != Ok)
  142. {
  143. wiauDbgError("ConvertToBmp", "Image constructor failed");
  144. hr = E_FAIL;
  145. goto Cleanup;
  146. }
  147. //
  148. // Ask GDI+ for the image dimensions, and fill in the
  149. // passed structure
  150. //
  151. Status = pSourceImage->GetPhysicalDimension(&gdipSize);
  152. if (Status != Ok)
  153. {
  154. wiauDbgError("ConvertToBmp", "GetPhysicalDimension failed");
  155. hr = E_FAIL;
  156. goto Cleanup;
  157. }
  158. pBmpImageInfo->Width = (INT) gdipSize.Width;
  159. pBmpImageInfo->Height = (INT) gdipSize.Height;
  160. PixelFormat PixFmt = pSourceImage->GetPixelFormat();
  161. DWORD PixDepth = (PixFmt & 0xFFFF) >> 8; // Cannot assume image is always 24bits/pixel
  162. if( PixDepth < 24 )
  163. PixDepth = 24;
  164. pBmpImageInfo->ByteWidth = ((pBmpImageInfo->Width * PixDepth + 31) & ~31) / 8;
  165. pBmpImageInfo->Size = pBmpImageInfo->ByteWidth * pBmpImageInfo->Height;
  166. switch (iSkipAmt) {
  167. case SKIP_OFF:
  168. pBmpImageInfo->Size += sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
  169. break;
  170. case SKIP_FILEHDR:
  171. pBmpImageInfo->Size += sizeof(BITMAPINFOHEADER);
  172. break;
  173. case SKIP_BOTHHDR:
  174. break;
  175. default:
  176. break;
  177. }
  178. if (pBmpImageInfo->Size == 0)
  179. {
  180. wiauDbgError("ConvertToBmp", "Size of image is zero");
  181. hr = E_FAIL;
  182. goto Cleanup;
  183. }
  184. //
  185. // See if the caller passed in a destination buffer, and make sure
  186. // it is big enough.
  187. //
  188. if (*ppDest) {
  189. if (*piDestSize < pBmpImageInfo->Size) {
  190. wiauDbgError("ConvertToBmp", "Passed buffer is too small");
  191. hr = E_INVALIDARG;
  192. goto Cleanup;
  193. }
  194. }
  195. //
  196. // Otherwise allocate memory for a buffer
  197. //
  198. else
  199. {
  200. pTempBuf = new BYTE[pBmpImageInfo->Size];
  201. REQUIRE_ALLOC(pTempBuf, hr, "ConvertToBmp");
  202. *ppDest = pTempBuf;
  203. *piDestSize = pBmpImageInfo->Size;
  204. }
  205. //
  206. // Create output IStream
  207. //
  208. pOutStream = new CImageStream;
  209. REQUIRE_ALLOC(pOutStream, hr, "ConvertToBmp");
  210. hr = pOutStream->SetBuffer(*ppDest, pBmpImageInfo->Size, iSkipAmt);
  211. REQUIRE_SUCCESS(hr, "ConvertToBmp", "SetBuffer failed");
  212. //
  213. // Write the Image to the output IStream in BMP format
  214. //
  215. pSourceImage->Save(pOutStream, &m_guidCodecBmp, NULL);
  216. if (pSourceImage->GetLastStatus() != Ok)
  217. {
  218. wiauDbgError("ConvertToBmp", "GDI+ Save failed");
  219. hr = E_FAIL;
  220. goto Cleanup;
  221. }
  222. Cleanup:
  223. if (FAILED(hr)) {
  224. if (pTempBuf) {
  225. delete []pTempBuf;
  226. pTempBuf = NULL;
  227. *ppDest = NULL;
  228. *piDestSize = 0;
  229. }
  230. }
  231. if (pInStream) {
  232. pInStream->Release();
  233. }
  234. if (pOutStream) {
  235. pOutStream->Release();
  236. }
  237. if (pSourceImage) {
  238. delete pSourceImage;
  239. }
  240. return hr;
  241. }