home *** CD-ROM | disk | FTP | other *** search
/ Multimedia Jumpstart / Multimedia Microsoft Jumpstart Version 1.1a (Microsoft).BIN / develpmt / source / blt / dib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-01-05  |  24.2 KB  |  995 lines

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