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