home *** CD-ROM | disk | FTP | other *** search
/ Prima Shareware 3 / DuCom_Prima-Shareware-3_cd1.bin / PROGRAMO / C / MRCE / SOURCE.ZIP / DIB.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1995-09-11  |  17.6 KB  |  565 lines

  1. // MRCEXT: Micro Focus Extension DLL for MFC 2.1+
  2. // Copyright (C)1994-5    Micro Focus Inc, 2465 East Bayshore Rd, Palo Alto, CA 94303.
  3. // 
  4. //  This program is free software; you can redistribute it and/or modify
  5. //  it under the terms of the GNU General Public License as published by
  6. //  the Free Software Foundation. In addition, you may also charge for any
  7. //  application    using MRCEXT, and are under no obligation to supply source
  8. //  code. You must accredit Micro Focus Inc in the "About Box", or banner
  9. //  of your application. 
  10. //
  11. //  This program is distributed in the hope that it will be useful,
  12. //  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. //  GNU General Public License for more details.
  15. //
  16. //  You should also have received a copy of the GNU General Public License with this
  17. //  software, also indicating additional rights you have when using MRCEXT.  
  18. //
  19. //
  20. // dib.cpp : implementation file
  21. // $Revision:   1.8  $
  22. // $Author:   MRC  $
  23. // $Date:   11 Sep 1995 09:48:10  $
  24. // This code implements a CMRCDib and CMRCDibPal class, suitable for loading/drawing
  25. // 256-color bitmaps. Most of the code is borrowed from MSDN9, Win32 Animation 
  26. // examples. It's probably a sledgehammer to crack a nut in terms of getting Sooty
  27. // to have a 256-color bitmap, but there isn't that much code here, and anyway it'll
  28. // probably come in useful elsewhere
  29.  
  30. #include "mrcstafx.h"
  31. #include "mrcext.h"
  32.  
  33. #ifdef _DEBUG
  34. #undef THIS_FILE
  35. static char BASED_CODE THIS_FILE[] = __FILE__;
  36. #endif
  37.  
  38. /////////////////////////////////////////////////////////////////////////////
  39. // CMRCDib
  40.  
  41. IMPLEMENT_DYNAMIC(CMRCDib, CObject)
  42. #ifdef USE_DEBUG_NEW
  43. #define new DEBUG_NEW
  44. #endif
  45.  
  46.  
  47. // Create a small DIB here so m_pBMI and m_pBits are always valid
  48. CMRCDib::CMRCDib()
  49. {
  50.     m_pBMI = NULL;
  51.     m_pBits = NULL;
  52.     m_cLoadedFromResource = 0;
  53.     Create(16, 16);
  54. }
  55.  
  56.  
  57. CMRCDib::~CMRCDib()
  58. {
  59.     // free the memory
  60.     DeleteContents();
  61. }
  62.  
  63. /////////////////////////////////////////////////////////////////////////////
  64. // Private functions
  65. //-------------------------------------------------------------------------
  66. void CMRCDib::DeleteContents()
  67. //-------------------------------------------------------------------------
  68. {
  69. // Separate the deallocation of memory, since resource-loaded Dib's don't need to
  70. // free their memory.
  71.     if (m_cLoadedFromResource == 0)
  72.     {
  73.         delete m_pBMI;
  74.         delete m_pBits;
  75.     }
  76.        m_pBMI = NULL;
  77.     m_pBits = NULL;
  78.     m_cLoadedFromResource = 0;
  79. }
  80.  
  81.  
  82.  
  83. //-------------------------------------------------------------------------
  84. static BOOL IsWinDIB(BITMAPINFOHEADER *pBIH)
  85. //-------------------------------------------------------------------------
  86. {
  87.     ASSERT(pBIH != NULL);
  88.     if (((BITMAPCOREHEADER *)pBIH)->bcSize == sizeof(BITMAPCOREHEADER)) 
  89.         return FALSE;
  90.     return TRUE;
  91. }
  92.  
  93.  
  94. //-------------------------------------------------------------------------
  95. static int NumDIBColorEntries(BITMAPINFO *pBmpInfo) 
  96. //-------------------------------------------------------------------------
  97. {
  98.     BITMAPINFOHEADER *pBIH;
  99.     BITMAPCOREHEADER *pBCH;
  100.     int iColors, iBitCount;
  101.  
  102.     ASSERT(pBmpInfo);
  103.  
  104.     pBIH = &(pBmpInfo->bmiHeader);
  105.     pBCH = (BITMAPCOREHEADER *) pBIH;
  106.  
  107.     // start off by assuming the color table size from
  108.     // the bit per pixel field
  109.     if (IsWinDIB(pBIH))
  110.         iBitCount = pBIH->biBitCount;
  111.     else 
  112.         iBitCount = pBCH->bcBitCount;
  113.  
  114.     switch (iBitCount)
  115.     {
  116.     case 1:
  117.         iColors = 2;
  118.         break;
  119.     case 4:
  120.         iColors = 16;
  121.         break;
  122.     case 8:
  123.         iColors = 256;
  124.         break;
  125.     default:
  126.         iColors = 0;
  127.         break;
  128.     }
  129.  
  130.     // If this is a Windows DIB, then the color table length
  131.     // is determined by the biClrUsed field if it is non-zero
  132.     if (IsWinDIB(pBIH) && (pBIH->biClrUsed != 0)) 
  133.         iColors = pBIH->biClrUsed;
  134.     return iColors;
  135. }
  136.  
  137.  
  138. /////////////////////////////////////////////////////////////////////////////
  139. // CMRCDib commands
  140.  
  141. //-------------------------------------------------------------------------
  142. BOOL CMRCDib::Create(int iWidth, int iHeight)
  143. // creates a simple 256-color bitmap, initialized to all black.
  144. //-------------------------------------------------------------------------
  145. {
  146.     // delete any existing stuff
  147.     DeleteContents();
  148.  
  149.     // allocate memory for the header
  150.     m_pBMI = (BITMAPINFO *) new BYTE[ sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD) ];
  151.     if (!m_pBMI)
  152.     {
  153.         TRACE("CMRCDib:Out of memory for DIB header\n");
  154.         return FALSE;
  155.     }
  156.  
  157.     // allocate memory for the bits (DWORD aligned)
  158.     int iBitsSize = ((iWidth + 3) & ~3) * iHeight;
  159.     m_pBits = new BYTE[iBitsSize];
  160.     if (!m_pBits)
  161.     {
  162.         TRACE("CMRCDib:Out of memory for DIB bits\n");
  163.         delete m_pBMI;
  164.         m_pBMI = NULL;
  165.         return FALSE;
  166.     }
  167.  
  168.     // fill in the header info
  169.     BITMAPINFOHEADER *pBI = (BITMAPINFOHEADER *) m_pBMI;
  170.     pBI->biSize = sizeof(BITMAPINFOHEADER);
  171.     pBI->biWidth = iWidth;
  172.     pBI->biHeight = iHeight;
  173.     pBI->biPlanes = 1;
  174.     pBI->biBitCount = 8;
  175.     pBI->biCompression = BI_RGB;
  176.     pBI->biSizeImage = 0;
  177.     pBI->biXPelsPerMeter = 0;
  178.     pBI->biYPelsPerMeter = 0;
  179.     pBI->biClrUsed = 0;
  180.     pBI->biClrImportant = 0;
  181.  
  182.     // create an arb color table (gray scale)
  183.     RGBQUAD *prgb = GetClrTabAddress();
  184.     for (int i = 0; i < 256; i++)
  185.     {
  186.         prgb->rgbBlue = prgb->rgbGreen = prgb->rgbRed = (BYTE) i;
  187.         prgb->rgbReserved = 0;
  188.         prgb++;
  189.     }
  190.  
  191.     // set all the bits to a known state (black)
  192.     memset(m_pBits, 0, iBitsSize);
  193.  
  194.     return TRUE;
  195. }
  196.  
  197.  
  198. //---------------------------------------------------------------------
  199. BOOL CMRCDib::LoadFileName(LPCTSTR lpszFileName)
  200. // Load DIB for a file name
  201. //---------------------------------------------------------------------
  202. {
  203.     CFile file;
  204.     if (!file.Open(lpszFileName, CFile::modeRead | CFile::shareDenyWrite))
  205.         return FALSE;   
  206.     return Load(&file);            // destructor will close the file
  207. }    
  208.  
  209.  
  210.  
  211. //---------------------------------------------------------------------
  212. BOOL CMRCDib::Load(CFile *fp)
  213. // Load a DIB from an open file.
  214. // code in here also handles PM format bitmaps 
  215. //---------------------------------------------------------------------
  216. {
  217. #ifdef HANDLE_PM_BITMAPS
  218.     BOOL bIsPM = FALSE;
  219. #endif // HANDLE_PM_BITMAPS
  220.     BITMAPINFO *pBmpInfo = NULL;
  221.     BYTE *pBits = NULL;
  222.  
  223.     // get the current file position
  224.     DWORD dwFileStart = fp->GetPosition();
  225.  
  226.     // read the file header to get the file size and to
  227.     // find where the bits start in the file
  228.     BITMAPFILEHEADER BmpFileHdr;
  229.     int iBytes;
  230.     iBytes = fp->Read(&BmpFileHdr, sizeof(BmpFileHdr));
  231.     if (iBytes != sizeof(BmpFileHdr))
  232.     {
  233.         TRACE("CMRCDib::Load() - failed to read file header\n");
  234.         goto $abort;
  235.     }
  236.  
  237.     // check we have the magic 'BM' at the start
  238.     if (BmpFileHdr.bfType != 0x4D42)
  239.     {
  240.         TRACE("CMRCDib::Load() - not a bitmap file\n");
  241.         goto $abort;
  242.     }
  243.  
  244.     // Assume file is a Windows DIB    and read the BITMAPINFOHEADER.  If it turns
  245.     // out to be a PM DIB file, convert it later.
  246.     BITMAPINFOHEADER BmpInfoHdr;
  247.     iBytes = fp->Read(&BmpInfoHdr, sizeof(BmpInfoHdr)); 
  248.     if (iBytes != sizeof(BmpInfoHdr))
  249.     {
  250.         TRACE("CMRCDib::Load() - failed to read BITMAPINFOHEADER\n");
  251.         goto $abort;
  252.     }
  253.  
  254.     // check we got a real Windows DIB file
  255.     if (BmpInfoHdr.biSize != sizeof(BITMAPINFOHEADER))
  256.     {
  257.         if (BmpInfoHdr.biSize != sizeof(BITMAPCOREHEADER))
  258.         {
  259.             TRACE("CMRCDib::Load() - file is not Windows or PM DIB format\n");
  260.             goto $abort;
  261.         }
  262.  
  263. #ifdef HANDLE_PM_BITMAPS
  264.         // set a flag to convert PM file to Win format later
  265.         bIsPM = TRUE;
  266.  
  267.         // back up the file pointer and read the BITMAPCOREHEADER
  268.         // and create the BITMAPINFOHEADER from it
  269.         fp->Seek(dwFileStart + sizeof(BITMAPFILEHEADER), CFile::begin);
  270.         BITMAPCOREHEADER BmpCoreHdr;
  271.         iBytes = fp->Read(&BmpCoreHdr, sizeof(BmpCoreHdr)); 
  272.         if (iBytes != sizeof(BmpCoreHdr))
  273.         {
  274.             TRACE("CMRCDib::Load() - failed to read BITMAPCOREHEADER");
  275.             goto $abort;
  276.         }
  277.  
  278.         BmpInfoHdr.biSize = sizeof(BITMAPINFOHEADER);
  279.         BmpInfoHdr.biWidth = (int) BmpCoreHdr.bcWidth;
  280.         BmpInfoHdr.biHeight = (int) BmpCoreHdr.bcHeight;
  281.         BmpInfoHdr.biPlanes = BmpCoreHdr.bcPlanes;
  282.         BmpInfoHdr.biBitCount = BmpCoreHdr.bcBitCount;
  283.         BmpInfoHdr.biCompression = BI_RGB;
  284.         BmpInfoHdr.biSizeImage = 0;
  285.         BmpInfoHdr.biXPelsPerMeter = 0;
  286.         BmpInfoHdr.biYPelsPerMeter = 0;
  287.         BmpInfoHdr.biClrUsed = 0;
  288.         BmpInfoHdr.biClrImportant = 0;
  289. #endif // HANDLE_PM_BITMAPS
  290.     }
  291.  
  292.     // Work out how much memory we need for the BITMAPINFO
  293.     // structure, color table and then for the bits.  
  294.     // Allocate the memory blocks, copy the BmpInfoHdr we have so far 
  295.     // and then read in the color table from the file.
  296.     int iColors;
  297.     int iColorTableSize;
  298.     iColors = NumDIBColorEntries((LPBITMAPINFO) &BmpInfoHdr);
  299.     iColorTableSize = iColors * sizeof(RGBQUAD);
  300.     int iBitsSize;
  301.     int iBISize;
  302.     // always allocate enough room for 256 entries
  303.     iBISize = sizeof(BITMAPINFOHEADER)    
  304.            + 256 * sizeof(RGBQUAD);
  305.     iBitsSize = BmpFileHdr.bfSize - 
  306.                 BmpFileHdr.bfOffBits;
  307.  
  308.     // allocate the memory for the header
  309.     pBmpInfo = (LPBITMAPINFO) new BYTE[iBISize];
  310.     if (!pBmpInfo)
  311.     {
  312.         TRACE("CMRCDib::Load() - Out of memory for DIB header");
  313.         goto $abort;
  314.     }
  315.  
  316.     // copy the header we already have
  317.     memcpy(pBmpInfo, &BmpInfoHdr, sizeof(BITMAPINFOHEADER));
  318.  
  319.     // now read the color table in from the file
  320. #ifdef HANDLE_PM_BITMAPS
  321.     if (bIsPM)
  322.     {
  323.         // read each PM color table entry in turn and convert it
  324.         // to Win DIB format as we go
  325.         LPRGBQUAD lpRGB;
  326.         lpRGB = (LPRGBQUAD) ((LPBYTE) pBmpInfo + sizeof(BITMAPINFOHEADER));
  327.         int i;
  328.         RGBTRIPLE rgbt;
  329.         for (i=0; i<iColors; i++)
  330.         {
  331.             iBytes = fp->Read(&rgbt, sizeof(RGBTRIPLE));
  332.             if (iBytes != sizeof(RGBTRIPLE))
  333.             {
  334.                 TRACE("Failed to read RGBTRIPLE");
  335.                 goto $abort;
  336.             }
  337.             lpRGB->rgbBlue = rgbt.rgbtBlue;
  338.             lpRGB->rgbGreen = rgbt.rgbtGreen;
  339.             lpRGB->rgbRed = rgbt.rgbtRed;
  340.             lpRGB->rgbReserved = 0;
  341.             lpRGB++;
  342.         }
  343.     }
  344.     else
  345.     {
  346. #endif // HANDLE_PM_BITMAPS
  347.         // read the color table from the file
  348.         iBytes = fp->Read(((LPBYTE) pBmpInfo) + sizeof(BITMAPINFOHEADER),
  349.                              iColorTableSize);
  350.         if (iBytes != iColorTableSize)
  351.         {
  352.             TRACE("CMRCDib::Load() - failed to read PM color table");
  353.             goto $abort;
  354.         }
  355. #ifdef HANDLE_PM_BITMAPS
  356.     }
  357. #endif // HANDLE_PM_BITMAPS
  358.  
  359.     // allocate the memory for the bits
  360.     pBits = new BYTE[iBitsSize];
  361.     if (!pBits)
  362.        {
  363.         TRACE("CMRCDib::Load() - out of memory for DIB bits");
  364.         goto $abort;
  365.     }
  366.  
  367.     // seek to the bits in the file
  368.     fp->Seek(dwFileStart + BmpFileHdr.bfOffBits, CFile::begin);
  369.  
  370.     // read the bits
  371.     iBytes = fp->Read(pBits, iBitsSize);
  372.     if (iBytes != iBitsSize)
  373.     {
  374.         TRACE("CMRCDib::Load() - failed to read bits");
  375.         goto $abort;
  376.     }
  377.  
  378.     // Everything went OK
  379.     DeleteContents();  // remove previous info, and delete this one
  380.     m_pBMI = pBmpInfo; 
  381.     m_pBits = pBits;
  382.     return TRUE;
  383.                 
  384. $abort: // something went wrong
  385.     if (pBmpInfo)
  386.          delete pBmpInfo;
  387.     if (pBits)
  388.          delete pBits;
  389.     return FALSE;    
  390. }
  391.  
  392.  
  393.  
  394. //--------------------------------------------------------------------------
  395. BOOL CMRCDib::LoadFromResource(const char * lpszResource)
  396. // load bitmap from a resource ID
  397. //--------------------------------------------------------------------------
  398. {
  399.     BITMAPINFO *pBmpInfo = NULL;
  400.     BYTE *pBits = NULL;
  401.  
  402.     HINSTANCE hResInst = AfxGetResourceHandle();
  403.     HRSRC hFindRes;
  404.     HGLOBAL hLoadRes;
  405.     LPBYTE lpRes, lpLockRes;
  406.  
  407.     hFindRes = ::FindResource(hResInst, lpszResource, RT_BITMAP);
  408.     if (hFindRes == NULL)
  409.         return FALSE;
  410.     hLoadRes = LoadResource(hResInst, hFindRes);    
  411.     if (hLoadRes == NULL)
  412.         return FALSE;
  413.     lpLockRes = (LPBYTE) ::LockResource(hLoadRes);
  414.     if (lpLockRes == NULL)
  415.         return FALSE;
  416.     lpRes = lpLockRes;
  417.                     
  418.     // check we got a real Windows DIB file
  419.     if (((LPBITMAPINFOHEADER)lpLockRes)->biSize != sizeof(BITMAPINFOHEADER))
  420.         return FALSE;
  421.     
  422.     // Look at color table size, and work out where image bits start
  423.     int iColors;
  424.     int iColorTableSize;
  425.     iColors = NumDIBColorEntries((LPBITMAPINFO)lpLockRes);
  426.     iColorTableSize = iColors * sizeof(RGBQUAD);
  427.     pBits = lpLockRes + sizeof(BITMAPINFOHEADER) + iColorTableSize;
  428.     
  429.     // Since the resource is now locked,we can just return pointers to the BITMAPINFO
  430.     // structure and the bits.
  431.      
  432.      DeleteContents();        // remove previous DIB, if any
  433.      m_pBMI = (BITMAPINFO *) lpLockRes;
  434.     m_pBits = pBits;
  435.     m_cLoadedFromResource = 1;
  436.     return TRUE;
  437. }
  438.  
  439.  
  440.  
  441.  
  442. //------------------------------------------------------------------
  443. void CMRCDib::Draw(CDC *pDC, int x, int y)
  444. // Draw the DIB to a given DC, at default size
  445. //------------------------------------------------------------------
  446. {
  447.     ::StretchDIBits(pDC->GetSafeHdc(),
  448.                   x,                        // dest x
  449.                   y,                        // dest y
  450.                   DibWidth(),                 // dest width
  451.                   DibHeight(),                // dest height
  452.                   0,                        // src x
  453.                   0,                        // src y
  454.                   DibWidth(),                 // src width
  455.                   DibHeight(),                // src height
  456.                   GetBitsAddress(),         // bits
  457.                   GetBitmapInfoAddress(),   // BITMAPINFO
  458.                   DIB_RGB_COLORS,           // options
  459.                   SRCCOPY);                 // rop
  460. }
  461.  
  462.  
  463. //------------------------------------------------------------------
  464. void CMRCDib::Draw(CDC *pDC, int x, int y, int cx, int cy)
  465. // Draw the DIB to a given DC
  466. //------------------------------------------------------------------
  467. {
  468.     ::StretchDIBits(pDC->GetSafeHdc(),
  469.                   x,                        // dest x
  470.                   y,                        // dest y
  471.                   cx,                         // dest width
  472.                   cy,                        // dest height
  473.                   0,                        // src x
  474.                   0,                        // src y
  475.                   DibWidth(),                 // src width
  476.                   DibHeight(),                // src height
  477.                   GetBitsAddress(),         // bits
  478.                   GetBitmapInfoAddress(),   // BITMAPINFO
  479.                   DIB_RGB_COLORS,           // options
  480.                   SRCCOPY);                 // rop
  481. }
  482.  
  483.  
  484. //------------------------------------------------------------------
  485. int CMRCDib::GetNumClrEntries()
  486. // get the number of color table entries
  487. //------------------------------------------------------------------
  488. {
  489.     return NumDIBColorEntries(m_pBMI);
  490. }
  491.  
  492.  
  493.  
  494.  
  495.  
  496. /////////////////////////////////////////////////////////////////////////////
  497. /////////////////////////////////////////////////////////////////////////////
  498. // CMRCDibPal
  499. /////////////////////////////////////////////////////////////////////////////
  500. /////////////////////////////////////////////////////////////////////////////
  501.  
  502. CMRCDibPal::CMRCDibPal()
  503. {
  504. }
  505.  
  506. CMRCDibPal::~CMRCDibPal()
  507. {
  508. }
  509.  
  510. //-----------------------------------------------------------------------
  511. BOOL CMRCDibPal::Create(CMRCDib *pDIB)
  512. // Create a palette from the color table in a CMRCDib
  513. //-----------------------------------------------------------------------
  514. {
  515.     DWORD dwColors = pDIB->GetNumClrEntries();
  516.     // Check the DIB has a color table
  517.     if (! dwColors)
  518.     {
  519.         TRACE("CMRCDibPal::Create() - no color table\n");   
  520.         return FALSE;
  521.     }
  522.  
  523.     // get a pointer to the RGB quads in the color table
  524.     RGBQUAD * pRGB = pDIB->GetClrTabAddress();
  525.  
  526.     // allocate a log pal and fill it with the color table info
  527.     LOGPALETTE *pPal = (LOGPALETTE *) new BYTE [ sizeof(LOGPALETTE) 
  528.                                              + dwColors * sizeof(PALETTEENTRY) ];
  529.     if (!pPal)
  530.     {
  531.         TRACE("CMRCDibPal::Create() - out of memory for logpal");
  532.         return FALSE;
  533.     }
  534.     pPal->palVersion = 0x300; // Windows 3.0
  535.     pPal->palNumEntries = (WORD) dwColors; // table size
  536.     for (DWORD dw=0; dw<dwColors; dw++)
  537.     {
  538.         pPal->palPalEntry[dw].peRed = pRGB[dw].rgbRed;
  539.         pPal->palPalEntry[dw].peGreen = pRGB[dw].rgbGreen;
  540.         pPal->palPalEntry[dw].peBlue = pRGB[dw].rgbBlue;
  541.         pPal->palPalEntry[dw].peFlags = 0;
  542.     }
  543.     BOOL bResult = CreatePalette(pPal);
  544.     delete pPal;
  545.     return bResult;
  546. }
  547.  
  548. /////////////////////////////////////////////////////////////////////////////
  549. // CMRCDibPal commands
  550.  
  551. //-----------------------------------------------------------------------
  552. int CMRCDibPal::GetNumColors()
  553. //-----------------------------------------------------------------------
  554. {
  555.     int iColors = 0;
  556.     if (!GetObject(sizeof(iColors), &iColors))
  557.     {
  558.         TRACE("CMRCDibPal::GetNumColors() - failed to get num pal colors");
  559.         return 0;
  560.     }
  561.     return iColors;
  562. }
  563.  
  564.  
  565.