home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 18.ddi / SAMPLES / SHOWDIB / DIB.C_ / DIB.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  33.6 KB  |  864 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.     WORD                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.     BOOL      f;
  695.  
  696.     if (!hdc || !hbm)
  697.         return FALSE;
  698.  
  699.     hdcBits = CreateCompatibleDC(hdc);
  700.     GetObject(hbm,sizeof(BITMAP),(LPSTR)&bm);
  701.     SelectObject(hdcBits,hbm);
  702.     f = BitBlt(hdc,0,0,bm.bmWidth,bm.bmHeight,hdcBits,0,0,rop);
  703.     DeleteDC(hdcBits);
  704.  
  705.     return f;
  706. }
  707. /****************************************************************************
  708.  *                                                                          *
  709.  *  FUNCTION   : DibBlt( HDC hdc,                                           *
  710.  *                       int x0, int y0,                                    *
  711.  *                       int dx, int dy,                                    *
  712.  *                       HANDLE hdib,                                       *
  713.  *                       int x1, int y1,                                    *
  714.  *                       LONG rop)                                          *
  715.  *                                                                          *
  716.  *  PURPOSE    : Draws a bitmap in CF_DIB format, using SetDIBits to device.*
  717.  *               taking the same parameters as BitBlt().                    *
  718.  *                                                                          *
  719.  *  RETURNS    : TRUE  - if function succeeds.                              *
  720.  *               FALSE - otherwise.                                         *
  721.  *                                                                          *
  722.  ****************************************************************************/
  723. BOOL DibBlt (hdc, x0, y0, dx, dy, hdib, x1, y1, rop)
  724. HDC        hdc;
  725. int        x0, y0, dx, dy;
  726. HANDLE     hdib;
  727. int        x1, y1;
  728. LONG       rop;
  729. {
  730.     LPBITMAPINFOHEADER   lpbi;
  731.     LPSTR                pBuf;
  732.  
  733.     if (!hdib)
  734.         return PatBlt(hdc,x0,y0,dx,dy,rop);
  735.  
  736.     lpbi = (VOID FAR *)GlobalLock(hdib);
  737.  
  738.     if (!lpbi)
  739.         return FALSE;
  740.  
  741.     pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
  742.     SetDIBitsToDevice (hdc, x0, y0, dx, dy,
  743.                        x1,y1,
  744.                        x1,
  745.                        dy,
  746.                        pBuf, (LPBITMAPINFO)lpbi,
  747.                        DIB_RGB_COLORS );
  748.  
  749.     GlobalUnlock(hdib);
  750.     return TRUE;
  751. }
  752. /****************************************************************************
  753.  *                                                                          *
  754.  *  FUNCTION   : StretchDibBlt( HDC hdc,                                    *
  755.  *                              int x, int y,                               *
  756.  *                              int dx, int dy,                             *
  757.  *                              HANDLE hdib,                                *
  758.  *                              int x0, int y0,                             *
  759.  *                              int dx0, int dy0,                           *
  760.  *                              LONG rop)                                   *
  761.  *                                                                          *
  762.  *  PURPOSE    : Draws a bitmap in CF_DIB format, using StretchDIBits()     *
  763.  *               taking the same parameters as StretchBlt().                *
  764.  *                                                                          *
  765.  *  RETURNS    : TRUE  - if function succeeds.                              *
  766.  *               FALSE - otherwise.                                         *
  767.  *                                                                          *
  768.  ****************************************************************************/
  769. BOOL StretchDibBlt (hdc, x, y, dx, dy, hdib, x0, y0, dx0, dy0, rop)
  770. HDC hdc;
  771. int x, y;
  772. int dx, dy;
  773. HANDLE hdib;
  774. int x0, y0;
  775. int dx0, dy0;
  776. LONG rop;
  777.  
  778. {
  779.     LPBITMAPINFOHEADER lpbi;
  780.     LPSTR        pBuf;
  781.     BOOL         f;
  782.  
  783.     if (!hdib)
  784.         return PatBlt(hdc,x,y,dx,dy,rop);
  785.  
  786.     lpbi = (VOID FAR *)GlobalLock(hdib);
  787.  
  788.     if (!lpbi)
  789.         return FALSE;
  790.  
  791.     pBuf = (LPSTR)lpbi + (WORD)lpbi->biSize + PaletteSize(lpbi);
  792.  
  793.     f = StretchDIBits ( hdc,
  794.                         x, y,
  795.                         dx, dy,
  796.                         x0, y0,
  797.                         dx0, dy0,
  798.                         pBuf, (LPBITMAPINFO)lpbi,
  799.                         DIB_RGB_COLORS,
  800.                         rop);
  801.  
  802.     GlobalUnlock(hdib);
  803.     return f;
  804. }
  805.  
  806.  /************* PRIVATE ROUTINES TO READ/WRITE MORE THAN 64K ***************/
  807. /****************************************************************************
  808.  *                                                                          *
  809.  *  FUNCTION   : lread(int fh, VOID FAR *pv, DWORD ul)                      *
  810.  *                                                                          *
  811.  *  PURPOSE    : Reads data in steps of 32k till all the data has been read.*
  812.  *                                                                          *
  813.  *  RETURNS    : 0 - If read did not proceed correctly.                     *
  814.  *               number of bytes read otherwise.                            *
  815.  *                                                                          *
  816.  ****************************************************************************/
  817. DWORD PASCAL lread (fh, pv, ul)
  818. int           fh;
  819. VOID far      *pv;
  820. DWORD         ul;
  821. {
  822.     DWORD     ulT = ul;
  823.     BYTE huge *hp = pv;
  824.  
  825.     while (ul > (DWORD)MAXREAD) {
  826.         if (_lread(fh, (LPSTR)hp, (WORD)MAXREAD) != MAXREAD)
  827.                 return 0;
  828.         ul -= MAXREAD;
  829.         hp += MAXREAD;
  830.     }
  831.     if (_lread(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
  832.         return 0;
  833.     return ulT;
  834. }
  835.  
  836. /****************************************************************************
  837.  *                                                                          *
  838.  *  FUNCTION   : lwrite(int fh, VOID FAR *pv, DWORD ul)                     *
  839.  *                                                                          *
  840.  *  PURPOSE    : Writes data in steps of 32k till all the data is written.  *
  841.  *                                                                          *
  842.  *  RETURNS    : 0 - If write did not proceed correctly.                    *
  843.  *               number of bytes written otherwise.                         *
  844.  *                                                                          *
  845.  ****************************************************************************/
  846. DWORD PASCAL lwrite (fh, pv, ul)
  847. int          fh;
  848. VOID FAR     *pv;
  849. DWORD        ul;
  850. {
  851.     DWORD     ulT = ul;
  852.     BYTE huge *hp = pv;
  853.  
  854.     while (ul > MAXREAD) {
  855.         if (_lwrite(fh, (LPSTR)hp, (WORD)MAXREAD) != MAXREAD)
  856.                 return 0;
  857.         ul -= MAXREAD;
  858.         hp += MAXREAD;
  859.     }
  860.     if (_lwrite(fh, (LPSTR)hp, (WORD)ul) != (WORD)ul)
  861.         return 0;
  862.     return ulT;
  863. }
  864.