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

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