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

  1. /*
  2.  * DIB.C contains routines for working with device-independent bitmaps.
  3.  * This module is adapted from the DIB.C module included with the ShowDIB
  4.  * sample application shipped with the Windows 3.0 SDK. This module includes
  5.  * improved handling for Presentation Manager DIBs, as well as several new
  6.  * functions for working with DIBs and DIB palettes.
  7.  *
  8.  *   (C) Copyright Microsoft Corp. 1991.  All rights reserved.
  9.  *
  10.  * You have a royalty-free right to use, modify, reproduce and 
  11.  * distribute the Sample Files (and/or any modified version) in 
  12.  * any way you find useful, provided that you agree that 
  13.  * Microsoft has no warranty obligations or liability for any 
  14.  * Sample Application Files which are modified. 
  15.  */     
  16.  
  17. #include <windows.h>
  18. #include "dib.h"
  19.  
  20. #define MAKEP(sel,off)  ((VOID FAR *)MAKELONG(off,sel))
  21. #define ALLOCP(ulBytes) ((VOID FAR*)MAKELONG(0, GlobalAlloc(GPTR,(DWORD)(ulBytes))))
  22. #define FREEP(lp)       GlobalFree((HANDLE)HIWORD((DWORD)(lp)));
  23.  
  24. HANDLE CreateLogicalDib(HBITMAP hbm, WORD biBits, HPALETTE hpal);
  25.  
  26. static DWORD NEAR PASCAL lread(int fh, VOID FAR *pv, DWORD ul);
  27. static DWORD NEAR PASCAL lwrite(int fh, VOID FAR *pv, DWORD ul);
  28.  
  29. /* flags for _lseek */
  30. #define  SEEK_CUR 1
  31. #define  SEEK_END 2
  32. #define  SEEK_SET 0
  33.  
  34. /* OpenDIB(szFile)
  35.  *
  36.  * Reads a DIB file and returns a handle to a memory DIB containing
  37.  * the BITMAPINFOHEADER, palette data, and bitmap bits.
  38.  */
  39. HANDLE OpenDIB(
  40.     int fh)               // Input file handle
  41. {
  42.     BITMAPINFOHEADER    bi;
  43.     LPBITMAPINFOHEADER  lpbi;
  44.     DWORD               dwLen;
  45.     DWORD               dwBits;
  46.     HANDLE              hdib;
  47.     HANDLE              h;
  48.  
  49.     if (fh == -1)
  50.         return NULL;
  51.  
  52.     /* Read the bitmap info header and palette from the file. */
  53.  
  54.     hdib = ReadDibBitmapInfo(fh);
  55.  
  56.     if (!hdib)
  57.         return NULL;
  58.  
  59.     /* Get the bitmap header information. */
  60.  
  61.     DibInfo(hdib,&bi);
  62.  
  63.     /* Calculate memory needed to store the DIB bits, and attempt to
  64.      * allocate the memory. */
  65.  
  66.     dwBits = bi.biSizeImage;
  67.     dwLen  = bi.biSize + PaletteSize(&bi) + dwBits;
  68.  
  69.     if (!(h = GlobalReAlloc(hdib,dwLen,0)))
  70.     {
  71.         GlobalFree(hdib);
  72.         hdib = NULL;
  73.     }
  74.     else
  75.     {
  76.         hdib = h;
  77.     }
  78.  
  79.     /* If memory allocation successful, read the bitmap bits. */
  80.  
  81.     if (hdib)
  82.     {
  83.         lpbi = (VOID FAR *)GlobalLock(hdib);
  84.  
  85.         lread(fh, (LPSTR)lpbi+(WORD)lpbi->biSize+PaletteSize(lpbi), dwBits);
  86.  
  87.         GlobalUnlock(hdib);
  88.     }
  89.  
  90.     return hdib;
  91. }
  92.  
  93. /*
  94.  * WriteDIB(szFile, hdib)
  95.  *
  96.  * Writes a global handle in CF_DIB format to a file.
  97.  */
  98. BOOL WriteDIB(
  99.     int fh,                     // Output file handle
  100.     HANDLE hdib)                // DIB to write
  101. {
  102.     BITMAPFILEHEADER    hdr;
  103.     LPBITMAPINFOHEADER  lpbi;
  104.     BITMAPINFOHEADER    bi;
  105.     DWORD               dwSize;
  106.  
  107.     if (!hdib)
  108.         return FALSE;
  109.  
  110.     if (fh == -1)
  111.         return FALSE;
  112.  
  113.     /* Calculate total size of DIB. */
  114.  
  115.     DibInfo(hdib, &bi);
  116.     dwSize = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  117.  
  118.     lpbi = (VOID FAR *)GlobalLock(hdib);
  119.  
  120.     /* Construct the BITMAPFILEHEADER and write the DIB. */
  121.  
  122.     hdr.bfType          = BFT_BITMAP;
  123.     hdr.bfSize          = dwSize + sizeof(BITMAPFILEHEADER);
  124.     hdr.bfReserved1     = 0;
  125.     hdr.bfReserved2     = 0;
  126.     hdr.bfOffBits       = (DWORD)sizeof(BITMAPFILEHEADER) + lpbi->biSize +
  127.                           PaletteSize(lpbi);
  128.  
  129.     _lwrite(fh, (LPVOID)&hdr, sizeof(BITMAPFILEHEADER));
  130.     lwrite(fh, (LPVOID)lpbi, dwSize);
  131.  
  132.     GlobalUnlock(hdib);
  133.  
  134.     return TRUE;
  135. }
  136.  
  137. /*
  138.  * DibInfo(hbi, lpbi)
  139.  *
  140.  * Retrieves the DIB info associated with a CF_DIB format memory block.
  141.  * Works with both the BITMAPINFOHEADER and BITMAPCOREHEADER formats.
  142.  */
  143. BOOL DibInfo(
  144.     HANDLE hbi,                     // Handle to bitmap
  145.     LPBITMAPINFOHEADER lpbi)        // Info header structure to fill in
  146. {
  147.     if(!hbi)
  148.         return FALSE;
  149.  
  150.     *lpbi = *(LPBITMAPINFOHEADER)GlobalLock(hbi);
  151.     GlobalUnlock(hbi);
  152.  
  153.     if(lpbi->biSize == sizeof(BITMAPCOREHEADER))
  154.     {
  155.         BITMAPCOREHEADER bc;
  156.  
  157.         bc = *(LPBITMAPCOREHEADER)lpbi;
  158.  
  159.         lpbi->biSize          = sizeof(BITMAPINFOHEADER);
  160.         lpbi->biWidth         = (DWORD)bc.bcWidth;
  161.         lpbi->biHeight        = (DWORD)bc.bcHeight;
  162.         lpbi->biPlanes        =  (WORD)bc.bcPlanes;
  163.         lpbi->biBitCount      =  (WORD)bc.bcBitCount;
  164.         lpbi->biCompression   = BI_RGB;
  165.         lpbi->biSizeImage     = 0;
  166.         lpbi->biXPelsPerMeter = 0;
  167.         lpbi->biYPelsPerMeter = 0;
  168.         lpbi->biClrUsed       = 0;
  169.         lpbi->biClrImportant  = 0;
  170.     }
  171.  
  172.     /* Fill in the default fields
  173.      */
  174.     if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
  175.     {
  176.         if (lpbi->biSizeImage == 0L)
  177.             lpbi->biSizeImage = WIDTHBYTES(lpbi->biWidth*lpbi->biBitCount) *
  178.                                 lpbi->biHeight;
  179.  
  180.         if (lpbi->biClrUsed == 0L)
  181.             lpbi->biClrUsed = DibNumColors(lpbi);
  182.     }
  183.     return TRUE;
  184. }
  185.  
  186. /*
  187.  * CreateBIPalette()
  188.  *
  189.  * Given a Pointer to a BITMAPINFO struct will create a
  190.  * a GDI palette object from the color table.
  191.  *
  192.  * Works with "old" (BITMAPCOREHEADER) and "new" (BITMAPINFOHEADER) DIBs.
  193.  *
  194.  */
  195. HPALETTE CreateBIPalette(
  196.     LPBITMAPINFOHEADER lpbi)        // Info header containing color table
  197. {
  198.     LOGPALETTE          *pPal;
  199.     HPALETTE            hpal = NULL;
  200.     WORD                nNumColors;
  201.     BYTE                red;
  202.     BYTE                green;
  203.     BYTE                blue;
  204.     WORD                i;
  205.     RGBQUAD        FAR *pRgb;
  206.     BOOL                fCoreHeader;
  207.  
  208.     if (!lpbi)
  209.         return NULL;
  210.  
  211.     fCoreHeader = (lpbi->biSize == sizeof(BITMAPCOREHEADER));
  212.  
  213.     pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
  214.     nNumColors = DibNumColors(lpbi);
  215.  
  216.     if (nNumColors)
  217.     {
  218.         /* Allocate a new color table, copy the palette entries to
  219.          * it, and create the palette. 
  220.          */
  221.         pPal = (LOGPALETTE *)LocalAlloc(LPTR, 
  222.                     sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  223.  
  224.         if (!pPal)
  225.             goto exit;
  226.  
  227.         pPal->palNumEntries = nNumColors;
  228.         pPal->palVersion    = PALVERSION;
  229.  
  230.         for (i = 0; i < nNumColors; i++)
  231.         {
  232.             pPal->palPalEntry[i].peRed   = pRgb->rgbRed;
  233.             pPal->palPalEntry[i].peGreen = pRgb->rgbGreen;
  234.             pPal->palPalEntry[i].peBlue  = pRgb->rgbBlue;
  235.             pPal->palPalEntry[i].peFlags = (BYTE)0;
  236.  
  237.             if (fCoreHeader)
  238.                 ((LPSTR)pRgb) += sizeof(RGBTRIPLE) ;
  239.             else
  240.                 pRgb++;
  241.         }
  242.  
  243.         hpal = CreatePalette(pPal);
  244.         LocalFree((HANDLE)pPal);
  245.     }
  246.     else if (lpbi->biBitCount == 24)
  247.     {
  248.         /* A DIB with a bit count of 24 has no color table entries. Set
  249.          * the number of entries to the maximum (256).
  250.          */
  251.         nNumColors = MAXPALETTE;
  252.         pPal = (LOGPALETTE *)LocalAlloc(LPTR,
  253.                     sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  254.  
  255.         if (!pPal)
  256.             goto exit;
  257.  
  258.         pPal->palNumEntries = nNumColors;
  259.         pPal->palVersion    = PALVERSION;
  260.  
  261.         red = green = blue = 0;
  262.  
  263.         /* Generate 256 (8 * 8 * 4) RGB combinations to fill the palette
  264.          * entries.
  265.          */
  266.         for (i = 0; i < pPal->palNumEntries; i++)
  267.         {
  268.             pPal->palPalEntry[i].peRed   = red;
  269.             pPal->palPalEntry[i].peGreen = green;
  270.             pPal->palPalEntry[i].peBlue  = blue;
  271.             pPal->palPalEntry[i].peFlags = (BYTE)0;
  272.  
  273.             if (!(red += 32))
  274.                 if (!(green += 32))
  275.                     blue += 64;
  276.         }
  277.  
  278.         hpal = CreatePalette(pPal);
  279.         LocalFree((HANDLE)pPal);
  280.     }
  281.  
  282. exit:
  283.     return hpal;
  284. }
  285.  
  286.  
  287. /*
  288.  *  CreateDibPalette()
  289.  *
  290.  *  Given a Global HANDLE to a BITMAPINFO Struct
  291.  *  will create a GDI palette object from the color table.
  292.  *
  293.  *  works with "old" and "new" DIB's
  294.  *
  295.  */
  296. HPALETTE CreateDibPalette(HANDLE hbi)
  297. {
  298.     HPALETTE hpal;
  299.  
  300.     if (!hbi)
  301.         return NULL;
  302.  
  303.     hpal = CreateBIPalette((LPBITMAPINFOHEADER)GlobalLock(hbi));
  304.     GlobalUnlock(hbi);
  305.     return hpal;
  306. }
  307.  
  308.  
  309. /* ReadDibBitmapInfo(fh)
  310.  *
  311.  * Reads a file in DIB format and returns a global HANDLE to its
  312.  * BITMAPINFO.  This function works with both "old" (BITMAPCOREHEADER)
  313.  * and "new" (BITMAPINFOHEADER) formats, but always returns a "new"
  314.  * BITMAPINFO structure.
  315.  */
  316. HANDLE ReadDibBitmapInfo(
  317.     int fh)                             // Handle to open DIB file
  318. {
  319.     DWORD     off;
  320.     HANDLE    hbi = NULL;
  321.     int       size;
  322.     int       i;
  323.     WORD      nNumColors;
  324.  
  325.     RGBQUAD FAR       *pRgb;
  326.     BITMAPINFOHEADER   bi;
  327.     BITMAPCOREHEADER   bc;
  328.     LPBITMAPINFOHEADER lpbi;
  329.     BITMAPFILEHEADER   bf;
  330.  
  331.     if (fh == -1)
  332.         return NULL;
  333.  
  334.     off = _llseek(fh,0L,SEEK_CUR);
  335.  
  336.     /* Read bitmap file header.
  337.      */
  338.     if (sizeof(bf) != _lread(fh,(LPSTR)&bf,sizeof(bf)))
  339.         return FALSE;
  340.  
  341.     /*
  342.      * Do we have a RC HEADER?
  343.      */
  344.     if (!ISDIB(bf.bfType))
  345.     {
  346.         bf.bfOffBits = 0L;
  347.         _llseek(fh,off,SEEK_SET);
  348.     }
  349.  
  350.     /* Read bitmap info header.
  351.      */
  352.     if (sizeof(bi) != _lread(fh,(LPSTR)&bi,sizeof(bi)))
  353.         return FALSE;
  354.  
  355.     nNumColors = DibNumColors(&bi);
  356.  
  357.     /* Determine type of bitmap info (BITMAPINFOHEADER or BITMAPCOREHEADER).
  358.      */
  359.     switch (size = (int)bi.biSize)
  360.     {
  361.         case sizeof(BITMAPINFOHEADER):
  362.             break;
  363.  
  364.         case sizeof(BITMAPCOREHEADER):
  365.  
  366.             /* Fill in the missing fields and seek back to the start of
  367.              * the color table.
  368.              */
  369.             bc = *(BITMAPCOREHEADER*)&bi;
  370.             bi.biSize               = sizeof(BITMAPINFOHEADER);
  371.             bi.biWidth              = (DWORD)bc.bcWidth;
  372.             bi.biHeight             = (DWORD)bc.bcHeight;
  373.             bi.biPlanes             =  (WORD)bc.bcPlanes;
  374.             bi.biBitCount           =  (WORD)bc.bcBitCount;
  375.             bi.biCompression        = BI_RGB;
  376.             bi.biSizeImage          = 0;
  377.             bi.biXPelsPerMeter      = 0;
  378.             bi.biYPelsPerMeter      = 0;
  379.             bi.biClrUsed            = nNumColors;
  380.             bi.biClrImportant       = nNumColors;
  381.  
  382.             _llseek(fh, (LONG)sizeof(BITMAPCOREHEADER)-
  383.                               sizeof(BITMAPINFOHEADER), SEEK_CUR);
  384.             break;
  385.  
  386.         default:
  387.             return NULL;       /* not a DIB */
  388.     }
  389.  
  390.     /* Fill in some default values.
  391.      */
  392.     if(bi.biSizeImage == 0)
  393.     {
  394.         bi.biSizeImage = WIDTHBYTES((DWORD)bi.biWidth * bi.biBitCount) *
  395.                             bi.biHeight;
  396.     }
  397.  
  398.     if(bi.biClrUsed == 0)
  399.     {
  400.         bi.biClrUsed = DibNumColors(&bi);
  401.     }
  402.  
  403.     /* Allocate space for the bitmap info header and color table.
  404.      */
  405.     hbi = GlobalAlloc(GMEM_MOVEABLE,
  406.                       (LONG)bi.biSize + nNumColors * sizeof(RGBQUAD));
  407.     if (!hbi)
  408.         return NULL;
  409.  
  410.     lpbi = (VOID FAR *)GlobalLock(hbi);
  411.  
  412.     *lpbi = bi;                     // Copy the bitmap header information.
  413.  
  414.     /* Read the color table, if it exists. */
  415.  
  416.     if(nNumColors)
  417.     {
  418.         pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + bi.biSize);
  419.         if (size == sizeof(BITMAPCOREHEADER))
  420.         {
  421.             /* Read an old color table (with 3-byte entries) and convert
  422.              * to the new color table format (with 4-byte entries).
  423.              */
  424.             _lread(fh,(LPSTR)pRgb,nNumColors * sizeof(RGBTRIPLE));
  425.  
  426.             for (i=nNumColors-1; i>=0; i--)
  427.             {
  428.                 RGBQUAD rgb;
  429.  
  430.                 rgb.rgbRed      = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
  431.                 rgb.rgbBlue     = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
  432.                 rgb.rgbGreen    = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
  433.                 rgb.rgbReserved = (BYTE)0;
  434.  
  435.                 pRgb[i] = rgb;
  436.             }
  437.         }
  438.         else
  439.         {
  440.             /* Read a new color table.
  441.              */
  442.             _lread(fh,(LPSTR)pRgb,nNumColors * sizeof(RGBQUAD));
  443.         }
  444.     }
  445.  
  446.     /* Seek to the start of the bitmap data.
  447.      */
  448.     if (bf.bfOffBits != 0L)
  449.         _llseek(fh, off + bf.bfOffBits, SEEK_SET);
  450.  
  451.     GlobalUnlock(hbi);
  452.     return hbi;
  453. }
  454.  
  455.  
  456.  
  457. /* PaletteSize(pv)
  458.  *
  459.  * Returns the size of the palette in bytes. The <pv> parameter can point
  460.  * to a BITMAPINFOHEADER or BITMAPCOREHEADER structure.
  461.  */
  462. WORD PaletteSize(
  463.     VOID FAR * pv)          // Pointer to the bitmap info header structure
  464. {
  465.     #define lpbi ((LPBITMAPINFOHEADER)pv)
  466.  
  467.     WORD    NumColors;
  468.  
  469.     NumColors = DibNumColors(lpbi);
  470.  
  471.     if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  472.         return NumColors * sizeof(RGBTRIPLE);
  473.     else
  474.         return NumColors * sizeof(RGBQUAD);
  475.  
  476.     #undef lpbi
  477. }
  478.  
  479.  
  480.  
  481. /* DibNumColors(pv)
  482.  *
  483.  * Returns the number of palette entries in the palette. The <pv> parameter
  484.  * can point to a BITMAPINFOHEADER or BITMAPCOREHEADER structure.
  485.  */
  486. WORD DibNumColors(
  487.     VOID FAR * pv)          // Pointer to the bitmap info header structure
  488. {
  489.     #define lpbi ((LPBITMAPINFOHEADER)pv)
  490.     #define lpbc ((LPBITMAPCOREHEADER)pv)
  491.  
  492.     int nBitCount;
  493.  
  494.     /* With a BITMAPINFOHEADER structure, the number of palette entries
  495.      * is in biClrUsed; otherwise, the count depends on the number of bits
  496.      * per pixel.
  497.      */
  498.     if (lpbi->biSize != sizeof(BITMAPCOREHEADER))
  499.     {
  500.         if(lpbi->biClrUsed != 0)
  501.             return (WORD)lpbi->biClrUsed;
  502.  
  503.         nBitCount = lpbi->biBitCount;
  504.     }
  505.     else
  506.     {
  507.         nBitCount = lpbc->bcBitCount;
  508.     }
  509.  
  510.     switch (nBitCount)
  511.     {
  512.         case 1:
  513.             return 2;
  514.  
  515.         case 4:
  516.             return 16;
  517.  
  518.         case 8:
  519.             return 256;
  520.  
  521.         default:
  522.             return 0;
  523.     }
  524.  
  525.     #undef lpbi
  526.     #undef lpbc
  527. }
  528.  
  529. /* DibFromBitmap()
  530.  *
  531.  * Creates a global memory block in DIB format that represents the device-
  532.  * dependent bitmap passed in. Returns the handle to the DIB.
  533.  */
  534. HANDLE DibFromBitmap(
  535.     HBITMAP hbm,     // Device-dependent bitmap to copy
  536.     DWORD biStyle,   // New DIB: Format of bitmap bits (BI_RGB, etc.)
  537.     WORD biBits,     // New DIB: Bits per pixel
  538.     HPALETTE hpal,   // New DIB: Palette or NULL to use system palette
  539.     WORD wUsage)     // New DIB: DIB palette usage (DIB_RGB_COLORS or
  540.                      //   DIB_PAL_COLORS)
  541. {                     
  542.     BITMAP               bm;
  543.     BITMAPINFOHEADER     bi;
  544.     BITMAPINFOHEADER FAR *lpbi;
  545.     DWORD                dwLen;
  546.     int                  nColors;
  547.     HANDLE               hdib;
  548.     HANDLE               h;
  549.     HDC                  hdc;
  550.  
  551.     if (!hbm)
  552.         return NULL;
  553.  
  554.     if (wUsage == 0)
  555.         wUsage = DIB_RGB_COLORS;
  556.  
  557.     if (biStyle == BI_RGB && wUsage == DIB_RGB_COLORS)
  558.         return CreateLogicalDib(hbm,biBits,hpal);
  559.  
  560.     if (hpal == NULL)
  561.         hpal = GetStockObject(DEFAULT_PALETTE);
  562.  
  563.     GetObject(hbm,sizeof(bm),(LPSTR)&bm);
  564.     GetObject(hpal,sizeof(nColors),(LPSTR)&nColors);
  565.  
  566.     if (biBits == 0)
  567.         biBits = bm.bmPlanes * bm.bmBitsPixel;
  568.  
  569.     bi.biSize               = sizeof(BITMAPINFOHEADER);
  570.     bi.biWidth              = bm.bmWidth;
  571.     bi.biHeight             = bm.bmHeight;
  572.     bi.biPlanes             = 1;
  573.     bi.biBitCount           = biBits;
  574.     bi.biCompression        = biStyle;
  575.     bi.biSizeImage          = 0;
  576.     bi.biXPelsPerMeter      = 0;
  577.     bi.biYPelsPerMeter      = 0;
  578.     bi.biClrUsed            = 0;
  579.     bi.biClrImportant       = 0;
  580.  
  581.     dwLen  = bi.biSize + PaletteSize(&bi);
  582.  
  583.     hdc = CreateCompatibleDC(NULL);
  584.     hpal = SelectPalette(hdc,hpal,FALSE);
  585.     RealizePalette(hdc);
  586.  
  587.     hdib = GlobalAlloc(GMEM_MOVEABLE,dwLen);
  588.  
  589.     if (!hdib)
  590.         goto exit;
  591.  
  592.     /* Calculate the biSizeImage field by calling GetDIBits with a NULL
  593.      * lpBits param.
  594.      */
  595.  
  596.     lpbi = (VOID FAR *)GlobalLock(hdib);
  597.  
  598.     *lpbi = bi;
  599.     GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
  600.                 NULL, (LPBITMAPINFO)lpbi, wUsage);
  601.     bi = *lpbi;
  602.  
  603.     GlobalUnlock(hdib);
  604.  
  605.     /*
  606.      * If the driver did not fill in the biSizeImage field, make one up
  607.      */
  608.     if (bi.biSizeImage == 0)
  609.     {
  610.         bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight;
  611.  
  612.         if (biStyle != BI_RGB)
  613.             bi.biSizeImage = (bi.biSizeImage * 3) / 2;
  614.     }
  615.  
  616.     /*
  617.      * Realloc the buffer big enough to hold all the bits
  618.      */
  619.     dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  620.     if (h = GlobalReAlloc(hdib,dwLen,0))
  621.     {
  622.         hdib = h;
  623.     }
  624.     else
  625.     {
  626.         GlobalFree(hdib);
  627.         hdib = NULL;
  628.         goto exit;
  629.     }
  630.  
  631.     /* Get the bitmap bits.
  632.      */
  633.     lpbi = (VOID FAR *)GlobalLock(hdib);
  634.  
  635.     GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
  636.                 (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi),
  637.                 (LPBITMAPINFO)lpbi, wUsage);
  638.  
  639.     GlobalUnlock(hdib);
  640.  
  641. exit:
  642.     SelectPalette(hdc,hpal,FALSE);
  643.     DeleteDC(hdc);
  644.     return hdib;
  645. }
  646.  
  647.  
  648.  
  649.  
  650. /*  BitmapFromDib()
  651.  *
  652.  *  Creates a DDB (Device Dependent Bitmap) given a global handle to
  653.  *  a memory block in CF_DIB format. Returns a handle to the DDB.
  654.  */
  655. HBITMAP BitmapFromDib(
  656.     HANDLE hdib,                    // Handle to original DIB
  657.     HPALETTE hpal,                  // Handle to original DIB palette
  658.     WORD wUsage)                    // Original DIB palette-entry usage
  659. {
  660.     LPBITMAPINFOHEADER lpbi;
  661.     HPALETTE    hpalT;
  662.     HDC         hdc;
  663.     HBITMAP     hbm;
  664.  
  665.     if (!hdib)
  666.         return NULL;
  667.  
  668.     if (wUsage == 0)
  669.         wUsage = DIB_RGB_COLORS;
  670.  
  671.     lpbi = (VOID FAR *)GlobalLock(hdib);
  672.  
  673.     if (!lpbi)
  674.         return NULL;
  675.  
  676.     hdc = GetDC(NULL);
  677.  
  678.     if (hpal)
  679.     {
  680.         hpalT = SelectPalette(hdc,hpal,FALSE);
  681.         RealizePalette(hdc);
  682.     }
  683.  
  684.     hbm = CreateDIBitmap(hdc,
  685.               (LPBITMAPINFOHEADER)lpbi,
  686.               (LONG)CBM_INIT,
  687.               (LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi),
  688.               (LPBITMAPINFO)lpbi,
  689.               wUsage );
  690.  
  691.     if (hpal && hpalT)
  692.         SelectPalette(hdc,hpalT,FALSE);
  693.  
  694.     ReleaseDC(NULL,hdc);
  695.  
  696.     GlobalUnlock(hdib);
  697.     return hbm;
  698. }
  699.  
  700.  
  701.  
  702.  
  703. /*  DibFromDib()
  704.  *
  705.  *  Converts a DIB to the specified format.
  706.  *
  707.  */
  708. HANDLE DibFromDib(
  709.     HANDLE hdib,        // DIB to convert
  710.     DWORD biStyle,      // New DIB: Compression format
  711.     WORD biBits,        // New DIB: Bits per pixel
  712.     HPALETTE hpal,      // New DIB: Palette (or NULL to use existing palette)
  713.     WORD wUsage)        // New DIB: Palette usage
  714. {
  715.     BITMAPINFOHEADER bi;
  716.     HBITMAP     hbm;
  717.     BOOL        fKillPalette=FALSE;
  718.  
  719.     if (!hdib)
  720.         return NULL;
  721.  
  722.     /* Determine whether the current format matches the requested format. */
  723.  
  724.     DibInfo(hdib,&bi);
  725.  
  726.     if (bi.biCompression == biStyle && bi.biBitCount == biBits)
  727.         return hdib;
  728.  
  729.     /* If no palette is specified, use the existing DIB palette. */
  730.  
  731.     if (hpal == NULL)
  732.     {
  733.         hpal = CreateDibPalette(hdib);
  734.         fKillPalette++;
  735.     }
  736.  
  737.     /* First create a DDB from the DIB. */
  738.  
  739.     hbm = BitmapFromDib(hdib,hpal,wUsage);
  740.  
  741.     if (hbm == NULL)
  742.     {
  743.         hdib = NULL;
  744.     }
  745.     else
  746.     {
  747.         /* Then create the DIB from the DDB. */
  748.  
  749.         hdib = DibFromBitmap(hbm,biStyle,biBits,hpal,wUsage);
  750.         DeleteObject(hbm);
  751.     }
  752.  
  753.     /* Delete palette, if we created it. */
  754.  
  755.     if (fKillPalette && hpal)
  756.         DeleteObject(hpal);
  757.  
  758.     return hdib;
  759. }
  760.  
  761.  
  762. /*  CreateLogicalDib(hbm, biBits, hPal)
  763.  *
  764.  *  Given a DDB and a HPALETTE create a "logical" DIB. If the HPALETTE is
  765.  *  NULL, it uses the system palette.
  766.  *
  767.  *  A "logical" DIB is a DIB where the DIB color table *exactly* matches
  768.  *  the passed logical palette.  There will be no system colors in the
  769.  *  color table, and a pixel value of <n> in the DIB corresponds to logical
  770.  *  palette index <n>.
  771.  *
  772.  *  Why create a "logical" DIB? When the DIB is written to a disk file and
  773.  *  then reloaded, the logical palette created from the DIB color table 
  774.  *  exactly matches the one used originaly to create the bitmap. It also
  775.  *  prevents GDI from doing nearest color matching on PC_RESERVED palettes.
  776.  *
  777.  *  To create the logical DIB, we call GetDIBits() with the DIB_PAL_COLORS
  778.  *  option. We then convert the palette indices returned in the color table
  779.  *  to logical RGB values.  The entire logical palette passed to <hpal> 
  780.  *  is always copied to the DIB color table.
  781.  *
  782.  *  The DIB color table will have exactly the same number of entries as
  783.  *  the logical palette.  Normally GetDIBits() sets the biClrUsed field to
  784.  *  the maximum colors supported by the device, regardless of the number of
  785.  *  colors in the logical palette. If the logical palette contains more 
  786.  *  than 256 colors, the function truncates the color table at 256 entries.
  787.  */
  788.  
  789. HANDLE CreateLogicalDib(
  790.     HBITMAP hbm,        // DDB to copy
  791.     WORD biBits,        // New DIB: bit count: 8, 4, or 0
  792.     HPALETTE hpal)      // New DIB: palette
  793. {
  794.     LPBITMAPINFOHEADER  lpbiDDB;      // Temporary pointer to DDB BITMAPINFO
  795.     WORD FAR *          lpDDBClrTbl;  // Pointer to DIB color table
  796.  
  797.     HANDLE              hLDib;
  798.     LPBITMAPINFOHEADER  lpLDib;       // Pointer to logical DIB header
  799.     BYTE FAR *          lpLDibBits;   // Pointer to logical DIB bits
  800.     RGBQUAD FAR *       lpLDibRGB;    // Pointer to logical DIB color table
  801.     int                 nLDibColors;  // How many colors in logical DIB
  802.     DWORD               dwLDibLen;    // Size of logical DIB
  803.  
  804.     HDC                 hdc;          // Temp stuff, working variables
  805.     BITMAP              bm;
  806.     BITMAPINFOHEADER    bi;
  807.     PALETTEENTRY        peT;
  808.     DWORD               dw;
  809.     int                 n;
  810.     HPALETTE            hpalT;
  811.  
  812.     if (hbm == NULL)
  813.         return NULL;
  814.  
  815.     if (hpal == NULL)
  816.         hpal = GetStockObject(DEFAULT_PALETTE);
  817.  
  818.     GetObject(hpal,sizeof(nLDibColors),(LPSTR)&nLDibColors);
  819.     GetObject(hbm,sizeof(bm),(LPSTR)&bm);
  820.  
  821.     /* Truncate palette entries at 256 if the logical palette has more
  822.      * than 256 entries.
  823.      */
  824.     if (nLDibColors > 256)
  825.         nLDibColors = 256;
  826.  
  827.     /* If bit count is zero, fill in bit count based on number of colors
  828.      * in palette.
  829.      */
  830.     if (biBits == 0)
  831.         biBits = nLDibColors > 16 ? 8 : 4;
  832.  
  833.     bi.biSize               = sizeof(BITMAPINFOHEADER);
  834.     bi.biWidth              = bm.bmWidth;
  835.     bi.biHeight             = bm.bmHeight;
  836.     bi.biPlanes             = 1;
  837.     bi.biBitCount           = biBits;
  838.     bi.biCompression        = BI_RGB;
  839.     bi.biSizeImage          = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * 
  840.                                 bm.bmHeight;
  841.     bi.biXPelsPerMeter      = 0;
  842.     bi.biYPelsPerMeter      = 0;
  843.     bi.biClrUsed            = nLDibColors;
  844.     bi.biClrImportant       = 0;
  845.  
  846.     dwLDibLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  847.  
  848.     hLDib = GlobalAlloc(GMEM_MOVEABLE,dwLDibLen);
  849.                                     
  850.     if (!hLDib)
  851.         return NULL;
  852.  
  853.     lpbiDDB = MAKEP(GlobalAlloc(GMEM_FIXED,
  854.                     bi.biSize + 256 * sizeof(RGBQUAD)),0);
  855.  
  856.     if (!lpbiDDB)
  857.     {
  858.         GlobalFree(hLDib);
  859.         return NULL;
  860.     }
  861.  
  862.     hdc = GetDC(NULL);
  863.     hpalT = SelectPalette(hdc,hpal,FALSE);
  864.     RealizePalette(hdc);
  865.  
  866.     lpLDib = (LPVOID)GlobalLock(hLDib);
  867.  
  868.     *lpbiDDB  = bi;
  869.     *lpLDib = bi;
  870.  
  871.     /* Get the DIB bits. With DIB_PAL_COLORS flag, the color table is
  872.      * filled with logical palette indices.
  873.      */
  874.     lpLDibBits = (LPSTR)lpLDib + (WORD)lpLDib->biSize + PaletteSize(lpLDib);
  875.  
  876.     GetDIBits(hdc,                    // Device context
  877.               hbm,                    // Bitmap we're copying
  878.               0,                      // Starting scan line
  879.               (WORD)bi.biHeight,      // Number of scan lines to copy
  880.               lpLDibBits,           // Receives bitmap bits in DIB format
  881.               (LPBITMAPINFO)lpbiDDB,  // Receives DDB color table
  882.               DIB_PAL_COLORS);        // Usage--copy indices into the 
  883.                                       // currently realized logical palette
  884.  
  885.     /* Convert the DIB bits from indices into the color table (which
  886.      * contains indices into the logical palette) to direct indices
  887.      * into the logical palette.
  888.      *
  889.      * lpDDBClrTbl   Points to the DIB color table, which is a WORD array of
  890.      *               logical palette indices.
  891.      *
  892.      * lpLDibBits    Points to the DIB bits. Each DIB pixel is a index into
  893.      *               the DIB color table.
  894.      */
  895.     lpDDBClrTbl = (WORD FAR *)((LPSTR)lpbiDDB + (WORD)lpbiDDB->biSize);
  896.  
  897.     if (biBits == 8)
  898.     {
  899.         for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE huge *)lpLDibBits)++)
  900.             *lpLDibBits = (BYTE)lpDDBClrTbl[*lpLDibBits];
  901.     }
  902.     else // biBits == 4
  903.     {
  904.         for (dw = 0; dw < bi.biSizeImage; dw++, ((BYTE huge *)lpLDibBits)++)
  905.             *lpLDibBits = (BYTE)(lpDDBClrTbl[*lpLDibBits & 0x0F] |
  906.                              (lpDDBClrTbl[(*lpLDibBits >> 4) & 0x0F] << 4));
  907.     }
  908.  
  909.     /* Now copy the RGBs in the logical palette to the DIB color table.
  910.      */
  911.     lpLDibRGB = (RGBQUAD FAR *)((LPSTR)lpLDib + (WORD)lpLDib->biSize);
  912.  
  913.     for (n=0; n<nLDibColors; n++, lpLDibRGB++)
  914.     {
  915.         GetPaletteEntries(hpal,n,1,&peT);
  916.  
  917.         lpLDibRGB->rgbRed      = peT.peRed;
  918.         lpLDibRGB->rgbGreen    = peT.peGreen;
  919.         lpLDibRGB->rgbBlue     = peT.peBlue;
  920.         lpLDibRGB->rgbReserved = (BYTE)0;
  921.     }
  922.  
  923.     GlobalUnlock(hLDib);
  924.     GlobalFree(HIWORD((DWORD)lpbiDDB));
  925.  
  926.     SelectPalette(hdc,hpalT,FALSE);
  927.     ReleaseDC(NULL,hdc);
  928.  
  929.     return hLDib;
  930. }
  931.  
  932. /* StretchBitmap(hdc, x, y, dx, dy, hbm, xSrc, ySrc, dxSrc, dySrc, rop)
  933.  *
  934.  * Draws bitmap <hbm> at the specifed position in DC <hdc>, stretching
  935.  * or compressing the bitmap as necessary to fit the dimensions of the
  936.  * destination rectangle.
  937.  */
  938. BOOL StretchBitmap(
  939.     HDC hdc,                    // Destination device context
  940.     int x, int y,               // Upper-left corner of destination rect
  941.     int dx, int dy,             // Destination rect extents
  942.     HBITMAP hbm,                // Bitmap to display
  943.     int xSrc, int ySrc,         // Upper-left corner of source rect
  944.     int dxSrc, int dySrc,       // Source rect extents
  945.     DWORD rop)                  // Raster operation
  946. {
  947.     HDC hdcBits;
  948.     HPALETTE hpal,hpalT;
  949.     BOOL f;
  950.  
  951.     if (!hdc || !hbm)
  952.         return FALSE;
  953.  
  954.     hpal = SelectPalette(hdc,GetStockObject(DEFAULT_PALETTE),FALSE);
  955.     SelectPalette(hdc,hpal,FALSE);
  956.  
  957.     hdcBits = CreateCompatibleDC(hdc);
  958.     SelectObject(hdcBits,hbm);
  959.     hpalT = SelectPalette(hdcBits,hpal,FALSE);
  960.     RealizePalette(hdcBits);
  961.     f = StretchBlt(hdc,x,y,dx,dy,hdcBits,xSrc,ySrc,dxSrc,dySrc,rop);
  962.     SelectPalette(hdcBits,hpalT,FALSE);
  963.     DeleteDC(hdcBits);
  964.  
  965.     return f;
  966. }
  967.  
  968.  
  969. /* DrawBitmap(hdc, x, y, hbm, DWORD)
  970.  *
  971.  * Draws bitmap <hbm> at the specifed position in DC <hdc>
  972.  *
  973.  */
  974. BOOL DrawBitmap(
  975.     HDC hdc,                    // Destination device context
  976.     int x, int y,               // Upper-left corner of destination rect
  977.     HBITMAP hbm,                // Bitmap to display
  978.     DWORD rop)                  // Raster operation
  979. {
  980.     HDC hdcBits;
  981.     BITMAP bm;
  982.     BOOL f;
  983.  
  984.     if (!hdc || !hbm)
  985.         return FALSE;
  986.  
  987.     hdcBits = CreateCompatibleDC(hdc);
  988.     GetObject(hbm,sizeof(BITMAP),(LPSTR)&bm);
  989.     SelectObject(hdcBits,hbm);
  990.     f = BitBlt(hdc,x,y,bm.bmWidth,bm.bmHeight,hdcBits,0,0,rop);
  991.     DeleteDC(hdcBits);
  992.  
  993.     return f;
  994. }
  995.  
  996. /* SetDibUsage(hdib,hpal,wUsage)
  997.  *
  998.  * Modifies the color table of the passed DIB for use with the wUsage
  999.  * parameter specifed.
  1000.  *
  1001.  * if wUsage is DIB_PAL_COLORS the DIB color table is set to 0-256
  1002.  * if wUsage is DIB_RGB_COLORS the DIB color table is set to the RGB values
  1003.  *     in the passed palette
  1004.  *
  1005.  */
  1006. BOOL SetDibUsage(
  1007.     HANDLE hdib,                // DIB to modify
  1008.     HPALETTE hpal,              // DIB palette
  1009.     WORD wUsage)                // New palette usage
  1010. {
  1011.     LPBITMAPINFOHEADER lpbi;
  1012.     PALETTEENTRY       ape[MAXPALETTE];
  1013.     RGBQUAD FAR *      pRgb;
  1014.     WORD FAR *         pw;
  1015.     int                nColors;
  1016.     int                n;
  1017.  
  1018.     if (hpal == NULL)
  1019.         hpal = GetStockObject(DEFAULT_PALETTE);
  1020.  
  1021.     if (!hdib)
  1022.         return FALSE;
  1023.  
  1024.     lpbi = (VOID FAR *)GlobalLock(hdib);
  1025.  
  1026.     if (!lpbi)
  1027.         return FALSE;
  1028.  
  1029.     nColors = DibNumColors(lpbi);
  1030.  
  1031.     if (nColors > 0)
  1032.     {
  1033.         pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
  1034.  
  1035.         switch (wUsage)
  1036.         {
  1037.             //
  1038.             // Set the DIB color table to palette indexes
  1039.             //
  1040.             case DIB_PAL_COLORS:
  1041.                 for (pw = (WORD FAR*)pRgb,n=0; n<nColors; n++,pw++)
  1042.                     *pw = n;
  1043.                 break;
  1044.  
  1045.             //
  1046.             // Set the DIB color table to RGBQUADS
  1047.             //
  1048.             default:
  1049.             case DIB_RGB_COLORS:
  1050.                 nColors = min(nColors,MAXPALETTE);
  1051.  
  1052.                 GetPaletteEntries(hpal,0,nColors,ape);
  1053.  
  1054.                 for (n=0; n<nColors; n++)
  1055.                 {
  1056.                     pRgb[n].rgbRed      = ape[n].peRed;
  1057.                     pRgb[n].rgbGreen    = ape[n].peGreen;
  1058.                     pRgb[n].rgbBlue     = ape[n].peBlue;
  1059.                     pRgb[n].rgbReserved = 0;
  1060.                 }
  1061.                 break;
  1062.         }
  1063.     }
  1064.     GlobalUnlock(hdib);
  1065.     return TRUE;
  1066. }
  1067.  
  1068. /*  SetPalFlags(hpal,iIndex, cnt, wFlags)
  1069.  *
  1070.  *  Modifies the palette flags of all indices in the range 
  1071.  *  (iIndex - nIndex+cnt) to the parameter specifed.
  1072.  */
  1073. BOOL SetPalFlags(
  1074.     HPALETTE hpal,              // Palette to modify
  1075.     int iIndex,                 // Starting index number
  1076.     int cntEntries,             // How many entries to modify
  1077.     WORD wFlags)                // New flag setting for pal entries
  1078. {
  1079.     int     i;
  1080.     BOOL    f;
  1081.     HANDLE  hpe;
  1082.     PALETTEENTRY FAR *lppe;
  1083.  
  1084.     if (hpal == NULL)
  1085.         return FALSE;
  1086.  
  1087.     if (cntEntries < 0)
  1088.         GetObject(hpal,sizeof(int),(LPSTR)&cntEntries);
  1089.  
  1090.     hpe = GlobalAlloc(GMEM_MOVEABLE,(LONG)cntEntries * sizeof(PALETTEENTRY));
  1091.  
  1092.     if (!hpe)
  1093.         return FALSE;
  1094.  
  1095.     lppe = (VOID FAR*)GlobalLock(hpe);
  1096.  
  1097.     GetPaletteEntries(hpal, iIndex, cntEntries, lppe);
  1098.  
  1099.     for (i=0; i<cntEntries; i++)
  1100.     {
  1101.         lppe[i].peFlags = (BYTE)wFlags;
  1102.     }
  1103.  
  1104.     f = SetPaletteEntries(hpal, iIndex, cntEntries, lppe);
  1105.  
  1106.     GlobalUnlock(hpe);
  1107.     GlobalFree(hpe);
  1108.     return f;
  1109. }
  1110.  
  1111. /* PalEq(hpal1,hpal2)
  1112.  *
  1113.  * Returns TRUE if the pallettes are the same
  1114.  *
  1115.  */
  1116. BOOL PalEq(HPALETTE hpal1, HPALETTE hpal2)
  1117. {
  1118.     BOOL    f;
  1119.     int     i;
  1120.     int     nPal1,nPal2;
  1121.     PALETTEENTRY FAR *ppe;
  1122.  
  1123.     if (hpal1 == hpal2)
  1124.         return TRUE;
  1125.  
  1126.     if (!hpal1 || !hpal2)
  1127.         return FALSE;
  1128.  
  1129.     GetObject(hpal1,sizeof(int),(LPSTR)&nPal1);
  1130.     GetObject(hpal2,sizeof(int),(LPSTR)&nPal2);
  1131.  
  1132.     if (nPal1 != nPal2)
  1133.         return FALSE;
  1134.  
  1135.     ppe = ALLOCP(nPal1 * 2 * sizeof(PALETTEENTRY));
  1136.  
  1137.     if (!ppe)
  1138.         return FALSE;
  1139.  
  1140.     GetPaletteEntries(hpal1, 0, nPal1, ppe);
  1141.     GetPaletteEntries(hpal2, 0, nPal2, ppe+nPal1);
  1142.  
  1143.     for (f=TRUE,i=0; f && i<nPal1; i++)
  1144.     {
  1145.         f &= (ppe[i].peRed   == ppe[i+nPal1].peRed   &&
  1146.               ppe[i].peBlue  == ppe[i+nPal1].peBlue  &&
  1147.               ppe[i].peGreen == ppe[i+nPal1].peGreen);
  1148.     }
  1149.  
  1150.     FREEP(ppe);
  1151.     return f;
  1152. }
  1153.  
  1154. /* StretchDibBlt(hdc, x, y, dx, dy, hdib, xSrc, ySrc, dxSrc, dySrc, rop, wUsage)
  1155.  *
  1156.  * Draws a bitmap in CF_DIB format StretchDIBits(). Uses the same
  1157.  * parameters as StretchBlt(), except takes a DIB rather than a source
  1158.  * device context.
  1159.  */
  1160. BOOL StretchDibBlt(
  1161.     HDC hdc,               // Destination device context
  1162.     int x, int y,          // Destination rect origin
  1163.     int dx, int dy,        // Destination rect extents
  1164.     HANDLE hdib,           // Bitmap to display
  1165.     int xSrc, int ySrc,    // Source rect origin
  1166.     int dxSrc, int dySrc,  // Source rect extents
  1167.     LONG rop,              // Raster operation
  1168.     WORD wUsage)           // Pal usage DIB_PAL_COLORS or DIB_RGB_COLORS
  1169. {
  1170.     LPBITMAPINFOHEADER lpbi;
  1171.     LPSTR        pBuf;
  1172.     BOOL         f;
  1173.  
  1174.     if (!hdib)
  1175.         return PatBlt(hdc,x,y,dx,dy,rop);
  1176.  
  1177.     if (wUsage == 0)
  1178.         wUsage = DIB_RGB_COLORS;
  1179.  
  1180.     lpbi = (VOID FAR *)GlobalLock(hdib);
  1181.  
  1182.     if (!lpbi)
  1183.         return FALSE;
  1184.  
  1185.     if (dxSrc == -1 && dySrc == -1)
  1186.     {
  1187.         if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  1188.         {
  1189.             dxSrc = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
  1190.             dySrc = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
  1191.         }
  1192.         else
  1193.         {
  1194.             dxSrc = (int)lpbi->biWidth;
  1195.             dySrc = (int)lpbi->biHeight;
  1196.         }
  1197.     }
  1198.  
  1199.     if (dx == -1 && dy == -1)
  1200.     {
  1201.         dx = dxSrc;
  1202.         dy = dySrc;
  1203.     }
  1204.  
  1205.     pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
  1206.  
  1207.     f = StretchDIBits (
  1208.         hdc,
  1209.         x,y,
  1210.         dx,dy,
  1211.         xSrc,ySrc,
  1212.         dxSrc,dySrc,
  1213.         pBuf, 
  1214.         (LPBITMAPINFO)lpbi,
  1215.         wUsage,
  1216.         rop);
  1217.  
  1218.     GlobalUnlock(hdib);
  1219.     return f;
  1220. }
  1221.  
  1222. /*  DibBlt(hdc, xDest, yDest, dxDest, dyDest, hdib, xSrc, ySrc, rop, wUsage)
  1223.  *
  1224.  *  Draws a bitmap in CF_DIB format, using SetDIBits to device.
  1225.  *
  1226.  *  Takes the same parameters as BitBlt(), except takes a DIB instead of
  1227.  *  a source device context.
  1228.  */
  1229. BOOL DibBlt(
  1230.     HDC hdc,                // Destination device context
  1231.     int xDest, int yDest,   // Destination rect origin
  1232.     int dxDest, int dyDest, // Destination rect extents
  1233.     HANDLE hdib,            // DIB to draw
  1234.     int xSrc, int ySrc,     // Source rect origin
  1235.     LONG rop,               // Raster op
  1236.     WORD wUsage)            // Pal usage (DIB_PAL_COLORS or DIB_RGB_COLORS)
  1237. {
  1238.     LPBITMAPINFOHEADER lpbi;
  1239.     LPSTR       pBuf;
  1240.     BOOL        f;
  1241.  
  1242.     if (!hdib)
  1243.         return PatBlt(hdc,xDest,yDest,dxDest,dyDest,rop);
  1244.  
  1245.     if (wUsage == 0)
  1246.         wUsage = DIB_RGB_COLORS;
  1247.  
  1248.     lpbi = (VOID FAR *)GlobalLock(hdib);
  1249.  
  1250.     if (!lpbi)
  1251.         return FALSE;
  1252.  
  1253.     if (dxDest == -1 && dyDest == -1)
  1254.     {
  1255.         if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  1256.         {
  1257.             dxDest = ((LPBITMAPCOREHEADER)lpbi)->bcWidth;
  1258.             dyDest = ((LPBITMAPCOREHEADER)lpbi)->bcHeight;
  1259.         }
  1260.         else
  1261.         {
  1262.             dxDest = (int)lpbi->biWidth;
  1263.             dyDest = (int)lpbi->biHeight;
  1264.         }
  1265.     }
  1266.  
  1267.     pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
  1268.  
  1269.     f = StretchDIBits (
  1270.         hdc,
  1271.         xDest,yDest,
  1272.         dxDest,dyDest,
  1273.         xSrc,ySrc,
  1274.         dxDest,dyDest,
  1275.         pBuf, (LPBITMAPINFO)lpbi,
  1276.         wUsage,
  1277.         rop);
  1278.  
  1279.     GlobalUnlock(hdib);
  1280.     return f;
  1281. }
  1282.  
  1283. /* DibLock(hdib, x, y)
  1284.  *
  1285.  * Locks a DIB and returns a pointer to the bitmap bits at the specified
  1286.  * coordinate.
  1287.  */
  1288. LPVOID DibLock(
  1289.     HANDLE hdib,            // DIB to lock
  1290.     int x, int y)           // Bit coordinates
  1291. {
  1292.     return DibXY((LPBITMAPINFOHEADER)GlobalLock(hdib),x,y);
  1293. }
  1294.  
  1295. /* DibUnlock(hdib)
  1296.  *
  1297.  * Unlocks a DIB.
  1298.  */
  1299. VOID DibUnlock(HANDLE hdib)
  1300. {
  1301.     GlobalUnlock(hdib);
  1302. }
  1303.  
  1304.  
  1305. /* DibXY(lpbi, x, y)
  1306.  *
  1307.  * Given a BITMAPINFOHEADER and a set of coordinates, returns a pointer
  1308.  * to the bitmap bits at the specified coordinates.
  1309.  */
  1310. LPVOID DibXY(LPBITMAPINFOHEADER lpbi,int x, int y)
  1311. {
  1312.     BYTE huge *pBits;
  1313.     DWORD ulWidthBytes;
  1314.  
  1315.     pBits = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
  1316.  
  1317.     ulWidthBytes = WIDTHBYTES(lpbi->biWidth*lpbi->biBitCount);
  1318.  
  1319.     pBits += (ulWidthBytes * (long)y) + x;
  1320.  
  1321.     return (LPVOID)pBits;
  1322. }
  1323.  
  1324. /* fmemcpy(fpDst, fpSrc, uiCount)
  1325.  *
  1326.  * Copies the specified number of bytes from the source to the destination.
  1327.  */
  1328. static void fmemcpy(
  1329.     void far *fpDst,            // Destination address
  1330.     void far *fpSrc,            // Source address
  1331.     unsigned int uiCount)       // How many bytes to copy
  1332. {
  1333.         while (uiCount-- > 0)
  1334.                 *((char far *) fpDst)++ = *((char far *) fpSrc)++;
  1335. }
  1336.  
  1337.  
  1338. /* CreateDib(hdib, dx, dy)
  1339.  *
  1340.  * Creates a DIB with the same header and color table as the original
  1341.  * DIB, with sufficient space to hold the indicated region. If the <hdib>
  1342.  * is NULL, creates a DIB header and uninitialized, 256-entry color table.
  1343.  */
  1344. HANDLE CreateDib(
  1345.     HANDLE hdib,       // DIB to copy or NULL
  1346.     int dx, int dy)    // Size of new DIB or -1 to use original DIB extents
  1347. {
  1348.     HANDLE              hdibN;
  1349.     BITMAPINFOHEADER    bi;
  1350.     LPBITMAPINFOHEADER  lpbi1;
  1351.     LPBITMAPINFOHEADER  lpbi2;
  1352.     RGBQUAD FAR *       pRgb1;
  1353.     RGBQUAD FAR *       pRgb2;
  1354.  
  1355.     if (hdib)                // Copy DIB header or create a new one
  1356.     {
  1357.         DibInfo(hdib,&bi);
  1358.     }
  1359.     else
  1360.     {
  1361.         bi.biSize           = sizeof(BITMAPINFOHEADER);
  1362.         bi.biPlanes         = 1;
  1363.         bi.biBitCount       = 8;
  1364.         bi.biWidth          = 0;
  1365.         bi.biHeight         = 0;
  1366.         bi.biCompression    = BI_RGB;
  1367.         bi.biSizeImage      = 0;
  1368.         bi.biXPelsPerMeter  = 0;
  1369.         bi.biYPelsPerMeter  = 0;
  1370.         bi.biClrUsed        = 256;
  1371.         bi.biClrImportant   = 0;
  1372.     }
  1373.  
  1374.  
  1375.     if (dx != -1)           // Use specified measurements or original extents
  1376.         bi.biWidth = dx;
  1377.  
  1378.     if (dy != -1)
  1379.         bi.biHeight = dy;
  1380.  
  1381.     bi.biSizeImage = WIDTHBYTES(bi.biWidth*bi.biBitCount) * (long)dy;
  1382.  
  1383.     hdibN = GlobalAlloc(GMEM_MOVEABLE,sizeof(BITMAPINFOHEADER) +
  1384.                 + (long)bi.biClrUsed * sizeof(RGBQUAD) + bi.biSizeImage);
  1385.  
  1386.     /*  Copy the color table across
  1387.      */
  1388.     if (hdibN && hdib)
  1389.     {
  1390.         lpbi1 = (VOID FAR*)GlobalLock(hdibN);
  1391.         lpbi2 = (VOID FAR*)GlobalLock(hdib);
  1392.  
  1393.         *lpbi1 = bi;
  1394.  
  1395.         pRgb1 = (VOID FAR *)((LPSTR)lpbi1 + lpbi1->biSize);
  1396.         pRgb2 = (VOID FAR *)((LPSTR)lpbi2 + lpbi2->biSize);
  1397.  
  1398.         while (bi.biClrUsed-- > 0)
  1399.             *pRgb1++ = *pRgb2++;
  1400.  
  1401.         GlobalUnlock(hdib);
  1402.         GlobalUnlock(hdibN);
  1403.     }
  1404.     return hdibN;
  1405. }
  1406.  
  1407.  
  1408. /*
  1409.  * Private routines to read/write more than 64k
  1410.  */
  1411.  
  1412. #define MAXREAD (WORD)(32 * 1024)
  1413.  
  1414. static DWORD NEAR PASCAL lread(int fh, VOID FAR *pv, DWORD ul)
  1415. {
  1416.     DWORD  ulT = ul;
  1417.     BYTE huge *hp = pv;
  1418.  
  1419.     while (ul > MAXREAD) {
  1420.         if (_lread(fh, (LPSTR)hp, MAXREAD) != MAXREAD)
  1421.                 return 0;
  1422.         ul -= MAXREAD;
  1423.         hp += MAXREAD;
  1424.     }
  1425.     if (_lread(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
  1426.         return 0;
  1427.     return ulT;
  1428. }
  1429.  
  1430. static DWORD NEAR PASCAL lwrite(int fh, VOID FAR *pv, DWORD ul)
  1431. {
  1432.     DWORD  ulT = ul;
  1433.     BYTE huge *hp = pv;
  1434.  
  1435.     while (ul > MAXREAD) {
  1436.         if (_lwrite(fh, (LPSTR)hp, MAXREAD) != MAXREAD)
  1437.                 return 0;
  1438.         ul -= MAXREAD;
  1439.         hp += MAXREAD;
  1440.     }
  1441.     if (_lwrite(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
  1442.         return 0;
  1443.     return ulT;
  1444. }
  1445.