fastdib.cpp
Upload User: xhy777
Upload Date: 2007-02-14
Package Size: 24088k
Code Size: 21k
Category:

Windows Kernel

Development Platform:

Visual C++

  1. /******************************Module*Header*******************************
  2. * Module Name: fastdib.c
  3. *
  4. * CreateCompatibleDIB implementation.
  5. *
  6. * Created: 23-Jan-1996 21:08:18
  7. * Author: Gilman Wong [gilmanw]
  8. *
  9. * Copyright (c) 1996 Microsoft Corporation
  10. *
  11. **************************************************************************/
  12. #include <StdAfx.h>
  13. #include <stddef.h>
  14. #include <stdio.h>
  15. #include <stdlib.h>
  16. #include "fastdib.h"
  17. static BOOL bFillBitmapInfo(HDC hdc, HPALETTE hpal, BITMAPINFO *pbmi);
  18. static BOOL bFillColorTable(HDC hdc, HPALETTE hpal, BITMAPINFO *pbmi);
  19. static UINT MyGetSystemPaletteEntries(HDC hdc, UINT iStartIndex, UINT nEntries,
  20.                                       LPPALETTEENTRY lppe);
  21. static BOOL bComputeLogicalToSurfaceMap(HDC hdc, HPALETTE hpal,
  22.                                         BYTE *pajVector);
  23. #if DBG
  24. ULONG DbgPrint(PCH DebugMessage, ...);
  25. #define DBGPRINT(str)                       DbgPrint(str)
  26. #define DBGPRINT1(str, arg1)                DbgPrint(str, arg1)
  27. #define DBGPRINT2(str, arg1, arg2)          DbgPrint(str, arg1, arg2)
  28. #define DBGPRINT3(str, arg1, arg2, arg3)    DbgPrint(str, arg1, arg2, arg3)
  29. #else
  30. #define DBGPRINT(str)
  31. #define DBGPRINT1(str, arg1)
  32. #define DBGPRINT2(str, arg1, arg2)
  33. #define DBGPRINT3(str, arg1, arg2, arg3)
  34. #endif
  35. /******************************Public*Routine******************************
  36. * CreateCompatibleDIB
  37. *
  38. * Create a DIB section with an optimal format w.r.t. the specified hdc.
  39. *
  40. * If DIB <= 8bpp, then the DIB color table is initialized based on the
  41. * specified palette.  If the palette handle is NULL, then the system
  42. * palette is used.
  43. *
  44. * Note: The hdc must be a direct DC (not an info or memory DC).
  45. *
  46. * Note: On palettized displays, if the system palette changes the
  47. *       UpdateDIBColorTable function should be called to maintain
  48. *       the identity palette mapping between the DIB and the display.
  49. *
  50. * Returns:
  51. *   Valid bitmap handle if successful, NULL if error.
  52. *
  53. * History:
  54. *  23-Jan-1996 -by- Gilman Wong [gilmanw]
  55. * Wrote it.
  56. **************************************************************************/
  57. HBITMAP APIENTRY
  58. CreateCompatibleDIB(HDC hdc, HPALETTE hpal, ULONG ulWidth, ULONG ulHeight,
  59.                     PVOID *ppvBits)
  60. {
  61.     HBITMAP hbmRet = (HBITMAP) NULL;
  62.     BYTE aj[sizeof(BITMAPINFO) + (sizeof(RGBQUAD) * 255)];
  63.     BITMAPINFO *pbmi = (BITMAPINFO *) aj;
  64.     //
  65.     // Validate hdc.
  66.     //
  67.     if ( GetObjectType(hdc) != OBJ_DC )
  68.     {
  69.         DBGPRINT("CreateCompatibleDIB: not OBJ_DCn");
  70.         return hbmRet;
  71.     }
  72.     memset(aj, 0, sizeof(aj));
  73.     if ( bFillBitmapInfo(hdc, hpal, pbmi) )
  74.     {
  75.         //
  76.         // Change bitmap size to match specified dimensions.
  77.         //
  78.         pbmi->bmiHeader.biWidth = ulWidth;
  79.         pbmi->bmiHeader.biHeight = ulHeight;
  80.         if (pbmi->bmiHeader.biCompression == BI_RGB)
  81.         {
  82.             pbmi->bmiHeader.biSizeImage = 0;
  83.         }
  84.         else
  85.         {
  86.             if ( pbmi->bmiHeader.biBitCount == 16 )
  87.                 pbmi->bmiHeader.biSizeImage = ulWidth * ulHeight * 2;
  88.             else if ( pbmi->bmiHeader.biBitCount == 32 )
  89.                 pbmi->bmiHeader.biSizeImage = ulWidth * ulHeight * 4;
  90.             else
  91.                 pbmi->bmiHeader.biSizeImage = 0;
  92.         }
  93.         pbmi->bmiHeader.biClrUsed = 0;
  94.         pbmi->bmiHeader.biClrImportant = 0;
  95.         //
  96.         // Create the DIB section.  Let Win32 allocate the memory and return
  97.         // a pointer to the bitmap surface.
  98.         //
  99.         hbmRet = CreateDIBSection(hdc, pbmi, DIB_RGB_COLORS, ppvBits, NULL, 0);
  100.         if ( !hbmRet )
  101.         {
  102.             DBGPRINT("CreateCompatibleDIB: CreateDIBSection failedn");
  103.         }
  104.     }
  105.     else
  106.     {
  107.         DBGPRINT("CreateCompatibleDIB: bFillBitmapInfo failedn");
  108.     }
  109.     return hbmRet;
  110. }
  111. /******************************Public*Routine******************************
  112. * UpdateDIBColorTable
  113. *
  114. * Synchronize the DIB color table to the specified palette hpal.
  115. * If hpal is NULL, then use the system palette.
  116. *
  117. * Returns:
  118. *   TRUE if successful, FALSE otherwise.
  119. *
  120. * History:
  121. *  23-Jan-1996 -by- Gilman Wong [gilmanw]
  122. * Wrote it.
  123. **************************************************************************/
  124. BOOL APIENTRY
  125. UpdateDIBColorTable(HDC hdcMem, HDC hdc, HPALETTE hpal)
  126. {
  127.     BOOL bRet = FALSE;
  128.     HBITMAP hbm;
  129.     DIBSECTION ds;
  130.     BYTE aj[(sizeof(RGBQUAD) + sizeof(PALETTEENTRY)) * 256];
  131.     LPPALETTEENTRY lppe = (LPPALETTEENTRY) aj;
  132.     LPRGBQUAD prgb = (LPRGBQUAD) (lppe + 256);
  133.     ULONG cColors;
  134.     //
  135.     // Validate hdc.
  136.     //
  137.     if ( GetObjectType(hdc) != OBJ_DC )
  138.     {
  139.         DBGPRINT("UpdateDIBColorTable: not OBJ_DCn");
  140.         return bRet;
  141.     }
  142.     if ( GetObjectType(hdcMem) != OBJ_MEMDC )
  143.     {
  144.         DBGPRINT("UpdateDIBColorTable: not OBJ_MEMDCn");
  145.         return bRet;
  146.     }
  147.     //
  148.     // Get the bitmap handle out of the memdc.
  149.     //
  150.     hbm = (HBITMAP)GetCurrentObject(hdcMem, OBJ_BITMAP);
  151.     //
  152.     // Validate bitmap (must be DIB section).
  153.     //
  154.     if ( (GetObject(hbm, sizeof(ds), &ds) == sizeof(ds)) &&
  155.          ds.dsBm.bmBits )
  156.     {
  157.         //
  158.         // Get palette entries from specified palette or system palette.
  159.         //
  160.         cColors = 1 << ds.dsBmih.biBitCount;
  161.         if ( hpal ? GetPaletteEntries(hpal, 0, cColors, lppe)
  162.                   : MyGetSystemPaletteEntries(hdc, 0, cColors, lppe)
  163.            )
  164.         {
  165.             UINT i;
  166.             //
  167.             // Convert to RGBQUAD.
  168.             //
  169.             for (i = 0; i < cColors; i++)
  170.             {
  171.                 prgb[i].rgbRed      = lppe[i].peRed;
  172.                 prgb[i].rgbGreen    = lppe[i].peGreen;
  173.                 prgb[i].rgbBlue     = lppe[i].peBlue;
  174.                 prgb[i].rgbReserved = 0;
  175.             }
  176.             //
  177.             // Set the DIB color table.
  178.             //
  179.             bRet = (BOOL) SetDIBColorTable(hdcMem, 0, cColors, prgb);
  180.             if (!bRet)
  181.             {
  182.                 DBGPRINT("UpdateDIBColorTable: SetDIBColorTable failedn");
  183.             }
  184.         }
  185.         else
  186.         {
  187.             DBGPRINT("UpdateDIBColorTable: MyGetSystemPaletteEntries failedn");
  188.         }
  189.     }
  190.     else
  191.     {
  192.         DBGPRINT("UpdateDIBColorTable: GetObject failedn");
  193.     }
  194.     return bRet;
  195. }
  196. /******************************Public*Routine******************************
  197. * GetCompatibleDIBInfo
  198. *
  199. * Copies pointer to bitmap origin to ppvBase and bitmap stride to plStride.
  200. * Win32 DIBs can be created bottom-up (the default) with the origin at the
  201. * lower left corner or top-down with the origin at the upper left corner.
  202. * If the bitmap is top-down, *plStride is positive; if bottom-up, *plStride
  203. * us negative.
  204. *
  205. * Also, because of restrictions on the alignment of scan lines the width
  206. * the bitmap is often not the same as the stride (stride is the number of
  207. * bytes between vertically adjacent pixels).
  208. *
  209. * The ppvBase and plStride value returned will allow you to address any
  210. * given pixel (x, y) in the bitmap as follows:
  211. *
  212. * PIXEL *ppix;
  213. *
  214. * ppix = (PIXEL *) (((BYTE *)*ppvBase) + (y * *plStride) + (x * sizeof(PIXEL)));
  215. *
  216. * Returns:
  217. *   TRUE if successful, FALSE otherwise.
  218. *
  219. * History:
  220. *  02-Feb-1996 -by- Gilman Wong [gilmanw]
  221. * Wrote it.
  222. **************************************************************************/
  223. BOOL APIENTRY
  224. GetCompatibleDIBInfo(HBITMAP hbm, PVOID *ppvBase, LONG *plStride)
  225. {
  226.     BOOL bRet = FALSE;
  227.     DIBSECTION ds;
  228.     //
  229.     // Call GetObject to return a DIBSECTION.  If successful, the
  230.     // bitmap is a DIB section and we can retrieve the pointer to
  231.     // the bitmap bits and other parameters.
  232.     //
  233.     if ( (GetObject(hbm, sizeof(ds), &ds) == sizeof(ds))
  234.          && ds.dsBm.bmBits )
  235.     {
  236.         //!!!dbug -- GDI Bug 19374: bmWidthBytes returns pitch assuming
  237.         //!!!        that DIB scanlines are WORD aligned (as they
  238.         //!!!        are in Win95).  But NT DIBs are DWORD aligned.
  239.         //!!!        When bug if corrected, we can remove this block of
  240.         //!!!        code.
  241.         #if 0
  242.         {
  243.             OSVERSIONINFO osvi;
  244.             osvi.dwOSVersionInfoSize = sizeof(osvi);
  245.             if (GetVersionEx(&osvi))
  246.             {
  247.                 if ( osvi.dwPlatformId == VER_PLATFORM_WIN32_NT )
  248.                 {
  249.                     ds.dsBm.bmWidthBytes = (ds.dsBm.bmWidthBytes + 3) & ~3;
  250.                 }
  251.             }
  252.             else
  253.             {
  254.                 DBGPRINT1("GetCompatibleDIBInfo: GetVersionEx failed with %dn", GetLastError());
  255.                 return bRet;
  256.             }
  257.         }
  258.         #endif
  259.         //
  260.         // If biHeight is positive, then the bitmap is a bottom-up DIB.
  261.         // If biHeight is negative, then the bitmap is a top-down DIB.
  262.         //
  263.         if ( ds.dsBmih.biHeight > 0 )
  264.         {
  265.             *ppvBase  = (PVOID) (((int) ds.dsBm.bmBits) + (ds.dsBm.bmWidthBytes * (ds.dsBm.bmHeight - 1)));
  266.             *plStride = (ULONG) (-ds.dsBm.bmWidthBytes);
  267.         }
  268.         else
  269.         {
  270.             *ppvBase  = ds.dsBm.bmBits;
  271.             *plStride = ds.dsBm.bmWidthBytes;
  272.         }
  273.         bRet = TRUE;
  274.     }
  275.     else
  276.     {
  277.         DBGPRINT("GetCompatibleDIBInfo: cannot get pointer to DIBSECTION bmBitsn");
  278.     }
  279.     return bRet;
  280. }
  281. /******************************Public*Routine******************************
  282. * GetDIBTranslationVector
  283. *
  284. * Copies the translation vector that maps colors in the specified palette,
  285. * hpal, to the DIB selected into the specified DC, hdcMem.
  286. *
  287. * Returns:
  288. *   TRUE if successful, FALSE otherwise.
  289. *
  290. * History:
  291. *  02-Feb-1996 -by- Gilman Wong [gilmanw]
  292. * Wrote it.
  293. **************************************************************************/
  294. BOOL APIENTRY
  295. GetDIBTranslationVector(HDC hdcMem, HPALETTE hpal, BYTE *pbVector)
  296. {
  297.     BOOL bRet = FALSE;
  298.     HBITMAP hbm;
  299.     DIBSECTION ds;
  300.     //
  301.     // Validate parameters.
  302.     //
  303.     if ( GetObjectType(hdcMem) != OBJ_MEMDC ||
  304.          GetObjectType(hpal) != OBJ_PAL ||
  305.          !pbVector )
  306.     {
  307.         DBGPRINT("GetDIBTranslationVector: bad parametern");
  308.         return bRet;
  309.     }
  310.     //
  311.     // The function bComputeLogicalToSurfaceMap cannot handle palettes
  312.     // greater than 256 entries.
  313.     //
  314.     if ( GetPaletteEntries(hpal, 0, 1, NULL) > 256 )
  315.     {
  316.         DBGPRINT("GetDIBTranslationVector: palette too bign");
  317.         return bRet;
  318.     }
  319.     //
  320.     // The DIB must have a color table.
  321.     //
  322.     hbm = (HBITMAP)GetCurrentObject(hdcMem, OBJ_BITMAP);
  323.     if ( (GetObject(hbm, sizeof(ds), &ds) == sizeof(ds))
  324.          && (ds.dsBmih.biBitCount <= 8) )
  325.     {
  326.         bRet = bComputeLogicalToSurfaceMap(hdcMem, hpal, pbVector);
  327.     }
  328.     else
  329.     {
  330.         DBGPRINT("GetDIBTranslationVector: not a DIB sectionn");
  331.         return bRet;
  332.     }
  333.     return bRet;
  334. }
  335. //////////////////// Below here are internal-only routines ////////////////////
  336. /******************************Public*Routine******************************
  337. * bFillBitmapInfo
  338. *
  339. * Fills in the fields of a BITMAPINFO so that we can create a bitmap
  340. * that matches the format of the display.
  341. *
  342. * This is done by creating a compatible bitmap and calling GetDIBits
  343. * to return the color masks.  This is done with two calls.  The first
  344. * call passes in biBitCount = 0 to GetDIBits which will fill in the
  345. * base BITMAPINFOHEADER data.  The second call to GetDIBits (passing
  346. * in the BITMAPINFO filled in by the first call) will return the color
  347. * table or bitmasks, as appropriate.
  348. *
  349. * Returns:
  350. *   TRUE if successful, FALSE otherwise.
  351. *
  352. * History:
  353. *  07-Jun-1995 -by- Gilman Wong [gilmanw]
  354. * Wrote it.
  355. **************************************************************************/
  356. static BOOL
  357. bFillBitmapInfo(HDC hdc, HPALETTE hpal, BITMAPINFO *pbmi)
  358. {
  359.     HBITMAP hbm;
  360.     BOOL    bRet = FALSE;
  361.     //
  362.     // Create a dummy bitmap from which we can query color format info
  363.     // about the device surface.
  364.     //
  365.     if ( (hbm = CreateCompatibleBitmap(hdc, 1, 1)) != NULL )
  366.     {
  367.         pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  368.         //
  369.         // Call first time to fill in BITMAPINFO header.
  370.         //
  371.         GetDIBits(hdc, hbm, 0, 0, NULL, pbmi, DIB_RGB_COLORS);
  372.         if ( pbmi->bmiHeader.biBitCount <= 8 )
  373.         {
  374.             bRet = bFillColorTable(hdc, hpal, pbmi);
  375.         }
  376.         else
  377.         {
  378.             if ( pbmi->bmiHeader.biCompression == BI_BITFIELDS )
  379.             {
  380.                 //
  381.                 // Call a second time to get the color masks.
  382.                 // It's a GetDIBits Win32 "feature".
  383.                 //
  384.                 GetDIBits(hdc, hbm, 0, pbmi->bmiHeader.biHeight, NULL, pbmi,
  385.                           DIB_RGB_COLORS);
  386.             }
  387.             bRet = TRUE;
  388.         }
  389.         DeleteObject(hbm);
  390.     }
  391.     else
  392.     {
  393.         DBGPRINT("bFillBitmapInfo: CreateCompatibleBitmap failedn");
  394.     }
  395.     return bRet;
  396. }
  397. /******************************Public*Routine******************************
  398. * bFillColorTable
  399. *
  400. * Initialize the color table of the BITMAPINFO pointed to by pbmi.  Colors
  401. * are set to the current system palette.
  402. *
  403. * Note: call only valid for displays of 8bpp or less.
  404. *
  405. * Returns:
  406. *   TRUE if successful, FALSE otherwise.
  407. *
  408. * History:
  409. *  23-Jan-1996 -by- Gilman Wong [gilmanw]
  410. * Wrote it.
  411. **************************************************************************/
  412. static BOOL
  413. bFillColorTable(HDC hdc, HPALETTE hpal, BITMAPINFO *pbmi)
  414. {
  415.     BOOL bRet = FALSE;
  416.     BYTE aj[sizeof(PALETTEENTRY) * 256];
  417.     LPPALETTEENTRY lppe = (LPPALETTEENTRY) aj;
  418.     RGBQUAD *prgb = (RGBQUAD *) &pbmi->bmiColors[0];
  419.     ULONG cColors;
  420.     cColors = 1 << pbmi->bmiHeader.biBitCount;
  421.     if ( cColors <= 256 )
  422.     {
  423.         if ( hpal ? GetPaletteEntries(hpal, 0, cColors, lppe)
  424.                   : MyGetSystemPaletteEntries(hdc, 0, cColors, lppe) )
  425.         {
  426.             UINT i;
  427.             for (i = 0; i < cColors; i++)
  428.             {
  429.                 prgb[i].rgbRed      = lppe[i].peRed;
  430.                 prgb[i].rgbGreen    = lppe[i].peGreen;
  431.                 prgb[i].rgbBlue     = lppe[i].peBlue;
  432.                 prgb[i].rgbReserved = 0;
  433.             }
  434.             bRet = TRUE;
  435.         }
  436.         else
  437.         {
  438.             DBGPRINT("bFillColorTable: MyGetSystemPaletteEntries failedn");
  439.         }
  440.     }
  441.     return bRet;
  442. }
  443. /******************************Public*Routine******************************
  444. * MyGetSystemPaletteEntries
  445. *
  446. * Internal version of GetSystemPaletteEntries.
  447. *
  448. * GetSystemPaletteEntries fails on some 4bpp devices.  This version
  449. * will detect the 4bpp case and supply the hardcoded 16-color VGA palette.
  450. * Otherwise, it will pass the call on to GDI's GetSystemPaletteEntries.
  451. *
  452. * It is expected that this call will only be called in the 4bpp and 8bpp
  453. * cases as it is not necessary for OpenGL to query the system palette
  454. * for > 8bpp devices.
  455. *
  456. * History:
  457. *  17-Aug-1995 -by- Gilman Wong [gilmanw]
  458. * Wrote it.
  459. **************************************************************************/
  460. static PALETTEENTRY gapeVgaPalette[16] =
  461. {
  462.     { 0,   0,   0,    0 },
  463.     { 0x80,0,   0,    0 },
  464.     { 0,   0x80,0,    0 },
  465.     { 0x80,0x80,0,    0 },
  466.     { 0,   0,   0x80, 0 },
  467.     { 0x80,0,   0x80, 0 },
  468.     { 0,   0x80,0x80, 0 },
  469.     { 0x80,0x80,0x80, 0 },
  470.     { 0xC0,0xC0,0xC0, 0 },
  471.     { 0xFF,0,   0,    0 },
  472.     { 0,   0xFF,0,    0 },
  473.     { 0xFF,0xFF,0,    0 },
  474.     { 0,   0,   0xFF, 0 },
  475.     { 0xFF,0,   0xFF, 0 },
  476.     { 0,   0xFF,0xFF, 0 },
  477.     { 0xFF,0xFF,0xFF, 0 }
  478. };
  479. static UINT
  480. MyGetSystemPaletteEntries(HDC hdc, UINT iStartIndex, UINT nEntries,
  481.                           LPPALETTEENTRY lppe)
  482. {
  483.     int nDeviceBits;
  484.     nDeviceBits = GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
  485.     //
  486.     // Some 4bpp displays will fail the GetSystemPaletteEntries call.
  487.     // So if detected, return the hardcoded table.
  488.     //
  489.     if ( nDeviceBits == 4 )
  490.     {
  491.         if ( lppe )
  492.         {
  493.             nEntries = min(nEntries, (16 - iStartIndex));
  494.             memcpy(lppe, &gapeVgaPalette[iStartIndex],
  495.                    nEntries * sizeof(PALETTEENTRY));
  496.         }
  497.         else
  498.             nEntries = 16;
  499.         return nEntries;
  500.     }
  501.     else
  502.     {
  503.         return GetSystemPaletteEntries(hdc, iStartIndex, nEntries, lppe);
  504.     }
  505. }
  506. /******************************Public*Routine******************************
  507. * bComputeLogicalToSurfaceMap
  508. *
  509. * Copy logical palette to surface palette translation vector to the buffer
  510. * pointed to by pajVector.  The logical palette is specified by hpal.  The
  511. * surface is specified by hdc.
  512. *
  513. * Note: The hdc may identify either a direct (display) dc or a DIB memory dc.
  514. * If hdc is a display dc, then the surface palette is the system palette.
  515. * If hdc is a memory dc, then the surface palette is the DIB color table.
  516. *
  517. * History:
  518. *  27-Jan-1996 -by- Gilman Wong [gilmanw]
  519. * Wrote it.
  520. **************************************************************************/
  521. static BOOL bComputeLogicalToSurfaceMap(HDC hdc, HPALETTE hpal, BYTE *pajVector)
  522. {
  523.     BOOL bRet = FALSE;
  524.     HPALETTE hpalSurf;
  525.     ULONG cEntries, cSysEntries;
  526.     DWORD dwDcType = GetObjectType(hdc);
  527.     LPPALETTEENTRY lppeTmp, lppeEnd;
  528.     BYTE aj[sizeof(LOGPALETTE) + (sizeof(PALETTEENTRY) * 512) + (sizeof(RGBQUAD) * 256)];
  529.     LOGPALETTE *ppal = (LOGPALETTE *) aj;
  530.     LPPALETTEENTRY lppeSurf = &ppal->palPalEntry[0];
  531.     LPPALETTEENTRY lppe = lppeSurf + 256;
  532.     RGBQUAD *prgb = (RGBQUAD *) (lppe + 256);
  533.     //
  534.     // Determine number of colors in each palette.
  535.     //
  536.     cEntries = GetPaletteEntries(hpal, 0, 1, NULL);
  537.     if ( dwDcType == OBJ_DC )
  538.         cSysEntries = MyGetSystemPaletteEntries(hdc, 0, 1, NULL);
  539.     else
  540.         cSysEntries = 256;
  541.     //
  542.     // Get the logical palette entries.
  543.     //
  544.     cEntries = GetPaletteEntries(hpal, 0, cEntries, lppe);
  545.     //
  546.     // Get the surface palette entries.
  547.     //
  548.     if ( dwDcType == OBJ_DC )
  549.     {
  550.         cSysEntries = MyGetSystemPaletteEntries(hdc, 0, cSysEntries, lppeSurf);
  551.         lppeTmp = lppeSurf;
  552.         lppeEnd = lppeSurf + cSysEntries;
  553.         for (; lppeTmp < lppeEnd; lppeTmp++)
  554.             lppeTmp->peFlags = 0;
  555.     }
  556.     else
  557.     {
  558.         RGBQUAD *prgbTmp;
  559.         //
  560.         // First get RGBQUADs from DIB color table...
  561.         //
  562.         cSysEntries = GetDIBColorTable(hdc, 0, cSysEntries, prgb);
  563.         //
  564.         // ...then convert RGBQUADs into PALETTEENTRIES.
  565.         //
  566.         prgbTmp = prgb;
  567.         lppeTmp = lppeSurf;
  568.         lppeEnd = lppeSurf + cSysEntries;
  569.         while ( lppeTmp < lppeEnd )
  570.         {
  571.             lppeTmp->peRed   = prgbTmp->rgbRed;
  572.             lppeTmp->peGreen = prgbTmp->rgbGreen;
  573.             lppeTmp->peBlue  = prgbTmp->rgbBlue;
  574.             lppeTmp->peFlags = 0;
  575.             lppeTmp++;
  576.             prgbTmp++;
  577.         }
  578.     }
  579.     //
  580.     // Construct a translation vector by using GetNearestPaletteIndex to
  581.     // map each entry in the logical palette to the surface palette.
  582.     //
  583.     if ( cEntries && cSysEntries )
  584.     {
  585.         //
  586.         // Create a temporary logical palette that matches the surface
  587.         // palette retrieved above.
  588.         //
  589.         ppal->palVersion = 0x300;
  590.         ppal->palNumEntries = (USHORT) cSysEntries;
  591.         if ( hpalSurf = CreatePalette(ppal) )
  592.         {
  593.             //
  594.             // Translate each logical palette entry into a surface palette
  595.             // index.
  596.             //
  597.             lppeTmp = lppe;
  598.             lppeEnd = lppe + cEntries;
  599.             for ( ; lppeTmp < lppeEnd; lppeTmp++, pajVector++)
  600.             {
  601.                 *pajVector = (BYTE) GetNearestPaletteIndex(
  602.                                         hpalSurf,
  603.                                         RGB(lppeTmp->peRed,
  604.                                             lppeTmp->peGreen,
  605.                                             lppeTmp->peBlue)
  606.                                         );
  607.             }
  608.             bRet = TRUE;
  609.             DeleteObject(hpalSurf);
  610.         }
  611.         else
  612.         {
  613.             DBGPRINT("bComputeLogicalToSurfaceMap: CreatePalette failedn");
  614.         }
  615.     }
  616.     else
  617.     {
  618.         DBGPRINT("bComputeLogicalToSurfaceMap: failed to get pal infon");
  619.     }
  620.     return bRet;
  621. }
  622. #if DBG
  623. /******************************Public*Routine******************************
  624. * DbgPrint
  625. *
  626. * Formatted string output to the debugger.
  627. *
  628. * History:
  629. *  26-Jan-1996 -by- Gilman Wong [gilmanw]
  630. * Wrote it.
  631. **************************************************************************/
  632. ULONG
  633. DbgPrint(PCH DebugMessage, ...)
  634. {
  635.     va_list ap;
  636.     char buffer[256];
  637.     va_start(ap, DebugMessage);
  638.     vsprintf(buffer, DebugMessage, ap);
  639.     OutputDebugStringA(buffer);
  640.     va_end(ap);
  641.     return(0);
  642. }
  643. #endif