Dib.cpp
上传用户:royluo
上传日期:2007-01-05
资源大小:1584k
文件大小:26k
源码类别:

游戏

开发平台:

Visual C++

  1. /*****************************************************************************
  2. *                                                                             
  3. *   Dib.cpp                                                            
  4. *                                                                             
  5. *   Electrical Engineering Faculty - Software Lab                             
  6. *   Spring semester 1998                                                      
  7. *                                                                             
  8. *   Tanks game                                                                
  9. *                                                                             
  10. *   Module description: Implements a DIB object.
  11. *                       
  12. *                                                                             
  13. *   Authors: Eran Yariv - 28484475                                           
  14. *            Moshe Zur  - 24070856                                           
  15. *                                                                            
  16. *                                                                            
  17. *   Date: 23/09/98                                                           
  18. *                                                                            
  19. ******************************************************************************/
  20. /////////////////////////////////////////////////////////////////////////////
  21. // Copyright (C) 1998 by Jorge Lodos
  22. // All rights reserved
  23. //
  24. // Distribute and use freely, except:
  25. // 1. Don't alter or remove this notice.
  26. // 2. Mark the changes you made
  27. //
  28. // Send bug reports, bug fixes, enhancements, requests, etc. to:
  29. //    lodos@cigb.edu.cu
  30. /////////////////////////////////////////////////////////////////////////////
  31. //  dib.cpp
  32. //
  33. #include "stdafx.h"
  34. #include "dib.h"
  35. #include <windowsx.h>
  36. #include <afxadv.h>
  37. /////////////////////////////////////////////////////////////////////////////
  38. // CDIB
  39. IMPLEMENT_DYNAMIC(CDIB, CObject)
  40. void CDIB::Free()
  41. {
  42.     // Make sure all member data that might have been allocated is freed.
  43.     if (m_pBits)
  44.     {
  45.         GlobalFreePtr(m_pBits);
  46.         m_pBits = NULL;
  47.     }
  48.     if (m_pBMI)
  49.     {
  50.         GlobalFreePtr(m_pBMI);
  51.         m_pBMI = NULL;
  52.     }
  53.     if (m_pPalette)
  54.     {
  55.         m_pPalette->DeleteObject();
  56.         delete m_pPalette;
  57.         m_pPalette = NULL;
  58.     }
  59. }
  60. /*************************************************************************
  61.  *
  62.  * Paint()
  63.  *
  64.  * Parameters:
  65.  *
  66.  * HDC hDC          - DC to do output to
  67.  *
  68.  * LPRECT lpDCRect  - rectangle on DC to do output to
  69.  *
  70.  * LPRECT lpDIBRect - rectangle of DIB to output into lpDCRect
  71.  *
  72.  * CPalette* pPal   - pointer to CPalette containing DIB's palette
  73.  *
  74.  * Return Value:
  75.  *
  76.  * BOOL             - TRUE if DIB was drawn, FALSE otherwise
  77.  *
  78.  * Description:
  79.  *   Painting routine for a DIB.  Calls StretchDIBits() or
  80.  *   SetDIBitsToDevice() to paint the DIB.  The DIB is
  81.  *   output to the specified DC, at the coordinates given
  82.  *   in lpDCRect.  The area of the DIB to be output is
  83.  *   given by lpDIBRect.
  84.  *
  85.  ************************************************************************/
  86. BOOL CDIB::Paint(CDC *pDC, LPRECT lpDCRect, LPRECT lpDIBRect) const
  87. {
  88.     if (!m_pBMI)
  89.         return FALSE;
  90.     CPalette *pOldPal = NULL;        // Previous palette
  91.     // Get the DIB's palette, then select it into DC
  92.     if (m_pPalette != NULL)
  93.     {
  94.         // Select as background since we have
  95.         // already realized in forground if needed
  96.         pOldPal = pDC->SelectPalette(m_pPalette, FALSE);
  97.         pDC->RealizePalette();
  98.     }
  99.     /* Make sure to use the stretching mode best for color pictures */
  100.     pDC->SetStretchBltMode(COLORONCOLOR);
  101.     /* Determine whether to call StretchDIBits() or SetDIBitsToDevice() */
  102.     CRect rFullDC;
  103.     if (NULL == lpDCRect)
  104.     {
  105.         rFullDC.SetRect (0,0, Width() - 1, Height() - 1);
  106.         lpDCRect = &rFullDC;
  107.     }
  108.     if (NULL == lpDIBRect)
  109.     {
  110.         rFullDC.SetRect (0,0, Width() - 1, Height() - 1);
  111.         lpDIBRect = &rFullDC;
  112.     }
  113.     BOOL bSuccess;
  114.     if ((RECTWIDTH(lpDCRect)  == RECTWIDTH(lpDIBRect)) &&
  115.         (RECTHEIGHT(lpDCRect) == RECTHEIGHT(lpDIBRect)))
  116.         bSuccess = ::SetDIBitsToDevice(
  117.            pDC->m_hDC,                 // hDC
  118.            lpDCRect->left,             // DestX
  119.            lpDCRect->top,              // DestY
  120.            RECTWIDTH(lpDCRect),        // nDestWidth
  121.            RECTHEIGHT(lpDCRect),       // nDestHeight
  122.            lpDIBRect->left,            // SrcX
  123.            (int)Height() -
  124.               lpDIBRect->top -
  125.               RECTHEIGHT(lpDIBRect),   // SrcY
  126.            0,                          // nStartScan
  127.            (WORD)Height(),             // nNumScans
  128.            m_pBits,                    // lpBits
  129.            m_pBMI,                     // lpBitsInfo
  130.            DIB_RGB_COLORS);            // wUsage
  131.    else
  132.       bSuccess = ::StretchDIBits(
  133.         pDC->m_hDC,                   // hDC
  134.         lpDCRect->left,               // DestX
  135.         lpDCRect->top,                // DestY
  136.         RECTWIDTH(lpDCRect),          // nDestWidth
  137.         RECTHEIGHT(lpDCRect),         // nDestHeight
  138.         lpDIBRect->left,              // SrcX
  139.         lpDIBRect->top,               // SrcY
  140.         RECTWIDTH(lpDIBRect),         // wSrcWidth
  141.         RECTHEIGHT(lpDIBRect),        // wSrcHeight
  142.         m_pBits,                      // lpBits
  143.         m_pBMI,                       // lpBitsInfo
  144.         DIB_RGB_COLORS,               // wUsage
  145.         SRCCOPY);                     // dwROP
  146.     /* Reselect old palette */
  147.     if (pOldPal != NULL)
  148.     {
  149.         pDC->SelectPalette(pOldPal, TRUE);
  150.     }
  151.     return bSuccess;
  152. }
  153. /*************************************************************************
  154.  *
  155.  * CreatePalette()
  156.  *
  157.  * Return Value:
  158.  *
  159.  * TRUE if succesfull, FALSE otherwise
  160.  *
  161.  * Description:
  162.  *
  163.  * This function creates a palette from a DIB by allocating memory for the
  164.  * logical palette, reading and storing the colors from the DIB's color table
  165.  * into the logical palette, creating a palette from this logical palette,
  166.  * and then returning the palette's handle. This allows the DIB to be
  167.  * displayed using the best possible colors (important for DIBs with 256 or
  168.  * more colors).
  169.  *
  170.  ************************************************************************/
  171. BOOL CDIB::CreatePalette()
  172. {
  173.     if (!m_pBMI)
  174.         return FALSE;
  175.    //get the number of colors in the DIB
  176.    WORD wNumColors = NumColors();
  177.    if (wNumColors != 0)
  178.    {
  179.         // allocate memory block for logical palette
  180.         HANDLE hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*wNumColors);
  181.         // if not enough memory, clean up and return NULL
  182.         if (hLogPal == 0)
  183.             return FALSE;
  184.         LPLOGPALETTE lpPal = (LPLOGPALETTE)::GlobalLock((HGLOBAL)hLogPal);
  185.         // set version and number of palette entries
  186.         lpPal->palVersion = PALVERSION;
  187.         lpPal->palNumEntries = (WORD)wNumColors;
  188.         for (int i = 0; i < (int)wNumColors; i++)
  189.         {
  190.             lpPal->palPalEntry[i].peRed = m_pBMI->bmiColors[i].rgbRed;
  191.             lpPal->palPalEntry[i].peGreen = m_pBMI->bmiColors[i].rgbGreen;
  192.             lpPal->palPalEntry[i].peBlue = m_pBMI->bmiColors[i].rgbBlue;
  193.             lpPal->palPalEntry[i].peFlags = 0;
  194.         }
  195.         /* create the palette and get handle to it */
  196.         if (m_pPalette)
  197.         {
  198.             m_pPalette->DeleteObject();
  199.             delete m_pPalette;
  200.         }
  201.         m_pPalette = new CPalette;
  202.         BOOL bResult = m_pPalette->CreatePalette(lpPal);
  203.         ::GlobalUnlock((HGLOBAL) hLogPal);
  204.         ::GlobalFree((HGLOBAL) hLogPal);
  205.         return bResult;
  206.     }
  207.     return TRUE;
  208. }
  209. /*************************************************************************
  210.  *
  211.  * NumColors()
  212.  *
  213.  * Return Value:
  214.  *
  215.  * WORD             - number of colors in the color table
  216.  *
  217.  * Description:
  218.  *
  219.  * This function calculates the number of colors in the DIB's color table
  220.  * by finding the bits per pixel for the DIB (whether Win3.0 or other-style
  221.  * DIB). If bits per pixel is 1: colors=2, if 4: colors=16, if 8: colors=256,
  222.  * if 24, no colors in color table.
  223.  *
  224.  ************************************************************************/
  225. WORD CDIB::NumColors() const
  226. {
  227.     if (!m_pBMI)
  228.         return 0;
  229.     WORD wBitCount;  // DIB bit count
  230.     /*  The number of colors in the color table can be less than 
  231.      *  the number of bits per pixel allows for (i.e. lpbi->biClrUsed
  232.      *  can be set to some value).
  233.      *  If this is the case, return the appropriate value.
  234.      */
  235.     DWORD dwClrUsed;
  236.     dwClrUsed = m_pBMI->bmiHeader.biClrUsed;
  237.     if (dwClrUsed != 0)
  238.         return (WORD)dwClrUsed;
  239.     /*  Calculate the number of colors in the color table based on
  240.      *  the number of bits per pixel for the DIB.
  241.      */
  242.     wBitCount = m_pBMI->bmiHeader.biBitCount;
  243.     /* return number of colors based on bits per pixel */
  244.     switch (wBitCount)
  245.     {
  246.         case 1:
  247.             return 2;
  248.         case 4:
  249.             return 16;
  250.         case 8:
  251.             return 256;
  252.         default:
  253.             return 0;
  254.     }
  255. }
  256. /*************************************************************************
  257.  *
  258.  * Save()
  259.  *
  260.  * Saves the specified DIB into the specified CFile.  The CFile
  261.  * is opened and closed by the caller.
  262.  *
  263.  * Parameters:
  264.  *
  265.  * CFile& file - open CFile used to save DIB
  266.  *
  267.  * Return value: Number of saved bytes or CFileException
  268.  *
  269.  *************************************************************************/
  270. DWORD CDIB::Save(CFile& file)
  271. {
  272.     BITMAPFILEHEADER bmfHdr; // Header for Bitmap file
  273.     DWORD dwDIBSize;
  274.     if (m_pBMI == NULL)
  275.         return 0;
  276.     // Fill in the fields of the file header
  277.     // Fill in file type (first 2 bytes must be "BM" for a bitmap)
  278.     bmfHdr.bfType = DIB_HEADER_MARKER;  // "BM"
  279.     // Calculating the size of the DIB is a bit tricky (if we want to
  280.     // do it right).  The easiest way to do this is to call GlobalSize()
  281.     // on our global handle, but since the size of our global memory may have
  282.     // been padded a few bytes, we may end up writing out a few too
  283.     // many bytes to the file (which may cause problems with some apps).
  284.     //
  285.     // So, instead let's calculate the size manually (if we can)
  286.     //
  287.     // First, find size of header plus size of color table.  Since the
  288.     // first DWORD in both BITMAPINFOHEADER and BITMAPCOREHEADER conains
  289.     // the size of the structure, let's use this.
  290.     dwDIBSize = *(LPDWORD)&m_pBMI->bmiHeader + PaletteSize();  // Partial Calculation
  291.     // Now calculate the size of the image
  292.     dwDIBSize += CalcImageSize ();
  293.     // Calculate the file size by adding the DIB size to sizeof(BITMAPFILEHEADER)
  294.     bmfHdr.bfSize = dwDIBSize + sizeof(BITMAPFILEHEADER);
  295.     bmfHdr.bfReserved1 = 0;
  296.     bmfHdr.bfReserved2 = 0;
  297.     /*
  298.      * Now, calculate the offset the actual bitmap bits will be in
  299.      * the file -- It's the Bitmap file header plus the DIB header,
  300.      * plus the size of the color table.
  301.      */
  302.     bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) + m_pBMI->bmiHeader.biSize + PaletteSize();
  303.     // Write the file header
  304.     file.Write((LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER));
  305.     DWORD dwBytesSaved = sizeof(BITMAPFILEHEADER); 
  306.     // Write the DIB header
  307.     UINT nCount = sizeof(BITMAPINFO) + (NumColors()-1)*sizeof(RGBQUAD);
  308.     dwBytesSaved += nCount; 
  309.     file.Write(m_pBMI, nCount);
  310.     
  311.     // Write the DIB bits
  312.     DWORD dwBytes = m_pBMI->bmiHeader.biBitCount * Width();
  313.   // Calculate the number of bytes per line
  314.     if (dwBytes%32 == 0)
  315.         dwBytes /= 8;
  316.     else
  317.         dwBytes = dwBytes/8 + (32-dwBytes%32)/8 + (((32-dwBytes%32)%8 > 0) ? 1 : 0); 
  318.     nCount = dwBytes * Height();
  319.     dwBytesSaved += nCount; 
  320.     file.WriteHuge(m_pBits, nCount);
  321.     return dwBytesSaved;
  322. }
  323. /*************************************************************************
  324.   Function:  Read (CFile&)
  325.    Purpose:  Reads in the specified DIB file into a global chunk of
  326.              memory.
  327.    Returns:  Number of read bytes.
  328. *************************************************************************/
  329. DWORD CDIB::Read(CFile& file)
  330. {
  331.     // Ensures no memory leaks will occur
  332.     Free();
  333.     
  334.     BITMAPFILEHEADER bmfHeader;
  335.     // Go read the DIB file header and check if it's valid.
  336.     if (file.Read((LPSTR)&bmfHeader, sizeof(bmfHeader)) != sizeof(bmfHeader))
  337.         return 0;
  338.     if (bmfHeader.bfType != DIB_HEADER_MARKER)
  339.         return 0;
  340.     DWORD dwReadBytes = sizeof(bmfHeader);
  341.     // Allocate memory for DIB
  342.     m_pBMI = (LPBITMAPINFO)GlobalAllocPtr(GHND, bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER) + 256*sizeof(RGBQUAD));
  343.     if (m_pBMI == 0)
  344.         return 0;
  345.     // Read header.
  346.     if (file.Read(m_pBMI, bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER)) != (UINT)(bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER)))
  347.     {
  348.         GlobalFreePtr(m_pBMI);
  349.         m_pBMI = NULL;
  350.         return 0;
  351.     }
  352.     dwReadBytes += bmfHeader.bfOffBits-sizeof(BITMAPFILEHEADER);
  353.     DWORD dwLength = file.GetLength();
  354.     // Go read the bits.
  355.     m_pBits = (LPBYTE)GlobalAllocPtr(GHND, dwLength - bmfHeader.bfOffBits);
  356.     if (m_pBits == 0)
  357.     {
  358.         GlobalFreePtr(m_pBMI);
  359.         m_pBMI = NULL;
  360.         return 0;
  361.     }
  362.     
  363.     if (file.ReadHuge(m_pBits, dwLength-bmfHeader.bfOffBits) != (dwLength - bmfHeader.bfOffBits))
  364.     {
  365.         GlobalFreePtr(m_pBMI);
  366.         m_pBMI = NULL;
  367.         GlobalFreePtr(m_pBits);
  368.         m_pBits = NULL;
  369.         return 0;
  370.     }
  371.     dwReadBytes += dwLength - bmfHeader.bfOffBits;
  372.     CreatePalette();
  373.     return dwReadBytes;
  374. }
  375. //////////////////////////////////////////////////////////////////////////
  376. //// Clipboard support
  377. //---------------------------------------------------------------------
  378. //
  379. // Function:   CopyToHandle
  380. //
  381. // Purpose:    Makes a copy of the DIB to a global memory block.  Returns
  382. //             a handle to the new memory block (NULL on error).
  383. //
  384. // Returns:    Handle to new global memory block.
  385. //
  386. //---------------------------------------------------------------------
  387. HGLOBAL CDIB::CopyToHandle()
  388. {
  389.     CSharedFile file;
  390.     try
  391.     {
  392.         if (Save(file)==0)
  393.             return 0;
  394.     }
  395.     catch (CFileException* e)
  396.     {
  397.         e->Delete();
  398.         return 0;
  399.     }
  400.         
  401.     return file.Detach();
  402. }
  403. //---------------------------------------------------------------------
  404. //
  405. // Function:   ReadFromHandle
  406. //
  407. // Purpose:    Initializes from the given global memory block.  
  408. //
  409. // Returns:    Number of read bytes.
  410. //
  411. //---------------------------------------------------------------------
  412. DWORD CDIB::ReadFromHandle(HGLOBAL hGlobal)
  413. {
  414.     CSharedFile file;
  415.     file.SetHandle(hGlobal, FALSE);
  416.     DWORD dwResult = Read(file);
  417.     file.Detach();
  418.     return dwResult;
  419. }
  420. //////////////////////////////////////////////////////////////////////////
  421. //// Serialization support
  422. void CDIB::Serialize(CArchive& ar) 
  423. {
  424.     CFile* pFile = ar.GetFile();
  425.     ASSERT(pFile != NULL);
  426.     if (ar.IsStoring())
  427.     {   // storing code
  428.         Save(*pFile);
  429.     }
  430.     else
  431.     {   // loading code
  432.         Read(*pFile);
  433.     }
  434. }
  435. //////////////////////////////////////////////////////////////////////////
  436. //// Resource support
  437. BOOL CDIB::ReadFromResource (UINT uResID)
  438. {
  439.     HINSTANCE   hInst   = AfxGetInstanceHandle();
  440.     CString     cstrResName;
  441.     //
  442.     // Find the bitmap resource
  443.     //
  444.     cstrResName.Format ("#%d",uResID);
  445.     HRSRC hResInfo = FindResource(hInst, cstrResName, "MY_BITMAP");
  446.     if (!hResInfo)
  447.     {
  448.         TRACE("CDIB: Failed to find resource %d.n", uResID);
  449.         return FALSE;
  450.     }
  451.     //
  452.     // Load the bitmap resource
  453.     //
  454.     HANDLE hRes = LoadResource(hInst, hResInfo);
  455.     if (!hRes)
  456.     {
  457.         TRACE("CDIB: Failed to load resource %d.n", uResID);
  458.         return FALSE;
  459.     }
  460.     //
  461.     // Lock the bitmap resource
  462.     //
  463.     PBYTE lpRes = (PBYTE)LockResource(hRes);
  464.     if (!lpRes)
  465.     {
  466.         TRACE("CDIB: Failed to lock resource.n");
  467.         FreeResource(hRes);
  468.         return FALSE;
  469.     }
  470.     DWORD dwResSize = SizeofResource (hInst, hResInfo);
  471.     CMemFile memFile (lpRes, dwResSize);
  472.     DWORD dwBytesRead = Read (memFile);
  473.     FreeResource (hRes);
  474.     return (dwResSize == dwBytesRead);
  475. }       
  476. //////////////////////////////////////////////////////////////////////////
  477. //// Misc support
  478. BOOL CDIB::CreateEmpty (UINT uXSize, UINT uYSize)
  479. {
  480.     Free ();
  481.     m_pBMI = (LPBITMAPINFO)GlobalAllocPtr(GHND, sizeof(BITMAPINFOHEADER) + 256*sizeof(RGBQUAD));
  482.     if (NULL == m_pBMI)
  483.         return FALSE;
  484.     // Clear palette to black
  485.     memset (m_pBMI->bmiColors, 120, 256 * sizeof(RGBQUAD));
  486.     DWORD dwBmBitsSize = WIDTHBYTES(uXSize*((DWORD)8)) * uYSize;
  487.     m_pBMI->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
  488.     m_pBMI->bmiHeader.biWidth = uXSize;
  489.     m_pBMI->bmiHeader.biHeight = uYSize;
  490.     m_pBMI->bmiHeader.biPlanes = 1;
  491.     m_pBMI->bmiHeader.biBitCount = 8;
  492.     m_pBMI->bmiHeader.biCompression = BI_RGB;
  493.     m_pBMI->bmiHeader.biSizeImage = dwBmBitsSize;
  494.     m_pBMI->bmiHeader.biXPelsPerMeter = 100;
  495.     m_pBMI->bmiHeader.biYPelsPerMeter = 100;
  496.     m_pBMI->bmiHeader.biClrUsed = 256;
  497.     m_pBMI->bmiHeader.biClrImportant = 256;
  498.     m_pBits = (LPBYTE)GlobalAllocPtr(GHND, dwBmBitsSize);
  499.     if (NULL == m_pBits)
  500.     {
  501.         GlobalFreePtr (m_pBMI);
  502.         return FALSE;
  503.     }
  504.     // Clear image to black
  505.     memset (m_pBits, 0, dwBmBitsSize);
  506.     return TRUE;
  507. }
  508. DWORD CDIB::CalcImageSize()
  509. {
  510.     if ((m_pBMI->bmiHeader.biCompression == BI_RLE8) || (m_pBMI->bmiHeader.biCompression == BI_RLE4))
  511.     {
  512.         // It's an RLE bitmap, we can't calculate size, so trust the
  513.         // biSizeImage field
  514.     }
  515.     else
  516.     {
  517.         DWORD dwBmBitsSize;  // Size of Bitmap Bits only
  518.         // It's not RLE, so size is Width (DWORD aligned) * Height
  519.         dwBmBitsSize = WIDTHBYTES((m_pBMI->bmiHeader.biWidth)*((DWORD)m_pBMI->bmiHeader.biBitCount)) * 
  520.                                    m_pBMI->bmiHeader.biHeight;
  521.         // Now, since we have calculated the correct size, why don't we
  522.         // fill in the biSizeImage field (this will fix any .BMP files which
  523.         // have this field incorrect).
  524.         m_pBMI->bmiHeader.biSizeImage = dwBmBitsSize;
  525.     }
  526.     return m_pBMI->bmiHeader.biSizeImage;
  527. }
  528. void CDIB::FillSolidColor (BYTE R, BYTE G, BYTE B)
  529. {
  530.     DWORD dwImageSize = CalcImageSize();
  531.     if (256<=NumColors())
  532.     {   // Palette based DIB
  533.         PIXEL ColorInd = PIXEL(m_pPalette->GetNearestPaletteIndex(RGB(R, G, B)));
  534.         memset (m_pBits, ColorInd, dwImageSize);
  535.     }
  536.     // We don't support non-palette DIBs for now
  537. }
  538. BOOL CDIB::CopyRectFrom (
  539.     CDIB *pSrcDIB, 
  540.     int SrcX, 
  541.     int SrcY, 
  542.     UINT SrcWidth, 
  543.     UINT SrcHeight,
  544.     int DstX, int DstY
  545. )
  546. {
  547.     if ((DstX >= int(Width())) || (DstY >= int(Height())))
  548.         return FALSE;     // Completely out of region
  549.     if ((DstX + int(SrcWidth) < 0) || (DstY + int(SrcHeight)) < 0)
  550.         return FALSE;     // Completely out of region
  551.     if (NumColors() != pSrcDIB->NumColors())
  552.         return FALSE;     // Must have same color depth
  553.     if (NumColors() > 256)
  554.         return FALSE;     // We currently don't support DIBs without palettes
  555.     if (DstX < 0)
  556.     {
  557.         SrcWidth += DstX;
  558.         SrcX -= DstX;
  559.         DstX = 0;
  560.     }
  561.     if (DstY < 0)
  562.     {
  563.         SrcHeight += DstY;
  564.         SrcY -= DstY;
  565.         DstY = 0;
  566.     }
  567.     DWORD dwSrcDIBWidth = pSrcDIB->Width();
  568.     DWORD dwSrcDIBHeight = pSrcDIB->Height();
  569.     DWORD dwMyWidth = Width();
  570.     ASSERT ((SrcX < int(dwSrcDIBWidth)) &&
  571.             (SrcY < int(dwSrcDIBHeight)));
  572.     ASSERT ((SrcX >= 0) && (SrcY >= 0));
  573.     SrcWidth = min (SrcWidth, UINT(dwMyWidth) - DstX);
  574.     SrcWidth = min (SrcWidth, UINT(dwSrcDIBWidth) - SrcX);
  575.     SrcHeight = min (SrcHeight, UINT(Height()) - DstY);
  576.     SrcHeight = min (SrcHeight, UINT(dwSrcDIBHeight) - SrcY);
  577.     PPIXEL pSrc = pSrcDIB->FindPixel(SrcX, SrcY);
  578.     PPIXEL pDst = FindPixel(DstX, DstY);
  579.     DWORD SrcInc = WIDTHBYTES(dwSrcDIBWidth << 3);
  580.     DWORD DstInc = WIDTHBYTES(dwMyWidth << 3);
  581.     for (UINT uCurHeight = 0; uCurHeight < SrcHeight; uCurHeight++)
  582.     {
  583.         memcpy (pDst, pSrc, SrcWidth);
  584.         pDst+= DstInc;
  585.         pSrc+= SrcInc;
  586.     }
  587.     return TRUE;
  588. }
  589. BOOL CDIB::CopyFrom (CDIB *pSrc)
  590. {
  591.     DWORD dwWidth = Width(),
  592.           dwHeight= Height();
  593.     if (NULL == pSrc)
  594.         return FALSE;   // Bad Src
  595.     if ((dwWidth != pSrc->Width()) ||
  596.         (dwHeight != pSrc->Height()) ||
  597.         (NumColors() != pSrc->NumColors())
  598.        )
  599.         return FALSE;   // Bad size or color depth
  600.     memcpy (m_pBits, pSrc->m_pBits, m_pBMI->bmiHeader.biSizeImage);
  601.     return TRUE;
  602. }
  603. void CDIB::PasteCKRect (CDIB *Dib, int x, int y, PIXEL ColorKey)
  604. {
  605.     // Clip Rect
  606.     int px,py,dx,dy,
  607.         mw = Width(),         // My width
  608.         mh = Height(),        // My height
  609.         ow = Dib->Width(),    // Other's width
  610.         oh = Dib->Height();   // Other's height
  611.     if (x >= 0)
  612.     {
  613.         px = x;
  614.         dx = ((x + ow) < mw) ? ow : mw - x;
  615.     }
  616.     else
  617.     {
  618.         px = 0;
  619.         dx = x + (((x + ow) < mw) ? ow : mw - x);
  620.     }
  621.     if (y >= 0)
  622.     {
  623.         py = y;
  624.         dy = ((y + oh) < mh) ? oh : mh - y;
  625.     }
  626.     else
  627.     {
  628.         py = 0;
  629.         dy = y + (((y + oh) < mh) ? oh : mh - y);
  630.     }    
  631.     // If Nothing to Paste return
  632.     if ( (dx <= 0) || (dy <= 0) )
  633.         return;
  634.     // Prepare Buffer Addresses
  635.     PPIXEL src = Dib->FindPixel (px-x, py-y);
  636.     PPIXEL dst = FindPixel (px, py);
  637.     DWORD SrcInc = WIDTHBYTES(ow << 3);
  638.     DWORD DstInc = WIDTHBYTES(mw << 3);
  639.     // Do Paste
  640.     while ( dy-- )
  641.     {
  642.         for ( int i=0; i<dx; i++ )
  643.             if (src[i] != ColorKey)
  644.                 dst[i]=src[i];
  645.         src+=SrcInc;
  646.         dst+=DstInc;
  647.     }
  648. }
  649. void CDIB::FillRect (int x, int y, int w, int h, int R, int G, int B )
  650. {
  651.     // Clip Rect
  652.     int iWidth = int(Width());
  653.     int iHeight = int(Height());
  654.     int px=(x>=0) ? x : 0;
  655.     int py=(y>=0) ? y : 0;
  656.     int dx=((x+w)<iWidth) ? w : iWidth-x;
  657.     int dy=((y+h)<iHeight) ? h : iHeight-y;
  658.     dx=(x>=0) ? dx : dx + x;
  659.     dy=(y>=0) ? dy : dy + y;
  660.     // If Nothing to Fill return
  661.     if ( (dx<=0) || (dy<=0) )
  662.         return;
  663.     // Prepare Buffer Address
  664.     PPIXEL dst = FindPixel (px, py);
  665.     PIXEL ColorInd = PIXEL(m_pPalette->GetNearestPaletteIndex(RGB(R, G, B)));
  666.     DWORD DstInc = WIDTHBYTES(iWidth << 3);
  667.     // Do Fill
  668.     while ( dy-- )
  669.     {
  670.         memset (dst, ColorInd, dx);
  671.         dst+=DstInc;
  672.     }
  673. }
  674. BOOL CDIB::CreateRotated (CDIB *pSrc, UINT uAngle /* 0, 90, 180 or 270 only */, BOOL bFlipHoriz, BOOL bFlipVert)
  675. {
  676.     ASSERT (uAngle == 0 || uAngle == 90 || uAngle == 180 || uAngle == 270);
  677.     UINT uSrcWidth = pSrc->Width();
  678.     UINT uSrcHeight= pSrc->Height();
  679.     UINT uDstWidth;
  680.     UINT uDstHeight;
  681.     if (uAngle == 180)
  682.         return CreateRotated (pSrc, 0, !bFlipHoriz, !bFlipVert);
  683.     if (uAngle == 270)
  684.         return CreateRotated (pSrc, 90, !bFlipHoriz, !bFlipVert);
  685.     BOOL bSuccess;
  686.     if (uAngle == 0)
  687.     {
  688.         bSuccess = CreateEmpty (uSrcWidth, uSrcHeight);
  689.         uDstWidth = uSrcWidth;
  690.         uDstHeight = uSrcHeight;
  691.     }
  692.     else
  693.     {
  694.         bSuccess = CreateEmpty (uSrcHeight, uSrcWidth);
  695.         uDstWidth = uSrcHeight;
  696.         uDstHeight = uSrcWidth;
  697.     }
  698.     if (!bSuccess)
  699.         return FALSE;   // Can't create
  700.     for (int x = 0; x < int(uDstWidth); x++)
  701.         for (int y = 0; y < int(uDstHeight); y++)
  702.             switch (uAngle)
  703.             {
  704.                 case   0:
  705.                     ColorAt (x, y) = pSrc->ColorAt ((bFlipHoriz ? uDstWidth-1-x : x), (bFlipVert ? uDstHeight-1-y : y));
  706.                     break;
  707.                 case 90:
  708.                     ColorAt (x, y) = 
  709.                         pSrc->ColorAt ((bFlipVert  ? uSrcWidth-1-y : y), (bFlipHoriz ? x : ( uSrcHeight-1-x )));
  710.                     break;
  711.                 default:
  712.                     ASSERT (FALSE);
  713.             }
  714.     return TRUE;
  715. }                        
  716. BOOL CDIB::CopyPalette (CDIB *pSrc)
  717. {
  718.     if ((NULL == pSrc) || (NULL == pSrc->m_pPalette))
  719.         return FALSE;   // Bad source or source has no palette
  720.     BOOL bRes = CopyPalette (pSrc->m_pPalette);
  721.     if (bRes)
  722.     {
  723.         memcpy (m_pBMI->bmiColors, pSrc->m_pBMI->bmiColors, 256 * sizeof (RGBQUAD));
  724.     }
  725.     return bRes;
  726. }
  727. BOOL CDIB::CopyPalette (CPalette *pPal)
  728. {
  729.     if (NULL == pPal)
  730.         return FALSE;
  731.     if (m_pPalette)
  732.     {
  733.         m_pPalette->DeleteObject();
  734.         delete m_pPalette;
  735.         m_pPalette = NULL;
  736.     }
  737.     UINT uNumColors = pPal->GetEntryCount();
  738.     // allocate memory block for logical palette
  739.     HANDLE hLogPal = ::GlobalAlloc(GHND, sizeof(LOGPALETTE) + sizeof(PALETTEENTRY)*uNumColors);
  740.     // if not enough memory, clean up and return NULL
  741.     if (hLogPal == 0)
  742.         return FALSE;
  743.     LPLOGPALETTE lpPal = (LPLOGPALETTE)::GlobalLock((HGLOBAL)hLogPal);
  744.     // set version and number of palette entries
  745.     lpPal->palVersion = PALVERSION;
  746.     lpPal->palNumEntries = (WORD)uNumColors;
  747.     UINT uCount = pPal->GetPaletteEntries(0, uNumColors, lpPal->palPalEntry);
  748.     if (uCount != uNumColors)
  749.     {
  750.         ::GlobalUnlock((HGLOBAL) hLogPal);
  751.         ::GlobalFree((HGLOBAL) hLogPal);
  752.         return FALSE;
  753.     }
  754.     m_pPalette = new CPalette;
  755.     BOOL bResult = m_pPalette->CreatePalette(lpPal);
  756.     ::GlobalUnlock((HGLOBAL) hLogPal);
  757.     ::GlobalFree((HGLOBAL) hLogPal);
  758.     return bResult;
  759. }
  760. BOOL CDIB::GetPaletteFromResourceBitmap (UINT uResID)
  761. {
  762.     CDIB tmpDIB;
  763.     if (!tmpDIB.ReadFromResource(uResID))
  764.         return FALSE;
  765.     return CopyPalette (&tmpDIB);
  766. }