home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / mfc / database / daoctl / accspict / strmdib.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-03-27  |  6.0 KB  |  260 lines

  1. // StreamDib.cpp : implementation file
  2. //
  3. // This is a part of the Microsoft Foundation Classes C++ library.
  4. // Copyright (C) 1992-1998 Microsoft Corporation
  5. // All rights reserved.
  6. //
  7. // This source code is only intended as a supplement to the
  8. // Microsoft Foundation Classes Reference and related
  9. // electronic documentation provided with the library.
  10. // See these sources for detailed information regarding the
  11. // Microsoft Foundation Classes product.
  12.  
  13. #include "stdafx.h"
  14. #include "AccsPict.h"
  15. #include "StrmDib.h"
  16.  
  17.  
  18. /////////////////////////////////////////////////////////////////////////////
  19. // Definitions
  20.  
  21. IMPLEMENT_DYNAMIC(CStreamDib, CObject)
  22.  
  23. #ifdef _DEBUG
  24. #define new DEBUG_NEW
  25.  
  26. #undef THIS_FILE
  27. static char THIS_FILE[] = __FILE__;
  28. #endif
  29.  
  30. /////////////////////////////////////////////////////////////////////////////
  31. // CStreamDib
  32.  
  33. CStreamDib::CStreamDib()
  34. {
  35.     m_lpbi = NULL;
  36.     m_size = CSize(0, 0);   // Initialize size to NULL;
  37.  
  38.     m_Palette.m_hObject = NULL;
  39.     m_Bitmap.m_hObject = NULL;
  40. }
  41.  
  42. CStreamDib::~CStreamDib()
  43. {
  44.     if (m_lpbi != NULL)
  45.     {
  46.         delete m_lpbi;
  47.         m_lpbi = NULL;
  48.     }
  49.  
  50.     // Kill off bitmap and palette
  51.     if (m_Palette.m_hObject != NULL)
  52.         m_Palette.DeleteObject();
  53.  
  54.     if (m_Bitmap.m_hObject != NULL)
  55.         m_Bitmap.DeleteObject();
  56. }
  57.  
  58.  
  59. /////////////////////////////////////////////////////////////////////////////
  60. // CStreamDib Attributes
  61.  
  62. CPalette* CStreamDib::GetPalette()
  63. {
  64.     if (m_Palette.m_hObject == NULL)
  65.         return NULL;
  66.  
  67.     return &m_Palette;
  68. }
  69.  
  70. CBitmap* CStreamDib::GetBitmap()
  71. {
  72.     if (m_Bitmap.m_hObject == NULL)
  73.         return NULL;
  74.  
  75.     return &m_Bitmap;
  76. }
  77.  
  78.  
  79. CSize CStreamDib::GetSize()
  80. {
  81.     return m_size;
  82. }
  83.  
  84. /////////////////////////////////////////////////////////////////////////////
  85. // CStreamDib Operations
  86.  
  87. BOOL CStreamDib::LoadBitmap(LPSTREAM lpStream)
  88. {
  89.     LPBYTE lpFileHeader = NULL;
  90.     ULONG ulRead;
  91.     int nColors;
  92.     LPBYTE lpInfo = NULL;
  93.     BYTE* pBits = NULL;
  94.  
  95.     TRY
  96.     {
  97.         if (lpStream == NULL)
  98.             AfxThrowMemoryException();
  99.  
  100.         // Read in the BITMAPFILEHEADER
  101.         lpFileHeader = new BYTE[sizeof(BITMAPFILEHEADER)];
  102.         if (FAILED(lpStream->Read((void*)lpFileHeader,
  103.             sizeof(BITMAPFILEHEADER), &ulRead)))
  104.             AfxThrowMemoryException();
  105.  
  106.         ASSERT(ulRead == sizeof(BITMAPFILEHEADER));
  107.  
  108.         LPBITMAPFILEHEADER lpfh = (LPBITMAPFILEHEADER)lpFileHeader;
  109.         if (lpfh->bfType != ((WORD) 'B' | ('M' << 8)))
  110.             AfxThrowMemoryException();
  111.  
  112.         // Read in the BITMAPINFO struct
  113.         // size equals BITMAPINFOHEADER plus difference between
  114.         // the bfOffBits and the header.  SO, sounds like you
  115.         // should allocate a bfOffBits
  116.         DWORD dwSize = lpfh->bfOffBits - sizeof(BITMAPFILEHEADER);
  117.         lpInfo = new BYTE[dwSize];
  118.  
  119.         if (FAILED(lpStream->Read((void*)lpInfo, dwSize, &ulRead)))
  120.             AfxThrowMemoryException();
  121.         ASSERT(ulRead == dwSize);
  122.  
  123.         LPBITMAPINFO lpbi = (LPBITMAPINFO)lpInfo;
  124.  
  125.         // This code only supports 2, 16, and 256 color bitmaps
  126.         if (lpbi->bmiHeader.biBitCount != 1 &&
  127.             lpbi->bmiHeader.biBitCount != 4 &&
  128.                 lpbi->bmiHeader.biBitCount != 8)
  129.             AfxThrowMemoryException();
  130.  
  131.         if (lpbi->bmiHeader.biClrUsed != 0)
  132.             nColors = lpbi->bmiHeader.biClrUsed;
  133.         else
  134.             nColors = 1 << lpbi->bmiHeader.biBitCount;
  135.  
  136.         MergePalette(lpbi->bmiColors, nColors);
  137.  
  138.         CSize size(lpbi->bmiHeader.biWidth, lpbi->bmiHeader.biHeight);
  139.         m_size = size;
  140.         CreateBitmap(size);
  141.  
  142.         // Read in the actual BITMAP
  143.         dwSize = lpfh->bfSize - lpfh->bfOffBits;
  144.         pBits = new BYTE[dwSize];
  145.  
  146.         if (FAILED(lpStream->Read((void*)pBits, dwSize, &ulRead)))
  147.             AfxThrowMemoryException();
  148.         ASSERT(ulRead == dwSize);
  149.  
  150.         // BLOCK: Set the DIB sections bits from the DIB we are loading
  151.         {
  152.             CWindowDC dc(NULL);
  153.             VERIFY( SetDIBits( dc.m_hDC, (HBITMAP)m_Bitmap.m_hObject, 0,
  154.                 lpbi->bmiHeader.biHeight, pBits, lpbi, DIB_RGB_COLORS )
  155.                 == lpbi->bmiHeader.biHeight );
  156.         }
  157.  
  158.         delete lpInfo;
  159.         delete lpFileHeader;
  160.         delete pBits;
  161.         lpInfo = NULL;
  162.         lpFileHeader = NULL;
  163.         pBits = NULL;
  164.     }
  165.     CATCH(CMemoryException, e)
  166.     {
  167.         if (lpInfo != NULL)
  168.         {
  169.             delete lpInfo;
  170.             lpInfo = NULL;
  171.         }
  172.  
  173.         if (lpFileHeader != NULL)
  174.         {
  175.             delete lpFileHeader;
  176.             lpFileHeader = NULL;
  177.         }
  178.  
  179.         if (pBits != NULL)
  180.         {
  181.             delete pBits;
  182.             pBits = NULL;
  183.         }
  184.  
  185.         return FALSE;
  186.     }
  187.     END_CATCH
  188. }
  189.  
  190.  
  191. ///////////////////////////////////////////////////////////////////////////
  192. // Implementation Functions
  193.  
  194. void CStreamDib::MergePalette(RGBQUAD* pColors, int nColors)
  195. {
  196.     CMap<DWORD, DWORD, BOOL, BOOL> PaletteMap;
  197.     DWORD dword;
  198.     BOOL bScrap;
  199.     int i;
  200.     POSITION pos;
  201.  
  202.     memcpy( m_rgbPalette, rgbStd256, sizeof(RGBQUAD) * 256 );
  203.  
  204.     for(i=0; i<nColors; i++)
  205.     {
  206.         PaletteMap.SetAt(MAKEDWORD(pColors[i]),TRUE);
  207.     }
  208.  
  209.     i = 0;
  210.     while (PaletteMap.GetCount() < 256)
  211.         PaletteMap.SetAt(MAKEDWORD(m_rgbPalette[i++]),FALSE);
  212.  
  213.  
  214.     for(i=0,pos=PaletteMap.GetStartPosition(); pos!=NULL; i++)
  215.     {
  216.         PaletteMap.GetNextAssoc(pos,dword,bScrap);
  217.         m_rgbPalette[i]=MAKERGBQUAD(dword);
  218.     }
  219. }
  220.  
  221.  
  222. void CStreamDib::CreateBitmap(CSize& size)
  223. {
  224.     BYTE*           pBits;
  225.  
  226.     if (m_Bitmap.m_hObject != NULL)
  227.         m_Bitmap.DeleteObject();
  228.  
  229.     ASSERT(m_lpbi == NULL);
  230.  
  231.     // Fill in the BITMAPINFOHEADER
  232.     m_lpbi = (LPBITMAPINFO) new BYTE[sizeof(BITMAPINFOHEADER)
  233.         + (256 * sizeof(RGBQUAD))];
  234.     m_lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  235.     m_lpbi->bmiHeader.biWidth = size.cx;
  236.     m_lpbi->bmiHeader.biHeight = size.cy;
  237.     m_lpbi->bmiHeader.biPlanes = 1;
  238.     m_lpbi->bmiHeader.biBitCount = 8;
  239.     m_lpbi->bmiHeader.biCompression = BI_RGB;
  240.     m_lpbi->bmiHeader.biSizeImage = WIDTHBYTES((DWORD)size.cx * 8) * size.cy;
  241.     m_lpbi->bmiHeader.biXPelsPerMeter = 0;
  242.     m_lpbi->bmiHeader.biYPelsPerMeter = 0;
  243.     m_lpbi->bmiHeader.biClrUsed = 0;
  244.     m_lpbi->bmiHeader.biClrImportant = 0;
  245.  
  246.     // Fill in the color table
  247.     UINT uUsage = DIB_RGB_COLORS;
  248.  
  249.     memcpy( m_lpbi->bmiColors, m_rgbPalette, sizeof(RGBQUAD) * 256 );
  250.  
  251.     CWindowDC dc(NULL);
  252.     HBITMAP hBitmap = CreateDIBSection( dc.m_hDC, m_lpbi, uUsage,
  253.         (VOID**)&pBits, NULL, 0 );
  254.  
  255.     m_Bitmap.Attach(hBitmap);
  256.  
  257.     delete [] (BYTE *)m_lpbi;
  258.     m_lpbi = NULL;
  259. }
  260.