home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / gdi / mandel / dibmp.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  26KB  |  870 lines

  1. /******************************Module*Header*******************************\
  2. * Module Name: dibmp.c
  3. *
  4. * Contains functions that manipulate the DIB color
  5. *
  6. * Copyright (C) 1993-1997 Microsoft Corporation
  7. *
  8. * These functions will be called from the ChildWndProc() as it processes
  9. * the corresponding WM_COMMAND message for changing the color of the bitmap.
  10. *
  11. * iCreatePenFrPal() is called by InitializeApp() for creating pens based on
  12. * either system or custom palette.
  13. *
  14. * Dependencies:
  15. *       none
  16. *
  17. \**************************************************************************/
  18. #include <windows.h>
  19. #include <stdio.h>
  20. #include "julia.h"
  21. #include "dibmp.h"
  22.  
  23. #define CYCLETHRD
  24.  
  25. //#define DEBUG
  26.  
  27. #ifndef DEBUG
  28.    #undef OutputDebugString
  29.    #define OutputDebugString(LPCSTR)
  30. #endif
  31.  
  32. extern HPALETTE        ghPal, ghPalOld;
  33. extern HWND ghwndMain;
  34. extern HWND ghwndClient;
  35. extern HANDLE hQuitEvent;
  36. extern char   gtext[256];
  37. extern HANDLE ghAccel;
  38. BOOL bValidMode(INT);
  39. BOOL bColor2BW(PBITMAPINFO);
  40. BOOL bChangeDIBColor(HDC, PINFO, INT);
  41. BOOL bColorShift(PBITMAPINFO);
  42. BOOL bColorReplace(PBITMAPINFO);
  43. BOOL bColorCycle(HDC, RECT, PBYTE, PBITMAPINFO, PINFO);
  44. BOOL bCycle(HWND);
  45. BOOL bColor2Mono(HDC, PINFO, PBITMAPINFO);
  46. INT  iCreatePenFrPal(HDC, PVOID *, INT, HPALETTE *);
  47. HPALETTE CopyPalette(HPALETTE);
  48. extern PINFO pGetInfoData(HWND);
  49. extern BOOL bReleaseInfoData(HWND);
  50.  
  51. /******************************Public*Routine******************************\
  52. *
  53. * bChangeDIBColor
  54. *
  55. * Effects: Main entry point for the color changing operations.  It
  56. *          1. validates the operation
  57. *          2. retrieves the bitmap info from the graphics engine
  58. *          3. dispatches the call to the right function
  59. *          4. saves the resulting bitmap
  60. *          5. updates the screen
  61. \**************************************************************************/
  62. BOOL bChangeDIBColor(HDC hDC, PINFO pInfo, INT iMode)
  63. {
  64.     BOOL                 bSuccess;
  65.     HBITMAP              hTmpBmp, hBmpOld;
  66.     PBITMAPINFO          pbmi;
  67.     PBYTE                pBits;
  68.     BITMAPINFO           bmi;
  69.     PBYTE                pjTmp, pjTmpBmi;
  70.     ULONG                sizBMI;
  71.     RECT                 rc;
  72.     BOOL                 bCycle;
  73.  
  74.  
  75.     bSuccess = TRUE;
  76.     if (!pInfo->hBmpSaved) 
  77.     {
  78.         MessageBox(ghwndMain, GetStringRes(IDS_NO_BITMAP), NULL, MB_OK);
  79.         return FALSE;
  80.     }
  81.  
  82.     if (!bValidMode(iMode)) 
  83.     {
  84.         OutputDebugString ("bChangeDIBColor: invalid mode!");
  85.         return FALSE;
  86.     }
  87.  
  88.     if (pInfo->hPal) {
  89.         HPALETTE hPalOld;
  90.         int     ii;
  91.  
  92.         hPalOld = SelectPalette(hDC, pInfo->hPal, FALSE);
  93.         ii = RealizePalette(hDC);
  94.  
  95.         if (ii){
  96.             UpdateColors (hDC);
  97.         }
  98.  
  99.     }
  100.  
  101.     //
  102.     // Let the graphics engine to retrieve the dimension of the bitmap for us
  103.     // GetDIBits uses the size to determine if it's BITMAPCOREINFO or BITMAPINFO
  104.     // if BitCount != 0, color table will be retrieved
  105.     //
  106.     bmi.bmiHeader.biSize = 0x28;              // GDI need this to work
  107.     bmi.bmiHeader.biBitCount = 0;             // don't get the color table
  108.     if ((GetDIBits(hDC, pInfo->hBmpSaved, 0, 0, (LPSTR)NULL, &bmi, DIB_RGB_COLORS)) == 0) 
  109.     {
  110.         OutputDebugString ("GetDIBits failed!");
  111.         return FALSE;
  112.     }
  113.  
  114.     //
  115.     // Now that we know the size of the image, alloc enough memory to retrieve
  116.     // the actual bits
  117.     //
  118.     if ((pBits = (PBYTE)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
  119.                 bmi.bmiHeader.biSizeImage)) == NULL) 
  120.     {
  121.         return FALSE;
  122.     }
  123.  
  124.     //
  125.     // Note: 24 bits per pixel has no color table.  So, we don't have to
  126.     // allocate memory for retrieving that.  Otherwise, we do.
  127.     //
  128.     pbmi = &bmi;                                      // assume no color table
  129.     if (bmi.bmiHeader.biBitCount != 24) {             // has color table
  130.         sizBMI = sizeof(BITMAPINFO)+sizeof(RGBQUAD)*(1<<bmi.bmiHeader.biBitCount);
  131.         //
  132.         // I need more memory for the color table
  133.         //
  134.         if ((pbmi = (PBITMAPINFO)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, sizBMI )) == NULL) 
  135.         {
  136.             bSuccess = FALSE;
  137.             goto ErrExit1;
  138.         }
  139.  
  140.         //
  141.         // Now that we've a bigger chunk of memory, let's copy the Bitmap
  142.         // info header data over
  143.         //
  144.         pjTmp = (PBYTE)pbmi;
  145.         pjTmpBmi = (PBYTE)&bmi;
  146.         sizBMI = sizeof(BITMAPINFOHEADER);
  147.  
  148.         while(sizBMI--)
  149.         {
  150.             *(((PBYTE)pjTmp)++) = *((pjTmpBmi)++);
  151.         }
  152.  
  153.     }
  154.  
  155.     //
  156.     // Bitmap can't be selected into a DC when calling GetDIBits
  157.     // Assume that the hDC is the DC where the bitmap would have been selected
  158.     // if indeed it has been selected
  159.     //
  160.     if (hTmpBmp = CreateCompatibleBitmap(hDC, pbmi->bmiHeader.biWidth, pbmi->bmiHeader.biHeight)) {
  161.         hBmpOld = SelectObject(hDC, hTmpBmp);
  162.         if ((GetDIBits(hDC, pInfo->hBmpSaved, 0, pbmi->bmiHeader.biHeight, (LPSTR)pBits, pbmi, DIB_RGB_COLORS))==0)
  163.         {
  164.             bSuccess = FALSE;
  165.             goto ErrExit4;
  166.         }
  167.     } else 
  168.     {
  169.         OutputDebugString ("Failed in creating bitmap!");
  170.         bSuccess = FALSE;
  171.         goto ErrExit3;
  172.     }
  173.  
  174.     bCycle = FALSE;
  175.     switch (iMode) {
  176.         case MM_BW:
  177.             if ((!bColor2Mono(hDC, pInfo, pbmi)) ||
  178.                 (pInfo->hBmpMono == NULL)) 
  179.             {
  180.                 OutputDebugString ("Failed in Color2Mono!");
  181.                 bSuccess = FALSE;
  182.                 goto ErrExit4;
  183.             }
  184.             pInfo->bUseMono = TRUE;
  185.             break;
  186.         case MM_SHIFT:
  187.  
  188.             if (!bColorShift(pbmi)) 
  189.             {
  190.                 OutputDebugString ("Failed in ColorShift!");
  191.                 bSuccess = FALSE;
  192.                 goto ErrExit4;
  193.             }
  194.             break;
  195.         case MM_CUSTOM:
  196.             bColorReplace(pbmi);
  197.             break;
  198.  
  199.         case MM_CYCLE:
  200.             bCycle = TRUE;
  201.             break;
  202.  
  203.         default:
  204.             bSuccess = FALSE;
  205.             break;
  206.     }
  207.  
  208.     if (SetDIBits(hDC, pInfo->hBmpSaved, 0, pbmi->bmiHeader.biHeight, (LPSTR)pBits,
  209.             pbmi, DIB_RGB_COLORS) == 0) 
  210.     {
  211.         bSuccess = FALSE;
  212.         goto ErrExit4;
  213.     }
  214.  
  215.     if (bCycle)
  216.         pInfo->bSetDIBsToDevice = TRUE;
  217.  
  218. #if 0
  219.     if (pInfo->bSetDIBsToDevice && !pInfo->bUseMono) {
  220.         //GetWindowRect(pInfo->hwnd, &rc);
  221.         GetClientRect(pInfo->hwnd, &rc);
  222.         //SetMapMode(hDC, MM_TEXT);
  223.  
  224.         //if (SetDIBitsToDevice(hDC, 0, 0, rc.right-rc.left, rc.bottom-rc.top,
  225.         //     0, 0, 0, pbmi->bmiHeader.biHeight, (LPSTR)pBits, pbmi, DIB_RGB_COLORS) == 0) {
  226.         //    MessageBox(ghwndMain, "Failed in SetDIBitsToDevice!", "Error", MB_OK);
  227.         //    MessageBox(ghwndMain, "SetDIBitsToDevice é┼âGâëü[é¬ö¡É╢é╡é▄é╡é╜!", "âGâëü[", MB_OK);
  228.         //    bSuccess = FALSE;
  229.         //    goto ErrExit4;
  230.         //}
  231.     } else 
  232.     {
  233. #endif
  234.         InvalidateRect(pInfo->hwnd, NULL, FALSE);
  235. //  }
  236.  
  237.     if (bCycle) {
  238.         //
  239.         // This is commented out because I don't want the system colors
  240.         // be affected by color cycling
  241.         //
  242.         //SetSystemPaletteUse(hDC, SYSPAL_NOSTATIC);
  243.         bColorCycle(hDC, rc, pBits, pbmi, pInfo);
  244.         //SetSystemPaletteUse(hDC, SYSPAL_STATIC);
  245.     }
  246.  
  247. ErrExit4:
  248.     SelectObject(hDC, hBmpOld);
  249.     DeleteObject(hTmpBmp);
  250. ErrExit3:
  251.     GlobalFree(pbmi);
  252. ErrExit1:
  253.     GlobalFree(pBits);
  254.     return bSuccess;
  255. }
  256.  
  257.  
  258. /******************************Public*Routine******************************\
  259. *
  260. * bValidMode
  261. *
  262. * Effects: validates the change mode for ChangeDIBColor function
  263. *          returns TRUE if mode is valid.  Otherwise, FALSE
  264. \**************************************************************************/
  265. BOOL bValidMode(INT iMode)
  266. {
  267.     if ((iMode == MM_BW)     || (iMode == MM_SHIFT) ||
  268.         (iMode == MM_CUSTOM) || (iMode == MM_CYCLE))
  269.         return TRUE;
  270.     else
  271.         return FALSE;
  272. }
  273.  
  274. /******************************Public*Routine******************************\
  275. *
  276. * bColor2BW
  277. *
  278. * Effects: changes the color table in the bitmapinfo to black and white
  279. *
  280. * Warnings: doesn't check if pbmi is valid or not
  281. \**************************************************************************/
  282. BOOL bColor2BW(PBITMAPINFO pbmi)
  283. {
  284.     INT iEntry;
  285.  
  286.     //
  287.     // CR! What's the right behavior?  Maybe I should convert this to a
  288.     // monochrome bitmap.  This will be very useful in MaskBlt().
  289.     //
  290.     iEntry = 1<<pbmi->bmiHeader.biBitCount;
  291.     while (--iEntry >= 0) {
  292.         if (iEntry <= iEntry / 2) {
  293.                 pbmi->bmiColors[iEntry].rgbBlue     = 0x00;
  294.                 pbmi->bmiColors[iEntry].rgbGreen    = 0x00;
  295.                 pbmi->bmiColors[iEntry].rgbRed      = 0x00;
  296.                 pbmi->bmiColors[iEntry].rgbReserved = 0x00;
  297.          } else {
  298.                 pbmi->bmiColors[iEntry].rgbBlue     = 0xFF;
  299.                 pbmi->bmiColors[iEntry].rgbGreen    = 0xFF;
  300.                 pbmi->bmiColors[iEntry].rgbRed      = 0xFF;
  301.                 pbmi->bmiColors[iEntry].rgbReserved = 0x00;
  302.         }
  303.     }
  304.     return TRUE;
  305. }
  306.  
  307.  
  308. /******************************Public*Routine******************************\
  309. *
  310. * bColorShift
  311. *
  312. * Effects: Shifting entries of the color table
  313. *
  314. \**************************************************************************/
  315.  
  316. BOOL bColorShift(PBITMAPINFO pbmi)
  317. {
  318.     INT iEntry;
  319.     RGBQUAD     Tmp;
  320.  
  321.     iEntry = 1<<pbmi->bmiHeader.biBitCount;
  322.  
  323.     Tmp.rgbBlue     = pbmi->bmiColors[iEntry-1].rgbBlue;
  324.     Tmp.rgbGreen    = pbmi->bmiColors[iEntry-1].rgbGreen;
  325.     Tmp.rgbRed      = pbmi->bmiColors[iEntry-1].rgbRed;
  326.     Tmp.rgbReserved = pbmi->bmiColors[iEntry-1].rgbReserved;
  327.  
  328.     while (--iEntry > 0) {
  329.          pbmi->bmiColors[iEntry].rgbBlue     =
  330.             pbmi->bmiColors[iEntry-1].rgbBlue;
  331.          pbmi->bmiColors[iEntry].rgbGreen    =
  332.             pbmi->bmiColors[iEntry-1].rgbGreen;
  333.          pbmi->bmiColors[iEntry].rgbRed      =
  334.             pbmi->bmiColors[iEntry-1].rgbRed;
  335.          pbmi->bmiColors[iEntry].rgbReserved =
  336.             pbmi->bmiColors[iEntry-1].rgbReserved;
  337.     }
  338.     pbmi->bmiColors[0].rgbBlue     = Tmp.rgbBlue;
  339.     pbmi->bmiColors[0].rgbGreen    = Tmp.rgbGreen;
  340.     pbmi->bmiColors[0].rgbRed      = Tmp.rgbRed;
  341.     pbmi->bmiColors[0].rgbReserved = Tmp.rgbReserved;
  342.     return TRUE;
  343.  
  344. }
  345.  
  346. BOOL bColorReplace(PBITMAPINFO pbmi)
  347. {
  348.     return FALSE;
  349.     UNREFERENCED_PARAMETER(pbmi);
  350. }
  351.  
  352. /******************************Public*Routine******************************\
  353. *
  354. * bColorCycle
  355. *
  356. * Effects:  Create a logical palette with a good spread of color
  357. *           Animate the palette, shift the palette entries and animate
  358. *           again for 256 times altogether.
  359. *           This creates the color cycling effect.
  360. *
  361. * Warnings: Only works in device that support palette.
  362. \**************************************************************************/
  363.  
  364. BOOL bColorCycle(HDC hDC, RECT rc, PBYTE pBits, PBITMAPINFO pbmi, PINFO pInfo)
  365. {
  366.     INT             iEntry, i, iNumClr;
  367.     PLOGPALETTE     plogPat;
  368.     ULONG           ulSize;
  369.     BOOL            bSuccess;
  370.     HPALETTE        hPal, hPalOld;
  371.     PALETTEENTRY    peTemp;
  372.  
  373. #ifdef CYCLETHRD
  374.     DWORD           dwWait;
  375. #else
  376.     MSG             msg;
  377. #endif
  378.     BOOL            bQuit;
  379.  
  380. //UINT uRC;
  381.  
  382.     bSuccess = TRUE;
  383.     iEntry = 1<<pbmi->bmiHeader.biBitCount;
  384.  
  385.     iNumClr = 236;          // 256 minus 20 reserved colors
  386.     ulSize = sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*256;
  387.  
  388.     if ((plogPat = (PLOGPALETTE) GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, ulSize)) == NULL) 
  389.     {
  390.         bSuccess = FALSE;
  391.         goto ErrExit1;
  392.     }
  393.  
  394.     plogPat->palVersion = 0x300;
  395.     plogPat->palNumEntries = (WORD) 256;
  396.  
  397.     {
  398.     int     iFirst, iSecond, iInc;
  399.  
  400.         iFirst = iNumClr/3;
  401.         iSecond = iFirst * 2;
  402.         iInc = (iNumClr <= 256) ? 3 : 1;
  403.  
  404.         for (i = 0; i < iNumClr; i++) {
  405.             if (i < iFirst) {
  406.                 plogPat->palPalEntry[i+10].peBlue   = 255-(i+1)*iInc;
  407.                 plogPat->palPalEntry[i+10].peGreen  = 0;
  408.                 plogPat->palPalEntry[i+10].peRed    = (i+1)*iInc;
  409.                 plogPat->palPalEntry[i+10].peFlags  = PC_RESERVED;
  410.                 continue;
  411.             }
  412.             if (i < iSecond) {
  413.                 plogPat->palPalEntry[i+10].peBlue   = 0;
  414.                 plogPat->palPalEntry[i+10].peGreen  = (i+1-iFirst)*iInc;
  415.                 plogPat->palPalEntry[i+10].peRed    = 255-(i+1-iFirst)*iInc;
  416.                 plogPat->palPalEntry[i+10].peFlags  = PC_RESERVED;
  417.                 continue;
  418.             }
  419.             plogPat->palPalEntry[i+10].peBlue   = (i+1-iSecond)*iInc;
  420.             plogPat->palPalEntry[i+10].peGreen  = 255-(i+1-iSecond)*iInc;
  421.             plogPat->palPalEntry[i+10].peRed    = 0;
  422.             plogPat->palPalEntry[i+10].peFlags  = PC_RESERVED;
  423.         }
  424.     }
  425.  
  426.     if ((hPal = CreatePalette(plogPat)) == (HPALETTE) NULL) 
  427.     {
  428.         bSuccess = FALSE;
  429.         goto ErrExit2;
  430.     }
  431.  
  432.     pInfo->hCyclePal = hPal;
  433.  
  434.     hPalOld = SelectPalette(hDC, hPal, FALSE);
  435.     RealizePalette(hDC);
  436.  
  437.  
  438. #ifndef CYCLETHRD
  439.  
  440.     bQuit = FALSE;
  441.     while (TRUE && !bQuit) {
  442.  
  443.         if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  444.             //sprintf( gtext,"msg = %lx\n", msg.message);
  445.             //OutputDebugString( gtext );
  446.  
  447.             if ((msg.message == WM_QUIT) || (msg.message == WM_CLOSE) ||
  448.                 ((msg.message == WM_SYSCOMMAND) && (msg.wParam == SC_CLOSE))) {
  449.                 sprintf( gtext,"msg = %lx, wPram = %lx\n", msg.message, msg.wParam);
  450.                 OutputDebugString( gtext );
  451.                 bQuit = TRUE;
  452.                 PostMessage(msg.hwnd, msg.message, msg.wParam, msg.lParam);
  453.             } else {
  454.                 if (!TranslateAccelerator( ghwndMain, ghAccel, &msg) &&
  455.                     !TranslateMDISysAccel(  ghwndClient, &msg)          ) {
  456.                     TranslateMessage(&msg);
  457.                     DispatchMessage(&msg);
  458.                 }
  459.            }
  460.         }
  461.  
  462. #else
  463.     bQuit = FALSE;
  464.     while (TRUE) {
  465.         //
  466.         // If parent gets a WM_CLOSE, we will return
  467.         //
  468.         dwWait = WaitForSingleObject(pInfo->hQuitEvent, 0);
  469.         if (dwWait == WAIT_TIMEOUT) 
  470.         {
  471.             MessageBox(ghwndMain, 
  472.                        GetStringRes(IDS_CYCLE_THREAD_QUIT),
  473.                        GetStringRes (IDS_CYCLE_THREAD), MB_OK);
  474.             break;
  475.         }
  476. #endif
  477.         if (!pInfo->bClrCycle) {
  478.             sprintf( gtext,"NOT to animate palette\n");
  479.             OutputDebugString( gtext );
  480.             bQuit = TRUE;
  481.         }
  482.  
  483.         if (!bQuit) {
  484.             sprintf( gtext,"About to animate palette\n");
  485.             OutputDebugString( gtext );
  486.  
  487.             peTemp = plogPat->palPalEntry[10];
  488.             for (i = 0; i < iNumClr; i++) {
  489.                 plogPat->palPalEntry[i+10] = plogPat->palPalEntry[i+10+1];
  490.             }
  491.             plogPat->palPalEntry[i-1+10] = peTemp;
  492.  
  493.             if (!AnimatePalette(hPal, 0, 256, plogPat->palPalEntry)) {
  494.                 sprintf( gtext,"Anmiate palette failed\n");
  495.                 OutputDebugString( gtext );
  496.             }
  497.             Sleep(50);
  498.  
  499. //
  500. // This is not needed anymore starting from build 475 14-Jun-1993
  501. //
  502. #if 0
  503.             //
  504.             // Not realizing stops color-cycling after moving back into
  505.             // foreground
  506.             //
  507.             if ((uRC = RealizePalette(hDC)) == GDI_ERROR) {
  508.                 sprintf( gtext,"Realize palette failed\n");
  509.                 OutputDebugString( gtext );
  510.             }
  511.  
  512.             if (!UpdateColors(hDC)) {
  513.                 sprintf( gtext,"Update Colors failed\n");
  514.                 OutputDebugString( gtext );
  515.             }
  516. #endif
  517.         }
  518.  
  519.     }
  520.  
  521.     SelectPalette(hDC, hPalOld, 0);
  522.     DeleteObject(hPal);
  523. ErrExit2:
  524.     GlobalFree(plogPat);
  525. ErrExit1:
  526.     return bSuccess;
  527.  
  528. }
  529.  
  530.  
  531. /******************************Public*Routine******************************\
  532. *
  533. * bCycle
  534. *
  535. * Effects: Wrapper for doing color cycling in a separate thread
  536. *          Called from MM_CYCLE
  537. *
  538. * Warnings: presents problem when the MDI child is closed if this thread
  539. *           is not done yet.  We will have to wait until DeleteDC is
  540. *           fully functional.
  541. \**************************************************************************/
  542. BOOL bCycle(HWND hwnd)
  543. {
  544.     HDC     hDC;
  545.     PINFO   pInfo;
  546.  
  547.     if ((pInfo = pGetInfoData(hwnd)) == NULL) {
  548.         return 0L;
  549.     }
  550.  
  551.     hDC = GetDC(pInfo->hwnd);
  552.     bChangeDIBColor(hDC, pInfo, MM_CYCLE);
  553.     ReleaseDC(pInfo->hwnd, hDC);
  554.  
  555.     bReleaseInfoData(hwnd);
  556.  
  557.     ExitThread(0);
  558.     return TRUE;
  559. }
  560.  
  561.  
  562. /******************************Public*Routine******************************\
  563. *
  564. * bColor2Mono
  565. *
  566. * Effects: Create a monochrome bitmap out of the colored one
  567. *          Using a different a source background clr every time it is called
  568. *          Saving the Monochrome bitmap in pInfo
  569. *
  570. * Warnings: It's more straight forward to use GetDIBits than this but
  571. *           that means some big changes to the bChangeDIBColor.
  572. *
  573. \**************************************************************************/
  574.  
  575. BOOL bColor2Mono(HDC hDC, PINFO pInfo, PBITMAPINFO pbmi) {
  576.     HDC     hDCMemDest, hDCMemSrc;
  577.     HBITMAP hOldBmpDest, hOldBmpSrc;
  578.     INT     iWidth, iHeight, iEntry;
  579.     static INT iCount=0;
  580.  
  581.  
  582.     iWidth = pbmi->bmiHeader.biWidth;
  583.     iHeight = pbmi->bmiHeader.biHeight;
  584.  
  585.     if (pInfo->hBmpMono)
  586.         DeleteObject(pInfo->hBmpMono);
  587.  
  588.     pInfo->hBmpMono = CreateBitmap(iWidth, iHeight, pbmi->bmiHeader.biPlanes, 1, NULL);
  589.     if (pInfo->hBmpMono == NULL) {
  590.         return(FALSE);
  591.     }
  592.  
  593.     hDCMemDest = CreateCompatibleDC(hDC);
  594.     hDCMemSrc  = CreateCompatibleDC(hDC);
  595.  
  596.     if (pInfo->hPal) {
  597.         SelectPalette(hDCMemSrc, pInfo->hPal, FALSE);
  598.         RealizePalette(hDCMemSrc);
  599.     }
  600.  
  601.     iEntry = 1<<pbmi->bmiHeader.biBitCount;
  602.     SetBkColor(hDCMemSrc, RGB( pbmi->bmiColors[iCount].rgbRed,
  603.                                pbmi->bmiColors[iCount].rgbGreen,
  604.                                pbmi->bmiColors[iCount].rgbBlue) );
  605.     //SetBkColor(hDCMemDest, RGB( 0, 0, 0));
  606.     //SetTextColor(hDCMemDest, RGB( 255, 255, 255));
  607.  
  608.     iCount++;
  609.     if (iCount >= iEntry)
  610.         iCount = 0;
  611.  
  612.     hOldBmpDest = SelectObject(hDCMemDest, pInfo->hBmpMono);
  613.     hOldBmpSrc  = SelectObject(hDCMemSrc,  pInfo->hBmpSaved);
  614.     BitBlt(hDCMemDest, 0, 0, iWidth, iHeight, hDCMemSrc, 0, 0, SRCCOPY);
  615.  
  616.     pInfo->hBmpMono = SelectObject(hDCMemDest, hOldBmpDest);
  617.     SelectObject(hDCMemSrc, hOldBmpSrc);
  618.  
  619.     DeleteDC(hDCMemDest);
  620.     DeleteDC(hDCMemSrc);
  621.  
  622.     return(TRUE);
  623.  
  624. }
  625.  
  626.  
  627. /******************************Public*Routine******************************\
  628. *
  629. * iCreatePenFrPal
  630. *
  631. * Effects: Create an array of pens from palette.
  632. *          If device supports palette, then first creates a logical palette
  633. *          with a good spread of color. Then select the logical palette into
  634. *          the DC. Create pen that corresponds to each palette entry.
  635. *          If system does not support palette, then use the system palette.
  636. *
  637. *          prghPen pointer to an array of hPen
  638. *                  If this is NULL, the required size of the array is
  639. *                  returned. If this is not NULL, the array will be filled
  640. *                  with hPens.
  641. *
  642. *          returns the number of hPens created.
  643. *
  644. \**************************************************************************/
  645. INT iCreatePenFrPal(HDC hDC, PVOID *prghPen, INT iWidth, HPALETTE *phPal)
  646. {
  647.     INT             iNumClr, iResult, i, iEntry;
  648.     PLOGPALETTE     plogPat;
  649.     ULONG           ulSize;
  650.  
  651.     iResult = 0;
  652.  
  653.     if (!((GetDeviceCaps(hDC, RASTERCAPS)) & RC_PALETTE)) {
  654.  
  655.         if (iNumClr = GetSystemPaletteEntries(hDC, 0, 0, NULL)) {
  656.             if (prghPen == NULL) {
  657.                 return (iNumClr);
  658.             }
  659.  
  660.             if (iWidth < 0) 
  661.             {
  662.                 MessageBox(GetFocus(), GetStringRes (IDS_IVALID_PEN_WIDTH),
  663.                            NULL, MB_OK);
  664.                 return 0L;
  665.             }
  666.  
  667.             for (i = 0; i < iNumClr; i++) {
  668.                 prghPen[i] =
  669.                      (PVOID) CreatePen(PS_SOLID, iWidth, PALETTEINDEX(i));
  670.                 iResult = i;
  671. #if 0
  672.                 SelectObject(hDC, (HPEN)prghPen[i]);
  673.                 MoveToEx(hDC, i*iWidth, 0, NULL);
  674.                 LineTo(hDC, i*iWidth, 300);
  675. #endif
  676.             }
  677.             return iResult;
  678.         }
  679.  
  680.         // GetPaletteEntries returns 0
  681.         iNumClr = 1 << GetDeviceCaps(hDC, BITSPIXEL);
  682.  
  683.         if (iNumClr <= 16) {
  684.             sprintf( gtext,"Assertion failed: iCreatePenFrPal() \n");
  685.             OutputDebugString( gtext);
  686.             sprintf( gtext,"iNumClr <= 16! iNumClr = %d\n", iNumClr);
  687.             OutputDebugString( gtext);
  688.             return (iNumClr);
  689.         }
  690.  
  691.         // Assuming at least 16 bit device
  692.         //
  693.         iNumClr = 768;      // COLORREF format: 0x00bbggrr r,g,b=[0,255]
  694.  
  695.         if (prghPen == NULL) {
  696.             return (iNumClr);
  697.         }
  698.  
  699.         if (iWidth < 0) 
  700.         {
  701.             MessageBox(GetFocus(), GetStringRes(IDS_IVALID_PEN_WIDTH),
  702.                        NULL, MB_OK);
  703.             return 0L;
  704.         }
  705.  
  706.         for (i = 0; i < iNumClr; i++) {
  707.             if (i < 256) {
  708.                 prghPen[i] =
  709.                     (PVOID) CreatePen(PS_SOLID, iWidth, RGB(i,0,255-i));
  710.                 iResult = i;
  711. #if 0
  712.                 SelectObject(hDC, (HPEN)prghPen[i]);
  713.                 MoveToEx(hDC, i*iWidth, 0, NULL);
  714.                 LineTo(hDC, i*iWidth, 300);
  715. #endif
  716.                 continue;
  717.             }
  718.  
  719.             if (i < 512) {
  720.                 prghPen[i] =
  721.                     (PVOID) CreatePen(PS_SOLID, iWidth, RGB(511-i,i-256,0));
  722.                 iResult = i;
  723. #if 0
  724.                 SelectObject(hDC, (HPEN)prghPen[i]);
  725.                 MoveToEx(hDC, i*iWidth, 0, NULL);
  726.                 LineTo(hDC, i*iWidth, 300);
  727. #endif
  728.                 continue;
  729.             }
  730.  
  731.  
  732.             prghPen[i] =
  733.                 (PVOID) CreatePen(PS_SOLID, iWidth, RGB(0,767-i,i-512));
  734.             iResult = i;
  735. #if 0
  736.             SelectObject(hDC, (HPEN)prghPen[i]);
  737.             MoveToEx(hDC, i*iWidth, 0, NULL);
  738.             LineTo(hDC, i*iWidth, 300);
  739. #endif
  740.         }
  741.  
  742.         return iResult;
  743.     }
  744.  
  745.     //
  746.     // Palette managed device
  747.     //
  748.     iEntry = iNumClr = 1 << GetDeviceCaps(hDC, BITSPIXEL);
  749.  
  750.     if (iNumClr > 256) {
  751.         sprintf( gtext,"Assertion failed: iCreatePenFrPal() \n");
  752.         OutputDebugString( gtext);
  753.         sprintf( gtext,"iNumClr > 256! iNumClr = %d\n", iNumClr);
  754.         OutputDebugString( gtext);
  755.         iEntry=iNumClr = 256;
  756.     }
  757.  
  758.     ulSize = sizeof(LOGPALETTE)+sizeof(PALETTEENTRY)*iNumClr;
  759.  
  760.     iNumClr -= GetDeviceCaps(hDC, NUMRESERVED);
  761.  
  762.     if (prghPen == NULL)
  763.         return iNumClr;
  764.  
  765.     if ((plogPat = (PLOGPALETTE) GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT, ulSize)) == NULL) 
  766.     {
  767.         goto ErrExit1;
  768.     }
  769.  
  770.     plogPat->palVersion = 0x300;
  771.     plogPat->palNumEntries = (WORD) iEntry;
  772.  
  773.     {
  774.     int     iFirst, iSecond, iInc;
  775.  
  776.         iFirst = iNumClr/3;
  777.         iSecond = iFirst * 2;
  778.         iInc = (iNumClr <= 256) ? 3 : 1;
  779.  
  780.         for (i = 0; i < iNumClr; i++) {
  781.             if (i < iFirst) {
  782.                 plogPat->palPalEntry[i+10].peBlue   = 255-(i+1)*iInc;
  783.                 plogPat->palPalEntry[i+10].peGreen  = 0;
  784.                 plogPat->palPalEntry[i+10].peRed    = (i+1)*iInc;
  785.                 plogPat->palPalEntry[i+10].peFlags  = PC_RESERVED;
  786.                 continue;
  787.             }
  788.             if (i < iSecond) {
  789.                 plogPat->palPalEntry[i+10].peBlue   = 0;
  790.                 plogPat->palPalEntry[i+10].peGreen  = (i+1-iFirst)*iInc;
  791.                 plogPat->palPalEntry[i+10].peRed    = 255-(i+1-iFirst)*iInc;
  792.                 plogPat->palPalEntry[i+10].peFlags  = PC_RESERVED;
  793.                 continue;
  794.             }
  795.             plogPat->palPalEntry[i+10].peBlue   = (i+1-iSecond)*iInc;
  796.             plogPat->palPalEntry[i+10].peGreen  = 255-(i+1-iSecond)*iInc;
  797.             plogPat->palPalEntry[i+10].peRed    = 0;
  798.             plogPat->palPalEntry[i+10].peFlags  = PC_RESERVED;
  799.         }
  800.     }
  801.  
  802.     DeleteObject(*phPal);
  803.  
  804.     if ((*phPal = CreatePalette(plogPat)) == (HPALETTE) NULL) 
  805.     {
  806.         goto ErrExit2;
  807.     }
  808.     if (*phPal) {
  809.        SelectPalette(hDC, *phPal, FALSE);
  810.        RealizePalette(hDC);
  811.     }
  812.  
  813.     for (i = 0; i < iNumClr; i++) {
  814.         HPEN    hPen;
  815.  
  816.         hPen = CreatePen(PS_SOLID, iWidth, PALETTEINDEX(i+10));
  817.         prghPen[i] = (PVOID) hPen;
  818.         iResult = i;
  819. #if 0
  820.         SelectObject(hDC, hPen);
  821.         MoveToEx(hDC, i*iWidth, 0, NULL);
  822.         LineTo(hDC, i*iWidth, 300);
  823. #endif
  824.     }
  825.  
  826. ErrExit2:
  827.     GlobalFree(plogPat);
  828. ErrExit1:
  829.     return iResult;
  830.  
  831. }
  832.  
  833.  
  834. /******************************Public*Routine******************************\
  835. *
  836. * HPALETTE CopyPalette
  837. *
  838. \**************************************************************************/
  839.  
  840. HPALETTE CopyPalette(HPALETTE hPalSrc)
  841. {
  842.     PLOGPALETTE     plogPal;
  843.     PBYTE           pjTmp;
  844.     int             iNumEntries=0;
  845.     HPALETTE        hPal;
  846.  
  847.     if ((iNumEntries = GetPaletteEntries(hPalSrc, 0, iNumEntries, NULL)) == 0) 
  848.     {
  849.         OutputDebugString ("No entry in palette to copy!");
  850.         return (HPALETTE) NULL;
  851.     }
  852.  
  853.     if ((plogPal = (PLOGPALETTE)GlobalAlloc(GMEM_FIXED | GMEM_ZEROINIT,
  854.             sizeof(DWORD) + sizeof(PALETTEENTRY)*iNumEntries )) == NULL) 
  855.     {
  856.         return (HPALETTE) NULL;
  857.     }
  858.  
  859.     plogPal->palVersion = 0x300;
  860.     plogPal->palNumEntries = (WORD) iNumEntries;
  861.     pjTmp = (PBYTE) plogPal;
  862.     pjTmp += 8;
  863.     GetPaletteEntries(hPalSrc, 0, iNumEntries, (PPALETTEENTRY)pjTmp);
  864.     hPal = CreatePalette(plogPal);
  865.  
  866.     GlobalFree(plogPal);
  867.  
  868.     return hPal;
  869. }
  870.