home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Multimedia Jumpstart 1.1a / CD_ROM.BIN / develpmt / source / rleapp / dib.c < prev    next >
C/C++ Source or Header  |  1992-09-12  |  39KB  |  1,657 lines

  1. /*----------------------------------------------------------------------------*\
  2. |   Routines for dealing with Device independent bitmaps                       |
  3. |                                                                              |
  4. \*----------------------------------------------------------------------------*/
  5.  
  6. /*
  7.      (C) Copyright Microsoft Corp. 1991, 1992.  All rights reserved.
  8.  
  9.      You have a royalty-free right to use, modify, reproduce and 
  10.      distribute the Sample Files (and/or any modified version) in 
  11.      any way you find useful, provided that you agree that 
  12.      Microsoft has no warranty obligations or liability for any 
  13.      Sample Application Files which are modified. 
  14.      
  15.      If you did not get this from Microsoft Sources, then it may not be the
  16.      most current version.  This sample code in particular will be updated
  17.      and include more documentation.  
  18.  
  19.      Sources are:
  20.          The MM Sys BBS: The phone number is 206 936-4082.
  21.     CompuServe: WINSDK forum, MDK section.
  22. */
  23.  
  24.  
  25. #include <windows.h>
  26. #include "gmem.h"
  27. #include "dib.h"
  28.  
  29. // in mem.asm
  30. LPVOID FAR PASCAL MemCopy(LPVOID dest, LPVOID source, LONG count);
  31.  
  32. HANDLE CreateLogicalDib(HBITMAP hbm, WORD biBits, HPALETTE hpal);
  33.  
  34. DWORD FAR PASCAL lread(int fh, LPVOID p, DWORD len);
  35. DWORD FAR PASCAL lwrite(int fh, LPVOID p, DWORD len);
  36. DWORD FAR PASCAL lseek(int fh, DWORD off, WORD w);
  37. int   FAR PASCAL lopen(LPSTR sz, WORD acc);
  38. int   FAR PASCAL lclose(int fh);
  39.  
  40. /* flags for _lseek */
  41. #define  SEEK_CUR 1
  42. #define  SEEK_END 2
  43. #define  SEEK_SET 0
  44.  
  45. /*
  46.  *   Open a DIB file and return a MEMORY DIB, a memory handle containing..
  47.  *
  48.  *   BITMAP INFO    bi
  49.  *   palette data
  50.  *   bits....
  51.  *
  52.  */
  53. HANDLE OpenDIB(LPSTR szFile)
  54. {
  55.     unsigned            fh;
  56.     DIB8                bi;
  57.     LPBITMAPINFOHEADER  lpbi;
  58.     DWORD               dwLen;
  59.     DWORD               dwBits;
  60.     HANDLE              hdib;
  61.  
  62.     if (HIWORD((DWORD)szFile) == 0)
  63.     fh = LOWORD((DWORD)szFile);
  64.     else
  65.         fh = lopen(szFile, OF_READ);
  66.  
  67.     if (fh == -1)
  68.     return NULL;
  69.  
  70.     if (!ReadDibBitmapInfo(fh,(LPBITMAPINFOHEADER)&bi))
  71.     return NULL;
  72.  
  73.     /* How much memory do we need to hold the DIB */
  74.  
  75.     dwBits = bi.biSizeImage;
  76.     dwLen  = bi.biSize + PaletteSize(&bi) + dwBits;
  77.  
  78.     /* Can we get more memory? */
  79.  
  80.     hdib = GAlloc(dwLen);
  81.  
  82.     if (hdib)
  83.     {
  84.     lpbi = GLock(hdib);
  85.  
  86.         MemCopy(lpbi,&bi,(int)bi.biSize+PaletteSize(&bi));
  87.  
  88.         if (lread(fh, (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi), dwBits) != dwBits)
  89.         {
  90.             GFree(hdib);
  91.             hdib = NULL;
  92.         }
  93.     }
  94.  
  95.     if (HIWORD((DWORD)szFile) != 0)
  96.         lclose(fh);
  97.  
  98.     return hdib;
  99. }
  100.  
  101. /*
  102.  *   Write a global handle in CF_DIB format to a file.
  103.  *
  104.  */
  105. BOOL WriteDIB(LPSTR szFile,HANDLE hdib)
  106. {
  107.     BITMAPFILEHEADER    hdr;
  108.     LPBITMAPINFOHEADER  lpbi;
  109.     BITMAPINFOHEADER    bi;
  110.     int                 fh;
  111.     DWORD               dwSize;
  112.     BOOL                f;
  113.  
  114.     if (!hdib)
  115.     return FALSE;
  116.  
  117.     if (HIWORD((DWORD)szFile) == 0)
  118.     {
  119.     fh = LOWORD((DWORD)szFile);
  120.     }
  121.     else
  122.     {
  123.         fh = lopen(szFile,OF_CREATE|OF_READWRITE);
  124.     }
  125.  
  126.     if (fh == -1)
  127.     return FALSE;
  128.  
  129.     DibInfo(hdib,&bi);
  130.  
  131.     dwSize = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  132.  
  133.     lpbi = GLock(hdib);
  134.  
  135.     hdr.bfType          = BFT_BITMAP;
  136.     hdr.bfSize          = dwSize + sizeof(BITMAPFILEHEADER);
  137.     hdr.bfReserved1     = 0;
  138.     hdr.bfReserved2     = 0;
  139.     hdr.bfOffBits       = (DWORD)sizeof(BITMAPFILEHEADER) + lpbi->biSize +
  140.               PaletteSize(lpbi);
  141.  
  142.     f  = lwrite(fh,(LPVOID)&hdr,sizeof(BITMAPFILEHEADER)) == sizeof(BITMAPFILEHEADER);
  143.     f &= lwrite(fh,(LPVOID)lpbi,dwSize) == dwSize;
  144.  
  145.     GUnlock(hdib);
  146.  
  147.     if (HIWORD((DWORD)szFile) != 0)
  148.         lclose(fh);
  149.  
  150.     return f;
  151. }
  152.  
  153. /*
  154.  *  DibInfo(hbi, lpbi)
  155.  *
  156.  *  retrives the DIB info associated with a CF_DIB format memory block.
  157.  */
  158. BOOL DibInfo(HANDLE hbi,LPBITMAPINFOHEADER lpbi)
  159. {
  160.     if (hbi)
  161.     {
  162.     *lpbi = *(LPBITMAPINFOHEADER)GLock(hbi);
  163.     GUnlock(hbi);
  164.  
  165.     if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  166.     {
  167.         BITMAPCOREHEADER bc;
  168.  
  169.         bc = *(LPBITMAPCOREHEADER)lpbi;
  170.  
  171.         lpbi->biSize               = sizeof(BITMAPINFOHEADER);
  172.         lpbi->biWidth              = (DWORD)bc.bcWidth;
  173.         lpbi->biHeight             = (DWORD)bc.bcHeight;
  174.         lpbi->biPlanes             =  (WORD)bc.bcPlanes;
  175.         lpbi->biBitCount           =  (WORD)bc.bcBitCount;
  176.         lpbi->biCompression        = BI_RGB;
  177.         lpbi->biSizeImage          = 0;
  178.         lpbi->biXPelsPerMeter      = 0;
  179.         lpbi->biYPelsPerMeter      = 0;
  180.         lpbi->biClrUsed            = 0;
  181.         lpbi->biClrImportant       = 0;
  182.     }
  183.  
  184.     /*
  185.      * fill in the default fields
  186.      */
  187.     if (lpbi->biSizeImage == 0L)
  188.         lpbi->biSizeImage = lpbi->biHeight * DIBWIDTHBYTES(*lpbi);
  189.  
  190.     if (lpbi->biClrUsed == 0L)
  191.         lpbi->biClrUsed = DibNumColors(lpbi);
  192.  
  193.     return TRUE;
  194.     }
  195.     return FALSE;
  196. }
  197.  
  198. /*
  199.  *  CreateBIPalette()
  200.  *
  201.  *  Given a Pointer to a BITMAPINFO struct will create a
  202.  *  a GDI palette object from the color table.
  203.  *
  204.  *  works with "old" and "new" DIB's
  205.  *
  206.  */
  207. HPALETTE CreateBIPalette(LPBITMAPINFOHEADER lpbi)
  208. {
  209.     LOGPALETTE          *pPal;
  210.     HPALETTE            hpal = NULL;
  211.     WORD                nNumColors;
  212.     WORD                i;
  213.     RGBQUAD        FAR *pRgb;
  214.     BOOL                fCoreHeader;
  215.  
  216.     if (!lpbi)
  217.     return NULL;
  218.  
  219.     fCoreHeader = (lpbi->biSize == sizeof(BITMAPCOREHEADER));
  220.  
  221.     pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
  222.     nNumColors = DibNumColors(lpbi);
  223.  
  224.     if (nNumColors)
  225.     {
  226.     pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  227.  
  228.     if (!pPal)
  229.         goto exit;
  230.  
  231.     pPal->palNumEntries = nNumColors;
  232.     pPal->palVersion    = PALVERSION;
  233.  
  234.     for (i = 0; i < nNumColors; i++)
  235.     {
  236.         pPal->palPalEntry[i].peRed   = pRgb->rgbRed;
  237.         pPal->palPalEntry[i].peGreen = pRgb->rgbGreen;
  238.         pPal->palPalEntry[i].peBlue  = pRgb->rgbBlue;
  239.         pPal->palPalEntry[i].peFlags = (BYTE)0;
  240.  
  241.         if (fCoreHeader)
  242.         ((LPSTR)pRgb) += sizeof(RGBTRIPLE) ;
  243.         else
  244.         pRgb++;
  245.     }
  246.  
  247.     hpal = CreatePalette(pPal);
  248.     LocalFree((HANDLE)pPal);
  249.     }
  250.     else if (lpbi->biBitCount == 24)
  251.     {
  252.     hpal = CreateColorPalette();
  253.     }
  254.  
  255. exit:
  256.     return hpal;
  257. }
  258.  
  259.  
  260. /*
  261.  *  CreateDibPalette()
  262.  *
  263.  *  Given a Global HANDLE to a BITMAPINFO Struct
  264.  *  will create a GDI palette object from the color table.
  265.  *
  266.  *  works with "old" and "new" DIB's
  267.  *
  268.  */
  269. HPALETTE CreateDibPalette(HANDLE hbi)
  270. {
  271.     HPALETTE hpal;
  272.  
  273.     if (!hbi)
  274.     return NULL;
  275.  
  276.     hpal = CreateBIPalette((LPBITMAPINFOHEADER)GLock(hbi));
  277.     GUnlock(hbi);
  278.     return hpal;
  279. }
  280.  
  281. //
  282. // create a 6*6*6 rainbow palette
  283. //
  284. HPALETTE CreateColorPalette()
  285. {
  286.     LOGPALETTE          *pPal;
  287.     PALETTEENTRY        *ppe;
  288.     HPALETTE            hpal = NULL;
  289.     WORD                nNumColors;
  290.     BYTE                r,g,b;
  291.  
  292.     nNumColors = 6*6*6;
  293.     pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  294.  
  295.     if (!pPal)
  296.     goto exit;
  297.  
  298.     pPal->palNumEntries = nNumColors;
  299.     pPal->palVersion    = PALVERSION;
  300.  
  301.     ppe = pPal->palPalEntry;
  302.  
  303.     for (r=0; r<6; r++)
  304.     for (g=0; g<6; g++)
  305.         for (b=0; b<6; b++)
  306.         {
  307.         ppe->peRed   = (BYTE)((WORD)r * 255 / 6);
  308.         ppe->peGreen = (BYTE)((WORD)g * 255 / 6);
  309.         ppe->peBlue  = (BYTE)((WORD)b * 255 / 6);
  310.         ppe->peFlags = (BYTE)0;
  311.         ppe++;
  312.         }
  313.  
  314.     hpal = CreatePalette(pPal);
  315.     LocalFree((HANDLE)pPal);
  316.  
  317. exit:
  318.     return hpal;
  319. }
  320.  
  321. /* CreateSystemPalette()
  322.  *
  323.  * Return a palette which represents the system (physical) palette.
  324.  * By selecting this palette into a screen DC and realizing the palette,
  325.  * the exact physical mapping will be restored
  326.  *
  327.  * one use for this is when "snaping" the screen as a bitmap
  328.  *
  329.  * On error (e.g. out of memory), NULL is returned.
  330.  */
  331. HPALETTE CreateSystemPalette()
  332. {
  333.     HDC             hdc;                    // DC onto the screen
  334.     int             iSizePalette;           // size of entire palette
  335.     int             iFixedPalette;          // number of reserved colors
  336.     NPLOGPALETTE    pLogPal = NULL;
  337.     HPALETTE        hpal = NULL;
  338.     int             i;
  339.  
  340.     hdc = GetDC(NULL);
  341.  
  342.     iSizePalette = GetDeviceCaps(hdc, SIZEPALETTE);
  343.  
  344.     //
  345.     // determine the number of 'static' system colors that
  346.     // are currently reserved
  347.     //
  348.     
  349.     // This call is correct.  There is a (ahem) bug in windows.h
  350.     // Ignore this warning from the C compiler...
  351.     if (GetSystemPaletteUse(hdc) == SYSPAL_STATIC)
  352.     iFixedPalette = GetDeviceCaps(hdc, NUMCOLORS);
  353.     else
  354.     iFixedPalette = 2;
  355.  
  356.     //
  357.     // create a logical palette containing the system colors;
  358.     // this palette has all entries except fixed (system) colors
  359.     // flagged as PC_NOCOLLAPSE
  360.     //
  361.     pLogPal = (NPLOGPALETTE)LocalAlloc(LPTR, sizeof(LOGPALETTE)
  362.         + iSizePalette * sizeof(PALETTEENTRY));
  363.  
  364.     if (pLogPal)
  365.     {
  366.     pLogPal->palVersion = 0x300;
  367.     pLogPal->palNumEntries = iSizePalette;
  368.  
  369.     GetSystemPaletteEntries(hdc, 0, iSizePalette, pLogPal->palPalEntry);
  370.  
  371.     for (i = iFixedPalette/2; i < iSizePalette-iFixedPalette/2; i++)
  372.         pLogPal->palPalEntry[i].peFlags = PC_NOCOLLAPSE;
  373.  
  374.     hpal = CreatePalette(pLogPal);
  375.     LocalFree((HANDLE)pLogPal);
  376.     }
  377.  
  378.     ReleaseDC(NULL,hdc);
  379.     return hpal;
  380. }
  381.  
  382.  
  383.  
  384.  
  385. /*
  386.  *  ReadDibBitmapInfo()
  387.  *
  388.  *  Will read a file in DIB format and return a global HANDLE to it's
  389.  *  BITMAPINFO.  This function will work with both "old" and "new"
  390.  *  bitmap formats, but will allways return a "new" BITMAPINFO
  391.  *
  392.  */
  393. BOOL ReadDibBitmapInfo(int fh, LPBITMAPINFOHEADER lpbi)
  394. {
  395.     DWORD     off;
  396.     HANDLE    hbi = NULL;
  397.     int       size;
  398.     int       i;
  399.     WORD      nNumColors;
  400.  
  401.     RGBQUAD FAR       *pRgb;
  402.     BITMAPCOREHEADER   bc;
  403.     BITMAPFILEHEADER   bf;
  404.  
  405.     if (fh == -1)
  406.     return NULL;
  407.  
  408.     off = lseek(fh,0L,SEEK_CUR);
  409.  
  410.     if (sizeof(bf) != (int)lread(fh,&bf,sizeof(bf)))
  411.     return FALSE;
  412.  
  413.     /*
  414.      *  do we have a RC HEADER?
  415.      */
  416.     if (!ISDIB(bf.bfType))
  417.     {
  418.     bf.bfOffBits = 0L;
  419.         lseek(fh,off,SEEK_SET);
  420.     }
  421.  
  422.     if (sizeof(*lpbi) != (int)lread(fh,lpbi,sizeof(*lpbi)))
  423.     return FALSE;
  424.  
  425.     nNumColors = DibNumColors(lpbi);
  426.  
  427.     /*
  428.      *  what type of bitmap info is this?
  429.      */
  430.     switch (size = (int)lpbi->biSize)
  431.     {
  432.     case sizeof(BITMAPINFOHEADER):
  433.         break;
  434.  
  435.     case sizeof(BITMAPCOREHEADER):
  436.             bc = *(LPBITMAPCOREHEADER)lpbi;
  437.             lpbi->biSize               = sizeof(BITMAPINFOHEADER);
  438.             lpbi->biWidth              = (DWORD)bc.bcWidth;
  439.             lpbi->biHeight             = (DWORD)bc.bcHeight;
  440.             lpbi->biPlanes             =  (WORD)bc.bcPlanes;
  441.             lpbi->biBitCount           =  (WORD)bc.bcBitCount;
  442.             lpbi->biCompression        = BI_RGB;
  443.             lpbi->biSizeImage          = 0;
  444.             lpbi->biXPelsPerMeter      = 0;
  445.             lpbi->biYPelsPerMeter      = 0;
  446.             lpbi->biClrUsed            = nNumColors;
  447.             lpbi->biClrImportant       = nNumColors;
  448.  
  449.             lseek(fh,(LONG)sizeof(BITMAPCOREHEADER)-sizeof(BITMAPINFOHEADER),SEEK_CUR);
  450.  
  451.         break;
  452.  
  453.     default:
  454.             return FALSE;       /* not a DIB */
  455.     }
  456.  
  457.     /*
  458.      *  fill in some default values!
  459.      */
  460.     if (lpbi->biSizeImage == 0)
  461.         lpbi->biSizeImage = lpbi->biHeight * DIBWIDTHBYTES(*lpbi);
  462.  
  463.     if (lpbi->biXPelsPerMeter == 0)
  464.         lpbi->biXPelsPerMeter = 0;         // ??????????????
  465.  
  466.     if (lpbi->biYPelsPerMeter == 0)
  467.         lpbi->biYPelsPerMeter = 0;         // ??????????????
  468.  
  469.     if (lpbi->biClrUsed == 0)
  470.         lpbi->biClrUsed = DibNumColors(lpbi);
  471.  
  472.     pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + lpbi->biSize);
  473.  
  474.     if (nNumColors)
  475.     {
  476.     if (size == sizeof(BITMAPCOREHEADER))
  477.     {
  478.         /*
  479.          * convert a old color table (3 byte entries) to a new
  480.          * color table (4 byte entries)
  481.          */
  482.             lread(fh,pRgb,nNumColors * sizeof(RGBTRIPLE));
  483.  
  484.         for (i=nNumColors-1; i>=0; i--)
  485.         {
  486.         RGBQUAD rgb;
  487.  
  488.         rgb.rgbRed      = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
  489.         rgb.rgbBlue     = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
  490.         rgb.rgbGreen    = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
  491.         rgb.rgbReserved = (BYTE)0;
  492.  
  493.         pRgb[i] = rgb;
  494.         }
  495.     }
  496.     else
  497.     {
  498.             lread(fh,(LPVOID)pRgb,nNumColors * sizeof(RGBQUAD));
  499.     }
  500.     }
  501.  
  502.     if (bf.bfOffBits != 0L)
  503.         lseek(fh,off + bf.bfOffBits,SEEK_SET);
  504.  
  505.     return TRUE;
  506. }
  507.  
  508. /*  How big is the palette? if bits per pel not 24
  509.  *  no of bytes to read is 6 for 1 bit, 48 for 4 bits
  510.  *  256*3 for 8 bits and 0 for 24 bits
  511.  */
  512. WORD PaletteSize(VOID FAR * pv)
  513. {
  514.     #define lpbi ((LPBITMAPINFOHEADER)pv)
  515.     #define lpbc ((LPBITMAPCOREHEADER)pv)
  516.  
  517.     WORD    NumColors;
  518.  
  519.     NumColors = DibNumColors(lpbi);
  520.  
  521.     if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  522.     return NumColors * sizeof(RGBTRIPLE);
  523.     else
  524.     return NumColors * sizeof(RGBQUAD);
  525.  
  526.     #undef lpbi
  527.     #undef lpbc
  528. }
  529.  
  530. /*  How Many colors does this DIB have?
  531.  *  this will work on both PM and Windows bitmap info structures.
  532.  */
  533. WORD DibNumColors(VOID FAR * pv)
  534. {
  535.     #define lpbi ((LPBITMAPINFOHEADER)pv)
  536.     #define lpbc ((LPBITMAPCOREHEADER)pv)
  537.  
  538.     int bits;
  539.  
  540.     /*
  541.      *  with the new format headers, the size of the palette is in biClrUsed
  542.      *  else is dependent on bits per pixel
  543.      */
  544.     if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
  545.     {
  546.     if (lpbi->biClrUsed != 0)
  547.         return (WORD)lpbi->biClrUsed;
  548.  
  549.     bits = lpbi->biBitCount;
  550.     }
  551.     else
  552.     {
  553.     bits = lpbc->bcBitCount;
  554.     }
  555.  
  556.     switch (bits)
  557.     {
  558.     case 1:
  559.         return 2;
  560.     case 4:
  561.         return 16;
  562.     case 8:
  563.         return 256;
  564.     default:
  565.         return 0;
  566.     }
  567.  
  568.     #undef lpbi
  569.     #undef lpbc
  570. }
  571.  
  572. /*
  573.  *  DibFromBitmap()
  574.  *
  575.  *  Will create a global memory block in DIB format that represents the DDB
  576.  *  passed in
  577.  *
  578.  */
  579. HANDLE DibFromBitmap(HBITMAP hbm, DWORD biStyle, WORD biBits, HPALETTE hpal, WORD wUsage)
  580. {
  581.     BITMAP               bm;
  582.     BITMAPINFOHEADER     bi;
  583.     BITMAPINFOHEADER FAR *lpbi;
  584.     DWORD                dwLen;
  585.     int                  nColors;
  586.     HANDLE               hdib;
  587.     HANDLE               h;
  588.     HDC                  hdc;
  589.  
  590.     if (wUsage == 0)
  591.     wUsage = DIB_RGB_COLORS;
  592.  
  593.     if (!hbm)
  594.     return NULL;
  595.  
  596.     if (biStyle == BI_RGB && wUsage == DIB_RGB_COLORS)
  597.     return CreateLogicalDib(hbm,biBits,hpal);
  598.  
  599.     if (hpal == NULL)
  600.     hpal = GetStockObject(DEFAULT_PALETTE);
  601.  
  602.     GetObject(hbm,sizeof(bm),(LPSTR)&bm);
  603.     GetObject(hpal,sizeof(nColors),(LPSTR)&nColors);
  604.  
  605.     if (biBits == 0)
  606.     biBits = bm.bmPlanes * bm.bmBitsPixel;
  607.  
  608.     bi.biSize               = sizeof(BITMAPINFOHEADER);
  609.     bi.biWidth              = bm.bmWidth;
  610.     bi.biHeight             = bm.bmHeight;
  611.     bi.biPlanes             = 1;
  612.     bi.biBitCount           = biBits;
  613.     bi.biCompression        = biStyle;
  614.     bi.biSizeImage          = 0;
  615.     bi.biXPelsPerMeter      = 0;
  616.     bi.biYPelsPerMeter      = 0;
  617.     bi.biClrUsed            = 0;
  618.     bi.biClrImportant       = 0;
  619.  
  620.     dwLen  = bi.biSize + PaletteSize(&bi);
  621.  
  622.     hdc = CreateCompatibleDC(NULL);
  623.     hpal = SelectPalette(hdc,hpal,FALSE);
  624.     RealizePalette(hdc);  // why is this needed on a MEMORY DC? GDI bug??
  625.  
  626.     hdib = GAlloc(dwLen);
  627.  
  628.     if (!hdib) {
  629.     goto exit;
  630.     }
  631.  
  632.     lpbi = GLock(hdib);
  633.  
  634.     *lpbi = bi;
  635.  
  636.     /*
  637.      *  call GetDIBits with a NULL lpBits param, so it will calculate the
  638.      *  biSizeImage field for us
  639.      */
  640.     GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
  641.     NULL, (LPBITMAPINFO)lpbi, wUsage);
  642.  
  643.     bi = *lpbi;
  644.     GUnlock(hdib);
  645.  
  646.     /*
  647.      * HACK! if the driver did not fill in the biSizeImage field, make one up
  648.      */
  649.     if (bi.biSizeImage == 0)
  650.     {
  651.     bi.biSizeImage = (DWORD)WIDTHBYTES(bm.bmWidth * biBits) * bm.bmHeight;
  652.  
  653.     if (biStyle != BI_RGB)
  654.         bi.biSizeImage = (bi.biSizeImage * 3) / 2;
  655.     }
  656.  
  657.     /*
  658.      *  realloc the buffer big enough to hold all the bits
  659.      */
  660.     dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  661.     if (h = GReAlloc(hdib,dwLen))
  662.     {
  663.     hdib = h;
  664.     }
  665.     else
  666.     {
  667.     GFree(hdib);
  668.     hdib = NULL;
  669.     goto exit;
  670.     }
  671.  
  672.     /*
  673.      *  call GetDIBits with a NON-NULL lpBits param, and actualy get the
  674.      *  bits this time
  675.      */
  676.     lpbi = GLock(hdib);
  677.  
  678.     GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
  679.     (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi),
  680.     (LPBITMAPINFO)lpbi, wUsage);
  681.  
  682.     bi = *lpbi;
  683.     GUnlock(hdib);
  684.  
  685. exit:
  686.     SelectPalette(hdc,hpal,FALSE);
  687.     DeleteDC(hdc);
  688.     return hdib;
  689. }
  690.  
  691. /*
  692.  *  BitmapFromDib()
  693.  *
  694.  *  Will create a DDB (Device Dependent Bitmap) given a global handle to
  695.  *  a memory block in CF_DIB format
  696.  *
  697.  */
  698. HBITMAP BitmapFromDib(HANDLE hdib, HPALETTE hpal, WORD wUsage)
  699. {
  700.     LPBITMAPINFOHEADER lpbi;
  701.     HPALETTE    hpalT;
  702.     HDC         hdc;
  703.     HBITMAP     hbm;
  704.  
  705.     if (!hdib)
  706.     return NULL;
  707.  
  708.     if (wUsage == 0)
  709.     wUsage = DIB_RGB_COLORS;
  710.  
  711.     lpbi = GLock(hdib);
  712.  
  713.     if (!lpbi)
  714.     return NULL;
  715.  
  716.     hdc = GetDC(NULL);
  717. //  hdc = CreateCompatibleDC(NULL);
  718.  
  719.     if (hpal)
  720.     {
  721.     hpalT = SelectPalette(hdc,hpal,FALSE);
  722.     RealizePalette(hdc);  // why is this needed on a MEMORY DC? GDI bug??
  723.     }
  724.  
  725.     hbm = CreateDIBitmap(hdc,
  726.         (LPBITMAPINFOHEADER)lpbi,
  727.         (LONG)CBM_INIT,
  728.         (LPSTR)lpbi + (int)lpbi->biSize + PaletteSize(lpbi),
  729.         (LPBITMAPINFO)lpbi,
  730.         wUsage );
  731.  
  732.     if (hpal && hpalT)
  733.     SelectPalette(hdc,hpalT,FALSE);
  734.  
  735.     ReleaseDC(NULL,hdc);
  736.  
  737.     GUnlock(hdib);
  738.     return hbm;
  739. }
  740.  
  741. /*
  742.  *  DibFromDib()
  743.  *
  744.  *  Will convert a DIB in 1 format to a DIB in the specifed format
  745.  *
  746.  */
  747. HANDLE DibFromDib(HANDLE hdib, DWORD biStyle, WORD biBits, HPALETTE hpal, WORD wUsage)
  748. {
  749.     BITMAPINFOHEADER bi;
  750.     HBITMAP     hbm;
  751.     BOOL        fKillPalette=FALSE;
  752.  
  753.     if (!hdib)
  754.     return NULL;
  755.  
  756.     DibInfo(hdib,&bi);
  757.  
  758.     /*
  759.      *  do we have the requested format already?
  760.      */
  761.     if (bi.biCompression == biStyle && bi.biBitCount == biBits)
  762.     return hdib;
  763.  
  764.     if (hpal == NULL)
  765.     {
  766.     hpal = CreateDibPalette(hdib);
  767.     fKillPalette++;
  768.     }
  769.  
  770.     hbm = BitmapFromDib(hdib,hpal,wUsage);
  771.  
  772.     if (hbm == NULL)
  773.     {
  774.     hdib = NULL;
  775.     }
  776.     else
  777.     {
  778.     hdib = DibFromBitmap(hbm,biStyle,biBits,hpal,wUsage);
  779.     DeleteObject(hbm);
  780.     }
  781.  
  782.     if (fKillPalette && hpal)
  783.     DeleteObject(hpal);
  784.  
  785.     return hdib;
  786. }
  787.  
  788. /*
  789.  *  CreateLogicalDib
  790.  *
  791.  *  Given a DDB and a HPALETTE create a "logical" DIB
  792.  *
  793.  *  if the HBITMAP is NULL create a DIB from the system "stock" bitmap
  794.  *      This is used to save a logical palette to a disk file as a DIB
  795.  *
  796.  *  if the HPALETTE is NULL use the system "stock" palette (ie the
  797.  *      system palette)
  798.  *
  799.  *  a "logical" DIB is a DIB where the DIB color table *exactly* matches
  800.  *  the passed logical palette.  There will be no system colors in the DIB
  801.  *  block, and a pixel value of <n> in the DIB will correspond to logical
  802.  *  palette index <n>.
  803.  *
  804.  *  This is accomplished by doing a GetDIBits() with the DIB_PAL_COLORS
  805.  *  option then converting the palindexes returned in the color table
  806.  *  from palette indexes to logical RGB values.  The entire passed logical
  807.  *  palette is always copied to the DIB color table.
  808.  *
  809.  *  The DIB color table will have exactly the same number of entries as
  810.  *  the logical palette.  Normaly GetDIBits() will always set biClrUsed to
  811.  *  the maximum colors supported by the device regardless of the number of
  812.  *  colors in the logical palette
  813.  *
  814.  *  Why would you want to do this?  The major reason for a "logical" DIB
  815.  *  is so when the DIB is written to a disk file then reloaded the logical
  816.  *  palette created from the DIB color table will be the same as one used
  817.  *  originaly to create the bitmap.  It also will prevent GDI from doing
  818.  *  nearest color matching on PC_RESERVED palettes.
  819.  *
  820.  *  ** What do we do if the logical palette has more than 256 entries!!!!!
  821.  *  ** GetDIBits() may return logical palette index's that are greater than
  822.  *  ** 256, we cant represent these colors in the "logical" DIB
  823.  *  **
  824.  *  ** for now hose the caller?????
  825.  *
  826.  */
  827.  
  828. HANDLE CreateLogicalDib(HBITMAP hbm, WORD biBits, HPALETTE hpal)
  829. {
  830.     BITMAP              bm;
  831.     BITMAPINFOHEADER    bi;
  832.     LPBITMAPINFOHEADER  lpDib;      // pointer to DIB
  833.     LPBITMAPINFOHEADER  lpbi;       // temp pointer to BITMAPINFO
  834.     DWORD               dwLen;
  835.     DWORD               dw;
  836.     int                 n;
  837.     int                 nColors;
  838.     HANDLE              hdib;
  839.     HDC                 hdc;
  840.     BYTE FAR *          lpBits;
  841.     WORD FAR *          lpCT;
  842.     RGBQUAD FAR *       lpRgb;
  843.     PALETTEENTRY        peT;
  844.     HPALETTE            hpalT;
  845.  
  846.     if (hpal == NULL)
  847.     hpal = GetStockObject(DEFAULT_PALETTE);
  848.  
  849.     if (hbm == NULL)
  850.     hbm = NULL; // ????GetStockObject(STOCK_BITMAP);
  851.  
  852.     GetObject(hpal,sizeof(nColors),(LPSTR)&nColors);
  853.     GetObject(hbm,sizeof(bm),(LPSTR)&bm);
  854.  
  855.     if (biBits == 0)
  856.     biBits = nColors > 16 ? 8 : 4;
  857.  
  858.     if (nColors > 256)      // ACK!
  859.     ;                   // How do we handle this????
  860.  
  861.     bi.biSize               = sizeof(BITMAPINFOHEADER);
  862.     bi.biWidth              = bm.bmWidth;
  863.     bi.biHeight             = bm.bmHeight;
  864.     bi.biPlanes             = 1;
  865.     bi.biBitCount           = biBits;
  866.     bi.biCompression        = BI_RGB;
  867.     bi.biSizeImage          = (DWORD)WIDTHBYTES(bm.bmWidth * biBits) * bm.bmHeight;
  868.     bi.biXPelsPerMeter      = 0;
  869.     bi.biYPelsPerMeter      = 0;
  870.     bi.biClrUsed            = nColors;
  871.     bi.biClrImportant       = 0;
  872.  
  873.     dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  874.  
  875.     hdib = GAlloc(dwLen);
  876.  
  877.     if (!hdib) {
  878.     return NULL;
  879.     }
  880.  
  881.     lpbi = GAllocPtr(bi.biSize + 256 * sizeof(RGBQUAD));
  882.  
  883.     if (!lpbi)
  884.     {
  885.     GFree(hdib);
  886.     return NULL;
  887.     }
  888.  
  889.     hdc = GetDC(NULL);
  890.     hpalT = SelectPalette(hdc,hpal,FALSE);
  891.     RealizePalette(hdc);  // why is this needed on a MEMORY DC? GDI bug??
  892.  
  893.     lpDib = GLock(hdib);
  894.  
  895.     *lpbi  = bi;
  896.     *lpDib = bi;
  897.     lpCT   = (WORD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
  898.     lpRgb  = (RGBQUAD FAR *)((LPSTR)lpDib + (WORD)lpDib->biSize);
  899.     lpBits = (LPSTR)lpDib + (WORD)lpDib->biSize + PaletteSize(lpDib);
  900.  
  901.     /*
  902.      *  call GetDIBits to get the DIB bits and fill the color table with
  903.      *  logical palette index's
  904.      */
  905.     GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
  906.     lpBits,(LPBITMAPINFO)lpbi, DIB_PAL_COLORS);
  907.  
  908.     /*
  909.      *  Now convert the DIB bits into "real" logical palette index's
  910.      *
  911.      *  lpCT        points to the DIB color table wich is a WORD array of
  912.      *              logical palette index's
  913.      *
  914.      *  lpBits      points to the DIB bits, each DIB pixel is a index into
  915.      *              the DIB color table.
  916.      *
  917.      */
  918.  
  919.     if (biBits == 8)
  920.     {
  921.     for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE huge *)lpBits)++)
  922.         *lpBits = (BYTE)lpCT[*lpBits];
  923.     }
  924.     else // biBits == 4
  925.     {
  926.     for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE huge *)lpBits)++)
  927.         *lpBits = (BYTE)(lpCT[*lpBits & 0x0F] | (lpCT[(*lpBits >> 4) & 0x0F] << 4));
  928.     }
  929.  
  930.     /*
  931.      *  Now copy the RGBs in the logical palette to the dib color table
  932.      */
  933.     for (n=0; n<nColors; n++,lpRgb++)
  934.     {
  935.     GetPaletteEntries(hpal,n,1,&peT);
  936.  
  937.     lpRgb->rgbRed      = peT.peRed;
  938.     lpRgb->rgbGreen    = peT.peGreen;
  939.     lpRgb->rgbBlue     = peT.peBlue;
  940.     lpRgb->rgbReserved = (BYTE)0;
  941.     }
  942.  
  943.     GUnlock(hdib);
  944.     GFreePtr(lpbi);
  945.  
  946.     SelectPalette(hdc,hpalT,FALSE);
  947.     ReleaseDC(NULL,hdc);
  948.  
  949.     return hdib;
  950. }
  951.  
  952. void xlatClut8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  953. {
  954.     DWORD dw;
  955.  
  956.     for (dw = 0; dw < dwSize; dw++, ((BYTE huge *)pb)++)
  957.     *pb = xlat[*pb];
  958. }
  959.  
  960. void xlatClut4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  961. {
  962.     DWORD dw;
  963.  
  964.     for (dw = 0; dw < dwSize; dw++, ((BYTE huge *)pb)++)
  965.     *pb = (BYTE)(xlat[*pb & 0x0F] | (xlat[(*pb >> 4) & 0x0F] << 4));
  966. }
  967.  
  968. #define RLE_ESCAPE  0
  969. #define RLE_EOL     0
  970. #define RLE_EOF     1
  971. #define RLE_JMP     2
  972.  
  973. void xlatRle8(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  974. {
  975.     BYTE    cnt;
  976.     BYTE    b;
  977.     BYTE huge *prle = pb;
  978.  
  979.     for(;;)
  980.     {
  981.     cnt = *prle++;
  982.     b   = *prle;
  983.  
  984.     if (cnt == RLE_ESCAPE)
  985.     {
  986.         prle++;
  987.  
  988.         switch (b)
  989.         {
  990.         case RLE_EOF:
  991.             return;
  992.  
  993.         case RLE_EOL:
  994.             break;
  995.  
  996.         case RLE_JMP:
  997.             prle++;     // skip dX
  998.             prle++;     // skip dY
  999.             break;
  1000.  
  1001.         default:
  1002.             cnt = b;
  1003.             for (b=0; b<cnt; b++,prle++)
  1004.             *prle = xlat[*prle];
  1005.  
  1006.             if (cnt & 1)
  1007.             prle++;
  1008.  
  1009.             break;
  1010.         }
  1011.     }
  1012.     else
  1013.     {
  1014.         *prle++ = xlat[b];
  1015.     }
  1016.     }
  1017. }
  1018.  
  1019. void xlatRle4(BYTE FAR *pb, DWORD dwSize, BYTE FAR *xlat)
  1020. {
  1021. }
  1022.  
  1023. //
  1024. // MapDib - map the given DIB so it matches the specifed palette
  1025. //
  1026. BOOL MapDib(HANDLE hdib, HPALETTE hpal)
  1027. {
  1028.     LPBITMAPINFOHEADER  lpbi;
  1029.     PALETTEENTRY        pe;
  1030.     int                 n;
  1031.     int                 nDibColors;
  1032.     int                 nPalColors;
  1033.     BYTE FAR *          lpBits;
  1034.     RGBQUAD FAR *       lpRgb;
  1035.     BYTE                xlat[256];
  1036.     DWORD               dwSize;
  1037.  
  1038.     if (!hpal || !hdib)
  1039.     return FALSE;
  1040.  
  1041.     lpbi   = GLock(hdib);
  1042.     lpRgb  = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
  1043.     lpBits = DibXY(lpbi,0,0);
  1044.  
  1045.     GetObject(hpal,sizeof(int),(LPSTR)&nPalColors);
  1046.     nDibColors = DibNumColors(lpbi);
  1047.  
  1048.     if (nPalColors > nDibColors)
  1049.     {
  1050.     //
  1051.     // This is bad, we need to grow the dib!  punt for now
  1052.     //
  1053.     nPalColors = nDibColors;
  1054.     }
  1055.  
  1056.     //
  1057.     //  build a xlat table. from the current DIB colors to the given
  1058.     //  palette.
  1059.     //
  1060.     for (n=0; n<nDibColors; n++)
  1061.     xlat[n] = (BYTE)GetNearestPaletteIndex(hpal,RGB(lpRgb[n].rgbRed,lpRgb[n].rgbGreen,lpRgb[n].rgbBlue));
  1062.  
  1063.     //
  1064.     // translate the DIB bits
  1065.     //
  1066.     if ((dwSize = lpbi->biSizeImage) == 0)
  1067.     dwSize = lpbi->biHeight * DIBWIDTHBYTES(*lpbi);
  1068.  
  1069.     switch ((WORD)lpbi->biCompression)
  1070.     {
  1071.     case BI_RLE8:
  1072.         xlatRle8(lpBits, dwSize, xlat);
  1073.         break;
  1074.  
  1075.     case BI_RLE4:
  1076.         xlatRle4(lpBits, dwSize, xlat);
  1077.         break;
  1078.  
  1079.     case BI_RGB:
  1080.         if (lpbi->biBitCount == 8)
  1081.         xlatClut8(lpBits, dwSize, xlat);
  1082.         else
  1083.         xlatClut4(lpBits, dwSize, xlat);
  1084.         break;
  1085.     }
  1086.  
  1087.     //
  1088.     //  Now copy the RGBs in the logical palette to the dib color table
  1089.     //
  1090.     for (n=0; n<nPalColors; n++)
  1091.     {
  1092.     GetPaletteEntries(hpal,n,1,&pe);
  1093.  
  1094.     lpRgb[n].rgbRed      = pe.peRed;
  1095.     lpRgb[n].rgbGreen    = pe.peGreen;
  1096.     lpRgb[n].rgbBlue     = pe.peBlue;
  1097.     lpRgb[n].rgbReserved = (BYTE)0;
  1098.     }
  1099.  
  1100.     for (n=nPalColors; n<nDibColors; n++)
  1101.     {
  1102.     lpRgb[n].rgbRed      = (BYTE)0;
  1103.     lpRgb[n].rgbGreen    = (BYTE)0;
  1104.     lpRgb[n].rgbBlue     = (BYTE)0;
  1105.     lpRgb[n].rgbReserved = (BYTE)0;
  1106.     }
  1107.  
  1108.     GUnlock(hdib);
  1109.     return TRUE;
  1110. }
  1111.  
  1112. HANDLE ResizeDib(HANDLE hdib, int dx, int dy)
  1113. {
  1114.     BITMAPINFOHEADER bi;
  1115.     HPALETTE hpal;
  1116.     HBITMAP hbm;
  1117.     HDC hdc,hdcM;
  1118.  
  1119.     DibInfo(hdib, &bi);
  1120.  
  1121.     if ((int)bi.biWidth == dx && (int)bi.biHeight == dy)
  1122.     {
  1123.         return CopyDib(hdib);
  1124.     }
  1125.     else
  1126.     {
  1127.         hdc  = GetDC(NULL);
  1128.         hdcM = CreateCompatibleDC(hdc);
  1129.         hpal = CreateDibPalette(hdib);
  1130.         hbm  = CreateCompatibleBitmap(hdc, dx, dy);
  1131.  
  1132.         hbm  = SelectObject(hdcM, hbm);
  1133.  
  1134.         hpal = SelectPalette(hdcM, hpal, FALSE);
  1135.         RealizePalette(hdcM);
  1136.  
  1137.         SetStretchBltMode(hdcM, COLORONCOLOR);
  1138.         StretchDibBlt(hdcM,0,0,dx,dy,hdib,0,0,-1,-1,SRCCOPY,DIB_RGB_COLORS);
  1139.  
  1140.         hpal = SelectPalette(hdcM, hpal, FALSE);
  1141.         hbm  = SelectObject(hdcM, hbm);
  1142.  
  1143.         hdib = DibFromBitmap(hbm,BI_RGB,8,hpal,DIB_RGB_COLORS);
  1144.  
  1145.         DeleteObject(hpal);
  1146.         DeleteObject(hbm);
  1147.         DeleteObject(hdcM);
  1148.         ReleaseDC(NULL,hdc);
  1149.     }
  1150.  
  1151.     return hdib;
  1152. }
  1153.  
  1154. /*
  1155.  *  Draws bitmap <hbm> at the specifed position in DC <hdc>
  1156.  *
  1157.  */
  1158. BOOL StretchBitmap(HDC hdc, int x, int y, int dx, int dy, HBITMAP hbm, int x0, int y0, int dx0, int dy0, DWORD rop)
  1159. {
  1160.     HDC hdcBits;
  1161.     HPALETTE hpal,hpalT;
  1162.     BOOL f;
  1163.  
  1164.     if (!hdc || !hbm)
  1165.     return FALSE;
  1166.  
  1167.     hpal = SelectPalette(hdc,GetStockObject(DEFAULT_PALETTE),FALSE);
  1168.     SelectPalette(hdc,hpal,FALSE);
  1169.  
  1170.     hdcBits = CreateCompatibleDC(hdc);
  1171.     SelectObject(hdcBits,hbm);
  1172.     hpalT = SelectPalette(hdcBits,hpal,FALSE);
  1173.     RealizePalette(hdcBits);
  1174.     f = StretchBlt(hdc,x,y,dx,dy,hdcBits,x0,y0,dx0,dy0,rop);
  1175.     SelectPalette(hdcBits,hpalT,FALSE);
  1176.     DeleteDC(hdcBits);
  1177.  
  1178.     return f;
  1179. }
  1180.  
  1181. /*
  1182.  *  Draws bitmap <hbm> at the specifed position in DC <hdc>
  1183.  *
  1184.  */
  1185. BOOL DrawBitmap(HDC hdc, int x, int y, HBITMAP hbm, DWORD rop)
  1186. {
  1187.     HDC hdcBits;
  1188.     BITMAP bm;
  1189.     BOOL f;
  1190.  
  1191.     if (!hdc || !hbm)
  1192.     return FALSE;
  1193.  
  1194.     hdcBits = CreateCompatibleDC(hdc);
  1195.     GetObject(hbm,sizeof(BITMAP),(LPSTR)&bm);
  1196.     SelectObject(hdcBits,hbm);
  1197.     f = BitBlt(hdc,x,y,bm.bmWidth,bm.bmHeight,hdcBits,0,0,rop);
  1198.     DeleteDC(hdcBits);
  1199.  
  1200.     return f;
  1201. }
  1202.  
  1203. /*
  1204.  *  Draws HDIB <hdib> at the specifed position in DC <hdc>
  1205.  *
  1206.  */
  1207. VOID DrawDib(HDC hdc, int x, int y, HANDLE hdib, HPALETTE hpal, WORD wUsage)
  1208. {
  1209.     HPALETTE hpalT;
  1210.  
  1211.     if (hpal)
  1212.     {
  1213.     hpalT = SelectPalette(hdc,hpal,FALSE);
  1214.     RealizePalette(hdc);
  1215.     }
  1216.  
  1217.     DibBlt(hdc,x,y,-1,-1,hdib,0,0,SRCCOPY,wUsage);
  1218.  
  1219.     if (hpal)
  1220.     {
  1221.     SelectPalette(hdc,hpalT,FALSE);
  1222.     }
  1223. }
  1224.  
  1225. /*
  1226.  *  SetDibUsage(hdib,hpal,wUsage)
  1227.  *
  1228.  *  Modifies the color table of the passed DIB for use with the wUsage
  1229.  *  parameter specifed.
  1230.  *
  1231.  *  if wUsage is DIB_PAL_COLORS the DIB color table is set to 0-256
  1232.  *  if wUsage is DIB_RGB_COLORS the DIB color table is set to the RGB values
  1233.  *      in the passed palette
  1234.  *
  1235.  */
  1236. BOOL SetDibUsage(HANDLE hdib, HPALETTE hpal,WORD wUsage)
  1237. {
  1238.     LPBITMAPINFOHEADER lpbi;
  1239.     PALETTEENTRY       ape[MAXPALETTE];
  1240.     RGBQUAD FAR *      pRgb;
  1241.     WORD FAR *         pw;
  1242.     int                nColors;
  1243.     int                n;
  1244.  
  1245.     if (hpal == NULL)
  1246.     hpal = GetStockObject(DEFAULT_PALETTE);
  1247.  
  1248.     if (!hdib)
  1249.     return FALSE;
  1250.  
  1251.     lpbi = GLock(hdib);
  1252.  
  1253.     if (!lpbi)
  1254.     return FALSE;
  1255.  
  1256.     nColors = DibNumColors(lpbi);
  1257.  
  1258.     if (nColors > 0)
  1259.     {
  1260.     pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
  1261.  
  1262.     switch (wUsage)
  1263.     {
  1264.         //
  1265.         // Set the DIB color table to palette indexes
  1266.         //
  1267.         case DIB_PAL_COLORS:
  1268.         for (pw = (WORD FAR*)pRgb,n=0; n<nColors; n++,pw++)
  1269.             *pw = n;
  1270.         break;
  1271.  
  1272.         //
  1273.         // Set the DIB color table to RGBQUADS
  1274.         //
  1275.         default:
  1276.         case DIB_RGB_COLORS:
  1277.         nColors = min(nColors,MAXPALETTE);
  1278.  
  1279.         GetPaletteEntries(hpal,0,nColors,ape);
  1280.  
  1281.         for (n=0; n<nColors; n++)
  1282.         {
  1283.             pRgb[n].rgbRed      = ape[n].peRed;
  1284.             pRgb[n].rgbGreen    = ape[n].peGreen;
  1285.             pRgb[n].rgbBlue     = ape[n].peBlue;
  1286.             pRgb[n].rgbReserved = 0;
  1287.         }
  1288.         break;
  1289.     }
  1290.     }
  1291.     GUnlock(hdib);
  1292.     return TRUE;
  1293. }
  1294.  
  1295. /*
  1296.  *  SetPalFlags(hpal,iIndex, cnt, wFlags)
  1297.  *
  1298.  *  Modifies the palette flags of all indexs in the range (iIndex - nIndex+cnt)
  1299.  *  to the parameter specifed.
  1300.  *
  1301.  */
  1302. BOOL SetPalFlags(HPALETTE hpal, int iIndex, int cntEntries, WORD wFlags)
  1303. {
  1304.     int     i;
  1305.     BOOL    f;
  1306.     PALETTEENTRY FAR *lppe;
  1307.  
  1308.     if (hpal == NULL)
  1309.     return FALSE;
  1310.  
  1311.     if (cntEntries < 0)
  1312.     GetObject(hpal,sizeof(int),(LPSTR)&cntEntries);
  1313.  
  1314.     lppe = GAllocPtr((LONG)cntEntries * sizeof(PALETTEENTRY));
  1315.  
  1316.     if (!lppe) {
  1317.     return FALSE;
  1318.     }
  1319.  
  1320.     GetPaletteEntries(hpal, iIndex, cntEntries, lppe);
  1321.  
  1322.     for (i=0; i<cntEntries; i++)
  1323.     {
  1324.     lppe[i].peFlags = (BYTE)wFlags;
  1325.     }
  1326.  
  1327.     f = SetPaletteEntries(hpal, iIndex, cntEntries, lppe);
  1328.  
  1329.     GFreePtr(lppe);
  1330.     return f;
  1331. }
  1332.  
  1333. /*
  1334.  *  PalEq(hpal1,hpal2)
  1335.  *
  1336.  *  return TRUE if the palette's are the same
  1337.  *
  1338.  */
  1339. BOOL PalEq(HPALETTE hpal1, HPALETTE hpal2)
  1340. {
  1341.     BOOL    f;
  1342.     int     i;
  1343.     int     nPal1,nPal2;
  1344.     PALETTEENTRY FAR *ppe;
  1345.  
  1346.     if (hpal1 == hpal2)
  1347.     return TRUE;
  1348.  
  1349.     if (!hpal1 || !hpal2)
  1350.     return FALSE;
  1351.  
  1352.     GetObject(hpal1,sizeof(int),(LPSTR)&nPal1);
  1353.     GetObject(hpal2,sizeof(int),(LPSTR)&nPal2);
  1354.  
  1355.     if (nPal1 != nPal2)
  1356.     return FALSE;
  1357.  
  1358.     ppe = GAllocPtr(nPal1 * 2 * sizeof(PALETTEENTRY));
  1359.  
  1360.     if (!ppe) {
  1361.         return FALSE;
  1362.     }
  1363.  
  1364.     GetPaletteEntries(hpal1, 0, nPal1, ppe);
  1365.     GetPaletteEntries(hpal2, 0, nPal2, ppe+nPal1);
  1366.  
  1367.     for (f=TRUE,i=0; f && i<nPal1; i++)
  1368.     {
  1369.     f &= (ppe[i].peRed   == ppe[i+nPal1].peRed   &&
  1370.           ppe[i].peBlue  == ppe[i+nPal1].peBlue  &&
  1371.           ppe[i].peGreen == ppe[i+nPal1].peGreen);
  1372.     }
  1373.  
  1374.     GFreePtr(ppe);
  1375.     return f;
  1376. }
  1377.  
  1378. /*
  1379.  *  StretchDibBlt()
  1380.  *
  1381.  *  draws a bitmap in CF_DIB format, using StretchDIBits()
  1382.  *
  1383.  *  takes the same parameters as StretchBlt()
  1384.  */
  1385. BOOL StretchDibBlt(HDC hdc, int x, int y, int dx, int dy, HANDLE hdib, int x0, int y0, int dx0, int dy0, LONG rop, WORD wUsage)
  1386. {
  1387.     LPBITMAPINFOHEADER lpbi;
  1388.     LPSTR        pBuf;
  1389.     BOOL         f;
  1390.  
  1391.     if (!hdib)
  1392.     return PatBlt(hdc,x,y,dx,dy,rop);
  1393.  
  1394.     if (wUsage == 0)
  1395.     wUsage = DIB_RGB_COLORS;
  1396.  
  1397.     lpbi = GLock(hdib);
  1398.  
  1399.     if (!lpbi)
  1400.     return FALSE;
  1401.  
  1402.     if (dx0 == -1 && dy0 == -1)
  1403.     {
  1404.     if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  1405.     {
  1406.         dx0 = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
  1407.         dy0 = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
  1408.     }
  1409.     else
  1410.     {
  1411.         dx0 = (int)lpbi->biWidth;
  1412.         dy0 = (int)lpbi->biHeight;
  1413.     }
  1414.     }
  1415.  
  1416.     if (dx < 0 && dy < 0)
  1417.     {
  1418.     dx = dx0 * -dx;
  1419.     dy = dy0 * -dy;
  1420.     }
  1421.  
  1422.     pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
  1423.  
  1424.     f = StretchDIBits (
  1425.     hdc,
  1426.     x,y,
  1427.     dx,dy,
  1428.     x0,y0,
  1429.     dx0,dy0,
  1430.     pBuf, (LPBITMAPINFO)lpbi,
  1431.     wUsage,
  1432.     rop);
  1433.  
  1434.     GUnlock(hdib);
  1435.     return f;
  1436. }
  1437.  
  1438. /*
  1439.  *  DibBlt()
  1440.  *
  1441.  *  draws a bitmap in CF_DIB format, using SetDIBits to device.
  1442.  *
  1443.  *  takes the same parameters as BitBlt()
  1444.  */
  1445. BOOL DibBlt(HDC hdc, int x0, int y0, int dx, int dy, HANDLE hdib, int x1, int y1, LONG rop, WORD wUsage)
  1446. {
  1447.     LPBITMAPINFOHEADER lpbi;
  1448.     LPSTR       pBuf;
  1449.     BOOL        f;
  1450.  
  1451.     if (!hdib)
  1452.     return PatBlt(hdc,x0,y0,dx,dy,rop);
  1453.  
  1454.     if (wUsage == 0)
  1455.     wUsage = DIB_RGB_COLORS;
  1456.  
  1457.     lpbi = GLock(hdib);
  1458.  
  1459.     if (!lpbi)
  1460.     return FALSE;
  1461.  
  1462.     if (dx == -1 && dy == -1)
  1463.     {
  1464.     if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  1465.     {
  1466.         dx = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
  1467.         dy = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
  1468.     }
  1469.     else
  1470.     {
  1471.         dx = (int)lpbi->biWidth;
  1472.         dy = (int)lpbi->biHeight;
  1473.     }
  1474.     }
  1475.  
  1476.     pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
  1477.  
  1478.     f = StretchDIBits (
  1479.     hdc,
  1480.     x0,y0,
  1481.     dx,dy,
  1482.     x1,y1,
  1483.     dx,dy,
  1484.     pBuf, (LPBITMAPINFO)lpbi,
  1485.     wUsage,
  1486.     rop);
  1487.  
  1488.     GUnlock(hdib);
  1489.     return f;
  1490. }
  1491.  
  1492. LPVOID DibLock(HANDLE hdib,int x, int y)
  1493. {
  1494.     return DibXY((LPBITMAPINFOHEADER)GLock(hdib),x,y);
  1495. }
  1496.  
  1497. VOID DibUnlock(HANDLE hdib)
  1498. {
  1499.     GUnlock(hdib);
  1500. }
  1501.  
  1502. LPVOID DibXY(LPBITMAPINFOHEADER lpbi,int x, int y)
  1503. {
  1504.     BYTE huge *pBits;
  1505.     DWORD ulWidthBytes;
  1506.  
  1507.     pBits = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
  1508.  
  1509.     ulWidthBytes = DIBWIDTHBYTES(*lpbi);
  1510.  
  1511.     pBits += (ulWidthBytes * (long)y) + (x * (int)lpbi->biBitCount / 8);
  1512.  
  1513.     return (LPVOID)pBits;
  1514. }
  1515.  
  1516. HANDLE CreateDib(int bits, int dx, int dy)
  1517. {
  1518.     HANDLE              hdib;
  1519.     BITMAPINFOHEADER    bi;
  1520.     LPBITMAPINFOHEADER  lpbi;
  1521.     DWORD FAR *         pRgb;
  1522.     DWORD               i;
  1523.  
  1524.     //
  1525.     // These are the standard VGA colors, we will be stuck with until the
  1526.     // end of time!
  1527.     //
  1528.     static DWORD CosmicColors[16] = {
  1529.      0x00000000        // 0000  black
  1530.     ,0x00800000        // 0001  dark red
  1531.     ,0x00008000        // 0010  dark green
  1532.     ,0x00808000        // 0011  mustard
  1533.     ,0x00000080        // 0100  dark blue
  1534.     ,0x00800080        // 0101  purple
  1535.     ,0x00008080        // 0110  dark turquoise
  1536.     ,0x00C0C0C0        // 1000  gray
  1537.     ,0x00808080        // 0111  dark gray
  1538.     ,0x00FF0000        // 1001  red
  1539.     ,0x0000FF00        // 1010  green
  1540.     ,0x00FFFF00        // 1011  yellow
  1541.     ,0x000000FF        // 1100  blue
  1542.     ,0x00FF00FF        // 1101  pink (magenta)
  1543.     ,0x0000FFFF        // 1110  cyan
  1544.     ,0x00FFFFFF        // 1111  white
  1545.     };
  1546.  
  1547.     if (bits <= 0)
  1548.     bits = 8;
  1549.  
  1550.     bi.biSize           = sizeof(BITMAPINFOHEADER);
  1551.     bi.biPlanes         = 1;
  1552.     bi.biBitCount       = bits;
  1553.     bi.biWidth          = dx;
  1554.     bi.biHeight         = dy;
  1555.     bi.biCompression    = BI_RGB;
  1556.     bi.biSizeImage      = (DWORD)WIDTHBYTES(bits*dx) * (DWORD)dy;
  1557.     bi.biXPelsPerMeter  = 0;
  1558.     bi.biYPelsPerMeter  = 0;
  1559.     bi.biClrUsed        = 0;
  1560.     bi.biClrImportant   = 0;
  1561.     bi.biClrUsed        = DibNumColors(&bi);
  1562.  
  1563.     hdib = GAllocF(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(BITMAPINFOHEADER)
  1564.     + (long)bi.biClrUsed * sizeof(RGBQUAD)
  1565.     + (long)dy * DIBWIDTHBYTES(bi));
  1566.  
  1567.     if (hdib)
  1568.     {
  1569.     lpbi  = GLock(hdib);
  1570.     *lpbi = bi;
  1571.  
  1572.     pRgb  = (LPVOID)((LPSTR)lpbi + (int)lpbi->biSize);
  1573.  
  1574.     //
  1575.     //  setup the color table
  1576.     //
  1577.     if (bits == 1)
  1578.     {
  1579.         pRgb[0] = CosmicColors[0];
  1580.         pRgb[1] = CosmicColors[15];
  1581.     }
  1582.     else
  1583.     {
  1584.         for (i=0; i<bi.biClrUsed; i++)
  1585.         pRgb[i] = CosmicColors[i % 16];
  1586.     }
  1587.  
  1588.     GUnlock(hdib);
  1589.     }
  1590.  
  1591.     return hdib;
  1592. }
  1593.  
  1594. HANDLE CopyDib (HANDLE hdib)
  1595. {
  1596.     HANDLE h;
  1597.     DWORD dwSize;
  1598.     LPBITMAPINFOHEADER lpbi;
  1599.  
  1600.     lpbi = GLock(hdib);
  1601.  
  1602.     if ((dwSize = lpbi->biSizeImage) == 0)
  1603.         dwSize = DIBWIDTHBYTES(*lpbi) * lpbi->biHeight;
  1604.  
  1605.     dwSize += lpbi->biSize + PaletteSize(lpbi);
  1606.  
  1607.     if (h = GAlloc(dwSize))
  1608.     {
  1609.         MemCopy(GLock(h),GLock(hdib),dwSize);
  1610.     }
  1611.  
  1612.     return h;
  1613. }
  1614.  
  1615.  
  1616. #if 0
  1617.  
  1618. /*
  1619.  * Private routines to read/write more than 64k
  1620.  */
  1621.  
  1622. #define MAXREAD (WORD)(32 * 1024)
  1623.  
  1624. static DWORD NEAR PASCAL lread(int fh, VOID FAR *pv, DWORD ul)
  1625. {
  1626.     DWORD  ulT = ul;
  1627.     BYTE huge *hp = pv;
  1628.  
  1629.     while (ul > MAXREAD) {
  1630.     if (_lread(fh, (LPSTR)hp, MAXREAD) != MAXREAD)
  1631.         return 0;
  1632.     ul -= MAXREAD;
  1633.     hp += MAXREAD;
  1634.     }
  1635.     if (_lread(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
  1636.     return 0;
  1637.     return ulT;
  1638. }
  1639.  
  1640. static DWORD NEAR PASCAL lwrite(int fh, VOID FAR *pv, DWORD ul)
  1641. {
  1642.     DWORD  ulT = ul;
  1643.     BYTE huge *hp = pv;
  1644.  
  1645.     while (ul > MAXREAD) {
  1646.     if (_lwrite(fh, (LPSTR)hp, MAXREAD) != MAXREAD)
  1647.         return 0;
  1648.     ul -= MAXREAD;
  1649.     hp += MAXREAD;
  1650.     }
  1651.     if (_lwrite(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
  1652.     return 0;
  1653.     return ulT;
  1654. }
  1655.  
  1656. #endif
  1657.