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.

302 lines
9.1 KiB

  1. //-----------------------------------------------------------------------------
  2. // File: ddutil.cpp
  3. //
  4. // Desc: Routines for loading bitmap and palettes from resources
  5. //
  6. //
  7. // Copyright (c) 1995-1999 Microsoft Corporation. All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #define STRICT
  10. #include <windows.h>
  11. #include <windowsx.h>
  12. #include <ddraw.h>
  13. #include "ddutil.h"
  14. //-----------------------------------------------------------------------------
  15. // Name: DDUtil_LoadBitmap()
  16. // Desc: Create a DirectDrawSurface from a bitmap resource.
  17. //-----------------------------------------------------------------------------
  18. LPDIRECTDRAWSURFACE7 DDUtil_LoadBitmap( LPDIRECTDRAW7 pDD, LPCSTR strBitmap,
  19. int dx, int dy )
  20. {
  21. HBITMAP hbm;
  22. BITMAP bm;
  23. DDSURFACEDESC2 ddsd;
  24. LPDIRECTDRAWSURFACE7 pdds;
  25. // Try to load the bitmap as a resource, if that fails, try it as a file
  26. hbm = (HBITMAP)LoadImage( GetModuleHandle(NULL), strBitmap, IMAGE_BITMAP,
  27. dx, dy, LR_CREATEDIBSECTION );
  28. if( NULL == hbm )
  29. hbm = (HBITMAP)LoadImage( NULL, strBitmap, IMAGE_BITMAP, dx, dy,
  30. LR_LOADFROMFILE | LR_CREATEDIBSECTION );
  31. if( NULL == hbm )
  32. return NULL;
  33. // Get size of the bitmap
  34. GetObject( hbm, sizeof(bm), &bm );
  35. // Create a DirectDrawSurface for this bitmap
  36. ZeroMemory( &ddsd, sizeof(ddsd) );
  37. ddsd.dwSize = sizeof(ddsd);
  38. ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
  39. ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  40. ddsd.dwWidth = bm.bmWidth;
  41. ddsd.dwHeight = bm.bmHeight;
  42. if( FAILED( pDD->CreateSurface( &ddsd, &pdds, NULL ) ) )
  43. return NULL;
  44. DDUtil_CopyBitmap( pdds, hbm, 0, 0, 0, 0 );
  45. DeleteObject( hbm );
  46. return pdds;
  47. }
  48. //-----------------------------------------------------------------------------
  49. // Name: DDUtil_ReLoadBitmap()
  50. // Desc: Load a bitmap from a file or resource into a directdraw surface.
  51. // normaly used to re-load a surface after a restore.
  52. //-----------------------------------------------------------------------------
  53. HRESULT DDUtil_ReLoadBitmap( LPDIRECTDRAWSURFACE7 pdds, LPCSTR strBitmap )
  54. {
  55. HBITMAP hbm;
  56. HRESULT hr;
  57. // Try to load the bitmap as a resource, if that fails, try it as a file
  58. hbm = (HBITMAP)LoadImage( GetModuleHandle(NULL), strBitmap, IMAGE_BITMAP,
  59. 0, 0, LR_CREATEDIBSECTION );
  60. if( NULL == hbm )
  61. hbm = (HBITMAP)LoadImage( NULL, strBitmap, IMAGE_BITMAP, 0, 0,
  62. LR_LOADFROMFILE | LR_CREATEDIBSECTION );
  63. if( NULL == hbm )
  64. {
  65. OutputDebugString( "DDUtil_ReLoadBitmap: handle is null\n" );
  66. return E_FAIL;
  67. }
  68. hr = DDUtil_CopyBitmap( pdds, hbm, 0, 0, 0, 0 );
  69. if( FAILED( hr ) )
  70. OutputDebugString( "DDUtil_ReLoadBitmap: copy bitmap failed\n" );
  71. DeleteObject( hbm );
  72. return hr;
  73. }
  74. //-----------------------------------------------------------------------------
  75. // Name: DDUtil_CopyBitmap()
  76. // Desc: Draw a bitmap into a DirectDrawSurface
  77. //-----------------------------------------------------------------------------
  78. HRESULT DDUtil_CopyBitmap( LPDIRECTDRAWSURFACE7 pdds, HBITMAP hbm,
  79. int x, int y, int dx, int dy )
  80. {
  81. HDC hdcImage;
  82. HDC hdc;
  83. BITMAP bm;
  84. DDSURFACEDESC2 ddsd;
  85. HRESULT hr = E_FAIL;
  86. if( hbm == NULL || pdds == NULL )
  87. return E_FAIL;
  88. // Make sure this surface is restored.
  89. pdds->Restore();
  90. // Select bitmap into a memoryDC so we can use it.
  91. hdcImage = CreateCompatibleDC( NULL );
  92. if( !hdcImage )
  93. {
  94. OutputDebugString("createcompatible dc failed\n");
  95. SelectObject( hdcImage, hbm );
  96. // Get size of the bitmap
  97. GetObject( hbm, sizeof(bm), &bm );
  98. dx = ( dx == 0 ? bm.bmWidth : dx ); // Use the passed size, unless zero
  99. dy = ( dy == 0 ? bm.bmHeight : dy );
  100. // Get size of surface.
  101. ddsd.dwSize = sizeof(ddsd);
  102. ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
  103. pdds->GetSurfaceDesc( &ddsd );
  104. if( SUCCEEDED( hr = pdds->GetDC( &hdc ) ) )
  105. {
  106. StretchBlt( hdc, 0, 0, ddsd.dwWidth, ddsd.dwHeight, hdcImage,
  107. x, y, dx, dy, SRCCOPY );
  108. pdds->ReleaseDC( hdc );
  109. }
  110. DeleteDC( hdcImage );
  111. }
  112. return hr;
  113. }
  114. //-----------------------------------------------------------------------------
  115. // Name: DDUtil_LoadPalette()
  116. // Desc: Create a DirectDraw palette object from a bitmap resource
  117. // if the resource does not exist or NULL is passed create a
  118. // default 332 palette.
  119. //-----------------------------------------------------------------------------
  120. LPDIRECTDRAWPALETTE DDUtil_LoadPalette( LPDIRECTDRAW7 pDD, LPCSTR strBitmap )
  121. {
  122. LPDIRECTDRAWPALETTE pPalette;
  123. int i;
  124. int n;
  125. int file;
  126. HRSRC hRes;
  127. BITMAPINFOHEADER* pbi;
  128. PALETTEENTRY pe[256];
  129. RGBQUAD* prgb;
  130. // Build a 332 palette as the default.
  131. for( i = 0; i < 256; i++ )
  132. {
  133. pe[i].peRed = (BYTE)( ( (i>>5) & 0x07 ) * 255 / 7 );
  134. pe[i].peGreen = (BYTE)( ( (i>>2) & 0x07 ) * 255 / 7 );
  135. pe[i].peBlue = (BYTE)( ( (i>>0) & 0x03 ) * 255 / 3 );
  136. pe[i].peFlags = (BYTE)0;
  137. }
  138. if( strBitmap )
  139. {
  140. // Get a pointer to the bitmap resource.
  141. if( hRes = FindResource( NULL, strBitmap, RT_BITMAP ) )
  142. {
  143. pbi = (BITMAPINFOHEADER*)LockResource( LoadResource( NULL, hRes ) );
  144. if( NULL == pbi )
  145. OutputDebugString("lock resource failed\n");
  146. prgb = (RGBQUAD*)( (BYTE*)pbi + pbi->biSize );
  147. if( NULL == pbi || pbi->biSize < sizeof(BITMAPINFOHEADER) )
  148. n = 0;
  149. else if( pbi->biBitCount > 8 )
  150. n = 0;
  151. else if( pbi->biClrUsed == 0 )
  152. n = 1 << pbi->biBitCount;
  153. else
  154. n = pbi->biClrUsed;
  155. // A DIB color table has its colors stored BGR not RGB
  156. // so flip them around.
  157. for( i = 0; i < n; i++ )
  158. {
  159. pe[i].peRed = prgb[i].rgbRed;
  160. pe[i].peGreen = prgb[i].rgbGreen;
  161. pe[i].peBlue = prgb[i].rgbBlue;
  162. pe[i].peFlags = 0;
  163. }
  164. }
  165. else if( ( file = _lopen( strBitmap, OF_READ ) ) != -1 )
  166. {
  167. BITMAPFILEHEADER bf;
  168. BITMAPINFOHEADER bi;
  169. _lread( file, &bf, sizeof(bf) );
  170. _lread( file, &bi, sizeof(bi) );
  171. _lread( file, pe, sizeof(pe) );
  172. _lclose( file );
  173. if( bi.biSize != sizeof(BITMAPINFOHEADER) )
  174. n = 0;
  175. else if( bi.biBitCount > 8 )
  176. n = 0;
  177. else if( bi.biClrUsed == 0 )
  178. n = 1 << bi.biBitCount;
  179. else
  180. n = bi.biClrUsed;
  181. // A DIB color table has its colors stored BGR not RGB
  182. // so flip them around.
  183. for (i = 0; i < n; i++)
  184. {
  185. BYTE r = pe[i].peRed;
  186. pe[i].peRed = pe[i].peBlue;
  187. pe[i].peBlue = r;
  188. }
  189. }
  190. }
  191. // Return the newly created palette
  192. if( FAILED( pDD->CreatePalette( DDPCAPS_8BIT, pe, &pPalette, NULL ) ) )
  193. return NULL;
  194. return pPalette;
  195. }
  196. //-----------------------------------------------------------------------------
  197. // Name: DDUtil_ColorMatch()
  198. // Desc: Convert a RGB color to a pysical color.
  199. // We do this by leting GDI SetPixel() do the color matching
  200. // then we lock the memory and see what it got mapped to.
  201. //-----------------------------------------------------------------------------
  202. DWORD DDUtil_ColorMatch( LPDIRECTDRAWSURFACE7 pdds, COLORREF rgb )
  203. {
  204. COLORREF rgbT = CLR_INVALID;
  205. HDC hdc;
  206. DWORD dw = CLR_INVALID;
  207. DDSURFACEDESC2 ddsd;
  208. HRESULT hr;
  209. // Use GDI SetPixel to color match for us
  210. if( rgb != CLR_INVALID && SUCCEEDED( pdds->GetDC( &hdc ) ) )
  211. {
  212. rgbT = GetPixel( hdc, 0, 0 ); // Save current pixel value
  213. SetPixel( hdc, 0, 0, rgb ); // Set our value
  214. pdds->ReleaseDC( hdc );
  215. }
  216. // Now lock the surface so we can read back the converted color
  217. ddsd.dwSize = sizeof(ddsd);
  218. while( ( hr = pdds->Lock( NULL, &ddsd, 0, NULL ) ) == DDERR_WASSTILLDRAWING )
  219. {
  220. // Wait for surface to be free
  221. }
  222. if( SUCCEEDED( hr ) )
  223. {
  224. dw = *(DWORD *)ddsd.lpSurface; // Get DWORD
  225. if( ddsd.ddpfPixelFormat.dwRGBBitCount < 32 )
  226. dw &= (1 << ddsd.ddpfPixelFormat.dwRGBBitCount) - 1; // Mask it to bpp
  227. pdds->Unlock( NULL );
  228. }
  229. // Now put the color that was there back.
  230. if( rgbT != CLR_INVALID && rgb != CLR_INVALID && SUCCEEDED( pdds->GetDC(&hdc) ) )
  231. {
  232. SetPixel( hdc, 0, 0, rgbT );
  233. pdds->ReleaseDC( hdc );
  234. }
  235. return dw;
  236. }
  237. //-----------------------------------------------------------------------------
  238. // Name: DDUtil_SetColorKey()
  239. // Desc: Set a color key for a surface, given a RGB.
  240. // If you pass CLR_INVALID as the color key, the pixel
  241. // in the upper-left corner will be used.
  242. //-----------------------------------------------------------------------------
  243. HRESULT DDUtil_SetColorKey( LPDIRECTDRAWSURFACE7 pdds, COLORREF rgb )
  244. {
  245. DDCOLORKEY ddck;
  246. ddck.dwColorSpaceLowValue = DDUtil_ColorMatch( pdds, rgb );
  247. ddck.dwColorSpaceHighValue = ddck.dwColorSpaceLowValue;
  248. return pdds->SetColorKey( DDCKEY_SRCBLT, &ddck );
  249. }