home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / gdi / showdib / dib.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  38KB  |  949 lines

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