home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Hits 1995 June / Image.iso / demos / woodruff / wing / dib.c_ / dib.c
Encoding:
C/C++ Source or Header  |  1994-06-20  |  24.3 KB  |  998 lines

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