⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dib.cpp

📁 分布式坦克游戏
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/*****************************************************************************
*                                                                             
*   Dib.cpp                                                            
*                                                                             
*   Electrical Engineering Faculty - Software Lab                             
*   Spring semester 1998                                                      
*                                                                             
*   Tanks game                                                                
*                                                                             
*   Module description: Implements a DIB object.
*                       
*                                                                             
*   Authors: Eran Yariv - 28484475                                           
*            Moshe Zur  - 24070856                                           
*                                                                            
*                                                                            
*   Date: 23/09/98                                                           
*                                                                            
******************************************************************************/

/////////////////////////////////////////////////////////////////////////////
// Copyright (C) 1998 by Jorge Lodos
// All rights reserved
//
// Distribute and use freely, except:
// 1. Don't alter or remove this notice.
// 2. Mark the changes you made
//
// Send bug reports, bug fixes, enhancements, requests, etc. to:
//    lodos@cigb.edu.cu
/////////////////////////////////////////////////////////////////////////////

//  dib.cpp
//

#include "stdafx.h"
#include "dib.h"
#include <windowsx.h>
#include <afxadv.h>

/////////////////////////////////////////////////////////////////////////////
// CDIB

IMPLEMENT_DYNAMIC(CDIB, CObject)


void CDIB::Free()
{
    // Make sure all member data that might have been allocated is freed.
    if (m_pBits)
    {
        GlobalFreePtr(m_pBits);
        m_pBits = NULL;
    }
    if (m_pBMI)
    {
        GlobalFreePtr(m_pBMI);
        m_pBMI = NULL;
    }
    if (m_pPalette)
    {
        m_pPalette->DeleteObject();
        delete m_pPalette;
        m_pPalette = NULL;
    }
}

/*************************************************************************
 *
 * Paint()
 *
 * Parameters:
 *
 * HDC hDC          - DC to do output to
 *
 * LPRECT lpDCRect  - rectangle on DC to do output to
 *
 * LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect
 *
 * CPalette* pPal   - pointer to CPalette containing DIB's palette
 *
 * Return Value:
 *
 * BOOL             - TRUE if DIB was drawn, FALSE otherwise
 *
 * Description:
 *   Painting routine for a DIB.  Calls StretchDIBits() or
 *   SetDIBitsToDevice() to paint the DIB.  The DIB is
 *   output to the specified DC, at the coordinates given
 *   in lpDCRect.  The area of the DIB to be output is
 *   given by lpDIBRect.
 *
 ************************************************************************/
BOOL CDIB::Paint(CDC *pDC, LPRECT lpDCRect, LPRECT lpDIBRect) const
{
    if (!m_pBMI)
        return FALSE;

    CPalette *pOldPal = NULL;        // Previous palette

    // Get the DIB's palette, then select it into DC
    if (m_pPalette != NULL)
    {
        // Select as background since we have
        // already realized in forground if needed
        pOldPal = pDC->SelectPalette(m_pPalette, FALSE);
        pDC->RealizePalette();
    }

    /* Make sure to use the stretching mode best for color pictures */
    pDC->SetStretchBltMode(COLORONCOLOR);

    /* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */
    CRect rFullDC;
    if (NULL == lpDCRect)
    {
        rFullDC.SetRect (0,0, Width() - 1, Height() - 1);
        lpDCRect = &rFullDC;
    }
    if (NULL == lpDIBRect)
    {
        rFullDC.SetRect (0,0, Width() - 1, Height() - 1);
        lpDIBRect = &rFullDC;
    }
    BOOL bSuccess;
    if ((RECTWIDTH(lpDCRect)  == RECTWIDTH(lpDIBRect)) &&
        (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))
        bSuccess = ::SetDIBitsToDevice(
           pDC->m_hDC,                 // hDC
           lpDCRect->left,             // DestX
           lpDCRect->top,              // DestY
           RECTWIDTH(lpDCRect),        // nDestWidth
           RECTHEIGHT(lpDCRect),       // nDestHeight
           lpDIBRect->left,            // SrcX
           (int)Height() -
              lpDIBRect->top -
              RECTHEIGHT(lpDIBRect),   // SrcY
           0,                          // nStartScan
           (WORD)Height(),             // nNumScans
           m_pBits,                    // lpBits
           m_pBMI,                     // lpBitsInfo
           DIB_RGB_COLORS);            // wUsage
   else
      bSuccess = ::StretchDIBits(
        pDC->m_hDC,                   // hDC
        lpDCRect->left,               // DestX
        lpDCRect->top,                // DestY
        RECTWIDTH(lpDCRect),          // nDestWidth
        RECTHEIGHT(lpDCRect),         // nDestHeight
        lpDIBRect->left,              // SrcX
        lpDIBRect->top,               // SrcY
        RECTWIDTH(lpDIBRect),         // wSrcWidth
        RECTHEIGHT(lpDIBRect),        // wSrcHeight
        m_pBits,                      // lpBits
        m_pBMI,                       // lpBitsInfo
        DIB_RGB_COLORS,               // wUsage
        SRCCOPY);                     // dwROP

    /* Reselect old palette */
    if (pOldPal != NULL)
    {
        pDC->SelectPalette(pOldPal, TRUE);
    }
    return bSuccess;
}

/*************************************************************************
 *
 * CreatePalette()
 *
 * Return Value:
 *
 * TRUE if succesfull, FALSE otherwise
 *
 * Description:
 *
 * This function creates a palette from a DIB by allocating memory for the
 * logical palette, reading and storing the colors from the DIB's color table
 * into the logical palette, creating a palette from this logical palette,
 * and then returning the palette's handle. This allows the DIB to be
 * displayed using the best possible colors (important for DIBs with 256 or
 * more colors).
 *
 ************************************************************************/
BOOL CDIB::CreatePalette()
{
    if (!m_pBMI)
        return FALSE;

   //get the number of colors in the DIB
   WORD wNumColors = NumColors();

   if (wNumColors != 0)
   {
        // allocate memory block for logical palette
        HANDLE hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*wNumColors);

        // if not enough memory, clean up and return NULL
        if (hLogPal == 0)
            return FALSE;

        LPLOGPALETTE lpPal = (LPLOGPALETTE)::GlobalLock((HGLOBAL)hLogPal);

        // set version and number of palette entries
        lpPal->palVersion = PALVERSION;
        lpPal->palNumEntries = (WORD)wNumColors;

        for (int i = 0; i < (int)wNumColors; i++)
        {
            lpPal->palPalEntry[i].peRed = m_pBMI->bmiColors[i].rgbRed;
            lpPal->palPalEntry[i].peGreen = m_pBMI->bmiColors[i].rgbGreen;
            lpPal->palPalEntry[i].peBlue = m_pBMI->bmiColors[i].rgbBlue;
            lpPal->palPalEntry[i].peFlags = 0;
        }

        /* create the palette and get handle to it */
        if (m_pPalette)
        {
            m_pPalette->DeleteObject();
            delete m_pPalette;
        }
        m_pPalette = new CPalette;
        BOOL bResult = m_pPalette->CreatePalette(lpPal);
        ::GlobalUnlock((HGLOBAL) hLogPal);
        ::GlobalFree((HGLOBAL) hLogPal);
        return bResult;
    }

    return TRUE;
}


/*************************************************************************
 *
 * NumColors()
 *
 * Return Value:
 *
 * WORD             - number of colors in the color table
 *
 * Description:
 *
 * This function calculates the number of colors in the DIB's color table
 * by finding the bits per pixel for the DIB (whether Win3.0 or other-style
 * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256,
 * if 24, no colors in color table.
 *
 ************************************************************************/
WORD CDIB::NumColors() const
{
    if (!m_pBMI)
        return 0;

    WORD wBitCount;  // DIB bit count

    /*  The number of colors in the color table can be less than 
     *  the number of bits per pixel allows for (i.e. lpbi->biClrUsed
     *  can be set to some value).
     *  If this is the case, return the appropriate value.
     */

    DWORD dwClrUsed;

    dwClrUsed = m_pBMI->bmiHeader.biClrUsed;
    if (dwClrUsed != 0)
        return (WORD)dwClrUsed;

    /*  Calculate the number of colors in the color table based on
     *  the number of bits per pixel for the DIB.
     */
    wBitCount = m_pBMI->bmiHeader.biBitCount;

    /* return number of colors based on bits per pixel */
    switch (wBitCount)
    {
        case 1:
            return 2;

        case 4:
            return 16;

        case 8:
            return 256;

        default:
            return 0;
    }
}

/*************************************************************************
 *
 * Save()
 *
 * Saves the specified DIB into the specified CFile.  The CFile
 * is opened and closed by the caller.
 *
 * Parameters:
 *
 * CFile& file - open CFile used to save DIB
 *
 * Return value: Number of saved bytes or CFileException
 *
 *************************************************************************/
DWORD CDIB::Save(CFile& file)
{
    BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
    DWORD dwDIBSize;

    if (m_pBMI == NULL)
        return 0;

    // Fill in the fields of the file header

    // Fill in file type (first 2 bytes must be "BM" for a bitmap)
    bmfHdr.bfType = DIB_HEADER_MARKER;  // "BM"

    // Calculating the size of the DIB is a bit tricky (if we want to
    // do it right).  The easiest way to do this is to call GlobalSize()
    // on our global handle, but since the size of our global memory may have
    // been padded a few bytes, we may end up writing out a few too
    // many bytes to the file (which may cause problems with some apps).
    //
    // So, instead let's calculate the size manually (if we can)
    //
    // First, find size of header plus size of color table.  Since the
    // first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains
    // the size of the structure, let's use this.
    dwDIBSize = *(LPDWORD)&m_pBMI->bmiHeader + PaletteSize();  // Partial Calculation

    // Now calculate the size of the image
    dwDIBSize += CalcImageSize ();

    // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)
    bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
    bmfHdr.bfReserved1 = 0;
    bmfHdr.bfReserved2 = 0;

    /*
     * Now, calculate the offset the actual bitmap bits will be in
     * the file -- It's the Bitmap file header plus the DIB header,
     * plus the size of the color table.
     */
    bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + m_pBMI->bmiHeader.biSize + PaletteSize();

    // Write the file header
    file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
    DWORD dwBytesSaved = sizeof(BITMAPFILEHEADER); 

    // Write the DIB header
    UINT nCount = sizeof(BITMAPINFO) + (NumColors()-1)*sizeof(RGBQUAD);
    dwBytesSaved += nCount; 
    file.Write(m_pBMI, nCount);
    
    // Write the DIB bits
    DWORD dwBytes = m_pBMI->bmiHeader.biBitCount * Width();
  // Calculate the number of bytes per line
    if (dwBytes%32 == 0)
        dwBytes /= 8;
    else
        dwBytes = dwBytes/8 + (32-dwBytes%32)/8 + (((32-dwBytes%32)%8 > 0) ? 1 : 0); 
    nCount = dwBytes * Height();
    dwBytesSaved += nCount; 
    file.WriteHuge(m_pBits, nCount);

    return dwBytesSaved;
}


/*************************************************************************

  Function:  Read (CFile&)

   Purpose:  Reads in the specified DIB file into a global chunk of
             memory.

   Returns:  Number of read bytes.

*************************************************************************/
DWORD CDIB::Read(CFile& file)
{
    // Ensures no memory leaks will occur
    Free();
    
    BITMAPFILEHEADER bmfHeader;

    // Go read the DIB file header and check if it's valid.
    if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
        return 0;
    if (bmfHeader.bfType != DIB_HEADER_MARKER)
        return 0;
    DWORD dwReadBytes = sizeof(bmfHeader);

    // Allocate memory for DIB
    m_pBMI = (LPBITMAPINFO)GlobalAllocPtr(GHND, bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER) + 256*sizeof(RGBQUAD));
    if (m_pBMI == 0)
        return 0;

    // Read header.
    if (file.Read(m_pBMI, bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER)) != (UINT)(bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER)))
    {
        GlobalFreePtr(m_pBMI);
        m_pBMI = NULL;
        return 0;
    }
    dwReadBytes += bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER);

    DWORD dwLength = file.GetLength();
    // Go read the bits.
    m_pBits = (LPBYTE)GlobalAllocPtr(GHND, dwLength - bmfHeader.bfOffBits);
    if (m_pBits == 0)
    {
        GlobalFreePtr(m_pBMI);
        m_pBMI = NULL;
        return 0;
    }
    
    if (file.ReadHuge(m_pBits, dwLength-bmfHeader.bfOffBits) != (dwLength - bmfHeader.bfOffBits))
    {
        GlobalFreePtr(m_pBMI);
        m_pBMI = NULL;
        GlobalFreePtr(m_pBits);
        m_pBits = NULL;
        return 0;
    }
    dwReadBytes += dwLength - bmfHeader.bfOffBits;
    CreatePalette();
    return dwReadBytes;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -