home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c480 / 18.ddi / SAMPLES / SHOWGDI / DIB.C_ / DIB.C
Encoding:
C/C++ Source or Header  |  1993-02-08  |  35.7 KB  |  961 lines

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