DibUtil.cpp
上传用户:shxiangxiu
上传日期:2007-01-03
资源大小:1101k
文件大小:93k
源码类别:

OpenGL

开发平台:

Visual C++

  1. ////////////////////////////////////////////////////////////////////////////
  2. // DibUtil.cpp : Defines the global Device Independent Bitmap (dib) functions
  3. //    for the application.
  4. //
  5. // glOOP (OpenGL Object Oriented Programming library)
  6. // Copyright (c) Craig Fahrnbach 1997, 1998
  7. //
  8. // OpenGL is a registered trademark of Silicon Graphics
  9. //
  10. //
  11. // This program is provided for educational and personal use only and
  12. // is provided without guarantee or warrantee expressed or implied.
  13. //
  14. // Commercial use is strickly prohibited without written permission
  15. // from ImageWare Development.
  16. //
  17. // This program is -not- in the public domain.
  18. //
  19. /////////////////////////////////////////////////////////////////////////////
  20. #include "stdafx.h"
  21. #include "glOOP.h"
  22. #include "DibUtil.h"
  23. /******************************************************************************
  24.  *                                                                            *
  25.  *  FUNCTION   :CountBits(DWORD dw)                                           *
  26.  *                                                                            *
  27.  *  PURPOSE    :Count the number of set bits in a given DWORD                 * 
  28.  *                                                                            *
  29.  *  *NOTE:     :Used only in CreateBIPalette() for extracting RGB values      *
  30.  *              from 16 and 32bpp DIBS                                        *
  31.  *                                                                            *
  32.  *****************************************************************************/
  33. BYTE  CountBits(DWORD dw)
  34. {
  35.   int i, Count = 0;
  36.   for (i=0; i<sizeof(DWORD) * 8; i++)
  37.     Count += (((1 << i) & dw) != 0);
  38.   return Count;
  39. }
  40. /******************************************************************************
  41.  *                                                                            *
  42.  *  FUNCTION   :CountBits(DWORD dw)                                           *
  43.  *                                                                            *
  44.  *  PURPOSE    :Count the number of set bits in a given DWORD                 * 
  45.  *                                                                            *
  46.  *  *NOTE:     :Used only in CreateBIPalette() for extracting RGB values      *
  47.  *              from 16 and 32bpp DIBS                                        *
  48.  *                                                                            *
  49.  *****************************************************************************/
  50. BYTE RightmostBit(DWORD dw)
  51. {
  52.   int i;
  53.   for (i=0; i<sizeof(DWORD) * 8; i++)
  54.     if (((1 << i) & dw) != 0)
  55.       return i;
  56.   return (BYTE)-1; // No bits are set
  57. }
  58. /******************************************************************************
  59.  *                                                                            *
  60.  *  FUNCTION   :LeftmostBit(DWORD dw)                                         *
  61.  *                                                                            *
  62.  *  PURPOSE    :Returns the position of the leftmost set bit in a DWORD       * 
  63.  *                                                                            *
  64.  *  *NOTE:     :Used only in CreateBIPalette() for extracting RGB values      *
  65.  *              from 16 and 32bpp DIBS                                        *
  66.  *                                                                            *
  67.  *****************************************************************************/
  68. BYTE LeftmostBit(DWORD dw)
  69. {
  70.   int i;
  71.   for (i=(sizeof(DWORD) * 8)-1; i >= 0; i--)
  72.     if (((1 << i) & dw) != 0)
  73.       return i;
  74.   return (BYTE)-1; // No bits are set
  75. }
  76. /******************************************************************************
  77.  *                                                                            *
  78.  *  FUNCTION   :ValidMask(DWORD dw)                                           *
  79.  *                                                                            *
  80.  *  PURPOSE    :Determines if a given DWORD is valid as a color mask for      * 
  81.  *              16 or 32bpp DIBS (are all the set bits contiguous)            *
  82.  *                                                                            *
  83.  *  *NOTE:     :Used only in CreateBIPalette()                                *
  84.  *                                                                            *
  85.  *****************************************************************************/
  86. BOOL ValidMask(DWORD dw)
  87. {
  88.   int iStart, iStop, i;
  89.   
  90.   iStart = LeftmostBit(dw);
  91.   iStop  = RightmostBit(dw);
  92.   if (iStart == iStop)
  93.     return TRUE;
  94.   for (i=iStart; i>=iStop; i--) 
  95.      if (((1 << i) & dw) == 0)
  96.        return FALSE;
  97.   return TRUE;
  98. }
  99. /******************************************************************************
  100.  *                                                                            *
  101.  * FUNCTION   : GlobalFreeDIB(HGLOBAL hDIB)                                  *
  102.  *                                                                            *
  103.  * PURPOSE    : Free the specified global memory object and invalidate       *
  104.  *  its handle.                                                  *
  105.  *                                                                            *
  106.  * RETURNS    : If the function succeeds, the return value is NULL.          *
  107.  *  If the function fails, the return value is equal to the      *
  108.  *  handle of the global memory object. To get extended error    *
  109.  *  information, call GetLastError.                              *
  110.  *                                                                            *
  111.  *****************************************************************************/
  112. HGLOBAL GlobalFreeDIB(HGLOBAL hDIB)
  113. {
  114.    LPBITMAPINFOHEADER lpbi = (LPBITMAPINFOHEADER)hDIB;
  115.    if (!lpbi->biClrImportant)
  116.      return GlobalFree(hDIB);
  117.    if (GlobalFlags((HGLOBAL)lpbi->biClrImportant) == GMEM_INVALID_HANDLE) {
  118.     SetLastError(0);
  119.     return GlobalFree(hDIB);
  120.   } else
  121.     return GlobalFree((HANDLE)lpbi->biClrImportant); 
  122. }
  123. /******************************************************************************
  124.  *                                                                            *
  125.  *  FUNCTION   :OpenDIB(LPSTR szFilename)                                     *
  126.  *                                                                            *
  127.  *  PURPOSE    :Open a DIB file and create a memory DIB -- a memory handle    *
  128.  *              containing BITMAPINFO, palette data and the bits.             * 
  129.  *                                                                            *
  130.  *  RETURNS    :A handle to the DIB.                                          *
  131.  *                                                                            *
  132.  *****************************************************************************/
  133. HANDLE OpenDIB(LPSTR szFilename)
  134. {
  135.     HFILE               hFile;
  136.     BITMAPINFOHEADER    bih;
  137.     LPBITMAPINFOHEADER  lpbih;
  138.     DWORD               dwLen = 0;
  139.     DWORD               dwBits;
  140.     HANDLE              hDIB;
  141.     HANDLE              hMem;
  142.     OFSTRUCT            of;
  143.     /* Open the file and read the DIB information */
  144.     hFile = OpenFile(szFilename, &of, (UINT)OF_READ);
  145.     if (hFile == HFILE_ERROR)
  146. {
  147. if(the3dEngine.m_bDisplayErrorMessages)
  148. {
  149. LPVOID lpMsgBuf;
  150. char buf[128];
  151. FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
  152.   NULL,
  153.   GetLastError(),
  154.   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  155.   (LPTSTR) &lpMsgBuf,
  156.   0,
  157.   NULL);
  158. // Display the string.
  159. sprintf(buf, "Error reading file '%s'.nn Error: %sn", szFilename, lpMsgBuf);
  160. MessageBox( NULL, buf, "OpenDIB File Error!", MB_OK|MB_ICONINFORMATION );
  161. // Free the buffer.
  162. LocalFree( lpMsgBuf );
  163. }
  164.     
  165. return NULL;
  166. }
  167.     hDIB = ReadDIBBitmapInfo(hFile);
  168.     if (!hDIB)
  169.         return NULL;
  170.     DIBInfo(hDIB, &bih);
  171.     /* Calculate the memory needed to hold the DIB */
  172.     dwBits = bih.biSizeImage;
  173.     dwLen  = bih.biSize + (DWORD)ColorTableSize (&bih) + dwBits;
  174.     /* Try to increase the size of the bitmap info. buffer to hold the DIB */
  175.     hMem = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE);
  176.     if (!hMem){
  177.         GlobalFreeDIB(hDIB);
  178.         hDIB = NULL;
  179.     }
  180.     else
  181.         hDIB = hMem;
  182.     /* Read in the bits */
  183.     if (hDIB){
  184.         lpbih = (LPBITMAPINFOHEADER)hDIB;
  185.         _hread(hFile, (LPSTR)lpbih + (WORD)lpbih->biSize + ColorTableSize(lpbih), dwBits);
  186.     }
  187.     _lclose(hFile);
  188.     return hDIB;
  189. }
  190. /******************************************************************************
  191.  *                                                                            *
  192.  *  FUNCTION   : WriteDIB(LPSTR szFilename, HANDLE hDIB)                      *
  193.  *                                                                            *
  194.  *  PURPOSE    : Write a global handle in CF_DIB format to a file.            *
  195.  *                                                                            *
  196.  *  RETURNS    : TRUE  - if successful.                                       *
  197.  *               FALSE - otherwise                                            *
  198.  *                                                                            *
  199.  *****************************************************************************/
  200. BOOL WriteDIB(LPSTR szFilename, HANDLE hDIB)
  201. {
  202.     BITMAPFILEHEADER    bmfhdr;
  203.     LPBITMAPINFOHEADER  lpbih;
  204.     HFILE               hFile;
  205.     OFSTRUCT            of;
  206.     if (!hDIB)
  207.         return FALSE;
  208.     hFile = OpenFile(szFilename, &of, (UINT)OF_CREATE|OF_READWRITE);
  209.     if (hFile == HFILE_ERROR)
  210.         return FALSE;
  211.     lpbih = (LPBITMAPINFOHEADER)hDIB;
  212.     /* Fill in the fields of the file header */
  213.     bmfhdr.bfType          = BFT_BITMAP;
  214.     bmfhdr.bfSize          = GlobalSize (hDIB) + SIZEOF_BITMAPFILEHEADER_PACKED;
  215.     bmfhdr.bfReserved1     = 0;
  216.     bmfhdr.bfReserved2     = 0;
  217.     bmfhdr.bfOffBits       = (DWORD)(SIZEOF_BITMAPFILEHEADER_PACKED + 
  218.                                   lpbih->biSize + ColorTableSize(lpbih));
  219.     WritePackedFileHeader(hFile, &bmfhdr);
  220.     /* Write the DIB header and the bits */
  221.     _hwrite (hFile, (LPSTR)lpbih, GlobalSize (hDIB));
  222.     _lclose(hFile);
  223.  
  224.     return TRUE;
  225. }
  226. /******************************************************************************
  227.  *                                                                            *
  228.  *  FUNCTION  : WriteDIBEx(LPSTR szFilename, HANDLE hDIB,                     *
  229.  *                         WORD wBPP, DWORD dwComp)                           *                           
  230.  *                                                                            *
  231.  *  PURPOSE   : Write a global handle in CF_DIB format to a file with a       *
  232.  *              specified pixel depth and compression format                  *
  233.  *                                                                            *
  234.  *  RETURNS   : TRUE  - if successful.                                        *
  235.  *              FALSE - otherwise                                             *
  236.  *                                                                            *
  237.  *****************************************************************************/
  238. BOOL WriteDIBEx(LPSTR szFilename, HANDLE hDIB, WORD wBPP, DWORD dwComp)
  239. {
  240.     BITMAPINFOHEADER bih;
  241.     HANDLE hNewDIB;
  242.     BOOL bReturn;
  243.     DIBInfo(hDIB, &bih);
  244.     if (((bih.biBitCount == wBPP) && (dwComp == bih.biCompression)) || ((wBPP == 0) && (dwComp == 0)))
  245.        return WriteDIB(szFilename, hDIB);
  246.     hNewDIB = CopyDIB(hDIB);
  247. //    StartWait();
  248.     
  249.     hDIB = ChangeDIBFormat(hNewDIB, wBPP, dwComp);
  250.     if (hDIB) {
  251.       bReturn = WriteDIB(szFilename, hDIB);
  252.       GlobalFreeDIB(hDIB);
  253.     } else {
  254.       bReturn = FALSE;
  255.       GlobalFreeDIB(hNewDIB);
  256.     }
  257. //    EndWait();
  258.      
  259.     return bReturn;
  260.  }
  261. /******************************************************************************
  262.  *                                                                            *
  263.  *  FUNCTION   : DIBInfo(HANDLE hbi, LPBITMAPINFOHEADER lpbih)                *
  264.  *                                                                            *
  265.  *  PURPOSE    : Retrieves the DIB info associated with a CF_DIB              *
  266.  *               format memory block.                                         *
  267.  *                                                                            *
  268.  *  RETURNS    : TRUE  - if successful.                                       *
  269.  *               FALSE - otherwise                                            *
  270.  *                                                                            *
  271.  *****************************************************************************/
  272. BOOL DIBInfo(HANDLE hbi, LPBITMAPINFOHEADER lpbih)
  273. {
  274.     if (hbi){
  275.       *lpbih = *(LPBITMAPINFOHEADER)hbi;
  276.       /* fill in the default fields */
  277.       if (NEW_DIB_FORMAT(lpbih)) {
  278.         if (lpbih->biSizeImage == 0L)
  279.           lpbih->biSizeImage = WIDTHBYTES(lpbih->biWidth*lpbih->biBitCount) * lpbih->biHeight;
  280.         if (lpbih->biClrUsed == 0L)
  281.           lpbih->biClrUsed = DIBNumColors (lpbih);
  282.       }
  283.       return TRUE;
  284.     }
  285.     return FALSE;
  286. }
  287. /******************************************************************************
  288.  *                                                                            *
  289.  *  FUNCTION   : CreateBIPalette(LPBITMAPINFOHEADER lpbih)                    *
  290.  *                                                                            *
  291.  *  PURPOSE    : Given a Pointer to a BITMAPINFO struct will create a         *
  292.  *               a GDI palette object from the color table.                   *
  293.  *                                                                            *
  294.  *  RETURNS    : A handle to the palette.                                     *
  295.  *                                                                            *
  296.  *****************************************************************************/
  297.               
  298. HPALETTE CreateBIPalette(LPBITMAPINFOHEADER lpbih)
  299. {
  300.     HPALETTE       hPal = NULL;
  301.     WORD           nNumColors;
  302.     LPRGBQUAD      lprgbq;
  303.     if (!lpbih)
  304.         return NULL;
  305.     if (!NEW_DIB_FORMAT(lpbih))  // Return if we dont have a BITMAPINFOHEADER
  306.         return NULL;
  307.     /* Get a pointer to the color table and the number of colors in it */
  308.     lprgbq = (LPRGBQUAD)((LPSTR)lpbih + (WORD)lpbih->biSize);
  309.     /* Adjust pointer for cases where BITFIELDS bitmaps might contain an optimal palette */
  310.     if (lpbih->biCompression == BI_BITFIELDS)
  311.       lprgbq = (LPRGBQUAD)((LPDWORD)lprgbq + 3); 
  312.     nNumColors = DIBNumColors(lpbih);
  313. lpbih->biClrUsed = nNumColors;
  314.     if (nNumColors)   /* Create a palette from the entries in the DIBs color table */
  315.         hPal = CreatePaletteFromRGBQUAD(lprgbq, nNumColors);
  316.     else 
  317.         {
  318.           HDC hDC = GetDC(NULL);
  319.           hPal = CreateHalftonePalette(hDC);
  320.           ReleaseDC(NULL, hDC);
  321.         } ;
  322.   
  323.     return hPal;
  324. }
  325. /******************************************************************************
  326.  *                                                                            *
  327.  *  FUNCTION   : ReadDIBBitmapInfo(int hFile)                                 *
  328.  *                                                                            *
  329.  *  PURPOSE    : Will read a file in DIB format and return a global HANDLE    *
  330.  *               to it's BITMAPINFO.  This function will work with both       *
  331.  *               "old" (BITMAPCOREHEADER) and "new" (BITMAPINFOHEADER)        *
  332.  *               bitmap formats, but will always return a "new" BITMAPINFO    *
  333.  *                                                                            *
  334.  *  RETURNS    : A handle to the BITMAPINFO of the DIB in the file.           *
  335.  *                                                                            *
  336.  *****************************************************************************/
  337. HANDLE ReadDIBBitmapInfo(INT hFile)
  338. {
  339.     DWORD              dwOffset;
  340.     HANDLE             hbi = NULL;
  341.     INT                size;
  342.     INT                i;
  343.     WORD               nNumColors;
  344.     LPRGBQUAD          lprgbq;
  345.     BITMAPINFOHEADER   bih;
  346.     BITMAPCOREHEADER   bch;
  347.     LPBITMAPINFOHEADER lpbih;
  348.     BITMAPFILEHEADER   bf;
  349.     DWORD              dwDWMasks= 0;
  350.     DWORD              dwWidth = 0;
  351.     DWORD              dwHeight = 0;
  352.     WORD               wPlanes, wBitCount;
  353.     if (hFile == HFILE_ERROR)
  354.         return NULL;
  355.     /* Read the bitmap file header */
  356.     ReadPackedFileHeader(hFile, &bf, &dwOffset);
  357.     /* Do we have a RC HEADER? */
  358.     if (!ISDIB (bf.bfType)) {    
  359.       bf.bfOffBits = 0L;               
  360.         _llseek(hFile, dwOffset, (UINT)SEEK_SET); /* seek back to beginning of file */
  361.     }
  362.     if (sizeof(bih) != _hread(hFile, (LPSTR)&bih, (UINT)sizeof(bih)))
  363.       return FALSE;
  364.     nNumColors = DIBNumColors (&bih);
  365.     /* Check the nature (BITMAPINFO or BITMAPCORE) of the info. block
  366.      * and extract the field information accordingly. If a BITMAPCOREHEADER, 
  367.      * transfer it's field information to a BITMAPINFOHEADER-style block
  368.      */
  369.     switch (size = (INT)bih.biSize){
  370.         case sizeof (BITMAPINFOHEADER):
  371.             break;
  372.         case sizeof (BITMAPCOREHEADER):
  373.             bch = *(LPBITMAPCOREHEADER)&bih;
  374.             dwWidth   = (DWORD)bch.bcWidth;
  375.             dwHeight  = (DWORD)bch.bcHeight;
  376.             wPlanes   = bch.bcPlanes;
  377.             wBitCount = bch.bcBitCount;
  378.             bih.biSize           = sizeof(BITMAPINFOHEADER);
  379.             bih.biWidth          = dwWidth;
  380.             bih.biHeight         = dwHeight;
  381.             bih.biPlanes         = wPlanes;
  382.             bih.biBitCount       = wBitCount;
  383.             bih.biCompression    = BI_RGB;
  384.             bih.biSizeImage      = 0;
  385.             bih.biXPelsPerMeter  = 0;
  386.             bih.biYPelsPerMeter  = 0;
  387.             bih.biClrUsed        = nNumColors;
  388.             bih.biClrImportant   = nNumColors;
  389.             _llseek(hFile, (LONG)sizeof (BITMAPCOREHEADER) - sizeof (BITMAPINFOHEADER), (UINT)SEEK_CUR);
  390.             break;
  391.         default:
  392.             /* Not a DIB! */
  393.             return NULL;
  394.     }
  395.     /*  Fill in some default values if they are zero */
  396.     if (bih.biSizeImage == 0){
  397.         bih.biSizeImage = WIDTHBYTES((DWORD)bih.biWidth * bih.biBitCount) * bih.biHeight;
  398.     }
  399.     if (bih.biClrUsed == 0)
  400.         bih.biClrUsed = DIBNumColors(&bih);
  401.     /* Allocate for the BITMAPINFO structure and the color table. */
  402.     if ((bih.biBitCount == 16) || (bih.biBitCount == 32))
  403.       dwDWMasks = sizeof(DWORD) * 3;
  404.     hbi = GlobalAlloc (GPTR, (LONG)bih.biSize + nNumColors * sizeof(RGBQUAD) + dwDWMasks);
  405.     if (!hbi)
  406.         return NULL;
  407.     lpbih = (LPBITMAPINFOHEADER)hbi;
  408.     *lpbih = bih;
  409.     /* Get a pointer to the color table */
  410.     lprgbq = (LPRGBQUAD)((LPSTR)lpbih + bih.biSize);
  411.     if (nNumColors){
  412.         if (size == sizeof(BITMAPCOREHEADER)){
  413.             /* Convert a old color table (3 byte RGBTRIPLEs) to a new
  414.              * color table (4 byte RGBQUADs)
  415.              */
  416.             _hread(hFile, (LPSTR)lprgbq, (UINT)nNumColors * sizeof(RGBTRIPLE));
  417.             for (i = nNumColors - 1; i >= 0; i--){
  418.                 RGBQUAD rgbq;
  419.                 rgbq.rgbRed      = ((RGBTRIPLE*)lprgbq)[i].rgbtRed;
  420.                 rgbq.rgbBlue     = ((RGBTRIPLE*)lprgbq)[i].rgbtBlue;
  421.                 rgbq.rgbGreen    = ((RGBTRIPLE*)lprgbq)[i].rgbtGreen;
  422.                 rgbq.rgbReserved = (BYTE)0;
  423.                 lprgbq[i] = rgbq;
  424.             }
  425.         }
  426.         else
  427.             _hread(hFile, (LPSTR)lprgbq, (UINT)nNumColors * sizeof(RGBQUAD));
  428.     } else
  429.         if (dwDWMasks)
  430.            _hread(hFile, (LPSTR)lprgbq, dwDWMasks);
  431.     if (bf.bfOffBits != 0L){
  432.         _llseek(hFile, dwOffset + bf.bfOffBits, (UINT)SEEK_SET);
  433.         }
  434.     
  435.     return hbi;
  436. }
  437. /******************************************************************************
  438.  *                                                                            *
  439.  *  FUNCTION   :  ColorTableSize(LPVOID lpv)                                  *
  440.  *                                                                            *
  441.  *  PURPOSE    :  Calculates the palette size in bytes. If the info. block    *
  442.  *                is of the BITMAPCOREHEADER type, the number of colors is    *
  443.  *                multiplied by 3 to give the palette size, otherwise the     *
  444.  *                number of colors is multiplied by 4.                        *
  445.  *                                                                            *
  446.  *  RETURNS    :  Color table size in number of bytes.                        *
  447.  *                                                                            *
  448.  *****************************************************************************/
  449. WORD ColorTableSize(LPVOID lpv)
  450. {
  451.     LPBITMAPINFOHEADER lpbih = (LPBITMAPINFOHEADER)lpv;
  452.     
  453.     if (NEW_DIB_FORMAT(lpbih))
  454.     {
  455.       if (((LPBITMAPINFOHEADER)(lpbih))->biCompression == BI_BITFIELDS)
  456.          /* Remember that 16/32bpp dibs can still have a color table */
  457.          return (sizeof(DWORD) * 3) + (DIBNumColors (lpbih) * sizeof (RGBQUAD));
  458.       else
  459.          return (DIBNumColors (lpbih) * sizeof (RGBQUAD));
  460.     }
  461.     else
  462.       return (DIBNumColors (lpbih) * sizeof (RGBTRIPLE));
  463. }
  464. /******************************************************************************
  465.  *                                                                            *
  466.  *  FUNCTION   : DIBNumColors(LPVOID lpv)                                     *
  467.  *                                                                            *
  468.  *  PURPOSE    : Determines the number of colors in the DIB by looking at     *
  469.  *               the BitCount and ClrUsed fields in the info block.           *
  470.  *                                                                            *
  471.  *  RETURNS    : The number of colors in the DIB. With DIBS with more than    *
  472.  *               8-bits-per-pixel that have a color table table included,     *
  473.  *               then the return value will be the number of colors in the    *
  474.  *               color table rather than the number of colors in the DIB.     *
  475.  *                                                                            *
  476.  *                                                                            *
  477.  *****************************************************************************/
  478. WORD DIBNumColors(LPVOID lpv)
  479. {
  480.     INT                 bits;
  481.     LPBITMAPINFOHEADER  lpbih = (LPBITMAPINFOHEADER)lpv;
  482.     LPBITMAPCOREHEADER  lpbch = (LPBITMAPCOREHEADER)lpv;
  483.     /*  With the BITMAPINFO format headers, the size of the palette
  484.      *  is in biClrUsed, whereas in the BITMAPCORE - style headers, it
  485.      *  is dependent on the bits per pixel ( = 2 raised to the power of
  486.      *  bits/pixel).
  487.      */
  488.     if (NEW_DIB_FORMAT(lpbih)) {
  489.       if (lpbih->biClrUsed != 0)
  490.         return (WORD)lpbih->biClrUsed;
  491.       bits = lpbih->biBitCount;
  492.     }
  493.     else
  494.       bits = lpbch->bcBitCount;
  495.     if (bits > 8) 
  496.       return 0; /* Since biClrUsed is 0, we dont have a an optimal palette */
  497.     else
  498.       return (1 << bits); 
  499. }
  500. /******************************************************************************
  501.  *                                                                            *
  502.  *  FUNCTION   : DIBFromBitmap()                                              *
  503.  *                                                                            *
  504.  *  PURPOSE    : Will create a global memory block in DIB format that         *
  505.  *               represents the Device-dependent bitmap (DDB) passed in.      *
  506.  *                                                                            *
  507.  *  RETURNS    : A handle to the DIB                                          *
  508.  *                                                                            *
  509.  *****************************************************************************/
  510. HANDLE DIBFromBitmap(HBITMAP hBitmap, DWORD biStyle, WORD biBits, HPALETTE hPal)
  511. {
  512.     BITMAP               Bitmap;
  513.     BITMAPINFOHEADER     bih;
  514.     LPBITMAPINFOHEADER   lpbih;
  515.     DWORD                dwLen;
  516.     HANDLE               hDIB;
  517.     HANDLE               hMem;
  518.     HDC                  hDC;
  519.     if (!hBitmap)
  520.         return NULL;
  521.     if (hPal == NULL)
  522.         hPal = (HPALETTE) GetStockObject(DEFAULT_PALETTE);
  523.     GetObject(hBitmap, sizeof(Bitmap), (LPSTR)&Bitmap);
  524.     if (biBits == 0)
  525.         biBits =  Bitmap.bmPlanes * Bitmap.bmBitsPixel;
  526.     bih.biSize            = sizeof(BITMAPINFOHEADER);
  527.     bih.biWidth           = Bitmap.bmWidth;
  528.     bih.biHeight          = Bitmap.bmHeight;
  529.     bih.biPlanes          = 1;
  530.     bih.biBitCount        = biBits;
  531.     bih.biCompression     = biStyle;
  532.     bih.biSizeImage       = 0;
  533.     bih.biXPelsPerMeter   = 0;
  534.     bih.biYPelsPerMeter   = 0;
  535.     bih.biClrUsed         = 0;
  536.     bih.biClrImportant    = 0;
  537.     dwLen  = bih.biSize + ColorTableSize(&bih);
  538.     hDC = GetDC(NULL);
  539.     hPal = SelectPalette(hDC, hPal, FALSE);
  540.     RealizePalette(hDC);
  541.     hDIB = GlobalAlloc(GPTR, dwLen);
  542.     if (!hDIB) {
  543.         SelectPalette(hDC, hPal, FALSE);
  544.         ReleaseDC(NULL, hDC);
  545.         return NULL;
  546.     }
  547.     lpbih = (LPBITMAPINFOHEADER)hDIB;
  548.     *lpbih = bih;
  549.     /*  call GetDIBits with a NULL lpBits param, so it will calculate the
  550.      *  biSizeImage field for us
  551.      */
  552.     GetDIBits(hDC, 
  553.               hBitmap, 
  554.               (UINT)0, 
  555.               (UINT)bih.biHeight, 
  556.               (LPVOID)NULL, 
  557.               (LPBITMAPINFO)lpbih, 
  558.               DIB_RGB_COLORS);
  559.     bih = *lpbih;
  560.     /* If the driver did not fill in the biSizeImage field, make one up */
  561.     if (bih.biSizeImage == 0){
  562.         bih.biSizeImage = WIDTHBYTES((DWORD)Bitmap.bmWidth * biBits) * Bitmap.bmHeight;
  563.         if (biStyle != BI_RGB)
  564.             bih.biSizeImage = (bih.biSizeImage * 3) / 2;
  565.     }
  566.     /*  realloc the buffer big enough to hold all the bits */
  567.     dwLen = bih.biSize + ColorTableSize(&bih) + bih.biSizeImage;
  568.     if (hMem = GlobalReAlloc(hDIB, dwLen, GMEM_MOVEABLE))
  569.         hDIB = hMem;
  570.     else {
  571.         GlobalFreeDIB(hDIB);
  572.         hDIB = NULL;
  573.         SelectPalette(hDC, hPal, FALSE);
  574.         ReleaseDC(NULL, hDC);
  575.         return hDIB;
  576.     }
  577.     /*  call GetDIBits with a NON-NULL lpBits param, and actualy get the
  578.      *  bits this time
  579.      */
  580.     lpbih = (LPBITMAPINFOHEADER)hDIB;
  581.     if (!GetDIBits(hDC, 
  582.                    hBitmap, 
  583.                    (UINT)0, 
  584.                    (UINT)bih.biHeight, 
  585.                    (LPBYTE)lpbih + (WORD)lpbih->biSize + ColorTableSize(lpbih), 
  586.                    (LPBITMAPINFO)lpbih, 
  587.                    DIB_RGB_COLORS)) {
  588.          hDIB = NULL;
  589.          SelectPalette(hDC, hPal, FALSE);
  590.          ReleaseDC(NULL, hDC);
  591.          return NULL;
  592.     }
  593.     bih = *lpbih;
  594.     SelectPalette(hDC, hPal, FALSE);
  595.     ReleaseDC(NULL, hDC);
  596.     return hDIB;
  597. }
  598. /******************************************************************************
  599.  *                                                                            *
  600.  *  FUNCTION   : BitmapFromDIB(HANDLE hDIB, HPALETTE hPal)                    *
  601.  *                                                                            *
  602.  *  PURPOSE    : Will create a DDB (Device Dependent Bitmap) given a global   *
  603.  *               handle to a memory block in CF_DIB format                    *
  604.  *                                                                            *
  605.  *  RETURNS    : A handle to the DDB.                                         *
  606.  *                                                                            *
  607.  *****************************************************************************/
  608. HBITMAP BitmapFromDIB(HANDLE hDIB, HPALETTE hPal)
  609. {
  610.     LPBITMAPINFOHEADER  lpbih;
  611.     HPALETTE            hPalOld;
  612.     HDC                 hDC;
  613.     HBITMAP             hBitmap;  
  614. //    StartWait();
  615.     if (!hDIB)
  616.         return NULL;
  617.     lpbih = (LPBITMAPINFOHEADER)hDIB;
  618.     if (!lpbih)
  619.         return NULL;
  620.     hDC = GetDC(NULL);
  621.     if (hPal){
  622.         hPalOld = SelectPalette(hDC, hPal, FALSE);
  623.         RealizePalette(hDC);     // GDI Bug...????
  624.     }                              
  625.    
  626.     hBitmap = CreateDIBitmap(hDC, 
  627.                 lpbih, 
  628.                 CBM_INIT, 
  629.                 (LPSTR)lpbih + lpbih->biSize + ColorTableSize(lpbih), 
  630.                 (LPBITMAPINFO)lpbih, 
  631.                 DIB_RGB_COLORS ); 
  632.     if (hPal)
  633.         SelectPalette(hDC, hPalOld, FALSE);
  634.     ReleaseDC(NULL, hDC);
  635. //    EndWait();
  636.     return hBitmap;
  637. }
  638. /******************************************************************************
  639.  *                                                                            *
  640.  *  FUNCTION   : DrawBitmap(HDC hDC, int x, int y,                            *
  641.  *                          HBITMAP hBitmap, DWORD dwROP)                     * 
  642.  *                                                                            *
  643.  *  PURPOSE    : Draws bitmap <hBitmap> at the specifed position in DC <hDC>  *
  644.  *                                                                            *
  645.  *  RETURNS    : Return value of BitBlt()                                     *
  646.  *                                                                            *
  647.  *****************************************************************************/
  648. BOOL DrawBitmap(HDC hDC, INT x, INT y, HBITMAP hBitmap, DWORD dwROP)
  649. {
  650.     HDC       hDCBits;
  651.     BITMAP    Bitmap;
  652.     BOOL      bResult;
  653.     if (!hDC || !hBitmap)
  654.         return FALSE;
  655.     hDCBits = CreateCompatibleDC(hDC);
  656.     GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
  657.     SelectObject(hDCBits, hBitmap);
  658.     bResult = BitBlt(hDC, x, y, Bitmap.bmWidth, Bitmap.bmHeight, hDCBits, 0, 0, dwROP);
  659.     DeleteDC(hDCBits);
  660.     return bResult;
  661. }
  662. /******************************************************************************
  663.  *                                                                            *
  664.  *  FUNCTION   : DIBBlt( HDC hDC,                                             *
  665.  *                       int x0, int y0,                                      *
  666.  *                       int dx, int dy,                                      *
  667.  *                       HANDLE hDIB,                                         *
  668.  *                       int x1, int y1,                                      *
  669.  *                       LONG dwROP)                                          *
  670.  *                                                                            *
  671.  *  PURPOSE    : Draws a bitmap in CF_DIB format, using SetDIBits to device.  *
  672.  *               taking the same parameters as BitBlt().                      *
  673.  *                                                                            *
  674.  *  RETURNS    : TRUE  - if function succeeds.                                *
  675.  *               FALSE - otherwise.                                           *
  676.  *                                                                            *
  677.  ******************************************************************************/
  678. BOOL DIBBlt (HDC hDC,     INT x0, INT y0, INT dx, INT dy, 
  679.   HANDLE hDIB, INT x1, INT y1, LONG  dwROP)
  680. {
  681.     LPBITMAPINFOHEADER   lpbih;
  682.     LPSTR                pBuf;
  683.     if (!hDIB)
  684.         return PatBlt(hDC, x0, y0, dx, dy, dwROP);
  685.     lpbih = (LPBITMAPINFOHEADER)hDIB;
  686.     if (!lpbih)
  687.         return FALSE;
  688.     pBuf = (LPSTR)lpbih + (WORD)lpbih->biSize + ColorTableSize(lpbih);
  689.     SetDIBitsToDevice (hDC, x0, y0, dx, dy, 
  690.                        x1, y1, 
  691.                        x1, 
  692.                        dy, 
  693.                        pBuf, (LPBITMAPINFO)lpbih, 
  694.                        DIB_RGB_COLORS );
  695.     return TRUE;
  696. }
  697. /******************************************************************************
  698.  *                                                                            *
  699.  *  FUNCTION   : StretchDIBBlt( HDC hDC,                                      *
  700.  *                              int x, int y,                                 *
  701.  *                              int dx, int dy,                               *
  702.  *                              HANDLE hDIB,                                  *
  703.  *                              int x0, int y0,                               *
  704.  *                              int dx0, int dy0,                             *
  705.  *                              LONG dwROP)                                   *
  706.  *                                                                            *
  707.  *  PURPOSE    : Draws a bitmap in CF_DIB format, using StretchDIBits()       *
  708.  *               taking the same parameters as StretchBlt().                  *
  709.  *                                                                            *
  710.  *  RETURNS    : TRUE  - if function succeeds.                                *
  711.  *               FALSE - otherwise.                                           *
  712.  *                                                                            *
  713.  ******************************************************************************/
  714. BOOL StretchDIBBlt (HDC hDC,     INT x,  INT y,  INT dx,  INT dy, 
  715. HANDLE hDIB, INT x0, INT y0, INT dx0, INT dy0, LONG dwROP)
  716. {
  717.     LPBITMAPINFOHEADER lpbih;
  718.     LPSTR        pBuf;
  719.     BOOL         bResult;
  720.     if (!hDIB)
  721.         return PatBlt(hDC, x, y, dx, dy, dwROP);
  722.     lpbih = (LPBITMAPINFOHEADER)hDIB;
  723.     if (!lpbih)
  724.         return FALSE;
  725.     pBuf = (LPSTR)lpbih + (WORD)lpbih->biSize + ColorTableSize(lpbih);
  726.     
  727.     bResult = StretchDIBits (hDC, x,  y,  dx,  dy, 
  728.                                   x0, y0, dx0, dy0, 
  729.                              pBuf, (LPBITMAPINFO)lpbih, 
  730.                              DIB_RGB_COLORS, dwROP);
  731.     return bResult;
  732. }
  733. /******************************************************************************
  734.  *                                                                            *
  735.  *  FUNCTION   : ReadPackedFileHeader(HFILE hFile, LPBITMAPFILEHEADER pbf)    *
  736.  *                                                                            *
  737.  *  PURPOSE    : read file header (which is packed) and convert into          *
  738.  *               unpacked BITMAPFILEHEADER strucutre                          *
  739.  *                                                                            *
  740.  *  RETURNS    : VOID                                                         *
  741.  *                                                                            *
  742.  *****************************************************************************/
  743. VOID ReadPackedFileHeader(HFILE hFile, LPBITMAPFILEHEADER lpbmfhdr, LPDWORD lpdwOffset)
  744. {
  745.     *lpdwOffset = _llseek(hFile, 0L, (UINT) SEEK_CUR);
  746.     _hread(hFile, (LPSTR) &lpbmfhdr->bfType, sizeof(WORD)); /* read in bfType*/            
  747.     _hread(hFile, (LPSTR) &lpbmfhdr->bfSize, sizeof(DWORD) * 3); /* read in last 3 dwords*/
  748. }
  749.   
  750. /******************************************************************************
  751.  *                                                                            *
  752.  *  FUNCTION   : WritePackedFileHeader(HFILE hFile, LPBITMAPFILEHEADER pbf)   *
  753.  *                                                                            *
  754.  *  PURPOSE    : write header structure (which NOT packed) and write          *
  755.  *               it out in PACKED format                                      *
  756.  *                                                                            *
  757.  *  RETURNS    : VOID                                                         *
  758.  *                                                                            *
  759.  *****************************************************************************/
  760. VOID WritePackedFileHeader(HFILE hFile, LPBITMAPFILEHEADER lpbmfhdr)
  761. {                                                       
  762.     _hwrite(hFile, (LPSTR)&lpbmfhdr->bfType, (UINT)sizeof (WORD)); 
  763.     /* pass over extra word and write next 3 DWORDS! */
  764.     _hwrite(hFile, (LPSTR)&lpbmfhdr->bfSize, sizeof(DWORD) * 3);   
  765. }
  766. /******************************************************************************
  767.  *                                                                            *
  768.  * HANDLE ConvertRGBDIB(HANDLE hSrcDIB, DWORD dwDstComp, WORD wDstBPP)        *
  769.  *                                                                            *
  770.  * Parameter:                                                                 *
  771.  *                                                                            *
  772.  * HDIB             - handle to packed-DIB in memory                          *
  773.  * WORD             - desired bits per pixel                                  *
  774.  * DWORD            - desired compression format                              *
  775.  *                                                                            *
  776.  * Return Value:                                                              *
  777.  *                                                                            *
  778.  * HDIB             - handle to the new DIB if successful, else NULL          *
  779.  *                                                                            *
  780.  * Description:                                                               *
  781.  *                                                                            *
  782.  * This function will create a new DIB with the specified BPP format using an *
  783.  * existing DIB as the source of the bits.  The conversion method will keep   *
  784.  * as much of the color information as possible. Both source and destination  *
  785.  * must be at least 16 bits-per-pixel.                                        *
  786.  *                                                                            *
  787.  * *Notes:                                                                    *
  788.  *    The source DIB is never destroyed                                       *
  789.  *    This function is not exposed and it is only called by ChangeDIBFormat() *
  790.  *    The function will return NULL if it fails                               *
  791.  *                                                                            *
  792.  *****************************************************************************/
  793. HANDLE ConvertRGBDIB(HANDLE hSrcDIB, DWORD dwDstComp, WORD wDstBPP)
  794. {
  795.     HDC hDC = GetDC(NULL);
  796.     HDC hSrcMemDC = CreateCompatibleDC(NULL);
  797.     HDC hDstMemDC = CreateCompatibleDC(NULL);
  798.     HBITMAP hSrcBmp = NULL, hDstBmp = NULL;
  799.     HANDLE hDstDIB = NULL;
  800.   LPBITMAPINFOHEADER biSrcPtr, biDstPtr;
  801.     LPRGBQUAD rgbqSrcPtr, rgbqDstPtr; 
  802.     RGBTRIPLE *bmSrcPtr, *bmDstPtr;
  803.     LPVOID pSrcDisp, pDstDisp;                                
  804.     __try {
  805.         /* This method of conversion only works with > 8bpp format DIBs */
  806.         if ((wDstBPP < 16) || (GetDIBBitCount(hSrcDIB) < 16))
  807.           RAISE_AN_EXCEPTION();
  808.         /* Initialize pointers for the source DIB */
  809.         if (!GetDIBPointers(hSrcDIB, (LPVOID*)&biSrcPtr, (LPVOID*)&rgbqSrcPtr, (LPVOID*)&bmSrcPtr))
  810.           RAISE_AN_EXCEPTION();
  811.         /* Create destination DIB and initialize pointers for it */
  812.         hDstDIB = CreateRGBDIB(biSrcPtr->biWidth, biSrcPtr->biHeight, wDstBPP, dwDstComp);
  813.         if (!GetDIBPointers(hDstDIB, (LPVOID*)&biDstPtr, (LPVOID*)&rgbqDstPtr, (LPVOID*)&bmDstPtr))
  814.           RAISE_AN_EXCEPTION();
  815.     
  816.      /* Create and load source DIB into source bitmap */
  817.      hSrcBmp = CreateDIBSection(hDC, (LPBITMAPINFO)biSrcPtr, 0, &pSrcDisp, NULL, 0);
  818.         if (!SelectObject(hSrcMemDC, hSrcBmp))
  819.           RAISE_AN_EXCEPTION();
  820.      CopyMemory(pSrcDisp, bmSrcPtr, biSrcPtr->biSizeImage);
  821.         /* Create destination bitmap */
  822.         hDstBmp = CreateDIBSection(hDC, (LPBITMAPINFO)biDstPtr, 0, &pDstDisp, NULL, 0);
  823.         if (!SelectObject(hDstMemDC, hDstBmp))
  824.           RAISE_AN_EXCEPTION();
  825.         /* Make GDI do the conversion between the different BPP formats */
  826.         BitBlt(hDstMemDC, 0, 0, biSrcPtr->biWidth, biSrcPtr->biHeight,
  827.                hSrcMemDC, 0, 0, SRCCOPY);
  828.         GdiFlush();
  829.           
  830.         /* Copy the converted data to our destination DIB */
  831.         CopyMemory(bmDstPtr, pDstDisp, biDstPtr->biSizeImage);
  832.     } __except (EXCEPTION_EXECUTE_HANDLER) {
  833.         /* Something got hosed, make sure we deallocate our destination DIB */
  834.         if (hDstDIB) {
  835.           GlobalFreeDIB(hDstDIB);
  836.           hDstDIB = NULL;
  837.         }                
  838.     }
  839.     /* Clean up the mess we made */
  840.     if (hDC) ReleaseDC(NULL, hDC);
  841.     if (hSrcMemDC) DeleteDC(hSrcMemDC);
  842.     if (hDstMemDC) DeleteDC(hDstMemDC);
  843.     if (hSrcBmp) DeleteObject(hSrcBmp);
  844.     if (hDstBmp) DeleteObject(hDstBmp);
  845.     return hDstDIB;          
  846. }
  847. /******************************************************************************
  848.  *                                                                            *
  849.  * HANDLE ChangeDIBFormat(HANDLE hDIB, WORD wBPP, DWORD dwComp)               *
  850.  *                                                                            *
  851.  * Parameter:                                                                 *
  852.  *                                                                            *
  853.  * HDIB             - handle to packed-DIB in memory                          *
  854.  * WORD             - desired bits per pixel                                  *
  855.  * DWORD            - desired compression format                              *
  856.  *                                                                            *
  857.  * Return Value:                                                              *
  858.  *                                                                            *
  859.  * HDIB             - handle to the new DIB if successful, else NULL          *
  860.  *                                                                            *
  861.  * Description:                                                               *
  862.  *                                                                            *
  863.  * This function will convert the bits per pixel and/or the compression       *
  864.  * format of the specified DIB. Note: If the conversion was unsuccessful,     *
  865.  * we return NULL. The original DIB is left alone. Don't use code like the    *
  866.  * following:                                                                 *
  867.  *                                                                            *
  868.  *    hMyDIB = ChangeDIBFormat(hMyDIB, 8, BI_RLE4);                           *
  869.  *                                                                            *
  870.  * The conversion will fail, but hMyDIB will now be NULL and the original     *
  871.  * DIB will now hang around in memory. We could have returned the old         *
  872.  * DIB, but we wanted to allow the programmer to check whether this           *
  873.  * conversion succeeded or failed.                                            *
  874.  *                                                                            *
  875.  *****************************************************************************/
  876. HANDLE ChangeDIBFormat(HANDLE hDIB, WORD wBPP, DWORD dwComp)
  877. {
  878.    HBITMAP            hBitmap;              // Handle to bitmap
  879.    LPBITMAPINFOHEADER lpbih;                // Pointer to bitmap info
  880.    HANDLE             hNewDIB = NULL;       // Handle to new DIB
  881.    HPALETTE           hPal;                 // Handle to palette, prev pal
  882.    WORD               wOldBPP, wNewBPP;     // DIB bits per pixel, new bpp
  883.    DWORD              dwOldComp, dwNewComp; // DIB compression, new compression
  884.     
  885.    /* Check for a valid DIB handle */
  886.    if (!hDIB)
  887.       return NULL;
  888.    
  889.    /* Get the old DIB's bits per pixel and compression format */
  890.    lpbih = (LPBITMAPINFOHEADER)hDIB;
  891.    wOldBPP = lpbih->biBitCount;
  892.    dwOldComp = lpbih->biCompression;
  893.    /* Validate wBPP and dwComp
  894.     * They must match correctly (i.e., BI_RLE4 and 4 BPP or
  895.     * BI_RLE8 and 8BPP, etc.) or we return failure */
  896.    if (wBPP == 0) {
  897.       wNewBPP = wOldBPP;
  898.       if ((dwComp == BI_RLE4 && wNewBPP == 4) ||
  899.           (dwComp == BI_RLE8 && wNewBPP == 8) ||
  900.           (dwComp == BI_RGB))
  901.         dwNewComp = dwComp;
  902.       else
  903.         return NULL;
  904.       }
  905.    else if (wBPP == 1 && dwComp == BI_RGB) {
  906.       wNewBPP = wBPP;
  907.       dwNewComp = BI_RGB;
  908.       }
  909.    else if (wBPP == 4) {
  910.       wNewBPP = wBPP;
  911.       if (dwComp == BI_RGB || dwComp == BI_RLE4)
  912.         dwNewComp = dwComp;
  913.       else
  914.         return NULL;
  915.       }
  916.    else if (wBPP == 8) {
  917.       wNewBPP = wBPP;
  918.       if (dwComp == BI_RGB || dwComp == BI_RLE8)
  919.         dwNewComp = dwComp;
  920.       else
  921.         return NULL;
  922.       }
  923.    else if (wBPP == 24 && dwComp == BI_RGB) {
  924.       wNewBPP = wBPP;
  925.       dwNewComp = BI_RGB;
  926.       }
  927.    else if (((wBPP == 16) || (wBPP == 32)) && 
  928.             ((dwComp == BI_BITFIELDS) || (dwComp == BI_RGB))) {
  929.         wNewBPP = wBPP;
  930.         dwNewComp = dwComp;
  931.       }
  932.    else
  933.         return NULL;
  934.    
  935.    if ((wOldBPP > 8) && (wNewBPP > 8)) 
  936.      /* Keep as much color info as possible */
  937.      hNewDIB = ConvertRGBDIB(hDIB, dwNewComp, wNewBPP);
  938.    if (!hNewDIB) {
  939.        /* Save the old DIB's palette */
  940.        hPal = CreateDIBPalette(hDIB);  
  941.        if (!hPal)
  942.           return NULL;
  943.    
  944.        /* Convert old DIB to a bitmap */
  945.        hBitmap = BitmapFromDIB(hDIB, hPal);
  946.        /* Convert Bitmap into a DIB with the new compression and BPP  */
  947.        hNewDIB = DIBFromBitmap(hBitmap, dwNewComp, wNewBPP, hPal);
  948.        
  949.        DeleteObject(hBitmap);
  950.        DeleteObject(hPal);
  951.    }
  952.    if (hNewDIB)
  953.          GlobalFreeDIB(hDIB);
  954.    return hNewDIB;
  955. }
  956. /******************************************************************************
  957.  *                                                                            *
  958.  * BOOL ChangeDIBPalette(HANDLE hDIB, HPALETTE hPal)                          *
  959.  *                                                                            *
  960.  * Parameter:                                                                 *
  961.  *                                                                            *
  962.  * HDIB             - handle to packed-DIB in memory                          *
  963.  * HPALETTE         - the new palette for the DIB                             *
  964.  *                                                                            *
  965.  * Return Value:                                                              *
  966.  *                                                                            *
  967.  * BOOL             - returns success or failure status                       *
  968.  *                                                                            *
  969.  * Description:                                                               *
  970.  *                                                                            *
  971.  * This function will remap the colors in the given DIB so that they          *
  972.  * reference the colors in the new palette - note that this is not the same   *
  973.  * changing the DIBs color table since we are forcing the bits to be          *
  974.  * remapped to new values in addition to changing the color table.            *
  975.  *                                                                            *
  976.  *****************************************************************************/
  977. BOOL ChangeDIBPalette(HANDLE hDIB, HPALETTE hPal)
  978. {
  979.    HDC                hDC;      
  980.    HBITMAP            hBitmap;  
  981.    LPBITMAPINFOHEADER lpbih;      // Pointer to bitmap info
  982.    HPALETTE           hOldPal;   // Handle to palette, prev pal
  983.       
  984.    /* Check for a valid DIB/Palette handle */
  985.    if (!hDIB || !hPal)
  986.       return FALSE;
  987.    /* Convert old DIB to a bitmap */
  988.    hBitmap = BitmapFromDIB(hDIB, hPal);
  989.    /* Make sure it worked */
  990.    if (!hBitmap) 
  991.       return FALSE;
  992.    /* Get a pointer to the DIB header */
  993.    lpbih = (LPBITMAPINFOHEADER)hDIB;
  994.    /* Get a DC and select/realize our palette in it */
  995.    hDC  = GetDC(NULL);
  996.    hOldPal = SelectPalette(hDC, hPal, FALSE);
  997.    RealizePalette(hDC);
  998.    /* Call GetDIBits and get the new DIB bits */
  999.    if (!GetDIBits(hDC, 
  1000.                   hBitmap, 
  1001.                   (UINT)0, 
  1002.                   (UINT)lpbih->biHeight, 
  1003.                   (LPBYTE)lpbih + (WORD)lpbih->biSize + ColorTableSize((LPSTR)lpbih), 
  1004.                   (LPBITMAPINFO)lpbih, 
  1005.                   DIB_RGB_COLORS)) 
  1006.       return FALSE;
  1007.    /* Clean up and return */
  1008.    SelectPalette(hDC, hOldPal, TRUE);
  1009.    RealizePalette(hDC);
  1010.    ReleaseDC(NULL, hDC);
  1011.    DeleteObject(hBitmap);
  1012.    return TRUE;
  1013. }
  1014. /******************************************************************************
  1015.  *                                                                            *
  1016.  * HANDLE CopyDIB(HANDLE hDIBSrc)                                             *
  1017.  *                                                                            *
  1018.  * Parameter:                                                                 *
  1019.  *                                                                            *
  1020.  * HANDLE           - The handle to the DIB you want to make a copy of.       *
  1021.  *                                                                            *
  1022.  * Return Value:                                                              *
  1023.  *                                                                            *
  1024.  * HANDLE           - A copy of the DIB passed as a parameter                 *  
  1025.  *                                                                            *
  1026.  *****************************************************************************/
  1027. HANDLE CopyDIB(HANDLE hDIBSrc)
  1028. {
  1029.   HANDLE hDIBDst = NULL;
  1030.   DWORD dwSize = GlobalSize(hDIBSrc);
  1031.     
  1032.   if (!hDIBSrc) 
  1033.     return NULL;
  1034.   
  1035.   hDIBDst = GlobalAlloc(GPTR, dwSize);
  1036.   if (!hDIBDst) 
  1037.     return NULL;
  1038.     
  1039.   CopyMemory(hDIBDst, hDIBSrc, dwSize); 
  1040.   return (hDIBDst);
  1041. }
  1042. /****************************************************************************
  1043.  *                                                                          *
  1044.  *  FUNCTION   : CopyBitmap (HBITMAP hBitmap)                               *
  1045.  *                                                                          *
  1046.  *  PURPOSE    : Copies the given bitmap to another.                        *
  1047.  *                                                                          *
  1048.  *  RETURNS    : A handle to the new bitmap.                                *
  1049.  *                                                                          *
  1050.  ****************************************************************************/
  1051. HBITMAP CopyBitmap (HBITMAP hBitmap)
  1052. {
  1053.     BITMAP  Bitmap;
  1054.     RECT    rect;
  1055.     if (!hBitmap)
  1056.          return NULL;
  1057.     GetObject (hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
  1058.     rect.left   = 0;
  1059.     rect.top    = 0;
  1060.     rect.right  = Bitmap.bmWidth;
  1061.     rect.bottom = Bitmap.bmHeight;
  1062.     return CropBitmap (hBitmap, &rect);
  1063. }
  1064. /****************************************************************************
  1065.  *                                                                          *
  1066.  *  FUNCTION   :  CropBitmap (HBITMAP hBitmap, LPRECT lpRect)               *
  1067.  *                                                                          *
  1068.  *  PURPOSE    :  Crops a bitmap to a new size specified by the lpRect      *
  1069.  *                parameter.                                                *
  1070.  *                                                                          *
  1071.  *  RETURNS    :  A handle to the new bitmap.                               *
  1072.  *                                                                          *
  1073.  ****************************************************************************/
  1074. HBITMAP CropBitmap (HBITMAP hBitmap, LPRECT lpRect)
  1075. {
  1076.     HDC     hMemDCsrc;
  1077.     HDC     hMemDCdst;
  1078.     HDC     hDC;
  1079.     HBITMAP hNewBm;
  1080.     BITMAP  Bitmap;
  1081.     INT     dx, dy;
  1082.     if (!hBitmap)
  1083.          return NULL;
  1084.     hDC = GetDC (NULL);
  1085.     hMemDCsrc = CreateCompatibleDC (hDC);
  1086.     hMemDCdst = CreateCompatibleDC (hDC);
  1087.     GetObject (hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
  1088.     dx = lpRect->right  - lpRect->left;
  1089.     dy = lpRect->bottom - lpRect->top;
  1090.     /*hNewBm = +++CreateBitmap - Not Recommended(use CreateDIBitmap)+++ (dx, dy, Bitmap.BitmapPlanes, Bitmap.BitmapBitsPixel, NULL);*/
  1091.     hNewBm = CreateBitmap(dx, dy, Bitmap.bmPlanes, Bitmap.bmBitsPixel, NULL);
  1092.     if (hNewBm) {
  1093.         SelectObject (hMemDCsrc, hBitmap);
  1094.         SelectObject (hMemDCdst, hNewBm);
  1095.         BitBlt (hMemDCdst, 
  1096.                 0, 
  1097.                 0, 
  1098.                 dx, 
  1099.                 dy, 
  1100.                 hMemDCsrc, 
  1101.                 lpRect->left, 
  1102.                 lpRect->top, 
  1103.                 SRCCOPY);
  1104.     }
  1105.     ReleaseDC (NULL, hDC);
  1106.     DeleteDC (hMemDCsrc);
  1107.     DeleteDC (hMemDCdst);
  1108.     return hNewBm;
  1109. }
  1110. /******************************************************************************
  1111.  *                                                                            *
  1112.  * BOOL CopyDIBData(HANDLE hDIBDst, HANDLE hDIBSrc)                           *
  1113.  *                                                                            *
  1114.  * Parameter:                                                                 *
  1115.  *                                                                            *
  1116.  * HANDLE           - The handle to the DIB you want to copy to.              *
  1117.  * HANDLE           - The handle to the DIB you want to copy from.            *
  1118.  *                                                                            *
  1119.  * Return Value:                                                              *
  1120.  *                                                                            *
  1121.  * HANDLE           - Success or failure of the function                      *  
  1122.  *                                                                            *
  1123.  *  Replaces the contents of the destination DIB with the contents of the     *
  1124.  *  source DIB.  This will fail if the initial sizes of the DIBS are          * 
  1125.  *  not equal.                                                                *
  1126.  *                                                                            *
  1127.  *****************************************************************************/
  1128. BOOL CopyDIBData(HANDLE hDIBDst, HANDLE hDIBSrc)
  1129. {
  1130.   DWORD dwDstSize = GlobalSize(hDIBDst);
  1131.   DWORD dwSrcSize = GlobalSize(hDIBSrc);
  1132.   
  1133.   if (dwDstSize != dwDstSize)
  1134.     return FALSE;
  1135.   CopyMemory(hDIBDst, hDIBSrc, dwDstSize); 
  1136.   return (TRUE);
  1137. }
  1138. /******************************************************************************
  1139.  *                                                                            *
  1140.  * HANDLE GetDIBFromClipboard(HWND hWnd)                                      *
  1141.  *                                                                            *
  1142.  * Parameter:                                                                 *
  1143.  *                                                                            *
  1144.  * HWND             - The handle of the window that will own the clipboard    *
  1145.  *                                                                            *
  1146.  * Return Value:                                                              *
  1147.  *                                                                            *
  1148.  * HANDLE           - Handle to the DIB that was on the Clipboard             *  
  1149.  *                                                                            *
  1150.  *****************************************************************************/
  1151. HANDLE GetDIBFromClipboard(HWND hWnd)
  1152. {   
  1153.   HANDLE hData;
  1154.   HANDLE hDIB;
  1155.   if (OpenClipboard(hWnd)) {
  1156.     hData = GetClipboardData(CF_DIB);
  1157. if (hData == NULL) {
  1158.    hData = GetClipboardData(CF_BITMAP);
  1159. if (hData != NULL) {
  1160.   HPALETTE hPal, hClipPal = (HPALETTE)GetClipboardData(CF_PALETTE);
  1161.   
  1162.   hPal = CopyPalette(hClipPal);
  1163.   hDIB = DIBFromBitmap((HBITMAP)hData, BI_RGB, 8, hPal);
  1164.           DeleteObject(hPal);
  1165. } else
  1166.   return NULL;
  1167. } else 
  1168. hDIB = CopyDIB(hData);
  1169.  
  1170. CloseClipboard();
  1171.   } else
  1172. return NULL;
  1173.   return hDIB;
  1174. }
  1175. /******************************************************************************
  1176.  *                                                                            *
  1177.  * BOOL GetDIBResolution(HANDLE hDIB, LONG *iXRes, LONG *iYRes)               *
  1178.  *                                                                            *
  1179.  * Parameter:                                                                 *
  1180.  *                                                                            *
  1181.  * HANDLE           - The handle to the DIB you want get the resolution of    *
  1182.  * LONG*            - Pointer to x resolution                                 *
  1183.  * LONG*            - Pointer to y resolution                                 *
  1184.  *                                                                            *
  1185.  * Return Value:                                                              *
  1186.  *                                                                            *
  1187.  * HANDLE           - Success or failure of the function                      *  
  1188.  *                                                                            *
  1189.  *  Reads the width and the height of a DIB from the BITMAPINFOHEADER and     *
  1190.  *  returns the values.                                                       *
  1191.  *                                                                            *
  1192.  *****************************************************************************/
  1193. BOOL GetDIBResolution(HANDLE hDIB, LONG *iXRes, LONG *iYRes)
  1194. {
  1195.   if (!hDIB) return FALSE;
  1196.   
  1197.   *iXRes = ((LPBITMAPINFOHEADER)hDIB)->biWidth;
  1198.   *iYRes = ((LPBITMAPINFOHEADER)hDIB)->biHeight;
  1199.   return TRUE;
  1200. }
  1201. /******************************************************************************
  1202.  *                                                                            *
  1203.  * DWORD GetDIBColorUsed(HANDLE hDIB)                                         *
  1204.  *                                                                            *
  1205.  * Parameter:                                                                 *
  1206.  *                                                                            *
  1207.  * HANDLE           - The handle to the DIB you want to check                 *
  1208.  *                                                                            *
  1209.  * Return Value:                                                              *
  1210.  *                                                                            *
  1211.  * DWORD            - Number of colors used by the DIB                        *  
  1212.  *                                                                            *
  1213.  *  Reads and returns the number of colors used from the BITMAPINFOHEADER     *
  1214.  *                                                                            *
  1215.  *****************************************************************************/
  1216. DWORD GetDIBColorUsed(HANDLE hDIB)
  1217. {
  1218.   DWORD dwClrUsed;
  1219.   if (!hDIB) 
  1220.     return 0;
  1221.   
  1222.   dwClrUsed = ((LPBITMAPINFOHEADER)hDIB)->biClrUsed;
  1223.   return dwClrUsed;
  1224. }
  1225. /******************************************************************************
  1226.  *                                                                            *
  1227.  * DWORD GetDIBCopmression(HANDLE hDIB)                                       *
  1228.  *                                                                            *
  1229.  * Parameter:                                                                 *
  1230.  *                                                                            *
  1231.  * HANDLE           - The handle to the DIB you want to check                 *
  1232.  *                                                                            *
  1233.  * Return Value:                                                              *
  1234.  *                                                                            *
  1235.  * DWORD            - The compression type for the given DIB                  *  
  1236.  *                                                                            *
  1237.  *****************************************************************************/
  1238. DWORD GetDIBCompression(HANDLE hDIB)
  1239. {
  1240.   DWORD dwComp;
  1241.   if (!hDIB) 
  1242.     return 0;
  1243.   
  1244.   dwComp = ((LPBITMAPINFOHEADER)hDIB)->biCompression;
  1245.   return dwComp;
  1246. }
  1247. /******************************************************************************
  1248.  *                                                                            *
  1249.  * DWORD GetDIBBitcount(HANDLE hDIB)                                          *
  1250.  *                                                                            *
  1251.  * Parameter:                                                                 *
  1252.  *                                                                            *
  1253.  * HANDLE           - The handle to the DIB you want to check                 *
  1254.  *                                                                            *
  1255.  * Return Value:                                                              *
  1256.  *                                                                            *
  1257.  * DWORD            - The number of bits per pixel for given DIB              *  
  1258.  *                                                                            *
  1259.  *****************************************************************************/
  1260. WORD GetDIBBitCount(HANDLE hDIB)
  1261. {
  1262.   WORD wBitCount;
  1263.   if (!hDIB) 
  1264.     return 0;
  1265.   
  1266.   wBitCount = ((LPBITMAPINFOHEADER)hDIB)->biBitCount;
  1267.   return wBitCount;
  1268. }
  1269. /******************************************************************************
  1270.  *                                                                            *
  1271.  *  FUNCTION   : CreateDIBPalette(HANDLE hbi)                                 *
  1272.  *                                                                            *
  1273.  *  PURPOSE    : Given a Global HANDLE to a BITMAPINFO Struct will create a   *
  1274.  *               GDI palette object from the color table. (BITMAPINFOHEADER   *
  1275.  *               format DIBs only)                                            *
  1276.  *                                                                            *
  1277.  *  RETURNS    : A handle to the palette.                                     *
  1278.  *                                                                            *
  1279.  *****************************************************************************/
  1280. HPALETTE CreateDIBPalette (HANDLE hbi)
  1281. {
  1282.     HPALETTE hPal;
  1283.     if (!hbi)
  1284.         return NULL;
  1285.     hPal = CreateBIPalette((LPBITMAPINFOHEADER)hbi);
  1286.     return hPal;
  1287. }
  1288. /******************************************************************************
  1289.  *                                                                            *
  1290.  *  FUNCTION   : CreateDIBPaletteEx(HANDLE hbi, BYTE bFlags)                  *
  1291.  *                                                                            *
  1292.  *  PURPOSE    : Given a Global HANDLE to a BITMAPINFO Struct will create a   *
  1293.  *               GDI palette object from the color table. (BITMAPINFOHEADER   *
  1294.  *               format DIBs only)  In addition, you can specify the palette  *
  1295.  *               palette flags for the palette entries.                       *
  1296.  *                                                                            *
  1297.  *  RETURNS    : A handle to the palette.                                     *
  1298.  *                                                                            *
  1299.  *****************************************************************************/
  1300. HPALETTE CreateDIBPaletteEx(HANDLE hDIB, BYTE bFlags)
  1301. {
  1302.     HPALETTE hPal, hNewPal;
  1303.     if (!hDIB)
  1304.         return NULL;
  1305.     hPal = CreateDIBPalette(hDIB);
  1306.     hNewPal = CopyPaletteEx(hPal, bFlags);
  1307.     DeleteObject(hPal);
  1308.        
  1309.     return hNewPal;
  1310. }
  1311. /******************************************************************************
  1312.  *                                                                            *
  1313.  *  FUNCTION   : GetDIBPointers(HANDLE hDIB, LPVOID *biPtr,                   *
  1314.  *                                     LPVOID *rgbqPtr, LPVOID *bmPtr)        *
  1315.  *                                                                            *
  1316.  *  PURPOSE    : Given a handle to a DIB in CF_DIB format, this function will *
  1317.  *               retrieve pointers for the bitmap info, color table, and bits *
  1318.  *                                                                            *
  1319.  *****************************************************************************/
  1320. BOOL GetDIBPointers(HANDLE hDIB, LPVOID *biPtr, LPVOID *rgbqPtr, LPVOID *bmPtr)
  1321. {  
  1322.    LPBITMAPINFO pbi;
  1323.    
  1324.    pbi = (LPBITMAPINFO)hDIB;  
  1325.    
  1326.    if (!pbi)
  1327.      return FALSE;
  1328.    *biPtr   = (LPVOID)pbi;
  1329.    
  1330.    *rgbqPtr = (LPVOID)((LPSTR)pbi + (WORD)((LPBITMAPINFOHEADER)pbi)->biSize);
  1331.    if (((LPBITMAPINFOHEADER)pbi)->biCompression == BI_BITFIELDS)
  1332.       rgbqPtr = (LPVOID*)((LPDWORD)rgbqPtr + 3); 
  1333.    *bmPtr   = (LPBYTE)pbi + (WORD)pbi->bmiHeader.biSize + ColorTableSize(pbi); 
  1334.    return TRUE;
  1335. }
  1336. /******************************************************************************
  1337.  *                                                                            *
  1338.  *  FUNCTION   : HANDLE CreateRGBDIB(DWORD dwWidth, DWORD dwHeight,           *
  1339.  *                                    WORD wBPP, DWORD dwComp);               *
  1340.  *                                                                            *
  1341.  *  PURPOSE    : Returns a handle to a RGB DIB (no color table) with the      *
  1342.  *               specified width, height, bits per pixel, and compression.    *
  1343.  *                                                                            *
  1344.  *****************************************************************************/
  1345. HANDLE CreateRGBDIB(DWORD dwWidth, DWORD dwHeight, WORD wBPP, DWORD dwComp)
  1346. {
  1347.    HANDLE hDIB;
  1348.    LPBITMAPINFOHEADER lpbih;
  1349.    DWORD dwSize;
  1350.    LPDWORD lpMasks;
  1351.    
  1352.    /* We cant support compression so check to see if that's what is being asked for */
  1353.    if ((dwComp == BI_RLE8) || (dwComp == BI_RLE4)) return NULL;
  1354.    /* Allocate enough memory to hold the DIB */
  1355.    switch (wBPP) {
  1356.      case  8: dwSize = ((DWORD)BYTESPERLINE(dwWidth, 8) * dwHeight) + sizeof(RGBQUAD) * 256; break;
  1357.      case 16: dwSize = ((dwWidth + (dwWidth & 1)) << 1) * dwHeight; break;
  1358.      case 24: dwSize = (DWORD)BYTESPERLINE(dwWidth, 24) * dwHeight; break;
  1359.      case 32: dwSize = ((dwWidth * dwHeight) << 2); break;
  1360.      default: return NULL;
  1361.    }                                               
  1362.    
  1363.    if (dwComp == BI_BITFIELDS) /* Add in space for DWORD masks */
  1364.      hDIB = GlobalAlloc(GPTR, (DWORD)sizeof(BITMAPINFOHEADER) + (sizeof(DWORD) * 3) + dwSize);
  1365.    else
  1366.      hDIB = GlobalAlloc(GPTR, (DWORD)sizeof(BITMAPINFOHEADER) + dwSize);
  1367.    if (!hDIB)
  1368.      return NULL;
  1369.    
  1370.    lpbih = (LPBITMAPINFOHEADER)hDIB;
  1371.    lpbih->biSize         = sizeof(BITMAPINFOHEADER);
  1372.    lpbih->biWidth        = dwWidth;
  1373.    lpbih->biHeight       = dwHeight;
  1374.    lpbih->biPlanes       = 1;
  1375.    lpbih->biBitCount     = wBPP;
  1376.    lpbih->biCompression  = dwComp;    
  1377.    lpbih->biSizeImage    = ((DWORD)BYTESPERLINE(dwWidth, wBPP) * dwHeight); 
  1378.    lpMasks = (LPDWORD)((LPSTR)lpbih + (WORD)lpbih->biSize);
  1379.    
  1380.    if (dwComp == BI_BITFIELDS) 
  1381.        if (wBPP == 16) {
  1382.          lpMasks[0] = MAKE565WORD(0xff, 0, 0);
  1383.          lpMasks[1] = MAKE565WORD(0, 0xff, 0);
  1384.          lpMasks[2] = MAKE565WORD(0, 0, 0xff);
  1385.        } else if (wBPP == 32) {
  1386.            lpMasks[0] = 0xff0000;
  1387.            lpMasks[1] = 0x00ff00;
  1388.            lpMasks[2] = 0x0000ff;
  1389.          }
  1390.       
  1391.    return hDIB;
  1392. }
  1393. /******************************************************************************
  1394.  *                                                                            *
  1395.  * PalEntriesOnDevice()                                                       *
  1396.  *                                                                            *
  1397.  * Parameter:                                                                 *
  1398.  *                                                                            *
  1399.  * HDC hDC          - device context                                          *
  1400.  *                                                                            *
  1401.  * Return Value:                                                              *
  1402.  *                                                                            *
  1403.  * int              - number of palette entries on device                     *
  1404.  *                                                                            *
  1405.  * Description:                                                               *
  1406.  *                                                                            *
  1407.  * This function gets the number of palette entries on the specified device   *
  1408.  *                                                                            *
  1409.  * History:   Date      Author               Reason                           *
  1410.  *            6/01/91   Garrett McAuliffe    Created                          *
  1411.  *            9/15/91   Patrick Schreiber    Added header and comments        *
  1412.  *                                                                            *
  1413.  *****************************************************************************/   
  1414. int PalEntriesOnDevice(HDC hDC)                                      
  1415. {                                                                        
  1416.    int nColors;  // number of colors                                     
  1417.    /*  Find out the number of palette entries on this
  1418.     *  device.
  1419.     */
  1420.    nColors = GetDeviceCaps(hDC, SIZEPALETTE);
  1421.    /*  For non-palette devices, we'll use the # of system
  1422.     *  colors for our palette size.
  1423.     */
  1424.    if (!nColors)
  1425.       nColors = GetDeviceCaps(hDC, NUMCOLORS);   
  1426.    return nColors;
  1427. }
  1428. /******************************************************************************
  1429.  *                                                                            *
  1430.  * HPALETTE CreatePaletteFromRGBQUAD(LPRGBQUAD rgbqPalette, WORD wEntries)    *
  1431.  *                                                                            *
  1432.  * Parameter:                                                                 *
  1433.  *                                                                            *
  1434.  * LPRGBQUAD        - pointer to RGBQUADs                                     *
  1435.  * WORD             - the number of RGBQUADs we are pointing to               *
  1436.  *                                                                            *
  1437.  * Return Value:                                                              *
  1438.  *                                                                            *
  1439.  * HPALETTE         - returns a handle to a palette or NULL if it failes      *
  1440.  *                                                                            *
  1441.  * Description:                                                               *
  1442.  *                                                                            *
  1443.  * This function will build a valid HPALETTE when given an array of RGBQUADs  *
  1444.  *                                                                            *
  1445.  *****************************************************************************/
  1446. HPALETTE CreatePaletteFromRGBQUAD(LPRGBQUAD rgbqPalette, WORD wEntries)
  1447.     HPALETTE hPal;
  1448.     LPLOGPALETTE lplgPal;
  1449.     PALETTEENTRY pe[256];
  1450.     int i;
  1451.     lplgPal = (LPLOGPALETTE)GlobalAlloc(GPTR, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * wEntries); 
  1452.     if (!lplgPal)
  1453.       return NULL;
  1454.     lplgPal->palVersion = PALVERSION;
  1455.     lplgPal->palNumEntries = wEntries;
  1456.     for (i=0; i<wEntries; i++) {
  1457.       lplgPal->palPalEntry[i].peRed   = rgbqPalette[i].rgbRed;
  1458.       lplgPal->palPalEntry[i].peGreen = rgbqPalette[i].rgbGreen;
  1459.       lplgPal->palPalEntry[i].peBlue  = rgbqPalette[i].rgbBlue;
  1460.       lplgPal->palPalEntry[i].peFlags = 0;
  1461.     }
  1462.     CopyMemory(pe, lplgPal->palPalEntry, wEntries * sizeof(PALETTEENTRY));
  1463.     hPal = CreatePalette(lplgPal);
  1464.     GlobalFree(lplgPal);
  1465.     return hPal;
  1466. }
  1467. /******************************************************************************
  1468.  *                                                                            *
  1469.  * WORD CreateRGBQUADFromPalette(LPRGBQUAD rgbqPalette, HPALETTE hPal);       *
  1470.  *                                                                            *
  1471.  * Parameter:                                                                 *
  1472.  *                                                                            *
  1473.  * LPRGBQUAD        - pointer to RGBQUADs                                     *
  1474.  * HPALETTE         - HANDLE of Palette                                       *
  1475.  *                                                                            *
  1476.  * Return Value:                                                              *
  1477.  *                                                                            *
  1478.  * WORD             - returns the number of palette entries copied into the   *
  1479.  *                    LPRGBQUAD array                                         *
  1480.  *                                                                            *
  1481.  * Description:                                                               *
  1482.  *                                                                            *
  1483.  * This function will fill an array of RGBQUAD from given a palette handle    *
  1484.  *                                                                            *
  1485.  *****************************************************************************/
  1486. WORD CreateRGBQUADFromPalette(LPRGBQUAD rgbqPalette, HPALETTE hPal)
  1487.     int i;
  1488.     WORD wEntries;
  1489.   
  1490.     GetObject(hPal, sizeof(wEntries), &wEntries);
  1491.     GetPaletteEntries(hPal, 0, wEntries, (LPPALETTEENTRY)rgbqPalette);
  1492.     for (i=0; i<wEntries; i++) {
  1493.       rgbqPalette[i].rgbReserved = rgbqPalette[i].rgbRed;
  1494.       rgbqPalette[i].rgbRed   = rgbqPalette[i].rgbBlue;
  1495.       rgbqPalette[i].rgbBlue  = rgbqPalette[i].rgbReserved;
  1496.       rgbqPalette[i].rgbReserved = 0;
  1497.     }
  1498.     return wEntries;
  1499. }
  1500. /******************************************************************************  
  1501.  *                                                                            *  
  1502.  * GetSystemPalette()                                                         *  
  1503.  *                                                                            *  
  1504.  * Parameters:                                                                *  
  1505.  *                                                                            *  
  1506.  * None                                                                       *  
  1507.  *                                                                            *  
  1508.  * Return Value:                                                              *  
  1509.  *                                                                            *  
  1510.  * HPALETTE  - handle to a copy of the current system palette          *  
  1511.  *                                                                            *  
  1512.  * Description:                                                               *  
  1513.  *                                                                            *  
  1514.  * This function returns a handle to a palette which represents the system    *  
  1515.  * palette.  The system RGB values are copied into our logical palette        *  
  1516.  * using the GetSystemPaletteEntries function.                                *  
  1517.  *                                                                            *  
  1518.  * History:                                                                   *  
  1519.  *                                                                            *  
  1520.  *    Date      Author               Reason                                   *
  1521.  *    6/01/91   Garrett McAuliffe    Created                                  *
  1522.  *    9/15/91   Patrick Schreiber    Added header and comments                *
  1523.  *    12/20/91  Mark Bader           Added GetSystemPaletteEntries call       *
  1524.  *                                                                            *
  1525.  *****************************************************************************/  
  1526. HPALETTE GetSystemPalette()
  1527. {
  1528.    HDC hDC;                // handle to a DC
  1529.    static HPALETTE hPal = NULL;   // handle to a palette
  1530.    HANDLE hLogPal;         // handle to a logical palette
  1531.    LPLOGPALETTE lpLogPal;  // pointer to a logical palette
  1532.    int nColors;            // number of colors
  1533.    /* Find out how many palette entries we want. */
  1534.    hDC = GetDC(NULL);
  1535.    if (!hDC)
  1536.       return NULL;
  1537.   
  1538.    if (!(GetDeviceCaps(hDC, RASTERCAPS) & RC_PALETTE)) {
  1539.      ReleaseDC(NULL, hDC);
  1540.      return NULL;
  1541.    }
  1542.    nColors = PalEntriesOnDevice(hDC);   // Number of palette entries
  1543.    /* Allocate room for the palette */
  1544.    hLogPal = GlobalAlloc(GPTR, sizeof(LOGPALETTE) + nColors * sizeof(PALETTEENTRY));
  1545.    /* if we didn't get a logical palette, return NULL */
  1546.    if (!hLogPal)
  1547.       return NULL;
  1548.    /* get a pointer to the logical palette */
  1549.    lpLogPal = (LPLOGPALETTE)hLogPal;
  1550.    /* set some important fields */
  1551.    lpLogPal->palVersion = PALVERSION;
  1552.    lpLogPal->palNumEntries = nColors;
  1553.    /* Copy the current system palette into our logical palette */
  1554.    GetSystemPaletteEntries(hDC, 0, nColors, 
  1555.                            (LPPALETTEENTRY)(lpLogPal->palPalEntry));
  1556.    /*  Go ahead and create the palette.  Once it's created, 
  1557.     *  we no longer need the LOGPALETTE, so free it.
  1558.     */
  1559.    hPal = CreatePalette(lpLogPal);
  1560.    /* clean up */
  1561.    GlobalFree(hLogPal);
  1562.    ReleaseDC(NULL, hDC);
  1563.    return hPal;
  1564. }
  1565. /******************************************************************************
  1566.  *                                                                            *
  1567.  * HPALETTE CreateNewPalette()   *
  1568.  *                                                                            *
  1569.  * Parameter:                                                               *
  1570.  *                                                                            *
  1571.  * HDC - Handle to a Device Context   *
  1572.  *                                                                            *
  1573.  * Return Value:                                                              *
  1574.  *                                                                            *
  1575.  * HPALETTE         - Returns a handle to a palette or NULL if it   *
  1576.  *                    fails.                                                  *
  1577.  *                                                                            *
  1578.  * Description:                                                               *
  1579.  *                                                                            *
  1580.  * This function will build a palette with a spectrum of colors.  It is       *
  1581.  * useful when you want to display a number of DIBs each with a different     *
  1582.  * palette yet still have an a good selection of colors for the DIBs to map   *
  1583.  * to.                                                                        *
  1584.  *                                                                            *
  1585.  *****************************************************************************/
  1586. HPALETTE CreateNewPalette(HDC hDC)
  1587. {
  1588. PIXELFORMATDESCRIPTOR pfd; // Pixel Format Descriptor
  1589. LOGPALETTE *pPal; // Pointer to memory for logical palette
  1590. HPALETTE hPal; // Handle to our palette
  1591. int nPixelFormat; // Pixel format index
  1592. int nColors; // Number of entries in palette
  1593. int i; // Counting variable
  1594. BYTE RedRange,GreenRange,BlueRange;
  1595. // Range for each color entry (7,7,and 3)
  1596. // Get the pixel format index and retrieve the pixel format description
  1597. nPixelFormat = GetPixelFormat(hDC);
  1598. DescribePixelFormat(hDC, nPixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
  1599. // Does this pixel format require a palette?  If not, do not create a
  1600. // palette and just return NULL
  1601. if(!(pfd.dwFlags & PFD_NEED_PALETTE))
  1602. return NULL;
  1603. // Number of entries in palette.  8 bits yeilds 256 entries
  1604. nColors = 1 << pfd.cColorBits;
  1605. // Allocate space for a logical palette structure plus all the palette entries
  1606. pPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE) +nColors*sizeof(PALETTEENTRY));
  1607. // Fill in palette header 
  1608. pPal->palVersion = 0x300; // Windows 3.0
  1609. pPal->palNumEntries = nColors; // table size
  1610. // Build mask of all 1's.  This creates a number represented by having
  1611. // the low order x bits set, where x = pfd.cRedBits, pfd.cGreenBits, and
  1612. // pfd.cBlueBits.  
  1613. RedRange = (1 << pfd.cRedBits) -1;
  1614. GreenRange = (1 << pfd.cGreenBits) - 1;
  1615. BlueRange = (1 << pfd.cBlueBits) -1;
  1616. // Loop through all the palette entries
  1617. for(i = 0; i < nColors; i++)
  1618. {
  1619. // Fill in the 8-bit equivalents for each component
  1620. pPal->palPalEntry[i].peRed = (i >> pfd.cRedShift) & RedRange;
  1621. pPal->palPalEntry[i].peRed = (unsigned char)(
  1622. (double) pPal->palPalEntry[i].peRed * 255.0 / RedRange);
  1623. pPal->palPalEntry[i].peGreen = (i >> pfd.cGreenShift) & GreenRange;
  1624. pPal->palPalEntry[i].peGreen = (unsigned char)(
  1625. (double)pPal->palPalEntry[i].peGreen * 255.0 / GreenRange);
  1626. pPal->palPalEntry[i].peBlue = (i >> pfd.cBlueShift) & BlueRange;
  1627. pPal->palPalEntry[i].peBlue = (unsigned char)(
  1628. (double)pPal->palPalEntry[i].peBlue * 255.0 / BlueRange);
  1629. pPal->palPalEntry[i].peFlags = (unsigned char) NULL;
  1630. }
  1631. // Create the palette
  1632. hPal = CreatePalette(pPal);
  1633. // Go ahead and select and realize the palette for this device context
  1634. // SelectPalette(hDC,(HPALETTE)hPalette,FALSE);
  1635. // RealizePalette(hDC);
  1636. // Free the memory used for the logical palette structure
  1637. free(pPal);
  1638. return hPal; // Return the handle to this palette
  1639. }
  1640. /******************************************************************************
  1641.  *                                                                            *
  1642.  * HPALETTE CreateSpectrumPalette2()                                          *
  1643.  *                                                                            *
  1644.  * Parameter:                                                                 *
  1645.  *                                                                            *
  1646.  * (none)                                                                     *
  1647.  *                                                                            *
  1648.  * Return Value:                                                              *
  1649.  *                                                                            *
  1650.  * HPALETTE         - Returns a handle to a spectrum palette or NULL if it    *
  1651.  *                    fails.                                                  *
  1652.  *                                                                            *
  1653.  * Description:                                                               *
  1654.  *                                                                            *
  1655.  * This function will build a palette with a spectrum of colors.  It is       *
  1656.  * useful when you want to display a number of DIBs each with a different     *
  1657.  * palette yet still have an a good selection of colors for the DIBs to map   *
  1658.  * to.                                                                        *
  1659.  *                                                                            *
  1660.  *****************************************************************************/
  1661. HPALETTE CreateSpectrumPalette2() 
  1662. {                 
  1663.     HPALETTE hPal;
  1664.     LPLOGPALETTE lplgPal;
  1665.     BYTE red, green, blue;
  1666.     int i; 
  1667.     
  1668.     lplgPal = (LPLOGPALETTE)GlobalAlloc(GPTR, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * MAXPALETTE); 
  1669.     if (!lplgPal)
  1670.       return NULL;
  1671.     
  1672.     lplgPal->palVersion = PALVERSION;
  1673.     lplgPal->palNumEntries = MAXPALETTE;
  1674.      
  1675.     red = green = blue = 0;
  1676.     for (i = 0; i < MAXPALETTE; i++) {
  1677.         lplgPal->palPalEntry[i].peRed   = red;
  1678.         lplgPal->palPalEntry[i].peGreen = green;
  1679.         lplgPal->palPalEntry[i].peBlue  = blue;
  1680.         lplgPal->palPalEntry[i].peFlags = (BYTE)0;
  1681.         if (!(red += 32))
  1682.             if (!(green += 32))
  1683.                 blue += 64;
  1684.     }
  1685.     hPal = CreatePalette(lplgPal);
  1686.     GlobalFree(lplgPal);
  1687.     return hPal;
  1688. }
  1689. /******************************************************************************
  1690.  *                                                                            *
  1691.  * HANDLE CopyPalette(HPALETTE hPal)                                          *
  1692.  *                                                                            *
  1693.  * Parameter:                                                                 *
  1694.  *                                                                            *
  1695.  * HPALETTE         - The handle to the palette you want to make a copy of.   *
  1696.  *                                                                            *
  1697.  * Return Value:                                                              *
  1698.  *                                                                            *
  1699.  * HPALETTE         - A copy of the palette passed as a parameter             *  
  1700.  *                                                                            *
  1701.  *****************************************************************************/
  1702. HPALETTE CopyPalette(HPALETTE hPal)
  1703. {
  1704.   HPALETTE hPalNew; 
  1705.   LPLOGPALETTE lplgPal;
  1706.   WORD iNumEntries;
  1707.   
  1708.   GetObject(hPal, sizeof(iNumEntries), &iNumEntries);
  1709.     
  1710.   lplgPal = (LPLOGPALETTE)GlobalAlloc(GPTR, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * iNumEntries); 
  1711.   if (!lplgPal)
  1712.     return NULL;
  1713.   lplgPal->palVersion = PALVERSION;
  1714.   lplgPal->palNumEntries = GetPaletteEntries(hPal, 0, iNumEntries, lplgPal->palPalEntry);
  1715.   
  1716.   hPalNew = CreatePalette(lplgPal);
  1717.   GlobalFree(lplgPal);
  1718.   return (hPalNew);
  1719. }
  1720. /******************************************************************************
  1721.  *                                                                            *
  1722.  *  FUNCTION   : CopyPaletteEx(HPALETTE hPal, BYTE bFlags)                    *
  1723.  *                                                                            *
  1724.  *  PURPOSE    : Given a handle to a palette, this function return a copy of  *
  1725.  *               the palette with all of the flags set to a the specified     *
  1726.  *               value.               *
  1727.  *                                                                            *
  1728.  *  RETURNS    : A handle to the palette.                                     *
  1729.  *                                                                            *
  1730.  *****************************************************************************/
  1731. HPALETTE CopyPaletteEx(HPALETTE hPal, BYTE bFlag)
  1732. {
  1733.    int i;
  1734.    WORD wNumColors;
  1735.    PALETTEENTRY pe[MAXPALETTE];
  1736.    HPALETTE hNewPal;
  1737.    if (!hPal || !GetObject(hPal, sizeof(wNumColors), &wNumColors))
  1738.      return NULL;
  1739.    
  1740.    hNewPal = CopyPalette(hPal);
  1741.    GetPaletteEntries(hNewPal, 0, wNumColors, (LPPALETTEENTRY)&pe);
  1742.    for (i=0; i<(int)wNumColors; i++) 
  1743.       pe[i].peFlags = bFlag;
  1744.    
  1745.    SetPaletteEntries(hNewPal, 0, wNumColors, (LPPALETTEENTRY)&pe);
  1746.    return hNewPal;
  1747. }
  1748. /******************************************************************************
  1749.  *                                                                            *
  1750.  *  HPALETTE CreateIdentityPalette(LPRGBQUAD lprgbq, int nColors)             *
  1751.  *                                                                            *
  1752.  * LPRGBQUAD        - pointer to RGBQUADs                                     *
  1753.  * int              - the number of RGBQUADs we are pointing to               *
  1754.  *                                                                            *
  1755.  * Return Value:                                                              *
  1756.  *                                                                            *
  1757.  * HPALETTE         - returns a handle to an identity palette or NULL if it   *
  1758.  *                    fails                                                   *
  1759.  *                                                                            *
  1760.  * *Note: This code was originally taken from the WinG online docs            *
  1761.  *****************************************************************************/
  1762. HPALETTE CreateIdentityPalette(LPRGBQUAD lprgbq, int nColors)
  1763. {
  1764. int i;
  1765. struct {
  1766. WORD Version;
  1767. WORD NumberOfEntries;
  1768. PALETTEENTRY aEntries[MAXPALETTE];
  1769. } Palette =
  1770. {
  1771. 0x300, 
  1772. MAXPALETTE
  1773. };
  1774. //*** Just use the screen DC where we need it
  1775. HDC hDC = GetDC(NULL);
  1776. //*** For SYSPAL_NOSTATIC, just copy the color table into
  1777. //*** a PALETTEENTRY array and replace the first and last entries
  1778. //*** with black and white
  1779. if (GetSystemPaletteUse(hDC) == SYSPAL_NOSTATIC)
  1780. {
  1781. //*** Fill in the palette with the given values, marking each
  1782. //*** as PC_NOCOLLAPSE
  1783. for(i = 0; i < nColors; i++)
  1784. {
  1785. Palette.aEntries[i].peRed = lprgbq[i].rgbRed;
  1786. Palette.aEntries[i].peGreen = lprgbq[i].rgbGreen;
  1787. Palette.aEntries[i].peBlue = lprgbq[i].rgbBlue;
  1788. Palette.aEntries[i].peFlags = PC_NOCOLLAPSE;
  1789. }
  1790. //*** Mark any unused entries PC_NOCOLLAPSE
  1791. for (; i < MAXPALETTE; ++i)
  1792. Palette.aEntries[i].peFlags = PC_NOCOLLAPSE;
  1793. //*** Make sure the last entry is white
  1794. //*** This may replace an entry in the array!
  1795. Palette.aEntries[255].peRed = 255;
  1796. Palette.aEntries[255].peGreen = 255;
  1797. Palette.aEntries[255].peBlue = 255;
  1798. Palette.aEntries[255].peFlags = 0;
  1799. //*** And the first is black
  1800. //*** This may replace an entry in the array!
  1801. Palette.aEntries[0].peRed = 0;
  1802. Palette.aEntries[0].peGreen = 0;
  1803. Palette.aEntries[0].peBlue = 0;
  1804. Palette.aEntries[0].peFlags = 0;
  1805. }
  1806. else
  1807. //*** For SYSPAL_STATIC, get the twenty static colors into
  1808. //*** the array, then fill in the empty spaces with the
  1809. //*** given color table
  1810. {
  1811. int nStaticColors;
  1812. int nUsableColors;
  1813. //*** Get the static colors from the system palette
  1814. nStaticColors = GetDeviceCaps(hDC, NUMCOLORS);
  1815. GetSystemPaletteEntries(hDC, 0, MAXPALETTE, Palette.aEntries);
  1816. //*** Set the peFlags of the lower static colors to zero
  1817. nStaticColors = nStaticColors / 2;
  1818. for (i=0; i<nStaticColors; i++)
  1819. Palette.aEntries[i].peFlags = 0;
  1820. //*** Fill in the entries from the given color table
  1821. nUsableColors = nColors - nStaticColors;   
  1822. for (; i<nUsableColors; i++)
  1823. {
  1824. Palette.aEntries[i].peRed = lprgbq[i].rgbRed;
  1825. Palette.aEntries[i].peGreen = lprgbq[i].rgbGreen;
  1826. Palette.aEntries[i].peBlue = lprgbq[i].rgbBlue;
  1827. Palette.aEntries[i].peFlags = PC_NOCOLLAPSE;
  1828. }
  1829. //*** Mark any empty entries as PC_NOCOLLAPSE
  1830.         for (; i<MAXPALETTE - nStaticColors; i++)
  1831. Palette.aEntries[i].peFlags = PC_NOCOLLAPSE;
  1832. //*** Set the peFlags of the upper static colors to zero
  1833. for (i = MAXPALETTE - nStaticColors; i<MAXPALETTE; i++)
  1834. Palette.aEntries[i].peFlags = 0;
  1835. }
  1836. //*** Remember to release the DC!
  1837. ReleaseDC(NULL, hDC);
  1838. //*** Return the palette
  1839. return CreatePalette((LPLOGPALETTE)&Palette);
  1840. }
  1841. /******************************************************************************
  1842.  *                                                                            *
  1843.  *  void ClearSystemPalette(void)                                             *
  1844.  *                                                                            *
  1845.  * Purpose:  Clears the system palette by realizing an all black palette.     *
  1846.  *           This will ensure that palette-managed applications executed      *
  1847.  *           before your application will not affect the identity mapping of  *
  1848.  *           your palette.                                                    * 
  1849.  *                                                                            *
  1850.  *                                                                            *
  1851.  * *Note: This code was originally taken from the WinG online docs            *
  1852.  *****************************************************************************/
  1853. void ClearSystemPalette(void)
  1854. {
  1855. //*** A dummy palette setup
  1856. struct
  1857. {
  1858. WORD Version;
  1859. WORD NumberOfEntries;
  1860. PALETTEENTRY aEntries[MAXPALETTE];
  1861. } Palette =
  1862. {
  1863. 0x300, 
  1864. MAXPALETTE
  1865. };
  1866. HPALETTE ScreenPalette = 0;
  1867. HDC ScreenDC;
  1868. int Counter;
  1869. //*** Reset everything in the system palette to black
  1870. for (Counter = 0; Counter < MAXPALETTE; Counter++)
  1871. {
  1872. Palette.aEntries[Counter].peRed = 0;
  1873. Palette.aEntries[Counter].peGreen = 0;
  1874. Palette.aEntries[Counter].peBlue = 0;
  1875. Palette.aEntries[Counter].peFlags = PC_NOCOLLAPSE;
  1876. }
  1877. //*** Create, select, realize, deselect, and delete the palette
  1878. ScreenDC = GetDC(NULL);
  1879. ScreenPalette = CreatePalette((LPLOGPALETTE)&Palette);
  1880. if (ScreenPalette)
  1881. {
  1882. ScreenPalette = SelectPalette(ScreenDC, ScreenPalette, FALSE);
  1883. RealizePalette(ScreenDC);
  1884. ScreenPalette = SelectPalette(ScreenDC, ScreenPalette, FALSE);
  1885. DeleteObject(ScreenPalette);
  1886. }
  1887. ReleaseDC(NULL, ScreenDC);
  1888. }