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.

469 lines
15 KiB

  1. /**************************************************************************\
  2. *
  3. * Copyright (c) 2000 Microsoft Corporation
  4. *
  5. * Module Name:
  6. *
  7. * Compatible DIBSections
  8. *
  9. * Abstract:
  10. *
  11. * Create a DIB section with an optimal format w.r.t. the specified hdc.
  12. * If the hdc format is <8bpp, returns an 8bpp DIBSection.
  13. * If the hdc format is not recognized, returns a 32bpp DIBSection.
  14. *
  15. * Notes:
  16. *
  17. * History:
  18. *
  19. * 01/23/1996 gilmanw
  20. * Created it.
  21. * 01/21/2000 agodfrey
  22. * Added it to GDI+ (from Gilman's 'fastdib.c'), and morphed it into
  23. * 'CreateSemiCompatibleDIB'.
  24. * 08/10/2000 agodfrey
  25. * Hacked it further so that if we don't understand the format, we make
  26. * a 32bpp section. Bug #96879.
  27. *
  28. \**************************************************************************/
  29. #include "precomp.hpp"
  30. #include "compatibleDIB.hpp"
  31. const DWORD AlphaMaskFromPixelFormatIndex[PIXFMT_MAX] = {
  32. 0x00000000, // PixelFormatUndefined
  33. 0x00000000, // PixelFormat1bppIndexed
  34. 0x00000000, // PixelFormat4bppIndexed
  35. 0x00000000, // PixelFormat8bppIndexed
  36. 0x00000000, // PixelFormat16bppGrayScale
  37. 0x00000000, // PixelFormat16bppRGB555
  38. 0x00000000, // PixelFormat16bppRGB565
  39. 0x00008000, // PixelFormat16bppARGB1555
  40. 0x00000000, // PixelFormat24bppRGB
  41. 0x00000000, // PixelFormat32bppRGB
  42. 0xff000000, // PixelFormat32bppARGB
  43. 0xff000000, // PixelFormat32bppPARGB
  44. 0x00000000, // PixelFormat48bppRGB
  45. 0x00000000, // PixelFormat64bppARGB
  46. 0x00000000, // PixelFormat64bppPARGB
  47. 0x00000000 // PixelFormat24bppBGR
  48. };
  49. const DWORD RedMaskFromPixelFormatIndex[PIXFMT_MAX] = {
  50. 0x00000000, // PixelFormatUndefined
  51. 0x00000000, // PixelFormat1bppIndexed
  52. 0x00000000, // PixelFormat4bppIndexed
  53. 0x00000000, // PixelFormat8bppIndexed
  54. 0x00000000, // PixelFormat16bppGrayScale
  55. 0x00007c00, // PixelFormat16bppRGB555
  56. 0x0000f800, // PixelFormat16bppRGB565
  57. 0x00007c00, // PixelFormat16bppARGB1555
  58. 0x00ff0000, // PixelFormat24bppRGB
  59. 0x00ff0000, // PixelFormat32bppRGB
  60. 0x00ff0000, // PixelFormat32bppARGB
  61. 0x00ff0000, // PixelFormat32bppPARGB
  62. 0x00000000, // PixelFormat48bppRGB
  63. 0x00000000, // PixelFormat64bppARGB
  64. 0x00000000, // PixelFormat64bppPARGB
  65. 0x000000ff // PixelFormat24bppBGR
  66. };
  67. const DWORD GreenMaskFromPixelFormatIndex[PIXFMT_MAX] = {
  68. 0x00000000, // PixelFormatUndefined
  69. 0x00000000, // PixelFormat1bppIndexed
  70. 0x00000000, // PixelFormat4bppIndexed
  71. 0x00000000, // PixelFormat8bppIndexed
  72. 0x00000000, // PixelFormat16bppGrayScale
  73. 0x000003e0, // PixelFormat16bppRGB555
  74. 0x000007e0, // PixelFormat16bppRGB565
  75. 0x000003e0, // PixelFormat16bppARGB1555
  76. 0x0000ff00, // PixelFormat24bppRGB
  77. 0x0000ff00, // PixelFormat32bppRGB
  78. 0x0000ff00, // PixelFormat32bppARGB
  79. 0x0000ff00, // PixelFormat32bppPARGB
  80. 0x00000000, // PixelFormat48bppRGB
  81. 0x00000000, // PixelFormat64bppARGB
  82. 0x00000000, // PixelFormat64bppPARGB
  83. 0x0000ff00 // PixelFormat24bppBGR
  84. };
  85. const DWORD BlueMaskFromPixelFormatIndex[PIXFMT_MAX] = {
  86. 0x00000000, // PixelFormatUndefined
  87. 0x00000000, // PixelFormat1bppIndexed
  88. 0x00000000, // PixelFormat4bppIndexed
  89. 0x00000000, // PixelFormat8bppIndexed
  90. 0x00000000, // PixelFormat16bppGrayScale
  91. 0x0000001f, // PixelFormat16bppRGB555
  92. 0x0000001f, // PixelFormat16bppRGB565
  93. 0x0000001f, // PixelFormat16bppARGB1555
  94. 0x000000ff, // PixelFormat24bppRGB
  95. 0x000000ff, // PixelFormat32bppRGB
  96. 0x000000ff, // PixelFormat32bppARGB
  97. 0x000000ff, // PixelFormat32bppPARGB
  98. 0x00000000, // PixelFormat48bppRGB
  99. 0x00000000, // PixelFormat64bppARGB
  100. 0x00000000, // PixelFormat64bppPARGB
  101. 0x00ff0000 // PixelFormat24bppBGR
  102. };
  103. /**************************************************************************\
  104. * CreatePBMIFromPixelFormat
  105. *
  106. * Fills in the fields of a BITMAPINFO so that we can create a bitmap
  107. * that matches the format of the display.
  108. *
  109. * This is done by analyzing the pixelFormat
  110. *
  111. * Arguments:
  112. * OUT pbmi : this must point to a valid BITMAPINFO structure
  113. * which has enough space for the palette (RGBQUAD array)
  114. * and MUST be zero initialized.
  115. * palette : Input palette that will be copied into the BITMAPINFO
  116. * if it's a palettized mode.
  117. * pixelFormat : Input pixel format.
  118. *
  119. *
  120. * History:
  121. * 06/07/1995 gilmanw
  122. * Created it.
  123. * 01/21/2000 agodfrey
  124. * Munged it for GDI+'s needs.
  125. * 08/11/2000 asecchia
  126. * Extracted the pixel format detection into a separate routine.
  127. * It now analyzes the pixelformat for all its data.
  128. *
  129. \**************************************************************************/
  130. static VOID
  131. CreatePBMIFromPixelFormat(
  132. OUT BITMAPINFO *pbmi,
  133. IN ColorPalette *palette,
  134. IN PixelFormatID pixelFormat
  135. )
  136. {
  137. // NOTE: Contents of pbmi should be zero initialized by the caller.
  138. ASSERT(pbmi != NULL);
  139. if(pixelFormat == PixelFormatUndefined) { return; }
  140. // GDI can't handle the following formats:
  141. ASSERT(
  142. pixelFormat != PixelFormatUndefined &&
  143. pixelFormat != PixelFormat16bppGrayScale &&
  144. pixelFormat != PixelFormat16bppARGB1555 &&
  145. pixelFormat != PixelFormat48bppRGB &&
  146. pixelFormat != PixelFormat64bppARGB &&
  147. pixelFormat != PixelFormat64bppPARGB
  148. );
  149. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  150. pbmi->bmiHeader.biWidth = 0;
  151. pbmi->bmiHeader.biHeight = 0;
  152. pbmi->bmiHeader.biPlanes = 1;
  153. pbmi->bmiHeader.biBitCount = (WORD)GetPixelFormatSize(pixelFormat);
  154. pbmi->bmiHeader.biCompression = BI_RGB;
  155. if (IsIndexedPixelFormat(pixelFormat))
  156. {
  157. // Fill the color table
  158. // If there's no palette, assume the caller is going to
  159. // set it up.
  160. if(palette)
  161. {
  162. RGBQUAD *rgb = pbmi->bmiColors;
  163. UINT i;
  164. for (i=0; i<palette->Count; i++, rgb++)
  165. {
  166. GpColor color(palette->Entries[i]);
  167. rgb->rgbRed = color.GetRed();
  168. rgb->rgbGreen = color.GetGreen();
  169. rgb->rgbBlue = color.GetBlue();
  170. }
  171. }
  172. }
  173. else
  174. {
  175. INT pfSize = GetPixelFormatSize(pixelFormat);
  176. if( (pfSize==16) || (pfSize==32) )
  177. {
  178. // BI_BITFIELDS is only valid on 16- and 32-bpp formats.
  179. pbmi->bmiHeader.biCompression = BI_BITFIELDS;
  180. }
  181. // Get the masks from the 16bpp, 24bpp and 32bpp formats.
  182. DWORD* masks = reinterpret_cast<DWORD*>(&pbmi->bmiColors[0]);
  183. INT formatIndex = GetPixelFormatIndex(pixelFormat);
  184. masks[0] = RedMaskFromPixelFormatIndex[formatIndex];
  185. masks[1] = GreenMaskFromPixelFormatIndex[formatIndex];
  186. masks[2] = BlueMaskFromPixelFormatIndex[formatIndex];
  187. }
  188. }
  189. /**************************************************************************\
  190. * CreateSemiCompatibleDIB
  191. *
  192. * Create a DIB section with an optimal format w.r.t. the specified hdc.
  193. *
  194. * If DC format <= 8bpp, creates an 8bpp section using the specified palette.
  195. * If the palette handle is NULL, then the system palette is used.
  196. *
  197. * Otherwise, if the DC format is not natively supported, creates a 32bpp
  198. * section.
  199. *
  200. * Note: The hdc must be a direct DC (not an info or memory DC).
  201. *
  202. * Arguments:
  203. *
  204. * hdc - The reference hdc
  205. * ulWidth - The width of the desired DIBSection
  206. * ulHeight - The height of the desired DIBSection
  207. * palette - The palette for <=8bpp modes
  208. * [OUT] ppvBits - A pointer to the DIBSection's bits
  209. * [OUT] pixelFormat - The pixel format of the returned DIBSection
  210. *
  211. * Returns:
  212. * Valid bitmap handle if successful, NULL if error.
  213. *
  214. * History:
  215. * 01/23/1996 gilmanw
  216. * Created it.
  217. * 01/21/2000 agodfrey
  218. * Munged it for GDI+'s needs.
  219. * 08/11/2000 asecchia
  220. * Call more general pixel format determination code.
  221. \**************************************************************************/
  222. HBITMAP
  223. CreateSemiCompatibleDIB(
  224. HDC hdc,
  225. ULONG ulWidth,
  226. ULONG ulHeight,
  227. ColorPalette *palette,
  228. PVOID *ppvBits,
  229. PixelFormatID *pixelFormat
  230. )
  231. {
  232. HBITMAP hbmRet = (HBITMAP) NULL;
  233. BYTE aj[sizeof(BITMAPINFO) + (sizeof(RGBQUAD) * 255)];
  234. BITMAPINFO *pbmi = (BITMAPINFO *) aj;
  235. ASSERT(GetDCType(hdc) == OBJ_DC);
  236. ASSERT(pixelFormat && ppvBits);
  237. // Zero initialize the pbmi. This is a requirement for
  238. // CreatePBMIFromPixelFormat()
  239. GpMemset(aj, 0, sizeof(aj));
  240. *pixelFormat = ExtractPixelFormatFromHDC(hdc);
  241. if(IsIndexedPixelFormat(*pixelFormat))
  242. {
  243. // For indexed modes, we only support 8bpp. Lower bit-depths
  244. // are supported via 8bpp mode, if at all.
  245. *pixelFormat = PixelFormat8bppIndexed;
  246. }
  247. // Not all printer HDC's have queriable palettes, the GpDevice()
  248. // constructor doesn't support it. Fake 32bpp in this case.
  249. // Also, if the format is undefined, use 32bpp, and the caller will use
  250. // GDI to do the conversion.
  251. if ( ( (GetDeviceCaps(hdc, TECHNOLOGY) == DT_RASPRINTER)
  252. && (IsIndexedPixelFormat(*pixelFormat))
  253. )
  254. || (*pixelFormat == PixelFormatUndefined)
  255. )
  256. {
  257. *pixelFormat = PixelFormat32bppRGB;
  258. }
  259. CreatePBMIFromPixelFormat(pbmi, palette, *pixelFormat);
  260. // Change bitmap size to match specified dimensions.
  261. pbmi->bmiHeader.biWidth = ulWidth;
  262. pbmi->bmiHeader.biHeight = ulHeight;
  263. if (pbmi->bmiHeader.biCompression == BI_RGB)
  264. {
  265. pbmi->bmiHeader.biSizeImage = 0;
  266. }
  267. else
  268. {
  269. if ( pbmi->bmiHeader.biBitCount == 16 )
  270. pbmi->bmiHeader.biSizeImage = ulWidth * ulHeight * 2;
  271. else if ( pbmi->bmiHeader.biBitCount == 32 )
  272. pbmi->bmiHeader.biSizeImage = ulWidth * ulHeight * 4;
  273. else
  274. pbmi->bmiHeader.biSizeImage = 0;
  275. }
  276. pbmi->bmiHeader.biClrUsed = 0;
  277. pbmi->bmiHeader.biClrImportant = 0;
  278. // Create the DIB section. Let Win32 allocate the memory and return
  279. // a pointer to the bitmap surface.
  280. hbmRet = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, ppvBits, NULL, 0);
  281. if ( !hbmRet )
  282. {
  283. ONCE(WARNING(("CreateSemiCompatibleDIB: CreateDIBSection failed")));
  284. }
  285. return hbmRet;
  286. }
  287. /**************************************************************************\
  288. * ExtractPixelFormatFromHDC
  289. *
  290. * Returns:
  291. * PixelFormatID if successful, PixelFormatUndefined if not.
  292. *
  293. * History:
  294. * 08/11/2000 asecchia
  295. * Created it.
  296. \**************************************************************************/
  297. PixelFormatID
  298. ExtractPixelFormatFromHDC(
  299. HDC hdc
  300. )
  301. {
  302. HBITMAP hbm;
  303. BOOL bRet = FALSE;
  304. PixelFormatID pixelFormat = PixelFormatUndefined;
  305. BYTE bmi_buf[sizeof(BITMAPINFO) + (sizeof(RGBQUAD) * 255)];
  306. BITMAPINFO *pbmi = (BITMAPINFO *) bmi_buf;
  307. GpMemset(bmi_buf, 0, sizeof(bmi_buf));
  308. // Create a dummy bitmap from which we can query color format info
  309. // about the device surface.
  310. if ( (hbm = CreateCompatibleBitmap(hdc, 1, 1)) != NULL )
  311. {
  312. pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  313. // Call first time to fill in BITMAPINFO header.
  314. GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS);
  315. // First handle the 'simple' case of indexed formats.
  316. if ( pbmi->bmiHeader.biBitCount <= 8 )
  317. {
  318. switch(pbmi->bmiHeader.biBitCount)
  319. {
  320. case 1: pixelFormat = PixelFormat1bppIndexed; break;
  321. case 4: pixelFormat = PixelFormat4bppIndexed; break;
  322. case 8: pixelFormat = PixelFormat8bppIndexed; break;
  323. // Fallthrough on default - the pixelFormat is already
  324. // initialized to PixelFormatUndefined.
  325. default:
  326. WARNING((
  327. "BitDepth %d from GetDIBits is not supported.",
  328. pbmi->bmiHeader.biBitCount
  329. ));
  330. }
  331. }
  332. else
  333. {
  334. DWORD redMask = 0;
  335. DWORD greenMask = 0;
  336. DWORD blueMask = 0;
  337. if ( pbmi->bmiHeader.biCompression == BI_BITFIELDS )
  338. {
  339. // Call a second time to get the color masks.
  340. // It's a GetDIBits Win32 "feature".
  341. GetDIBits(
  342. hdc,
  343. hbm,
  344. 0,
  345. pbmi->bmiHeader.biHeight,
  346. NULL,
  347. pbmi,
  348. DIB_RGB_COLORS
  349. );
  350. DWORD* masks = reinterpret_cast<DWORD*>(&pbmi->bmiColors[0]);
  351. redMask = masks[0];
  352. greenMask = masks[1];
  353. blueMask = masks[2];
  354. }
  355. else if (pbmi->bmiHeader.biCompression == BI_RGB)
  356. {
  357. redMask = 0x00ff0000;
  358. greenMask = 0x0000ff00;
  359. blueMask = 0x000000ff;
  360. }
  361. if ((redMask == 0x00ff0000) &&
  362. (greenMask == 0x0000ff00) &&
  363. (blueMask == 0x000000ff))
  364. {
  365. if (pbmi->bmiHeader.biBitCount == 24)
  366. {
  367. pixelFormat = PixelFormat24bppRGB;
  368. }
  369. else if (pbmi->bmiHeader.biBitCount == 32)
  370. {
  371. pixelFormat = PixelFormat32bppRGB;
  372. }
  373. }
  374. else if ((redMask == 0x000000ff) &&
  375. (greenMask == 0x0000ff00) &&
  376. (blueMask == 0x00ff0000) &&
  377. (pbmi->bmiHeader.biBitCount == 24))
  378. {
  379. pixelFormat = PIXFMT_24BPP_BGR;
  380. }
  381. else if ((redMask == 0x00007c00) &&
  382. (greenMask == 0x000003e0) &&
  383. (blueMask == 0x0000001f) &&
  384. (pbmi->bmiHeader.biBitCount == 16))
  385. {
  386. pixelFormat = PixelFormat16bppRGB555;
  387. }
  388. else if ((redMask == 0x0000f800) &&
  389. (greenMask == 0x000007e0) &&
  390. (blueMask == 0x0000001f) &&
  391. (pbmi->bmiHeader.biBitCount == 16))
  392. {
  393. pixelFormat = PixelFormat16bppRGB565;
  394. }
  395. }
  396. if (pixelFormat == PixelFormatUndefined)
  397. {
  398. ONCE(WARNING(("(once) ExtractPixelFormatFromHDC: Unrecognized pixel format")));
  399. }
  400. DeleteObject(hbm);
  401. }
  402. else
  403. {
  404. WARNING(("ExtractPixelFormatFromHDC: CreateCompatibleBitmap failed"));
  405. }
  406. return pixelFormat;
  407. }