home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / d / d020_1_4 / 6.ddi / SHOWDIB / DIB.C next >
Encoding:
C/C++ Source or Header  |  1990-06-01  |  25.3 KB  |  868 lines

  1. /*******************************************************************************
  2.  *                                           *
  3.  *  MODULE    : DIB.C                                *
  4.  *                                           *
  5.  *  DESCRIPTION : Routines for dealing with Device Independent Bitmaps.        *
  6.  *                                           *
  7.  *  FUNCTIONS    : OpenDIB()          - Opens DIB file and creates a memory DIB*
  8.  *                                           *
  9.  *          WriteDIB()          - Writes a global handle in CF_DIB format*
  10.  *                    to a file.                   *
  11.  *                                           *
  12.  *          DibInfo()          - Retrieves the info. block associated   *
  13.  *                    with a CF_DIB format memory block.     *
  14.  *                                           *
  15.  *          CreateBIPalette()   - Creates a GDI palette given a pointer  *
  16.  *                    to a BITMAPINFO structure.           *
  17.  *                                           *
  18.  *          CreateDibPalette()  - Creates a GDI palette given a HANDLE   *
  19.  *                    to a BITMAPINFO structure.           *
  20.  *                                           *
  21.  *          ReadDibBitmapInfo() - Reads a file in DIB format and returns *
  22.  *                    a global handle to it's BITMAPINFO     *
  23.  *                                           *
  24.  *          PaletteSize()       - Calculates the palette size in bytes   *
  25.  *                    of given DIB                   *
  26.  *                                           *
  27.  *          DibNumColors()      - Determines the number of colors in DIB *
  28.  *                                           *
  29.  *          BitmapFromDib()     - Creates a DDB given a global handle to *
  30.  *                    a block in CF_DIB format.           *
  31.  *                                           *
  32.  *          DibFromBitmap()     - Creates a DIB repr. the DDB passed in. *
  33.  *                                           *
  34.  *          DrawBitmap()          - Draws a bitmap at specified position   *
  35.  *                    in the DC.                   *
  36.  *                                           *
  37.  *          DibBlt()          - Draws a bitmap in CIF_DIB format using *
  38.  *                    SetDIBitsToDevice()               *
  39.  *                                           *
  40.  *          StretchDibBlt()     - Draws a bitmap in CIF_DIB format using *
  41.  *                    StretchDIBits()                *
  42.  *                                           *
  43.  *          lread()          - Private routine to read more than 64k  *
  44.  *                                           *
  45.  *          lwrite()          - Private routine to write more than 64k *
  46.  *                                           *
  47.  *******************************************************************************/
  48.  
  49. #include <windows.h>
  50. #include "showdib.h"
  51. static     HCURSOR hcurSave;
  52.  
  53. /****************************************************************************
  54.  *                                        *
  55.  *  FUNCTION   :OpenDIB(LPSTR szFile)                        *
  56.  *                                        *
  57.  *  PURPOSE    :Open a DIB file and create a MEMORY DIB, a memory handle    *
  58.  *        containing BITMAPINFO, palette data and the bits.        *
  59.  *                                        *
  60.  *  RETURNS    :A handle to the DIB.                        *
  61.  *                                        *
  62.  ****************************************************************************/
  63. HANDLE OpenDIB (szFile)
  64. LPSTR szFile;
  65. {
  66.     unsigned        fh;
  67.     BITMAPINFOHEADER    bi;
  68.     LPBITMAPINFOHEADER  lpbi;
  69.     DWORD        dwLen = 0;
  70.     DWORD        dwBits;
  71.     HANDLE        hdib;
  72.     HANDLE              h;
  73.     OFSTRUCT        of;
  74.  
  75.     /* Open the file and read the DIB information */
  76.     fh = OpenFile(szFile, &of, OF_READ);
  77.     if (fh == -1)
  78.     return NULL;
  79.  
  80.     hdib = ReadDibBitmapInfo(fh);
  81.     if (!hdib)
  82.     return NULL;
  83.     DibInfo(hdib,&bi);
  84.  
  85.     /* Calculate the memory needed to hold the DIB */
  86.     dwBits = bi.biSizeImage;
  87.     dwLen  = bi.biSize + (DWORD)PaletteSize (&bi) + dwBits;
  88.  
  89.     /* Try to increase the size of the bitmap info. buffer to hold the DIB */
  90.     h = GlobalReAlloc(hdib, dwLen, GHND);
  91.     if (!h){
  92.     GlobalFree(hdib);
  93.     hdib = NULL;
  94.     }
  95.     else
  96.     hdib = h;
  97.  
  98.     /* Read in the bits */
  99.     if (hdib){
  100.  
  101.         lpbi = (VOID FAR *)GlobalLock(hdib);
  102.     lread(fh, (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi), dwBits);
  103.     GlobalUnlock(hdib);
  104.     }
  105.     _lclose(fh);
  106.  
  107.     return hdib;
  108. }
  109.  
  110. /****************************************************************************
  111.  *                                        *
  112.  *  FUNCTION   : WriteDIB(LPSTR szFile,HANDLE hdib)                *
  113.  *                                        *
  114.  *  PURPOSE    : Write a global handle in CF_DIB format to a file.        *
  115.  *                                        *
  116.  *  RETURNS    : TRUE  - if successful.                     *
  117.  *         FALSE - otherwise                        *
  118.  *                                        *
  119.  ****************************************************************************/
  120. BOOL WriteDIB (szFile, hdib)
  121. LPSTR szFile;
  122. HANDLE hdib;
  123. {
  124.     BITMAPFILEHEADER    hdr;
  125.     LPBITMAPINFOHEADER  lpbi;
  126.     int                 fh;
  127.     OFSTRUCT            of;
  128.  
  129.     if (!hdib)
  130.     return FALSE;
  131.  
  132.     fh = OpenFile (szFile, &of, OF_CREATE|OF_READWRITE);
  133.     if (fh == -1)
  134.     return FALSE;
  135.  
  136.     lpbi = (VOID FAR *)GlobalLock (hdib);
  137.  
  138.     /* Fill in the fields of the file header */
  139.     hdr.bfType        = BFT_BITMAP;
  140.     hdr.bfSize        = GlobalSize (hdib) + sizeof (BITMAPFILEHEADER);
  141.     hdr.bfReserved1     = 0;
  142.     hdr.bfReserved2     = 0;
  143.     hdr.bfOffBits       = (DWORD)sizeof(BITMAPFILEHEADER) + lpbi->biSize +
  144.                           PaletteSize(lpbi);
  145.  
  146.     /* Write the file header */
  147.     _lwrite (fh, (LPSTR)&hdr, sizeof (BITMAPFILEHEADER));
  148.  
  149.     /* Write the DIB header and the bits */
  150.     lwrite (fh, (LPSTR)lpbi, GlobalSize (hdib));
  151.  
  152.     GlobalUnlock (hdib);
  153.     _lclose (fh);
  154.     return TRUE;
  155. }
  156.  
  157. /****************************************************************************
  158.  *                                        *
  159.  *  FUNCTION   : DibInfo(HANDLE hbi,LPBITMAPINFOHEADER lpbi)            *
  160.  *                                        *
  161.  *  PURPOSE    : Retrieves the DIB info associated with a CF_DIB        *
  162.  *         format memory block.                        *
  163.  *                                        *
  164.  *  RETURNS    : TRUE  - if successful.                     *
  165.  *         FALSE - otherwise                        *
  166.  *                                        *
  167.  ****************************************************************************/
  168. BOOL DibInfo (hbi, lpbi)
  169. HANDLE hbi;
  170. LPBITMAPINFOHEADER lpbi;
  171. {
  172.     if (hbi){
  173.     *lpbi = *(LPBITMAPINFOHEADER)GlobalLock (hbi);
  174.  
  175.     /* fill in the default fields */
  176.     if (lpbi->biSize != sizeof (BITMAPCOREHEADER)){
  177.             if (lpbi->biSizeImage == 0L)
  178.         lpbi->biSizeImage =
  179.             WIDTHBYTES(lpbi->biWidth*lpbi->biBitCount) * lpbi->biHeight;
  180.  
  181.             if (lpbi->biClrUsed == 0L)
  182.         lpbi->biClrUsed = DibNumColors (lpbi);
  183.         }
  184.     GlobalUnlock (hbi);
  185.     return TRUE;
  186.     }
  187.     return FALSE;
  188. }
  189.  
  190. /****************************************************************************
  191.  *                                        *
  192.  *  FUNCTION   : CreateBIPalette(LPBITMAPINFOHEADER lpbi)            *
  193.  *                                        *
  194.  *  PURPOSE    : Given a Pointer to a BITMAPINFO struct will create a        *
  195.  *         a GDI palette object from the color table.            *
  196.  *                                        *
  197.  *  RETURNS    : A handle to the palette.                    *
  198.  *                                        *
  199.  ****************************************************************************/
  200. HPALETTE CreateBIPalette (lpbi)
  201. LPBITMAPINFOHEADER lpbi;
  202. {
  203.     LOGPALETTE          *pPal;
  204.     HPALETTE            hpal = NULL;
  205.     WORD                nNumColors;
  206.     BYTE                red;
  207.     BYTE                green;
  208.     BYTE                blue;
  209.     int                 i;
  210.     RGBQUAD        FAR *pRgb;
  211.  
  212.     if (!lpbi)
  213.     return NULL;
  214.  
  215.     if (lpbi->biSize != sizeof(BITMAPINFOHEADER))
  216.     return NULL;
  217.  
  218.     /* Get a pointer to the color table and the number of colors in it */
  219.     pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + (WORD)lpbi->biSize);
  220.     nNumColors = DibNumColors(lpbi);
  221.  
  222.     if (nNumColors){
  223.     /* Allocate for the logical palette structure */
  224.         pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  225.     if (!pPal)
  226.         return NULL;
  227.  
  228.         pPal->palNumEntries = nNumColors;
  229.     pPal->palVersion    = PALVERSION;
  230.  
  231.     /* Fill in the palette entries from the DIB color table and
  232.      * create a logical color palette.
  233.      */
  234.     for (i = 0; i < nNumColors; i++){
  235.             pPal->palPalEntry[i].peRed   = pRgb[i].rgbRed;
  236.             pPal->palPalEntry[i].peGreen = pRgb[i].rgbGreen;
  237.             pPal->palPalEntry[i].peBlue  = pRgb[i].rgbBlue;
  238.             pPal->palPalEntry[i].peFlags = (BYTE)0;
  239.         }
  240.         hpal = CreatePalette(pPal);
  241.         LocalFree((HANDLE)pPal);
  242.     }
  243.     else if (lpbi->biBitCount == 24){
  244.     /* A 24 bitcount DIB has no color table entries so, set the number of
  245.      * to the maximum value (256).
  246.      */
  247.     nNumColors = MAXPALETTE;
  248.         pPal = (LOGPALETTE*)LocalAlloc(LPTR,sizeof(LOGPALETTE) + nNumColors * sizeof(PALETTEENTRY));
  249.         if (!pPal)
  250.         return NULL;
  251.  
  252.     pPal->palNumEntries = nNumColors;
  253.     pPal->palVersion    = PALVERSION;
  254.  
  255.     red = green = blue = 0;
  256.  
  257.     /* Generate 256 (= 8*8*4) RGB combinations to fill the palette
  258.      * entries.
  259.      */
  260.     for (i = 0; i < pPal->palNumEntries; i++){
  261.             pPal->palPalEntry[i].peRed   = red;
  262.             pPal->palPalEntry[i].peGreen = green;
  263.             pPal->palPalEntry[i].peBlue  = blue;
  264.             pPal->palPalEntry[i].peFlags = (BYTE)0;
  265.  
  266.         if (!(red += 32))
  267.         if (!(green += 32))
  268.             blue += 64;
  269.         }
  270.         hpal = CreatePalette(pPal);
  271.         LocalFree((HANDLE)pPal);
  272.     }
  273.     return hpal;
  274. }
  275.  
  276. /****************************************************************************
  277.  *                                        *
  278.  *  FUNCTION   : CreateDibPalette(HANDLE hbi)                    *
  279.  *                                        *
  280.  *  PURPOSE    : Given a Global HANDLE to a BITMAPINFO Struct            *
  281.  *         will create a GDI palette object from the color table.     *
  282.  *         (BITMAPINFOHEADER format DIBs only)                     *
  283.  *                                        *
  284.  *  RETURNS    : A handle to the palette.                    *
  285.  *                                        *
  286.  ****************************************************************************/
  287. HPALETTE CreateDibPalette (hbi)
  288. HANDLE hbi;
  289. {
  290.     HPALETTE hpal;
  291.  
  292.     if (!hbi)
  293.     return NULL;
  294.     hpal = CreateBIPalette((LPBITMAPINFOHEADER)GlobalLock(hbi));
  295.     GlobalUnlock(hbi);
  296.     return hpal;
  297. }
  298.  
  299. /****************************************************************************
  300.  *                                        *
  301.  *  FUNCTION   : ReadDibBitmapInfo(int fh)                    *
  302.  *                                        *
  303.  *  PURPOSE    : Will read a file in DIB format and return a global HANDLE  *
  304.  *         to it's BITMAPINFO.  This function will work with both     *
  305.  *         "old" (BITMAPCOREHEADER) and "new" (BITMAPINFOHEADER)        *
  306.  *         bitmap formats, but will always return a "new" BITMAPINFO  *
  307.  *                                        *
  308.  *  RETURNS    : A handle to the BITMAPINFO of the DIB in the file.        *
  309.  *                                        *
  310.  ****************************************************************************/
  311. HANDLE ReadDibBitmapInfo (fh)
  312. int fh;
  313. {
  314.     DWORD     off;
  315.     HANDLE    hbi = NULL;
  316.     int       size;
  317.     int       i;
  318.     WORD      nNumColors;
  319.  
  320.     RGBQUAD FAR       *pRgb;
  321.     BITMAPINFOHEADER   bi;
  322.     BITMAPCOREHEADER   bc;
  323.     LPBITMAPINFOHEADER lpbi;
  324.     BITMAPFILEHEADER   bf;
  325.     DWORD           dwWidth = 0;
  326.     DWORD           dwHeight = 0;
  327.     WORD           wPlanes, wBitCount;
  328.  
  329.     if (fh == -1)
  330.         return NULL;
  331.  
  332.     /* Reset file pointer and read file header */
  333.     off = _llseek(fh, 0L, SEEK_CUR);
  334.     if (sizeof (bf) != _lread (fh, (LPSTR)&bf, sizeof (bf)))
  335.         return FALSE;
  336.  
  337.     /* Do we have a RC HEADER? */
  338.     if (!ISDIB (bf.bfType)) {
  339.         bf.bfOffBits = 0L;
  340.     _llseek (fh, off, SEEK_SET);
  341.     }
  342.     if (sizeof (bi) != _lread (fh, (LPSTR)&bi, sizeof(bi)))
  343.         return FALSE;
  344.  
  345.     nNumColors = DibNumColors (&bi);
  346.  
  347.     /* Check the nature (BITMAPINFO or BITMAPCORE) of the info. block
  348.      * and extract the field information accordingly. If a BITMAPCOREHEADER,
  349.      * transfer it's field information to a BITMAPINFOHEADER-style block
  350.      */
  351.     switch (size = (int)bi.biSize){
  352.     case sizeof (BITMAPINFOHEADER):
  353.             break;
  354.  
  355.     case sizeof (BITMAPCOREHEADER):
  356.  
  357.         bc = *(BITMAPCOREHEADER*)&bi;
  358.  
  359.         dwWidth   = (DWORD)bc.bcWidth;
  360.         dwHeight  = (DWORD)bc.bcHeight;
  361.         wPlanes   = bc.bcPlanes;
  362.         wBitCount = bc.bcBitCount;
  363.  
  364.             bi.biSize               = sizeof(BITMAPINFOHEADER);
  365.         bi.biWidth            = dwWidth;
  366.         bi.biHeight         = dwHeight;
  367.         bi.biPlanes         = wPlanes;
  368.         bi.biBitCount        = wBitCount;
  369.  
  370.             bi.biCompression        = BI_RGB;
  371.             bi.biSizeImage          = 0;
  372.             bi.biXPelsPerMeter      = 0;
  373.             bi.biYPelsPerMeter      = 0;
  374.             bi.biClrUsed            = nNumColors;
  375.             bi.biClrImportant       = nNumColors;
  376.  
  377.         _llseek (fh, (LONG)sizeof (BITMAPCOREHEADER) - sizeof (BITMAPINFOHEADER), SEEK_CUR);
  378.             break;
  379.  
  380.     default:
  381.         /* Not a DIB! */
  382.         return NULL;
  383.     }
  384.  
  385.     /*    Fill in some default values if they are zero */
  386.     if (bi.biSizeImage == 0){
  387.     bi.biSizeImage = WIDTHBYTES ((DWORD)bi.biWidth * bi.biBitCount)
  388.              * bi.biHeight;
  389.     }
  390.     if (bi.biClrUsed == 0)
  391.     bi.biClrUsed = DibNumColors(&bi);
  392.  
  393.     /* Allocate for the BITMAPINFO structure and the color table. */
  394.     hbi = GlobalAlloc (GHND, (LONG)bi.biSize + nNumColors * sizeof(RGBQUAD));
  395.     if (!hbi)
  396.         return NULL;
  397.     lpbi = (VOID FAR *)GlobalLock (hbi);
  398.     *lpbi = bi;
  399.  
  400.     /* Get a pointer to the color table */
  401.     pRgb = (RGBQUAD FAR *)((LPSTR)lpbi + bi.biSize);
  402.     if (nNumColors){
  403.     if (size == sizeof(BITMAPCOREHEADER)){
  404.         /* Convert a old color table (3 byte RGBTRIPLEs) to a new
  405.          * color table (4 byte RGBQUADs)
  406.              */
  407.         _lread (fh, (LPSTR)pRgb, nNumColors * sizeof(RGBTRIPLE));
  408.  
  409.         for (i = nNumColors - 1; i >= 0; i--){
  410.                 RGBQUAD rgb;
  411.  
  412.                 rgb.rgbRed      = ((RGBTRIPLE FAR *)pRgb)[i].rgbtRed;
  413.                 rgb.rgbBlue     = ((RGBTRIPLE FAR *)pRgb)[i].rgbtBlue;
  414.                 rgb.rgbGreen    = ((RGBTRIPLE FAR *)pRgb)[i].rgbtGreen;
  415.                 rgb.rgbReserved = (BYTE)0;
  416.  
  417.                 pRgb[i] = rgb;
  418.             }
  419.         }
  420.     else
  421.             _lread(fh,(LPSTR)pRgb,nNumColors * sizeof(RGBQUAD));
  422.     }
  423.  
  424.     if (bf.bfOffBits != 0L)
  425.         _llseek(fh,off + bf.bfOffBits,SEEK_SET);
  426.  
  427.     GlobalUnlock(hbi);
  428.     return hbi;
  429. }
  430.  
  431. /****************************************************************************
  432.  *                                        *
  433.  *  FUNCTION   :  PaletteSize(VOID FAR * pv)                    *
  434.  *                                        *
  435.  *  PURPOSE    :  Calculates the palette size in bytes. If the info. block  *
  436.  *          is of the BITMAPCOREHEADER type, the number of colors is  *
  437.  *          multiplied by 3 to give the palette size, otherwise the   *
  438.  *          number of colors is multiplied by 4.                                *
  439.  *                                        *
  440.  *  RETURNS    :  Palette size in number of bytes.                *
  441.  *                                        *
  442.  ****************************************************************************/
  443. WORD PaletteSize (pv)
  444. VOID FAR * pv;
  445. {
  446.     LPBITMAPINFOHEADER lpbi;
  447.     WORD           NumColors;
  448.  
  449.     lpbi      = (LPBITMAPINFOHEADER)pv;
  450.     NumColors = DibNumColors(lpbi);
  451.  
  452.     if (lpbi->biSize == sizeof(BITMAPCOREHEADER))
  453.         return NumColors * sizeof(RGBTRIPLE);
  454.     else
  455.         return NumColors * sizeof(RGBQUAD);
  456. }
  457.  
  458. /****************************************************************************
  459.  *                                        *
  460.  *  FUNCTION   : DibNumColors(VOID FAR * pv)                    *
  461.  *                                        *
  462.  *  PURPOSE    : Determines the number of colors in the DIB by looking at   *
  463.  *         the BitCount filed in the info block.                *
  464.  *                                        *
  465.  *  RETURNS    : The number of colors in the DIB.                *
  466.  *                                        *
  467.  ****************************************************************************/
  468. WORD DibNumColors (pv)
  469. VOID FAR * pv;
  470. {
  471.     int         bits;
  472.     LPBITMAPINFOHEADER    lpbi;
  473.     LPBITMAPCOREHEADER    lpbc;
  474.  
  475.     lpbi = ((LPBITMAPINFOHEADER)pv);
  476.     lpbc = ((LPBITMAPCOREHEADER)pv);
  477.  
  478.     /*    With the BITMAPINFO format headers, the size of the palette
  479.      *    is in biClrUsed, whereas in the BITMAPCORE - style headers, it
  480.      *    is dependent on the bits per pixel ( = 2 raised to the power of
  481.      *    bits/pixel).
  482.      */
  483.     if (lpbi->biSize != sizeof(BITMAPCOREHEADER)){
  484.         if (lpbi->biClrUsed != 0)
  485.             return (WORD)lpbi->biClrUsed;
  486.         bits = lpbi->biBitCount;
  487.     }
  488.     else
  489.         bits = lpbc->bcBitCount;
  490.  
  491.     switch (bits){
  492.     case 1:
  493.         return 2;
  494.     case 4:
  495.         return 16;
  496.     case 8:
  497.         return 256;
  498.     default:
  499.         /* A 24 bitcount DIB has no color table */
  500.         return 0;
  501.     }
  502. }
  503. /****************************************************************************
  504.  *                                        *
  505.  *  FUNCTION   : DibFromBitmap()                        *
  506.  *                                        *
  507.  *  PURPOSE    : Will create a global memory block in DIB format that        *
  508.  *         represents the Device-dependent bitmap (DDB) passed in.    *
  509.  *                                        *
  510.  *  RETURNS    : A handle to the DIB                        *
  511.  *                                        *
  512.  ****************************************************************************/
  513. HANDLE DibFromBitmap (hbm, biStyle, biBits, hpal)
  514. HBITMAP      hbm;
  515. DWORD         biStyle;
  516. WORD         biBits;
  517. HPALETTE     hpal;
  518. {
  519.     BITMAP               bm;
  520.     BITMAPINFOHEADER     bi;
  521.     BITMAPINFOHEADER FAR *lpbi;
  522.     DWORD                dwLen;
  523.     HANDLE               hdib;
  524.     HANDLE               h;
  525.     HDC                  hdc;
  526.  
  527.     if (!hbm)
  528.     return NULL;
  529.  
  530.     if (hpal == NULL)
  531.         hpal = GetStockObject(DEFAULT_PALETTE);
  532.  
  533.     GetObject(hbm,sizeof(bm),(LPSTR)&bm);
  534.  
  535.     if (biBits == 0)
  536.     biBits =  bm.bmPlanes * bm.bmBitsPixel;
  537.  
  538.     bi.biSize               = sizeof(BITMAPINFOHEADER);
  539.     bi.biWidth              = bm.bmWidth;
  540.     bi.biHeight             = bm.bmHeight;
  541.     bi.biPlanes             = 1;
  542.     bi.biBitCount           = biBits;
  543.     bi.biCompression        = biStyle;
  544.     bi.biSizeImage          = 0;
  545.     bi.biXPelsPerMeter      = 0;
  546.     bi.biYPelsPerMeter      = 0;
  547.     bi.biClrUsed            = 0;
  548.     bi.biClrImportant       = 0;
  549.  
  550.     dwLen  = bi.biSize + PaletteSize(&bi);
  551.  
  552.     hdc = GetDC(NULL);
  553.     hpal = SelectPalette(hdc,hpal,FALSE);
  554.      RealizePalette(hdc);
  555.  
  556.     hdib = GlobalAlloc(GHND,dwLen);
  557.  
  558.     if (!hdib){
  559.     SelectPalette(hdc,hpal,FALSE);
  560.     ReleaseDC(NULL,hdc);
  561.     return NULL;
  562.     }
  563.  
  564.     lpbi = (VOID FAR *)GlobalLock(hdib);
  565.  
  566.     *lpbi = bi;
  567.  
  568.     /*    call GetDIBits with a NULL lpBits param, so it will calculate the
  569.      *  biSizeImage field for us
  570.      */
  571.     GetDIBits(hdc, hbm, 0, (WORD)bi.biHeight,
  572.         NULL, (LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
  573.  
  574.     bi = *lpbi;
  575.     GlobalUnlock(hdib);
  576.  
  577.     /* If the driver did not fill in the biSizeImage field, make one up */
  578.     if (bi.biSizeImage == 0){
  579.         bi.biSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * biBits) * bm.bmHeight;
  580.  
  581.         if (biStyle != BI_RGB)
  582.             bi.biSizeImage = (bi.biSizeImage * 3) / 2;
  583.     }
  584.  
  585.     /*    realloc the buffer big enough to hold all the bits */
  586.     dwLen = bi.biSize + PaletteSize(&bi) + bi.biSizeImage;
  587.     if (h = GlobalReAlloc(hdib,dwLen,0))
  588.         hdib = h;
  589.     else{
  590.         GlobalFree(hdib);
  591.     hdib = NULL;
  592.  
  593.     SelectPalette(hdc,hpal,FALSE);
  594.     ReleaseDC(NULL,hdc);
  595.     return hdib;
  596.     }
  597.  
  598.     /*    call GetDIBits with a NON-NULL lpBits param, and actualy get the
  599.      *  bits this time
  600.      */
  601.     lpbi = (VOID FAR *)GlobalLock(hdib);
  602.  
  603.     if (GetDIBits( hdc,
  604.            hbm,
  605.            0,
  606.            (WORD)bi.biHeight,
  607.            (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi),
  608.            (LPBITMAPINFO)lpbi, DIB_RGB_COLORS) == 0){
  609.      GlobalUnlock(hdib);
  610.      hdib = NULL;
  611.      SelectPalette(hdc,hpal,FALSE);
  612.      ReleaseDC(NULL,hdc);
  613.      return NULL;
  614.     }
  615.  
  616.     bi = *lpbi;
  617.     GlobalUnlock(hdib);
  618.  
  619.     SelectPalette(hdc,hpal,FALSE);
  620.     ReleaseDC(NULL,hdc);
  621.     return hdib;
  622. }
  623.  
  624. /****************************************************************************
  625.  *                                        *
  626.  *  FUNCTION   : BitmapFromDib(HANDLE hdib, HPALETTE hpal)            *
  627.  *                                        *
  628.  *  PURPOSE    : Will create a DDB (Device Dependent Bitmap) given a global *
  629.  *         handle to a memory block in CF_DIB format            *
  630.  *                                        *
  631.  *  RETURNS    : A handle to the DDB.                        *
  632.  *                                        *
  633.  ****************************************************************************/
  634. HBITMAP BitmapFromDib (hdib, hpal)
  635. HANDLE       hdib;
  636. HPALETTE   hpal;
  637. {
  638.     LPBITMAPINFOHEADER    lpbi;
  639.     HPALETTE        hpalT;
  640.     HDC         hdc;
  641.     HBITMAP        hbm;
  642.  
  643.     StartWait();
  644.  
  645.     if (!hdib)
  646.     return NULL;
  647.  
  648.     lpbi = (VOID FAR *)GlobalLock(hdib);
  649.  
  650.     if (!lpbi)
  651.     return NULL;
  652.  
  653.     hdc = GetDC(NULL);
  654.  
  655.     if (hpal){
  656.         hpalT = SelectPalette(hdc,hpal,FALSE);
  657.         RealizePalette(hdc);     // GDI Bug...????
  658.     }
  659.  
  660.     hbm = CreateDIBitmap(hdc,
  661.                 (LPBITMAPINFOHEADER)lpbi,
  662.                 (LONG)CBM_INIT,
  663.                 (LPSTR)lpbi + lpbi->biSize + PaletteSize(lpbi),
  664.                 (LPBITMAPINFO)lpbi,
  665.                 DIB_RGB_COLORS );
  666.  
  667.     if (hpal)
  668.         SelectPalette(hdc,hpalT,FALSE);
  669.  
  670.     ReleaseDC(NULL,hdc);
  671.     GlobalUnlock(hdib);
  672.  
  673.     EndWait();
  674.  
  675.     return hbm;
  676. }
  677. /****************************************************************************
  678.  *                                        *
  679.  *  FUNCTION   : DrawBitmap(HDC hdc, int x, int y, HBITMAP hbm, DWORD rop)  *
  680.  *                                        *
  681.  *  PURPOSE    : Draws bitmap <hbm> at the specifed position in DC <hdc>    *
  682.  *                                        *
  683.  *  RETURNS    : Return value of BitBlt()                    *
  684.  *                                        *
  685.  ****************************************************************************/
  686. BOOL DrawBitmap (hdc, x, y, hbm, rop)
  687. HDC       hdc;
  688. int       x, y;
  689. HBITMAP    hbm;
  690. DWORD       rop;
  691. {
  692.     HDC       hdcBits;
  693.     BITMAP    bm;
  694.     HPALETTE  hpalT;
  695.     BOOL      f;
  696.  
  697.     if (!hdc || !hbm)
  698.         return FALSE;
  699.  
  700.     hdcBits = CreateCompatibleDC(hdc);
  701.     GetObject(hbm,sizeof(BITMAP),(LPSTR)&bm);
  702.     SelectObject(hdcBits,hbm);
  703.     f = BitBlt(hdc,0,0,bm.bmWidth,bm.bmHeight,hdcBits,0,0,rop);
  704.     DeleteDC(hdcBits);
  705.  
  706.     return f;
  707. }
  708. /****************************************************************************
  709.  *                                        *
  710.  *  FUNCTION   : DibBlt( HDC hdc,                        *
  711.  *             int x0, int y0,                    *
  712.  *             int dx, int dy,                    *
  713.  *             HANDLE hdib,                        *
  714.  *             int x1, int y1,                    *
  715.  *             LONG rop)                        *
  716.  *                                        *
  717.  *  PURPOSE    : Draws a bitmap in CF_DIB format, using SetDIBits to device.*
  718.  *         taking the same parameters as BitBlt().            *
  719.  *                                        *
  720.  *  RETURNS    : TRUE  - if function succeeds.                    *
  721.  *         FALSE - otherwise.                        *
  722.  *                                        *
  723.  ****************************************************************************/
  724. BOOL DibBlt (hdc, x0, y0, dx, dy, hdib, x1, y1, rop)
  725. HDC       hdc;
  726. int       x0, y0, dx, dy;
  727. HANDLE       hdib;
  728. int       x1, y1;
  729. LONG       rop;
  730. {
  731.     LPBITMAPINFOHEADER     lpbi;
  732.     HPALETTE         hpal,hpalT;
  733.     LPSTR         pBuf;
  734.     HDC          hdcMem;
  735.     HBITMAP         hbm,hbmT;
  736.  
  737.     if (!hdib)
  738.     return PatBlt(hdc,x0,y0,dx,dy,rop);
  739.  
  740.     lpbi = (VOID FAR *)GlobalLock(hdib);
  741.  
  742.     if (!lpbi)
  743.     return FALSE;
  744.  
  745.     pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
  746.     SetDIBitsToDevice (hdc, x0, y0, dx, dy,
  747.                x1,y1,
  748.                x1,
  749.                dy,
  750.                pBuf, (LPBITMAPINFO)lpbi,
  751.                DIB_RGB_COLORS );
  752.  
  753.     GlobalUnlock(hdib);
  754.     return TRUE;
  755. }
  756. /****************************************************************************
  757.  *                                        *
  758.  *  FUNCTION   : StretchDibBlt( HDC hdc,                    *
  759.  *                int x, int y,                    *
  760.  *                int dx, int dy,                 *
  761.  *                HANDLE hdib,                    *
  762.  *                int x0, int y0,                 *
  763.  *                int dx0, int dy0,                *
  764.  *                LONG rop)                    *
  765.  *                                        *
  766.  *  PURPOSE    : Draws a bitmap in CF_DIB format, using StretchDIBits()     *
  767.  *         taking the same parameters as StretchBlt().            *
  768.  *                                        *
  769.  *  RETURNS    : TRUE  - if function succeeds.                    *
  770.  *         FALSE - otherwise.                        *
  771.  *                                        *
  772.  ****************************************************************************/
  773. BOOL StretchDibBlt (hdc, x, y, dx, dy, hdib, x0, y0, dx0, dy0, rop)
  774. HDC hdc;
  775. int x, y;
  776. int dx, dy;
  777. HANDLE hdib;
  778. int x0, y0;
  779. int dx0, dy0;
  780. LONG rop;
  781.  
  782. {
  783.     LPBITMAPINFOHEADER lpbi;
  784.     LPSTR        pBuf;
  785.     BOOL         f;
  786.  
  787.     if (!hdib)
  788.         return PatBlt(hdc,x,y,dx,dy,rop);
  789.  
  790.     lpbi = (VOID FAR *)GlobalLock(hdib);
  791.  
  792.     if (!lpbi)
  793.         return FALSE;
  794.  
  795.     pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
  796.  
  797.     f = StretchDIBits ( hdc,
  798.             x, y,
  799.             dx, dy,
  800.             x0, y0,
  801.             dx0, dy0,
  802.             pBuf, (LPBITMAPINFO)lpbi,
  803.             DIB_RGB_COLORS,
  804.             rop);
  805.  
  806.     GlobalUnlock(hdib);
  807.     return f;
  808. }
  809.  
  810.  /************* PRIVATE ROUTINES TO READ/WRITE MORE THAN 64K ***************/
  811. /****************************************************************************
  812.  *                                        *
  813.  *  FUNCTION   : lread(int fh, VOID FAR *pv, DWORD ul)                *
  814.  *                                        *
  815.  *  PURPOSE    : Reads data in steps of 32k till all the data has been read.*
  816.  *                                        *
  817.  *  RETURNS    : 0 - If read did not proceed correctly.             *
  818.  *         number of bytes read otherwise.                *
  819.  *                                        *
  820.  ****************************************************************************/
  821. DWORD PASCAL lread (fh, pv, ul)
  822. int          fh;
  823. VOID far      *pv;
  824. DWORD          ul;
  825. {
  826.     DWORD     ulT = ul;
  827.     BYTE huge *hp = pv;
  828.  
  829.     while (ul > (DWORD)MAXREAD) {
  830.     if (_lread(fh, (LPSTR)hp, (WORD)MAXREAD) != MAXREAD)
  831.         return 0;
  832.     ul -= MAXREAD;
  833.     hp += MAXREAD;
  834.     }
  835.     if (_lread(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
  836.     return 0;
  837.     return ulT;
  838. }
  839.  
  840. /****************************************************************************
  841.  *                                        *
  842.  *  FUNCTION   : lwrite(int fh, VOID FAR *pv, DWORD ul)             *
  843.  *                                        *
  844.  *  PURPOSE    : Writes data in steps of 32k till all the data is written.  *
  845.  *                                        *
  846.  *  RETURNS    : 0 - If write did not proceed correctly.            *
  847.  *         number of bytes written otherwise.                *
  848.  *                                        *
  849.  ****************************************************************************/
  850. DWORD PASCAL lwrite (fh, pv, ul)
  851. int         fh;
  852. VOID FAR     *pv;
  853. DWORD         ul;
  854. {
  855.     DWORD     ulT = ul;
  856.     BYTE huge *hp = pv;
  857.  
  858.     while (ul > MAXREAD) {
  859.     if (_lwrite(fh, (LPSTR)hp, (WORD)MAXREAD) != MAXREAD)
  860.         return 0;
  861.     ul -= MAXREAD;
  862.     hp += MAXREAD;
  863.     }
  864.     if (_lwrite(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
  865.     return 0;
  866.     return ulT;
  867. }
  868.