home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Hits 1995 June / Image.iso / demos / woodruff / wing / dib.cp_ / dib.cp
Encoding:
Text File  |  1994-06-25  |  24.1 KB  |  986 lines

  1. /*----------------------------------------------------------------------------*\
  2. |   Routines for dealing with Device independent bitmaps                       |
  3. \*----------------------------------------------------------------------------*/
  4.  
  5. #include <windows.h>
  6. #include <windowsx.h>
  7. #include "dib.hpp"
  8.  
  9. #if defined(WIN32) || defined(_WIN32)
  10.     #include <memory.h>             // for _fmemcpy()
  11.     #define _huge
  12.     #define hmemcpy memcpy
  13. #endif
  14.  
  15. #define BFT_ICON   0x4349   /* 'IC' */
  16. #define BFT_BITMAP 0x4d42   /* 'BM' */
  17. #define BFT_CURSOR 0x5450   /* 'PT' */
  18.  
  19. /* flags for _lseek */
  20. #define  SEEK_CUR 1
  21. #define  SEEK_END 2
  22. #define  SEEK_SET 0
  23.  
  24. /*
  25.  *   Open a DIB file and return a MEMORY DIB, a memory handle containing..
  26.  *
  27.  *   BITMAP INFO    bi
  28.  *   palette data
  29.  *   bits....
  30.  *
  31.  */
  32. PDIB DibOpenFile(LPSTR szFile)
  33. {
  34.     HFILE               fh;
  35.     DWORD               dwLen;
  36.     DWORD               dwBits;
  37.     PDIB                pdib;
  38.     LPVOID              p;
  39.     OFSTRUCT            of;
  40.  
  41. #if defined(WIN32) || defined(_WIN32)
  42.     #define GetCurrentInstance()    GetModuleHandle(NULL)
  43. #else
  44.     #define GetCurrentInstance()    (HINSTANCE)SELECTOROF((LPVOID)&of)
  45. #endif
  46.  
  47.     fh = OpenFile(szFile, &of, OF_READ);
  48.  
  49.     if (fh == -1)
  50.     {
  51.         HRSRC h;
  52.  
  53.         h = FindResource(GetCurrentInstance(), szFile, RT_BITMAP);
  54.  
  55. #if defined(WIN32) || defined(_WIN32)
  56.         //!!! can we call GlobalFree() on this? is it the right format.
  57.         //!!! can we write to this resource?
  58.         if (h)
  59.             return (PDIB)LockResource(LoadResource(GetCurrentInstance(), h));
  60. #else
  61.         if (h)
  62.             fh = AccessResource(GetCurrentInstance(), h);
  63. #endif
  64.     }
  65.  
  66.     if (fh == -1)
  67.         return NULL;
  68.  
  69.     pdib = DibReadBitmapInfo(fh);
  70.  
  71.     if (!pdib)
  72.         return NULL;
  73.  
  74.     /* How much memory do we need to hold the DIB */
  75.  
  76.     dwBits = pdib->biSizeImage;
  77.     dwLen  = pdib->biSize + DibPaletteSize(pdib) + dwBits;
  78.  
  79.     /* Can we get more memory? */
  80.  
  81.     p = GlobalReAllocPtr(pdib,dwLen,0);
  82.  
  83.     if (!p)
  84.     {
  85.         GlobalFreePtr(pdib);
  86.         pdib = NULL;
  87.     }
  88.     else
  89.     {
  90.         pdib = (PDIB)p;
  91.     }
  92.  
  93.     if (pdib)
  94.     {
  95.         /* read in the bits */
  96.         _hread(fh, (LPBYTE)pdib + (UINT)pdib->biSize + DibPaletteSize(pdib), dwBits);
  97.     }
  98.  
  99.     _lclose(fh);
  100.  
  101.     return pdib;
  102. }
  103.  
  104. /*
  105.  *   Write a global handle in CF_DIB format to a file.
  106.  *
  107.  */
  108. BOOL DibWriteFile(PDIB pdib, LPSTR szFile)
  109. {
  110.     BITMAPFILEHEADER    hdr;
  111.     HFILE               fh;
  112.     OFSTRUCT            of;
  113.     DWORD               dwSize;
  114.  
  115.     if (!pdib)
  116.         return FALSE;
  117.  
  118.     fh = OpenFile(szFile,&of,OF_CREATE|OF_READWRITE);
  119.  
  120.     if (fh == -1)
  121.         return FALSE;
  122.  
  123.     dwSize = DibSize(pdib);
  124.  
  125.     hdr.bfType          = BFT_BITMAP;
  126.     hdr.bfSize          = dwSize + sizeof(BITMAPFILEHEADER);
  127.     hdr.bfReserved1     = 0;
  128.     hdr.bfReserved2     = 0;
  129.     hdr.bfOffBits       = (DWORD)sizeof(BITMAPFILEHEADER) + pdib->biSize +
  130.                           DibPaletteSize(pdib);
  131.  
  132.     _lwrite(fh,(LPCSTR)(LPVOID)&hdr,sizeof(BITMAPFILEHEADER));
  133.     _hwrite(fh,(LPCSTR)(LPVOID)pdib,dwSize);
  134.  
  135.     _lclose(fh);
  136.  
  137.     return TRUE;
  138. }
  139.  
  140. /*
  141.  *  CreateBIPalette()
  142.  *
  143.  *  Given a Pointer to a BITMAPINFO struct will create a
  144.  *  a GDI palette object from the color table.
  145.  *
  146.  */
  147. HPALETTE DibCreatePalette(PDIB pdib)
  148. {
  149.     LOGPALETTE         *pPal;
  150.     HPALETTE            hpal = NULL;
  151.     int                 nNumColors;
  152.     int                 i;
  153.     RGBQUAD FAR *       pRgb;
  154.  
  155.     if (!pdib)
  156.         return NULL;
  157.  
  158.     nNumColors = DibNumColors(pdib);
  159.     
  160.     if (nNumColors == 3 && DibCompression(pdib) == BI_BITFIELDS)
  161.         nNumColors = 0;
  162.  
  163.     if (nNumColors > 0)
  164.     {
  165.         pRgb = DibColors(pdib);
  166.         pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  167.  
  168.         if (!pPal)
  169.             goto exit;
  170.  
  171.         pPal->palNumEntries = nNumColors;
  172.         pPal->palVersion    = 0x300;
  173.  
  174.         for (i = 0; i < nNumColors; i++)
  175.         {
  176.             pPal->palPalEntry[i].peRed   = pRgb->rgbRed;
  177.             pPal->palPalEntry[i].peGreen = pRgb->rgbGreen;
  178.             pPal->palPalEntry[i].peBlue  = pRgb->rgbBlue;
  179.             pPal->palPalEntry[i].peFlags = (BYTE)0;
  180.  
  181.             pRgb++;
  182.         }
  183.  
  184.         hpal = CreatePalette(pPal);
  185.         LocalFree((HLOCAL)pPal);
  186.     }
  187.     else
  188.     {
  189. #if defined(WIN32) || defined(_WIN32)                 
  190.         HDC hdc = GetDC(NULL);
  191.         hpal = CreateHalftonePalette(hdc);      
  192.         ReleaseDC(NULL, hdc);
  193. #endif          
  194.     }
  195.  
  196. exit:
  197.     return hpal;
  198. }
  199.  
  200. /*
  201.  *  ReadDibBitmapInfo()
  202.  *
  203.  *  Will read a file in DIB format and return a global HANDLE to it's
  204.  *  BITMAPINFO.  This function will work with both "old" and "new"
  205.  *  bitmap formats, but will allways return a "new" BITMAPINFO
  206.  *
  207.  */
  208. PDIB DibReadBitmapInfo(HFILE fh)
  209. {
  210.     DWORD     off;
  211.     HANDLE    hbi = NULL;
  212.     int       size;
  213.     int       i;
  214.     int       nNumColors;
  215.  
  216.     RGBQUAD FAR       *pRgb;
  217.     BITMAPINFOHEADER   bi;
  218.     BITMAPCOREHEADER   bc;
  219.     BITMAPFILEHEADER   bf;
  220.     PDIB               pdib;
  221.  
  222.     if (fh == -1)
  223.         return NULL;
  224.  
  225.     off = _llseek(fh,0L,SEEK_CUR);
  226.  
  227.     if (sizeof(bf) != _lread(fh,(LPSTR)&bf,sizeof(bf)))
  228.         return FALSE;
  229.  
  230.     /*
  231.      *  do we have a RC HEADER?
  232.      */
  233.     if (bf.bfType != BFT_BITMAP)
  234.     {
  235.         bf.bfOffBits = 0L;
  236.         _llseek(fh,off,SEEK_SET);
  237.     }
  238.  
  239.     if (sizeof(bi) != _lread(fh,(LPSTR)&bi,sizeof(bi)))
  240.         return FALSE;
  241.  
  242.     /*
  243.      *  what type of bitmap info is this?
  244.      */
  245.     switch (size = (int)bi.biSize)
  246.     {
  247.         default:
  248.         case sizeof(BITMAPINFOHEADER):
  249.             break;
  250.  
  251.         case sizeof(BITMAPCOREHEADER):
  252.             bc = *(BITMAPCOREHEADER*)&bi;
  253.             bi.biSize               = sizeof(BITMAPINFOHEADER);
  254.             bi.biWidth              = (DWORD)bc.bcWidth;
  255.             bi.biHeight             = (DWORD)bc.bcHeight;
  256.             bi.biPlanes             =  (UINT)bc.bcPlanes;
  257.             bi.biBitCount           =  (UINT)bc.bcBitCount;
  258.             bi.biCompression        = BI_RGB;
  259.             bi.biSizeImage          = 0;
  260.             bi.biXPelsPerMeter      = 0;
  261.             bi.biYPelsPerMeter      = 0;
  262.             bi.biClrUsed            = 0;
  263.             bi.biClrImportant       = 0;
  264.  
  265.             _llseek(fh,(LONG)sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER),SEEK_CUR);
  266.  
  267.             break;
  268.     }
  269.  
  270.     nNumColors = DibNumColors(&bi);
  271.  
  272. #if 0
  273.     if (bi.biSizeImage == 0)
  274.         bi.biSizeImage = DibSizeImage(&bi);
  275.  
  276.     if (bi.biClrUsed == 0)
  277.         bi.biClrUsed = DibNumColors(&bi);
  278. #else
  279.     FixBitmapInfo(&bi);
  280. #endif
  281.  
  282.     pdib = (PDIB)GlobalAllocPtr(GMEM_MOVEABLE,(LONG)bi.biSize + nNumColors * sizeof(RGBQUAD));
  283.  
  284.     if (!pdib)
  285.         return NULL;
  286.  
  287.     *pdib = bi;
  288.  
  289.     pRgb = DibColors(pdib);
  290.  
  291.     if (nNumColors)
  292.     {
  293.         if (size == sizeof(BITMAPCOREHEADER))
  294.         {
  295.             /*
  296.              * convert a old color table (3 byte entries) to a new
  297.              * color table (4 byte entries)
  298.              */
  299.             _lread(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBTRIPLE));
  300.  
  301.             for (i=nNumColors-1; i>=0; i--)
  302.             {
  303.                 RGBQUAD rgb;
  304.  
  305.                 rgb.rgbRed      = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
  306.                 rgb.rgbBlue     = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
  307.                 rgb.rgbGreen    = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
  308.                 rgb.rgbReserved = (BYTE)0;
  309.  
  310.                 pRgb[i] = rgb;
  311.             }
  312.         }
  313.         else
  314.         {
  315.             _lread(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBQUAD));
  316.         }
  317.     }
  318.  
  319.     if (bf.bfOffBits != 0L)
  320.         _llseek(fh,off + bf.bfOffBits,SEEK_SET);
  321.  
  322.     return pdib;
  323. }
  324.  
  325. /*
  326.  *  DibFromBitmap()
  327.  *
  328.  *  Will create a global memory block in DIB format that represents the DDB
  329.  *  passed in
  330.  *
  331.  */
  332. PDIB DibFromBitmap(HBITMAP hbm, DWORD biStyle, UINT biBits, HPALETTE hpal, UINT wUsage)
  333. {   
  334.     PDIB                 pdib;
  335.     BITMAP               bm;
  336.     int                  nColors=0;
  337.     HDC                  hdc;
  338.     LPVOID               p;
  339.     UINT                 u;     
  340.  
  341.     if (!hbm)
  342.         return NULL;
  343.  
  344.     if (hpal == NULL)
  345.         hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  346.  
  347.     GetObject(hbm,sizeof(bm),(LPVOID)&bm);
  348.     GetObject(hpal,sizeof(nColors),(LPVOID)&nColors);
  349.  
  350.     if (biBits == 0)
  351.         biBits = bm.bmPlanes * bm.bmBitsPixel;
  352.  
  353.     pdib = (PDIB)GlobalAllocPtr(GMEM_MOVEABLE,sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD));
  354.  
  355.     if (!pdib)
  356.         return NULL;
  357.  
  358.     pdib->biSize               = sizeof(BITMAPINFOHEADER);
  359.     pdib->biWidth              = bm.bmWidth;
  360.     pdib->biHeight             = bm.bmHeight;
  361.     pdib->biPlanes             = 1;
  362.     pdib->biBitCount           = biBits;
  363.     pdib->biCompression        = biStyle;
  364.     pdib->biSizeImage          = 0;
  365.     pdib->biXPelsPerMeter      = 0;
  366.     pdib->biYPelsPerMeter      = 0;
  367.     pdib->biClrUsed            = 0;
  368.     pdib->biClrImportant       = 0;
  369.     pdib->biClrUsed            = DibNumColors(pdib);
  370.  
  371.     // this is a silly hack to test Win32/NT and BI_BITFIELDS
  372.     // convert to a 565 (for 16 bit) or a RGB DIB (for 32/24 bit)
  373.     if (biStyle == BI_BITFIELDS)
  374.     {            
  375.         LPDWORD pdw = (LPDWORD)DibColors(pdib);
  376.                       
  377.         switch (biBits)
  378.         {
  379.             case 16:            
  380.                 pdw[0] = 0xF800;        // masks for RGB 565
  381.                 pdw[1] = 0x07E0;
  382.                 pdw[2] = 0x001F;
  383.                 break;
  384.                                 
  385.             case 24:
  386.             case 32:
  387.                 pdw[0] = 0x0000FF;      // masks for RGB (not normal BGR)
  388.                 pdw[1] = 0x00FF00;
  389.                 pdw[2] = 0xFF0000;
  390.                 break;    
  391.         }
  392.     }   
  393.  
  394.     hdc = CreateCompatibleDC(NULL);
  395.     hpal = SelectPalette(hdc,hpal,FALSE);
  396.     RealizePalette(hdc);
  397.     
  398. #if defined(WIN32) || defined(_WIN32)                                   
  399.     SetStretchBltMode(hdc, HALFTONE);
  400. #endif    
  401.  
  402.     /*
  403.      *  call GetDIBits with a NULL lpBits param, so it will calculate the
  404.      *  biSizeImage field for us
  405.      */
  406.     GetDIBits(hdc, hbm, 0, (UINT)pdib->biHeight,
  407.         NULL, (LPBITMAPINFO)pdib, wUsage);
  408.  
  409.     pdib->biClrUsed = DibNumColors(pdib);
  410.     pdib->biSizeImage = DibSizeImage(pdib);
  411.  
  412.     /*
  413.      * HACK! if the driver did not fill in the biSizeImage field, make one up
  414.      */
  415.     if (pdib->biSizeImage == 0)
  416.     {
  417.         pdib->biSizeImage = DibSizeImage(pdib);
  418.  
  419.         if (biStyle != BI_RGB)
  420.             pdib->biSizeImage = (pdib->biSizeImage * 3) / 2;
  421.     }
  422.  
  423.     /*
  424.      *  realloc the buffer big enough to hold all the bits
  425.      */
  426.     if (p = GlobalReAllocPtr(pdib,DibSize(pdib),0))
  427.     {
  428.         pdib = (PDIB)p;
  429.     }
  430.     else
  431.     {
  432.         GlobalFreePtr(pdib);
  433.         pdib = NULL;
  434.         goto exit;
  435.     }
  436.  
  437.     /*
  438.      *  call GetDIBits with a NON-NULL lpBits param, and actualy get the
  439.      *  bits this time
  440.      */
  441.     u = GetDIBits(hdc, hbm, 0, (UINT)pdib->biHeight,
  442.         DibPtr(pdib),(LPBITMAPINFO)pdib, wUsage);
  443.  
  444.     pdib->biClrUsed = DibNumColors(pdib);
  445.     pdib->biSizeImage = DibSizeImage(pdib);
  446.     
  447.     // error getting bits.
  448.     
  449.     if (u == 0)
  450.     {
  451.         DibFree(pdib);
  452.         pdib = NULL;
  453.     }   
  454.  
  455. exit:
  456.     SelectPalette(hdc,hpal,FALSE);
  457.     DeleteDC(hdc);
  458.     return pdib;
  459. }
  460.  
  461. /*
  462.  *  BitmapFromDib()
  463.  *
  464.  *  Will create a DDB (Device Dependent Bitmap) given a global handle to
  465.  *  a memory block in CF_DIB format
  466.  *
  467.  */
  468. HBITMAP BitmapFromDib(PDIB pdib, HPALETTE hpal, UINT wUsage)
  469. {
  470.     HPALETTE    hpalT;
  471.     HDC         hdc;
  472.     HBITMAP     hbm;
  473.     DWORD       dwFlags = CBM_INIT;
  474.  
  475.     if (!pdib)
  476.         return NULL;
  477.  
  478. #if defined(WIN32) || defined(_WIN32)
  479.     if (wUsage == (UINT)-1)     // silly hack for ConvertDib
  480.         if (pdib->biCompression == 0 || 
  481.             pdib->biCompression == BI_BITFIELDS)
  482.         dwFlags |= CBM_CREATEDIB;    
  483. #endif
  484.     if (wUsage == (UINT)-1)
  485.     wUsage = DIB_RGB_COLORS;    // silly hack for ConvertDib
  486.  
  487.     hdc = GetDC(NULL);
  488.  
  489.     if (hpal)
  490.     {
  491.         hpalT = SelectPalette(hdc,hpal,FALSE);
  492.         RealizePalette(hdc);
  493.     }
  494.                     
  495. #if defined(WIN32) || defined(_WIN32)                                   
  496.     SetStretchBltMode(hdc, HALFTONE);       //??? does this do anything?
  497. #endif    
  498.  
  499.     hbm = CreateDIBitmap(hdc,
  500.                 pdib,dwFlags,
  501.                 DibPtr(pdib),
  502.                 (LPBITMAPINFO)pdib,
  503.                 wUsage);
  504.  
  505.     if (hpal && hpalT)
  506.         SelectPalette(hdc,hpalT,FALSE);
  507.  
  508.     ReleaseDC(NULL,hdc);
  509.  
  510.     return hbm;
  511. }
  512.  
  513. /*
  514.  *  DibSetUsage(hdib,hpal,wUsage)
  515.  *
  516.  *  Modifies the color table of the passed DIB for use with the wUsage
  517.  *  parameter specifed.
  518.  *
  519.  *  if wUsage is DIB_PAL_COLORS the DIB color table is set to 0-256
  520.  *  if wUsage is DIB_RGB_COLORS the DIB color table is set to the RGB values
  521.  *      in the passed palette
  522.  *
  523.  */
  524. BOOL DibSetUsage(PDIB pdib, HPALETTE hpal,UINT wUsage)
  525. {
  526.     PALETTEENTRY       ape[256];
  527.     RGBQUAD FAR *      pRgb;
  528.     WORD FAR *         pw;
  529.     int                nColors;
  530.     int                n;
  531.  
  532.     if (hpal == NULL)
  533.         hpal = (HPALETTE)GetStockObject(DEFAULT_PALETTE);
  534.  
  535.     if (!pdib)
  536.         return FALSE;
  537.  
  538.     nColors = DibNumColors(pdib);
  539.     
  540.     if (nColors == 3 && DibCompression(pdib) == BI_BITFIELDS)
  541.         nColors = 0;
  542.  
  543.     if (nColors > 0)
  544.     {
  545.         pRgb = DibColors(pdib);
  546.  
  547.         switch (wUsage)
  548.         {
  549. #if defined(WIN32) || defined(_WIN32)
  550.             case DIB_PAL_INDICES:
  551.                 // hack!!! fall through  
  552. #endif
  553.             //
  554.             // Set the DIB color table to palette indexes
  555.             //
  556.             case DIB_PAL_COLORS:
  557.                 for (pw = (WORD FAR*)pRgb,n=0; n<nColors; n++,pw++)
  558.                     *pw = n;
  559.                 break;
  560.  
  561.             //
  562.             // Set the DIB color table to RGBQUADS
  563.             //
  564.             default:
  565.             case DIB_RGB_COLORS:
  566.                 nColors = min(nColors,256);
  567.  
  568.                 GetPaletteEntries(hpal,0,nColors,ape);
  569.  
  570.                 for (n=0; n<nColors; n++)
  571.                 {
  572.                     pRgb[n].rgbRed      = ape[n].peRed;
  573.                     pRgb[n].rgbGreen    = ape[n].peGreen;
  574.                     pRgb[n].rgbBlue     = ape[n].peBlue;
  575.                     pRgb[n].rgbReserved = 0;
  576.                 }
  577.                 break;
  578.         }
  579.     }
  580.     return TRUE;
  581. }
  582.  
  583. /*
  584.  *  DibDraw()
  585.  */
  586. BOOL DibDraw(HDC hdc,  int x,  int y,  int dx,  int dy,
  587.             PDIB pdib, int x0, int y0, int dx0, int dy0,
  588.             LONG rop, UINT wUsage)
  589. {
  590.     BOOL f;
  591.     LPVOID lpBits;
  592.  
  593.     if (!pdib)
  594.         return FALSE;
  595.  
  596.     if (dx0 == -1 && dy0 == -1)
  597.     {
  598.         dx0 = DibWidth(pdib);
  599.         dy0 = DibHeight(pdib);
  600.     }
  601.  
  602.     if (dx == -1 && dy == -1)
  603.     {
  604.     dx = dx0;
  605.     dy = dy0;
  606.     }          
  607.         
  608. #if 0                                   
  609. #if defined(WIN32) || defined(_WIN32)
  610.     if (pdib->biBitCount > 8)
  611.         SetStretchBltMode(hdc, HALFTONE);
  612.     else
  613.         SetStretchBltMode(hdc, COLORONCOLOR);
  614. #else    
  615.     SetStretchBltMode(hdc, COLORONCOLOR);
  616. #endif    
  617. #endif
  618.  
  619.     lpBits = DibPtr(pdib);
  620.     
  621.     f = StretchDIBits(
  622.         hdc,
  623.         x,y,
  624.         dx,dy,
  625.         x0,y0,
  626.         dx0,dy0,
  627.         lpBits, (LPBITMAPINFO)pdib,
  628.         wUsage,
  629.         rop);
  630.  
  631.     return f;
  632. }
  633.  
  634. PDIB DibCopy(PDIB pdib)
  635. {
  636.     PDIB pdibCopy;
  637.  
  638.     if (pdib == NULL)
  639.         return NULL;
  640.  
  641.     if (pdibCopy = (PDIB)GlobalAllocPtr(GMEM_MOVEABLE,DibSize(pdib)))
  642.         hmemcpy(pdibCopy, pdib, DibSize(pdib));
  643.  
  644.     return pdibCopy;
  645. }
  646.  
  647. PDIB DibCreate(int bits, int dx, int dy)
  648. {
  649.     LPBITMAPINFOHEADER lpbi ;
  650.     DWORD       dwSizeImage;
  651.     int         i;
  652.     DWORD FAR  *pdw;
  653.  
  654.     dwSizeImage = dy*(DWORD)((dx*bits/8+3)&~3);
  655.  
  656.     lpbi = (PDIB)GlobalAllocPtr(GHND,sizeof(BITMAPINFOHEADER)+dwSizeImage + 1024);
  657.  
  658.     if (lpbi == NULL)
  659.         return NULL;
  660.  
  661.     lpbi->biSize            = sizeof(BITMAPINFOHEADER) ;
  662.     lpbi->biWidth           = dx;
  663.     lpbi->biHeight          = dy;
  664.     lpbi->biPlanes          = 1;
  665.     lpbi->biBitCount        = bits ;
  666.     lpbi->biCompression     = BI_RGB ;
  667.     lpbi->biSizeImage       = dwSizeImage;
  668.     lpbi->biXPelsPerMeter   = 0 ;
  669.     lpbi->biYPelsPerMeter   = 0 ;
  670.     lpbi->biClrUsed         = 0 ;
  671.     lpbi->biClrImportant    = 0 ;
  672.  
  673.     if (bits == 4)
  674.         lpbi->biClrUsed = 16;
  675.  
  676.     else if (bits == 8)
  677.         lpbi->biClrUsed = 256;
  678.  
  679.     pdw = (DWORD FAR *)((LPBYTE)lpbi+(int)lpbi->biSize);
  680.  
  681.     for (i=0; i<(int)lpbi->biClrUsed/16; i++)
  682.     {
  683.         *pdw++ = 0x00000000;    // 0000  black
  684.         *pdw++ = 0x00800000;    // 0001  dark red
  685.         *pdw++ = 0x00008000;    // 0010  dark green
  686.         *pdw++ = 0x00808000;    // 0011  mustard
  687.         *pdw++ = 0x00000080;    // 0100  dark blue
  688.         *pdw++ = 0x00800080;    // 0101  purple
  689.         *pdw++ = 0x00008080;    // 0110  dark turquoise
  690.         *pdw++ = 0x00C0C0C0;    // 1000  gray
  691.         *pdw++ = 0x00808080;    // 0111  dark gray
  692.         *pdw++ = 0x00FF0000;    // 1001  red
  693.         *pdw++ = 0x0000FF00;    // 1010  green
  694.         *pdw++ = 0x00FFFF00;    // 1011  yellow
  695.         *pdw++ = 0x000000FF;    // 1100  blue
  696.         *pdw++ = 0x00FF00FF;    // 1101  pink (magenta)
  697.         *pdw++ = 0x0000FFFF;    // 1110  cyan
  698.         *pdw++ = 0x00FFFFFF;    // 1111  white
  699.     }
  700.  
  701.     return (PDIB)lpbi;
  702. }
  703.  
  704. PDIB DibConvert(PDIB pdib, int BitCount, DWORD biCompression)
  705. {
  706.     HBITMAP hbm;            
  707.     HPALETTE hpal = NULL;
  708.     
  709.     if (pdib == NULL)
  710.         return NULL;
  711.  
  712.     if (DibNumColors(pdib) > 3)
  713.         hpal = DibCreatePalette(pdib);
  714.     // pass -1 as wUsage so we dont get a device bitmap, see
  715.     // BitmapFromDib for the Hack. NOTE only in Win32
  716.     hbm = BitmapFromDib(pdib, hpal, (UINT)-1 /*DIB_RGB_COLORS*/); 
  717.         
  718.     if (hbm)
  719.         pdib = DibFromBitmap(hbm, biCompression, BitCount, hpal, DIB_RGB_COLORS);
  720.     else
  721.         pdib = NULL;
  722.         
  723.     if (hbm)
  724.         DeleteObject(hbm);
  725.         
  726.     if (hpal)
  727.         DeleteObject(hpal);
  728.         
  729.     return pdib;
  730. }
  731.  
  732.  
  733. static void xlatClut8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  734. {
  735.     DWORD dw;
  736.  
  737. #ifdef __cplusplus
  738.     for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *&)pb)++)
  739. #else
  740.     for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *)pb)++)
  741. #endif
  742.         *pb = xlat[*pb];
  743. }
  744.  
  745. static void xlatClut4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  746. {
  747.     DWORD dw;
  748.  
  749. #ifdef __cplusplus
  750.     for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *&)pb)++)
  751. #else
  752.     for (dw = 0; dw < dwSize; dw++, ((BYTE _huge *)pb)++)
  753. #endif
  754.         *pb = (BYTE)(xlat[*pb & 0x0F] | (xlat[(*pb >> 4) & 0x0F] << 4));
  755. }
  756.  
  757. #define RLE_ESCAPE  0
  758. #define RLE_EOL     0
  759. #define RLE_EOF     1
  760. #define RLE_JMP     2
  761.  
  762. static void xlatRle8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  763. {
  764.     BYTE    cnt;
  765.     BYTE    b;
  766.     BYTE _huge *prle = pb;
  767.  
  768.     for(;;)
  769.     {
  770.         cnt = *prle++;
  771.         b   = *prle;
  772.  
  773.         if (cnt == RLE_ESCAPE)
  774.         {
  775.             prle++;
  776.  
  777.             switch (b)
  778.             {
  779.                 case RLE_EOF:
  780.                     return;
  781.  
  782.                 case RLE_EOL:
  783.                     break;
  784.  
  785.                 case RLE_JMP:
  786.                     prle++;     // skip dX
  787.                     prle++;     // skip dY
  788.                     break;
  789.  
  790.                 default:
  791.                     cnt = b;
  792.                     for (b=0; b<cnt; b++,prle++)
  793.                         *prle = xlat[*prle];
  794.  
  795.                     if (cnt & 1)
  796.                         prle++;
  797.  
  798.                     break;
  799.             }
  800.         }
  801.         else
  802.         {
  803.             *prle++ = xlat[b];
  804.         }
  805.     }
  806. }
  807.  
  808. static void xlatRle4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  809. {
  810. }
  811.  
  812. static void memmove(BYTE _huge *d, BYTE _huge *s, LONG len)
  813. {
  814.     d += len-1;
  815.     s += len-1;
  816.  
  817.     while (len--)
  818.         *d-- = *s--;
  819. }
  820.  
  821. //
  822. // MapDib - map the given DIB so it matches the specifed palette
  823. //
  824. void DibMapToPalette(PDIB pdib, HPALETTE hpal)
  825. {
  826.     LPBITMAPINFOHEADER  lpbi;
  827.     PALETTEENTRY        pe;
  828.     int                 n;
  829.     int                 nDibColors;
  830.     int                 nPalColors=0;
  831.     BYTE FAR *          lpBits;
  832.     RGBQUAD FAR *       lpRgb;
  833.     BYTE                xlat[256];
  834.     DWORD               SizeImage;
  835.  
  836.     if (!hpal || !pdib)
  837.         return;
  838.  
  839.     lpbi   = (LPBITMAPINFOHEADER)pdib;
  840.     lpRgb  = DibColors(pdib);
  841.  
  842.     GetObject(hpal,sizeof(int),(LPSTR)&nPalColors);
  843.     nDibColors = DibNumColors(pdib);
  844.  
  845.     if ((SizeImage = lpbi->biSizeImage) == 0)
  846.         SizeImage = DibSizeImage(lpbi);
  847.  
  848.     //
  849.     //  build a xlat table. from the current DIB colors to the given
  850.     //  palette.
  851.     //
  852.     for (n=0; n<nDibColors; n++)
  853.         xlat[n] = (BYTE)GetNearestPaletteIndex(hpal,RGB(lpRgb[n].rgbRed,lpRgb[n].rgbGreen,lpRgb[n].rgbBlue));
  854.  
  855.     lpBits = (LPBYTE)DibPtr(lpbi);
  856.     lpbi->biClrUsed = nPalColors;
  857.  
  858.     //
  859.     // re-size the DIB
  860.     //
  861.     if (nPalColors > nDibColors)
  862.     {
  863.         GlobalReAllocPtr(lpbi, lpbi->biSize + nPalColors*sizeof(RGBQUAD) + SizeImage, 0);
  864.         memmove((BYTE _huge *)DibPtr(lpbi), (BYTE _huge *)lpBits, SizeImage);
  865.         lpBits = (LPBYTE)DibPtr(lpbi);
  866.     }
  867.     else if (nPalColors < nDibColors)
  868.     {
  869.         hmemcpy(DibPtr(lpbi), lpBits, SizeImage);
  870.         GlobalReAllocPtr(lpbi, lpbi->biSize + nPalColors*sizeof(RGBQUAD) + SizeImage, 0);
  871.         lpBits = (LPBYTE)DibPtr(lpbi);
  872.     }
  873.  
  874.     //
  875.     // translate the DIB bits
  876.     //
  877.     switch (lpbi->biCompression)
  878.     {
  879.         case BI_RLE8:
  880.             xlatRle8(lpBits, SizeImage, xlat);
  881.             break;
  882.  
  883.         case BI_RLE4:
  884.             xlatRle4(lpBits, SizeImage, xlat);
  885.             break;
  886.  
  887.         case BI_RGB:
  888.             if (lpbi->biBitCount == 8)
  889.                 xlatClut8(lpBits, SizeImage, xlat);
  890.             else
  891.                 xlatClut4(lpBits, SizeImage, xlat);
  892.             break;
  893.     }
  894.  
  895.     //
  896.     //  Now copy the RGBs in the logical palette to the dib color table
  897.     //
  898.     for (n=0; n<nPalColors; n++)
  899.     {
  900.         GetPaletteEntries(hpal,n,1,&pe);
  901.  
  902.         lpRgb[n].rgbRed      = pe.peRed;
  903.         lpRgb[n].rgbGreen    = pe.peGreen;
  904.         lpRgb[n].rgbBlue     = pe.peBlue;
  905.         lpRgb[n].rgbReserved = (BYTE)0;
  906.     }
  907.  
  908.     return;
  909. }
  910.  
  911. void MakeIdentityPalette(HPALETTE hpal)
  912. {
  913.     HDC hdc;
  914.     PALETTEENTRY ape[256];
  915.     HPALETTE hpalT;
  916.     int nColors;
  917.     int nCosmic;
  918.     int i;
  919.     HWND hwnd = GetActiveWindow();
  920.  
  921.     hdc = GetDC(hwnd);
  922.  
  923.     nColors = GetDeviceCaps(hdc, SIZEPALETTE);
  924.     nCosmic = GetDeviceCaps(hdc, NUMCOLORS);
  925.  
  926.     if ((GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) && nColors <= 256)
  927.     {
  928.         SetSystemPaletteUse(hdc, SYSPAL_NOSTATIC);
  929.         SetSystemPaletteUse(hdc, SYSPAL_STATIC);
  930.  
  931.         hpalT = SelectPalette(hdc, hpal, FALSE);
  932.         RealizePalette(hdc);
  933.         SelectPalette(hdc, hpalT, FALSE);
  934.  
  935.         GetSystemPaletteEntries(hdc, 0, nColors, ape);
  936.  
  937.         for (i=0; i<nCosmic/2; i++)
  938.             ape[i].peFlags = 0;
  939.  
  940.         for (; i<nColors-nCosmic/2; i++)
  941.             ape[i].peFlags = PC_NOCOLLAPSE;
  942.  
  943.         for (; i<nColors-nCosmic/2; i++)
  944.             ape[i].peFlags = 0;
  945.  
  946.         ResizePalette(hpal, nColors);
  947.         SetPaletteEntries(hpal, 0, nColors, ape);
  948.     }
  949.  
  950.     ReleaseDC(hwnd,hdc);
  951. }
  952.  
  953. /*
  954.  * CopyPalette, makes a copy of a GDI logical palette
  955.  */
  956. HPALETTE CopyPalette(HPALETTE hpal)
  957. {
  958.     PLOGPALETTE ppal;
  959.     int         nNumEntries=0;
  960.  
  961.     if (!hpal)
  962.         return NULL;
  963.  
  964.     GetObject(hpal,sizeof(int),(LPSTR)&nNumEntries);
  965.  
  966.     if (nNumEntries == 0)
  967.         return NULL;
  968.  
  969.     ppal = (PLOGPALETTE)LocalAlloc(LPTR,sizeof(LOGPALETTE) +
  970.                 nNumEntries * sizeof(PALETTEENTRY));
  971.  
  972.     if (!ppal)
  973.         return NULL;
  974.  
  975.     ppal->palVersion    = 0x0300;
  976.     ppal->palNumEntries = nNumEntries;
  977.  
  978.     GetPaletteEntries(hpal,0,nNumEntries,ppal->palPalEntry);
  979.  
  980.     hpal = CreatePalette(ppal);
  981.  
  982.     LocalFree((HANDLE)ppal);
  983.     return hpal;
  984. }
  985.  
  986.