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.

380 lines
12 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORPORATION, 1998, 1999, 2000
  4. *
  5. * TITLE: IMGS.CPP
  6. *
  7. * VERSION: 1.0
  8. *
  9. * AUTHOR: ShaunIv
  10. *
  11. * DATE: 1/13/1999
  12. *
  13. * DESCRIPTION: Image class
  14. *
  15. *******************************************************************************/
  16. #include "precomp.h"
  17. #pragma hdrstop
  18. #include "imgs.h"
  19. #include <windowsx.h>
  20. #include <atlbase.h>
  21. #include "isdbg.h"
  22. #include "ssutil.h"
  23. #include "gphelper.h"
  24. CBitmapImage::CBitmapImage(void)
  25. : m_hBitmap(NULL),
  26. m_hPalette(NULL)
  27. {
  28. WIA_PUSHFUNCTION(TEXT("CBitmapImage::CBitmapImage"));
  29. }
  30. CBitmapImage::~CBitmapImage(void)
  31. {
  32. WIA_PUSHFUNCTION(TEXT("CBitmapImage::~CBitmapImage"));
  33. Destroy();
  34. }
  35. void CBitmapImage::Destroy(void)
  36. {
  37. WIA_PUSHFUNCTION(TEXT("CBitmapImage::Destroy"));
  38. if (m_hBitmap)
  39. DeleteObject(m_hBitmap);
  40. m_hBitmap = NULL;
  41. if (m_hPalette)
  42. DeleteObject(m_hPalette);
  43. m_hPalette = NULL;
  44. }
  45. bool CBitmapImage::IsValid(void) const
  46. {
  47. return(m_hBitmap != NULL);
  48. }
  49. HPALETTE CBitmapImage::Palette(void) const
  50. {
  51. return(m_hPalette);
  52. }
  53. HBITMAP CBitmapImage::GetBitmap(void) const
  54. {
  55. return(m_hBitmap);
  56. }
  57. // Create a palette for the image
  58. HPALETTE CBitmapImage::PreparePalette( CSimpleDC &dc, HBITMAP hBitmap )
  59. {
  60. WIA_PUSHFUNCTION(TEXT("CBitmapImage::PreparePalette"));
  61. HPALETTE hPalette = NULL;
  62. if (GetDeviceCaps(dc,RASTERCAPS) & RC_PALETTE)
  63. {
  64. if (hBitmap)
  65. {
  66. DIBSECTION ds = {0};
  67. GetObject(hBitmap, sizeof (DIBSECTION), &ds);
  68. int nColors;
  69. if (ds.dsBmih.biClrUsed != 0)
  70. {
  71. nColors = ds.dsBmih.biClrUsed;
  72. }
  73. else
  74. {
  75. //
  76. // Handle the special case of an image that claims to be
  77. // a 32bit DIB as a 24bit DIB
  78. //
  79. if (ds.dsBmih.biBitCount == 32)
  80. {
  81. nColors = 1 << 24;
  82. }
  83. else
  84. {
  85. nColors = 1 << ds.dsBmih.biBitCount;
  86. }
  87. }
  88. //
  89. // Create a halftone palette if the DIB section contains more
  90. // than 256 colors
  91. //
  92. if (nColors > 256)
  93. {
  94. hPalette = CreateHalftonePalette(dc);
  95. }
  96. //
  97. // Create a custom palette from the DIB section's color table
  98. // if the number of colors is 256 or less
  99. //
  100. else
  101. {
  102. RGBQUAD* pRGB = new RGBQUAD[nColors];
  103. if (pRGB)
  104. {
  105. CSimpleDC MemDC;
  106. MemDC.CreateCompatibleDC(dc);
  107. SelectObject( MemDC, hBitmap );
  108. GetDIBColorTable( MemDC, 0, nColors, pRGB );
  109. UINT nSize = sizeof (LOGPALETTE) + (sizeof (PALETTEENTRY) * (nColors - 1));
  110. LOGPALETTE* pLP = (LOGPALETTE*) new BYTE[nSize];
  111. if (pLP)
  112. {
  113. pLP->palVersion = 0x300;
  114. pLP->palNumEntries = (WORD)nColors;
  115. for (int i=0; i<nColors; i++)
  116. {
  117. pLP->palPalEntry[i].peRed = pRGB[i].rgbRed;
  118. pLP->palPalEntry[i].peGreen = pRGB[i].rgbGreen;
  119. pLP->palPalEntry[i].peBlue = pRGB[i].rgbBlue;
  120. pLP->palPalEntry[i].peFlags = 0;
  121. }
  122. hPalette = CreatePalette(pLP);
  123. delete[] pLP;
  124. }
  125. delete[] pRGB;
  126. }
  127. }
  128. }
  129. }
  130. else
  131. {
  132. hPalette = CreateHalftonePalette(dc);
  133. }
  134. WIA_TRACE((TEXT("Returning palette %08X"), hPalette ));
  135. return hPalette;
  136. }
  137. SIZE CBitmapImage::ImageSize(void) const
  138. {
  139. SIZE sizeImage = {0,0};
  140. if (IsValid())
  141. {
  142. BITMAP bm = {0};
  143. if (GetObject( m_hBitmap, sizeof(bm), &bm ))
  144. {
  145. sizeImage.cx = bm.bmWidth;
  146. sizeImage.cy = bm.bmHeight;
  147. }
  148. }
  149. return(sizeImage);
  150. }
  151. bool CBitmapImage::CreateFromText( LPCTSTR pszText, const RECT &rcScreen, int nMaxScreenPercent )
  152. {
  153. Destroy();
  154. HDC hDesktopDC = GetDC(NULL);
  155. if (hDesktopDC)
  156. {
  157. //
  158. // Calculate the maximum size of the text rectangle
  159. //
  160. RECT rcImage = { 0, 0, WiaUiUtil::MulDivNoRound(rcScreen.right - rcScreen.left,nMaxScreenPercent,100), WiaUiUtil::MulDivNoRound(rcScreen.bottom - rcScreen.top,nMaxScreenPercent,100) };
  161. //
  162. // Create a mem dc to hold the bitmap
  163. //
  164. CSimpleDC MemDC;
  165. if (MemDC.CreateCompatibleDC(hDesktopDC))
  166. {
  167. //
  168. // Use the default UI font
  169. //
  170. SelectObject( MemDC, GetStockObject( DEFAULT_GUI_FONT ) );
  171. //
  172. // Figure out how big the bitmap has to be
  173. //
  174. DrawText( MemDC, pszText, lstrlen(pszText), &rcImage, DT_NOPREFIX|DT_WORDBREAK|DT_CALCRECT|DT_RTLREADING );
  175. //
  176. // Create the bitmap
  177. //
  178. m_hBitmap = CreateCompatibleBitmap( hDesktopDC, rcImage.right, rcImage.bottom );
  179. if (m_hBitmap)
  180. {
  181. //
  182. // Set the appropriate colors and select the bitmap into the DC
  183. //
  184. SetBkColor( MemDC, RGB(0,0,0) );
  185. SetTextColor( MemDC, RGB(255,255,255) );
  186. SelectBitmap( MemDC, m_hBitmap );
  187. //
  188. // Draw the actual text
  189. //
  190. DrawText( MemDC, pszText, lstrlen(pszText), &rcImage, DT_NOPREFIX|DT_WORDBREAK|DT_RTLREADING );
  191. }
  192. }
  193. //
  194. // Free the desktop DC
  195. //
  196. ReleaseDC(NULL,hDesktopDC);
  197. }
  198. return m_hBitmap != NULL;
  199. }
  200. bool CBitmapImage::Load( CSimpleDC &dc,
  201. LPCTSTR pszFilename,
  202. const RECT &rcScreen,
  203. int nMaxScreenPercent,
  204. bool bAllowStretching,
  205. bool bDisplayFilename
  206. )
  207. {
  208. //
  209. // Clean up, if necessary
  210. //
  211. Destroy();
  212. //
  213. // Validate the arguments
  214. //
  215. if (!pszFilename || !lstrlen(pszFilename))
  216. {
  217. return false;
  218. }
  219. //
  220. // Try to load and scale the image using GDI plus
  221. //
  222. CGdiPlusHelper GdiPlusHelper;
  223. if (SUCCEEDED(GdiPlusHelper.LoadAndScale( m_hBitmap, pszFilename, WiaUiUtil::MulDivNoRound(rcScreen.right - rcScreen.left,nMaxScreenPercent,100), WiaUiUtil::MulDivNoRound(rcScreen.bottom - rcScreen.top,nMaxScreenPercent,100), bAllowStretching )) && m_hBitmap)
  224. {
  225. //
  226. // Get the size of the image
  227. //
  228. SIZE sizeImage = ImageSize();
  229. //
  230. // Prepare the image's palette, if it has one
  231. //
  232. m_hPalette = PreparePalette( dc, m_hBitmap );
  233. //
  234. // Add the image title
  235. //
  236. if (bDisplayFilename && *pszFilename)
  237. {
  238. CSimpleDC MemoryDC;
  239. if (MemoryDC.CreateCompatibleDC(dc))
  240. {
  241. //
  242. // Prepare the DC and select the current image into it
  243. //
  244. ScreenSaverUtil::SelectPalette( MemoryDC, Palette(), FALSE );
  245. SelectBitmap( MemoryDC, m_hBitmap );
  246. SetBkMode( MemoryDC, TRANSPARENT );
  247. //
  248. // Create the title DC
  249. //
  250. CSimpleDC ImageTitleDC;
  251. if (ImageTitleDC.CreateCompatibleDC(dc))
  252. {
  253. //
  254. // Prepare the title DC
  255. //
  256. ScreenSaverUtil::SelectPalette( ImageTitleDC, Palette(), FALSE );
  257. SelectFont( ImageTitleDC, (HFONT)GetStockObject(DEFAULT_GUI_FONT) );
  258. SetBkMode( ImageTitleDC, TRANSPARENT );
  259. //
  260. // Calculate the rectangle needed to print the filename
  261. //
  262. RECT rcText;
  263. rcText.left = 0;
  264. rcText.top = 0;
  265. rcText.right = sizeImage.cx;
  266. rcText.bottom = sizeImage.cy;
  267. //
  268. // Make a nice margin
  269. //
  270. InflateRect( &rcText, -2, -2 );
  271. DrawText( ImageTitleDC, pszFilename, lstrlen(pszFilename), &rcText, DT_PATH_ELLIPSIS|DT_SINGLELINE|DT_NOPREFIX|DT_TOP|DT_LEFT|DT_CALCRECT );
  272. InflateRect( &rcText, 2, 2 );
  273. //
  274. // If the text rect is bigger than the scaled image, make it the same size
  275. //
  276. if (rcText.right > sizeImage.cx)
  277. rcText.right = sizeImage.cx;
  278. if (rcText.bottom > sizeImage.cy)
  279. rcText.bottom = sizeImage.cy;
  280. //
  281. // Create the bitmap we'll use for the filename
  282. //
  283. BITMAPINFO bmi;
  284. ZeroMemory( &bmi, sizeof(BITMAPINFO) );
  285. bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  286. bmi.bmiHeader.biWidth = rcText.right - rcText.left;
  287. bmi.bmiHeader.biHeight = rcText.bottom - rcText.top;
  288. bmi.bmiHeader.biPlanes = 1;
  289. bmi.bmiHeader.biBitCount = 24;
  290. bmi.bmiHeader.biCompression = BI_RGB;
  291. PBYTE pBitmapData = NULL;
  292. HBITMAP hBmpImageTitle = CreateDIBSection( dc, &bmi, DIB_RGB_COLORS, (LPVOID*)&pBitmapData, NULL, 0 );
  293. if (hBmpImageTitle)
  294. {
  295. //
  296. // Initialize the Alpha blend stuff
  297. //
  298. BLENDFUNCTION BlendFunction;
  299. ZeroMemory( &BlendFunction, sizeof(BlendFunction) );
  300. BlendFunction.BlendOp = AC_SRC_OVER;
  301. BlendFunction.SourceConstantAlpha = 128;
  302. //
  303. // Select our new bitmap into the memory dc
  304. //
  305. HBITMAP hOldBitmap = SelectBitmap( ImageTitleDC, hBmpImageTitle );
  306. //
  307. // White background
  308. //
  309. FillRect( ImageTitleDC, &rcText, (HBRUSH)GetStockObject(WHITE_BRUSH));
  310. //
  311. // Alpha blend from the stretched bitmap to our text rect
  312. //
  313. AlphaBlend( ImageTitleDC, 0, 0, rcText.right - rcText.left, rcText.bottom - rcText.top, MemoryDC, rcText.left, rcText.top, rcText.right, rcText.bottom, BlendFunction );
  314. //
  315. // Draw the actual text
  316. //
  317. InflateRect( &rcText, -2, -2 );
  318. DrawText( ImageTitleDC, pszFilename, lstrlen(pszFilename), &rcText, DT_PATH_ELLIPSIS|DT_SINGLELINE|DT_NOPREFIX|DT_TOP|DT_LEFT );
  319. InflateRect( &rcText, 2, 2 );
  320. //
  321. // Copy back to the current image
  322. //
  323. BitBlt( MemoryDC, rcText.left, rcText.top, rcText.right - rcText.left, rcText.bottom - rcText.top, ImageTitleDC, 0, 0, SRCCOPY );
  324. //
  325. // Restore the dc's bitmap, and delete our title background
  326. //
  327. DeleteObject( SelectObject( ImageTitleDC, hOldBitmap ) );
  328. }
  329. }
  330. }
  331. }
  332. }
  333. return (m_hBitmap != NULL);
  334. }