How to make a bmp or gif file from a device context?

I record the mouse drawing data on memory device context and want to transfer them to a file(bitmap or GIF) but don't know how...
Esmond071901Asked:
Who is Participating?
 
MichaelSCommented:
0
 
Meir RivkinFull stack Software EngineerCommented:
add this class to your application:

//Here is class to handle DIBs in the MFC:
// header

#ifndef __DIBITMAP_H
#define __DIBITMAP_H

#include "stdafx.h"

class CDIBitmap
{
public:
   BOOL AssignDDP(HBITMAP);
   CDIBitmap(HBITMAP hbm);
   ~CDIBitmap();
   CDIBitmap();

   BOOL    Draw(CDC& dc, CRect& rc);
   BOOL      Save(CFile& File);
   BOOL      Load(CFile& File);
     void    RealizeDIBPalette(HDC hDC, LPBITMAPINFO lpbmi);
     WORD    DIBNumColors();
     WORD    PaletteSize();
     DWORD   DIBHeight() {return wDIBHeight;}
     DWORD   DIBWidth()  {return wDIBWidth;}

protected:
   void ResetDIB();
     HBITMAP DIBToBitmap();
     LPSTR    FindDIBBits();
     HPALETTE CreateDIBPalette();
     HANDLE   BitmapToDIB(HBITMAP hBitmap);
     HPALETTE GetSystemPalette ();
     void     InitBitmapInfoHeader (LPBITMAPINFOHEADER lpBmInfoHdr,
                                           DWORD dwWidth,
                                           DWORD dwHeight,
                                             int nBPP);
private:
   LPSTR lpbi;

  HANDLE      hDIB;                // Handle to the DIB
  HPALETTE    hPal;                // Handle to the bitmap's palette.
  HBITMAP     hBitmap;             // Handle to the DDB.

  WORD        wDIBType;            // DIB's type - RGB, RLE4, RLE8, PM
  WORD        wDIBBits;            // Bits per pixel
  WORD        wDIBWidth;           // Print width of the DIB
  WORD        wDIBHeight;          // Print height of the DIB
};


#endif //__DIBITMAP_H

//implementation

#include "stdafx.h"
//#include "cdibitmap.h"

#define WIDTHBYTES(bits)      (((bits) + 31) / 32 * 4)
#define IS_WIN30_DIB(lpbi)  ((*(LPDWORD) (lpbi)) == sizeof (BITMAPINFOHEADER))
#define PALVERSION   0x300
#define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B')

void CDIBitmap::RealizeDIBPalette(HDC, LPBITMAPINFO)
{
}

LPSTR CDIBitmap::FindDIBBits()

{
  return (lpbi + *(LPDWORD)lpbi + PaletteSize ());
}


HANDLE CDIBitmap::BitmapToDIB(HBITMAP hBmp)
{
  BITMAP             Bitmap;
  BITMAPINFOHEADER   bmInfoHdr;
  LPBITMAPINFOHEADER lpbmInfoHdr;
  LPSTR              lpBits;
  HDC                hMemDC;
  HPALETTE           hOldPal = NULL;

     // Do some setup -- make sure the Bitmap passed in is valid,
     //  get info on the bitmap (like its height, width, etc.),
     //  then setup a BITMAPINFOHEADER.

  if (!hBmp)
     return NULL;

  if (!GetObject (hBmp, sizeof (Bitmap), (LPSTR) &Bitmap))
     return NULL;

  InitBitmapInfoHeader (&bmInfoHdr,
                        Bitmap.bmWidth,
                        Bitmap.bmHeight,
                        4);


     // Now allocate memory for the DIB.  Then, set the BITMAPINFOHEADER
     //  into this memory, and find out where the bitmap bits go.
   lpbi = (LPSTR)&bmInfoHdr;

  hDIB = GlobalAlloc (GHND, sizeof (BITMAPINFOHEADER) + PaletteSize()+bmInfoHdr.biSizeImage);

  if (!hDIB)
     return NULL;

  lpbmInfoHdr  = (LPBITMAPINFOHEADER) GlobalLock (hDIB);
  *lpbmInfoHdr = bmInfoHdr;
  lpbi = (LPSTR)lpbmInfoHdr;
  lpBits  = (LPSTR)lpbmInfoHdr + lpbmInfoHdr->biSize + PaletteSize();


     // Now, we need a DC to hold our bitmap.  If the app passed us
     //  a palette, it should be selected into the DC.

  hMemDC       = GetDC (NULL);

  if (hPal)
     {
     hOldPal = SelectPalette (hMemDC, hPal, FALSE);
     RealizePalette (hMemDC);
     }



     // We're finally ready to get the DIB.  Call the driver and let
     //  it party on our bitmap.  It will fill in the color table,
     //  and bitmap bits of our global memory block.

  if (!GetDIBits (hMemDC,
                  hBmp,
                  0,
                  Bitmap.bmHeight,
                  lpBits,
                  (LPBITMAPINFO) lpbmInfoHdr,
                  DIB_RGB_COLORS))
     {
     GlobalUnlock (hDIB);
     GlobalFree (hDIB);
     hDIB = NULL;
     }
  else
     GlobalUnlock (hDIB);


     // Finally, clean up and return.

  if (hOldPal)
     SelectPalette (hMemDC, hOldPal, FALSE);

  ReleaseDC (NULL, hMemDC);

  return hDIB;
}

HPALETTE CDIBitmap::CreateDIBPalette()

{
  LPLOGPALETTE     lpPal;
  HANDLE           hLogPal;
  int              i, wNumColors;
  LPBITMAPINFO     lpbmi;
  LPBITMAPCOREINFO lpbmc;
  BOOL             bWinStyleDIB;

  if (!hDIB)
     return NULL;

  lpbi         = (LPSTR)GlobalLock (hDIB);
  lpbmi        = (LPBITMAPINFO) lpbi;
  lpbmc        = (LPBITMAPCOREINFO) lpbi;
  wNumColors   = DIBNumColors ();
  bWinStyleDIB = IS_WIN30_DIB (lpbi);

  if (wNumColors)
     {
     hLogPal = GlobalAlloc (GHND, sizeof (LOGPALETTE) +
                            sizeof (PALETTEENTRY) * wNumColors);

     if (!hLogPal)
        {
//         DIBError (ERR_CREATEPAL);
        GlobalUnlock (hDIB);
        return NULL;
        }

     lpPal = (LPLOGPALETTE) GlobalLock (hLogPal);

     lpPal->palVersion    = PALVERSION;
     lpPal->palNumEntries = wNumColors;

     for (i = 0;  i < wNumColors;  i++)
        {
        if (bWinStyleDIB)
           {
           lpPal->palPalEntry[i].peRed   = lpbmi->bmiColors[i].rgbRed;
           lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
           lpPal->palPalEntry[i].peBlue  = lpbmi->bmiColors[i].rgbBlue;
           lpPal->palPalEntry[i].peFlags = 0;
           }
        else
           {
           lpPal->palPalEntry[i].peRed   = lpbmc->bmciColors[i].rgbtRed;
           lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
           lpPal->palPalEntry[i].peBlue  = lpbmc->bmciColors[i].rgbtBlue;
           lpPal->palPalEntry[i].peFlags = 0;
           }
        }

     hPal = CreatePalette (lpPal);

//      if (!hPal)
//         DIBError (ERR_CREATEPAL);

     GlobalUnlock (hLogPal);
     GlobalFree   (hLogPal);
  }

  GlobalUnlock (hDIB);

  return hPal;
}

void CDIBitmap::InitBitmapInfoHeader(LPBITMAPINFOHEADER lpBmInfoHdr, DWORD dwWidth, DWORD dwHeight,
int nBPP)

{


  memset (lpBmInfoHdr, 0, sizeof (BITMAPINFOHEADER));

  lpBmInfoHdr->biSize      = sizeof (BITMAPINFOHEADER);
  lpBmInfoHdr->biWidth     = dwWidth;
  lpBmInfoHdr->biHeight    = dwHeight;
  lpBmInfoHdr->biPlanes    = 1;

  if (nBPP <= 1)
     nBPP = 1;
  else if (nBPP <= 4)
     nBPP = 4;
  else if (nBPP <= 8)
     nBPP = 8;
  else
     nBPP = 24;

  lpBmInfoHdr->biBitCount  = nBPP;
     wDIBHeight = dwHeight;
     wDIBWidth = dwWidth;
     wDIBType =  BI_RGB;
     wDIBBits = nBPP;
     lpBmInfoHdr->biSizeImage = WIDTHBYTES (dwWidth * nBPP) * dwHeight;
}

WORD CDIBitmap::DIBNumColors()

{
  WORD wBitCount;


     // If this is a Windows style DIB, 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.

  if (IS_WIN30_DIB (lpbi))
     {
     DWORD dwClrUsed;

     dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed;

     if (dwClrUsed)
        return (WORD) dwClrUsed;
     }


     // Calculate the number of colors in the color table based on
     //  the number of bits per pixel for the DIB.

  if (IS_WIN30_DIB (lpbi))
     wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;
  else
     wBitCount = ((LPBITMAPCOREHEADER) lpbi)->bcBitCount;

  switch (wBitCount)
     {
     case 1:
        return 2;

     case 4:
        return 16;

     case 8:
        return 256;

     default:
        return 0;
     }
}

WORD CDIBitmap::PaletteSize()
{
  if (IS_WIN30_DIB (lpbi))
     return (DIBNumColors () * sizeof (RGBQUAD));
  else
     return (DIBNumColors () * sizeof (RGBTRIPLE));
}

BOOL CDIBitmap::Load(CFile& File)

{
     BITMAPFILEHEADER   bmfHeader;
     LPBITMAPINFOHEADER lpbih;
     DWORD              dwBitsSize;
     LPSTR              pDIB;


     // get length of DIB in bytes for use when reading

     // Go read the DIB file header and check if it's valid.

     if ((File.Read ((void*) &bmfHeader, sizeof (bmfHeader)) != sizeof (bmfHeader)) ||
         (bmfHeader.bfType != DIB_HEADER_MARKER))
       {
     //      DIBError (ERR_NOT_DIB);
       return NULL;
       }

     dwBitsSize = bmfHeader.bfSize;


     hDIB = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize - sizeof(BITMAPFILEHEADER));

     if (hDIB == 0)
      {
     //     DIBError (ERR_MEMORY);
      return NULL;
      }

     pDIB = (LPSTR)GlobalLock (hDIB);
     lpbih = (LPBITMAPINFOHEADER )pDIB;
     // Go read the bits.

     if (!File.Read(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)))
       {
       GlobalUnlock (hDIB);
       GlobalFree   (hDIB);
     //      DIBError (ERR_READ);
       return NULL;
       }

     wDIBHeight = lpbih->biHeight;
     wDIBWidth = lpbih->biWidth;
     wDIBType =  BI_RGB;
     wDIBBits = lpbih->biBitCount*lpbih->biPlanes;

     GlobalUnlock (hDIB);
     hPal = CreateDIBPalette();
     hBitmap = DIBToBitmap();
     return TRUE;
}


BOOL CDIBitmap::Save(CFile& File)
{
   BITMAPFILEHEADER     hdr;
   LPBITMAPINFOHEADER  lpbih;

   if (!hDIB)
     return FALSE;

   lpbi = (LPSTR)GlobalLock (hDIB);
     lpbih = (LPBITMAPINFOHEADER)lpbi;
   /* Fill in the fields of the file header */
   hdr.bfType          = DIB_HEADER_MARKER;
   hdr.bfSize          = GlobalSize(hDIB) + sizeof (BITMAPFILEHEADER);
   hdr.bfReserved1 = 0;
   hdr.bfReserved2 = 0;
   hdr.bfOffBits   = (DWORD)sizeof(BITMAPFILEHEADER) + lpbih->biSize + PaletteSize();

   /* Write the file header */
   File.Write((LPSTR)&hdr, sizeof (BITMAPFILEHEADER));

   /* Write the DIB header and the bits */
   File.Write((LPSTR)lpbi, GlobalSize(hDIB));

   GlobalUnlock (hDIB);
   return TRUE;
}

HBITMAP CDIBitmap::DIBToBitmap()
{
 LPSTR    lpDIBHdr, lpDIBBits;
  HDC      hDC;
  HPALETTE hOldPal = NULL;

  if (!hDIB)
     return NULL;

  lpDIBHdr  = lpbi = (LPSTR) GlobalLock (hDIB);

  lpDIBBits = FindDIBBits ();
  hDC       = GetDC (NULL);

  if (!hDC)
     {
     GlobalUnlock (hDIB);
     return NULL;
     }

  if (hPal)
     hOldPal = SelectPalette (hDC, hPal, FALSE);

  RealizePalette (hDC);

  hBitmap = CreateDIBitmap (hDC,
                            (LPBITMAPINFOHEADER) lpDIBHdr,
                            CBM_INIT,
                            lpDIBBits,
                            (LPBITMAPINFO) lpDIBHdr,
                            DIB_RGB_COLORS);

//   if (!hBitmap)
//      DIBError (ERR_CREATEDDB);

  if (hOldPal)
     SelectPalette (hDC, hOldPal, FALSE);

  ReleaseDC (NULL, hDC);
  GlobalUnlock (hDIB);

  return hBitmap;
}


BOOL CDIBitmap::Draw(CDC&dc, CRect& rc)

{
  HDC      hMemDC;
  HBITMAP  hOldBitmap;
  HPALETTE hOldPal1 = NULL;
  HPALETTE hOldPal2 = NULL;


  hMemDC = CreateCompatibleDC (dc.m_hDC);

  if (!hMemDC)
     return FALSE;

  if (hPal)
     {
     hOldPal1   = SelectPalette (hMemDC, hPal, FALSE);
     hOldPal2   = SelectPalette (dc.m_hDC, hPal, FALSE);
     // Assume the palette's already been realized (no need to
     //  call RealizePalette().  It should have been realized in
     //  our WM_QUERYNEWPALETTE or WM_PALETTECHANGED messages...
     }

  hOldBitmap = (HBITMAP)SelectObject (hMemDC, hBitmap);

  SetStretchBltMode (dc.m_hDC, COLORONCOLOR);

  BitBlt (dc.m_hDC,
             rc.left,
             rc.top,
             rc.right - rc.left,
             rc.bottom - rc.top,
             hMemDC,
             0,0,
             SRCCOPY);

  SelectObject (hMemDC, hOldBitmap);

  if (hOldPal1)
     SelectPalette (hMemDC, hOldPal1, FALSE);

  if (hOldPal2)
     SelectPalette (dc.m_hDC, hOldPal2, FALSE);

  DeleteDC (hMemDC);
  return TRUE;
}

CDIBitmap::CDIBitmap()

{
     hPal = NULL;
     hDIB = NULL;
     hBitmap = NULL;
     lpbi = NULL;
     wDIBBits = wDIBHeight = wDIBType = wDIBWidth = 0;
}

CDIBitmap::~CDIBitmap()
{
     if (hPal)
          DeleteObject(hPal);
     if (hBitmap)
          DeleteObject(hBitmap);
     if (hDIB)
          GlobalFree(hDIB);
}

CDIBitmap::CDIBitmap(HBITMAP hbm)

{
}

BOOL CDIBitmap::AssignDDP(HBITMAP hBmp)
{
     if (!hBmp)
          return NULL;

     ResetDIB();
     /* get the current palette */
     hPal = GetSystemPalette();
     BitmapToDIB(hBmp);
     hBitmap = DIBToBitmap();
return TRUE;
}

void CDIBitmap::ResetDIB()
{
     if (hPal)
          DeleteObject(hPal);
     if (hBitmap)
          DeleteObject(hBitmap);
     if (hDIB)
          GlobalFree(hDIB);
}

HPALETTE CDIBitmap::GetSystemPalette ()
{
  HDC           hDC;
  HPALETTE      hPal = NULL;
  HANDLE        hLogPal;
  LPLOGPALETTE  lpLogPal;
  int           i, nColors;


     // Find out how many palette entries we want.

  hDC = GetDC (NULL);
  if (!hDC)
     {
//      DIBError (ERR_GETDC);
     return NULL;
     }

     // Find out the number of palette entries on this
     //  defice.

  nColors = GetDeviceCaps (hDC, SIZEPALETTE);

     // For non-palette devices, we'll use the # of system
     //  colors for our palette size.

  if (!nColors)
     nColors = GetDeviceCaps (hDC, NUMCOLORS);

  ReleaseDC (NULL, hDC);

     // Allocate room for the palette and lock it.

  hLogPal = GlobalAlloc (GHND, sizeof (LOGPALETTE) +
                          nColors * sizeof (PALETTEENTRY));

  if (!hLogPal)
     {
//      DIBError (ERR_CREATEPAL);
     return NULL;
     }

  lpLogPal = (LPLOGPALETTE) GlobalLock (hLogPal);

  lpLogPal->palVersion    = PALVERSION;
  lpLogPal->palNumEntries = nColors;

  for (i = 0;  i < nColors;  i++)
     {
     lpLogPal->palPalEntry[i].peBlue  = 0;
     *((LPWORD) (&lpLogPal->palPalEntry[i].peRed)) = i;
     lpLogPal->palPalEntry[i].peFlags = PC_EXPLICIT;
     }

     // Go ahead and create the palette.  Once it's created,
     //  we no longer need the LOGPALETTE, so free it.

  hPal = CreatePalette (lpLogPal);

  GlobalUnlock (hLogPal);
  GlobalFree (hLogPal);

  return hPal;
}


void CGuiView::OnFileSaveAsImage()
{
      // configure dialog
      CFileDialog dlgFile( false );
      dlgFile.m_ofn.lpstrTitle  = "Save as an Image";

      // set directory
      CString strPath = GetDocument()->GetPathName();
      int start = strPath.ReverseFind('\\') + 1;
      CString strDir( strPath.Left(start) );
      dlgFile.m_ofn.lpstrInitialDir = strDir;

      // set type
      dlgFile.m_ofn.lpstrDefExt = "";
      dlgFile.m_ofn.lpstrFilter = "Bitmap File (*.bmp)\0*.bmp\0Tiff File (*.tif)\0*.tif\0Gif File (*.gif)\0*.gif\0Jpeg File(*.jpg)\0*.jpg\0\0";
      dlgFile.m_ofn.nFilterIndex = 1;

      // show dialog
      if ( dlgFile.DoModal() != IDOK )
            return;

      // get file name; if no extension then add one
      CString strFileName = dlgFile.GetPathName();
      if (strFileName.Find('.') < 0) { // no extension
            switch ( dlgFile.m_ofn.nFilterIndex ) {
            case 1:
                  strFileName += "bmp";
                  break;
            case 2:
                  strFileName += "tif";
                  break;
            case 3:
                  strFileName += "gif";
                  break;
            case 4:
                  strFileName += "jpg";
                  break;
            }      
      }

      BeginWaitCursor();
      
      CRect rect;
      GetClientRect(&rect);
      HBITMAP hBitmap = GetViewBitmap(GetParent(), rect.TopLeft().x, rect.TopLeft().y,
                                                                  rect.Width(), rect.Height());
      CFile file((LPCTSTR)strFileName, CFile::modeCreate|CFile::modeWrite);
      CDIBitmap DIBitmap;
      DIBitmap.AssignDDP(hBitmap);
      ASSERT(DIBitmap.Save(file));
      file.Close();

      EndWaitCursor();
}

//Here is class to handle DIBs in the MFC:
// header

#ifndef __DIBITMAP_H
#define __DIBITMAP_H

#include "stdafx.h"

class CDIBitmap
{
public:
   BOOL AssignDDP(HBITMAP);
   CDIBitmap(HBITMAP hbm);
   ~CDIBitmap();
   CDIBitmap();

   BOOL    Draw(CDC& dc, CRect& rc);
   BOOL      Save(CFile& File);
   BOOL      Load(CFile& File);
     void    RealizeDIBPalette(HDC hDC, LPBITMAPINFO lpbmi);
     WORD    DIBNumColors();
     WORD    PaletteSize();
     DWORD   DIBHeight() {return wDIBHeight;}
     DWORD   DIBWidth()  {return wDIBWidth;}

protected:
   void ResetDIB();
     HBITMAP DIBToBitmap();
     LPSTR    FindDIBBits();
     HPALETTE CreateDIBPalette();
     HANDLE   BitmapToDIB(HBITMAP hBitmap);
     HPALETTE GetSystemPalette ();
     void     InitBitmapInfoHeader (LPBITMAPINFOHEADER lpBmInfoHdr,
                                           DWORD dwWidth,
                                           DWORD dwHeight,
                                             int nBPP);
private:
   LPSTR lpbi;

  HANDLE      hDIB;                // Handle to the DIB
  HPALETTE    hPal;                // Handle to the bitmap's palette.
  HBITMAP     hBitmap;             // Handle to the DDB.

  WORD        wDIBType;            // DIB's type - RGB, RLE4, RLE8, PM
  WORD        wDIBBits;            // Bits per pixel
  WORD        wDIBWidth;           // Print width of the DIB
  WORD        wDIBHeight;          // Print height of the DIB
};


#endif //__DIBITMAP_H

//implementation

#include "stdafx.h"
//#include "cdibitmap.h"

#define WIDTHBYTES(bits)      (((bits) + 31) / 32 * 4)
#define IS_WIN30_DIB(lpbi)  ((*(LPDWORD) (lpbi)) == sizeof (BITMAPINFOHEADER))
#define PALVERSION   0x300
#define DIB_HEADER_MARKER   ((WORD) ('M' << 8) | 'B')

void CDIBitmap::RealizeDIBPalette(HDC, LPBITMAPINFO)
{
}

LPSTR CDIBitmap::FindDIBBits()

{
  return (lpbi + *(LPDWORD)lpbi + PaletteSize ());
}


HANDLE CDIBitmap::BitmapToDIB(HBITMAP hBmp)
{
  BITMAP             Bitmap;
  BITMAPINFOHEADER   bmInfoHdr;
  LPBITMAPINFOHEADER lpbmInfoHdr;
  LPSTR              lpBits;
  HDC                hMemDC;
  HPALETTE           hOldPal = NULL;

     // Do some setup -- make sure the Bitmap passed in is valid,
     //  get info on the bitmap (like its height, width, etc.),
     //  then setup a BITMAPINFOHEADER.

  if (!hBmp)
     return NULL;

  if (!GetObject (hBmp, sizeof (Bitmap), (LPSTR) &Bitmap))
     return NULL;

  InitBitmapInfoHeader (&bmInfoHdr,
                        Bitmap.bmWidth,
                        Bitmap.bmHeight,
                        4);


     // Now allocate memory for the DIB.  Then, set the BITMAPINFOHEADER
     //  into this memory, and find out where the bitmap bits go.
   lpbi = (LPSTR)&bmInfoHdr;

  hDIB = GlobalAlloc (GHND, sizeof (BITMAPINFOHEADER) + PaletteSize()+bmInfoHdr.biSizeImage);

  if (!hDIB)
     return NULL;

  lpbmInfoHdr  = (LPBITMAPINFOHEADER) GlobalLock (hDIB);
  *lpbmInfoHdr = bmInfoHdr;
  lpbi = (LPSTR)lpbmInfoHdr;
  lpBits  = (LPSTR)lpbmInfoHdr + lpbmInfoHdr->biSize + PaletteSize();


     // Now, we need a DC to hold our bitmap.  If the app passed us
     //  a palette, it should be selected into the DC.

  hMemDC       = GetDC (NULL);

  if (hPal)
     {
     hOldPal = SelectPalette (hMemDC, hPal, FALSE);
     RealizePalette (hMemDC);
     }



     // We're finally ready to get the DIB.  Call the driver and let
     //  it party on our bitmap.  It will fill in the color table,
     //  and bitmap bits of our global memory block.

  if (!GetDIBits (hMemDC,
                  hBmp,
                  0,
                  Bitmap.bmHeight,
                  lpBits,
                  (LPBITMAPINFO) lpbmInfoHdr,
                  DIB_RGB_COLORS))
     {
     GlobalUnlock (hDIB);
     GlobalFree (hDIB);
     hDIB = NULL;
     }
  else
     GlobalUnlock (hDIB);


     // Finally, clean up and return.

  if (hOldPal)
     SelectPalette (hMemDC, hOldPal, FALSE);

  ReleaseDC (NULL, hMemDC);

  return hDIB;
}

HPALETTE CDIBitmap::CreateDIBPalette()

{
  LPLOGPALETTE     lpPal;
  HANDLE           hLogPal;
  int              i, wNumColors;
  LPBITMAPINFO     lpbmi;
  LPBITMAPCOREINFO lpbmc;
  BOOL             bWinStyleDIB;

  if (!hDIB)
     return NULL;

  lpbi         = (LPSTR)GlobalLock (hDIB);
  lpbmi        = (LPBITMAPINFO) lpbi;
  lpbmc        = (LPBITMAPCOREINFO) lpbi;
  wNumColors   = DIBNumColors ();
  bWinStyleDIB = IS_WIN30_DIB (lpbi);

  if (wNumColors)
     {
     hLogPal = GlobalAlloc (GHND, sizeof (LOGPALETTE) +
                            sizeof (PALETTEENTRY) * wNumColors);

     if (!hLogPal)
        {
//         DIBError (ERR_CREATEPAL);
        GlobalUnlock (hDIB);
        return NULL;
        }

     lpPal = (LPLOGPALETTE) GlobalLock (hLogPal);

     lpPal->palVersion    = PALVERSION;
     lpPal->palNumEntries = wNumColors;

     for (i = 0;  i < wNumColors;  i++)
        {
        if (bWinStyleDIB)
           {
           lpPal->palPalEntry[i].peRed   = lpbmi->bmiColors[i].rgbRed;
           lpPal->palPalEntry[i].peGreen = lpbmi->bmiColors[i].rgbGreen;
           lpPal->palPalEntry[i].peBlue  = lpbmi->bmiColors[i].rgbBlue;
           lpPal->palPalEntry[i].peFlags = 0;
           }
        else
           {
           lpPal->palPalEntry[i].peRed   = lpbmc->bmciColors[i].rgbtRed;
           lpPal->palPalEntry[i].peGreen = lpbmc->bmciColors[i].rgbtGreen;
           lpPal->palPalEntry[i].peBlue  = lpbmc->bmciColors[i].rgbtBlue;
           lpPal->palPalEntry[i].peFlags = 0;
           }
        }

     hPal = CreatePalette (lpPal);

//      if (!hPal)
//         DIBError (ERR_CREATEPAL);

     GlobalUnlock (hLogPal);
     GlobalFree   (hLogPal);
  }

  GlobalUnlock (hDIB);

  return hPal;
}

void CDIBitmap::InitBitmapInfoHeader(LPBITMAPINFOHEADER lpBmInfoHdr, DWORD dwWidth, DWORD dwHeight,
int nBPP)

{


  memset (lpBmInfoHdr, 0, sizeof (BITMAPINFOHEADER));

  lpBmInfoHdr->biSize      = sizeof (BITMAPINFOHEADER);
  lpBmInfoHdr->biWidth     = dwWidth;
  lpBmInfoHdr->biHeight    = dwHeight;
  lpBmInfoHdr->biPlanes    = 1;

  if (nBPP <= 1)
     nBPP = 1;
  else if (nBPP <= 4)
     nBPP = 4;
  else if (nBPP <= 8)
     nBPP = 8;
  else
     nBPP = 24;

  lpBmInfoHdr->biBitCount  = nBPP;
     wDIBHeight = dwHeight;
     wDIBWidth = dwWidth;
     wDIBType =  BI_RGB;
     wDIBBits = nBPP;
     lpBmInfoHdr->biSizeImage = WIDTHBYTES (dwWidth * nBPP) * dwHeight;
}

WORD CDIBitmap::DIBNumColors()

{
  WORD wBitCount;


     // If this is a Windows style DIB, 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.

  if (IS_WIN30_DIB (lpbi))
     {
     DWORD dwClrUsed;

     dwClrUsed = ((LPBITMAPINFOHEADER) lpbi)->biClrUsed;

     if (dwClrUsed)
        return (WORD) dwClrUsed;
     }


     // Calculate the number of colors in the color table based on
     //  the number of bits per pixel for the DIB.

  if (IS_WIN30_DIB (lpbi))
     wBitCount = ((LPBITMAPINFOHEADER) lpbi)->biBitCount;
  else
     wBitCount = ((LPBITMAPCOREHEADER) lpbi)->bcBitCount;

  switch (wBitCount)
     {
     case 1:
        return 2;

     case 4:
        return 16;

     case 8:
        return 256;

     default:
        return 0;
     }
}

WORD CDIBitmap::PaletteSize()
{
  if (IS_WIN30_DIB (lpbi))
     return (DIBNumColors () * sizeof (RGBQUAD));
  else
     return (DIBNumColors () * sizeof (RGBTRIPLE));
}

BOOL CDIBitmap::Load(CFile& File)

{
     BITMAPFILEHEADER   bmfHeader;
     LPBITMAPINFOHEADER lpbih;
     DWORD              dwBitsSize;
     LPSTR              pDIB;


     // get length of DIB in bytes for use when reading

     // Go read the DIB file header and check if it's valid.

     if ((File.Read ((void*) &bmfHeader, sizeof (bmfHeader)) != sizeof (bmfHeader)) ||
         (bmfHeader.bfType != DIB_HEADER_MARKER))
       {
     //      DIBError (ERR_NOT_DIB);
       return NULL;
       }

     dwBitsSize = bmfHeader.bfSize;


     hDIB = GlobalAlloc (GMEM_MOVEABLE | GMEM_ZEROINIT, dwBitsSize - sizeof(BITMAPFILEHEADER));

     if (hDIB == 0)
      {
     //     DIBError (ERR_MEMORY);
      return NULL;
      }

     pDIB = (LPSTR)GlobalLock (hDIB);
     lpbih = (LPBITMAPINFOHEADER )pDIB;
     // Go read the bits.

     if (!File.Read(pDIB, dwBitsSize - sizeof(BITMAPFILEHEADER)))
       {
       GlobalUnlock (hDIB);
       GlobalFree   (hDIB);
     //      DIBError (ERR_READ);
       return NULL;
       }

     wDIBHeight = lpbih->biHeight;
     wDIBWidth = lpbih->biWidth;
     wDIBType =  BI_RGB;
     wDIBBits = lpbih->biBitCount*lpbih->biPlanes;

     GlobalUnlock (hDIB);
     hPal = CreateDIBPalette();
     hBitmap = DIBToBitmap();
     return TRUE;
}


BOOL CDIBitmap::Save(CFile& File)
{
   BITMAPFILEHEADER     hdr;
   LPBITMAPINFOHEADER  lpbih;

   if (!hDIB)
     return FALSE;

   lpbi = (LPSTR)GlobalLock (hDIB);
     lpbih = (LPBITMAPINFOHEADER)lpbi;
   /* Fill in the fields of the file header */
   hdr.bfType          = DIB_HEADER_MARKER;
   hdr.bfSize          = GlobalSize(hDIB) + sizeof (BITMAPFILEHEADER);
   hdr.bfReserved1 = 0;
   hdr.bfReserved2 = 0;
   hdr.bfOffBits   = (DWORD)sizeof(BITMAPFILEHEADER) + lpbih->biSize + PaletteSize();

   /* Write the file header */
   File.Write((LPSTR)&hdr, sizeof (BITMAPFILEHEADER));

   /* Write the DIB header and the bits */
   File.Write((LPSTR)lpbi, GlobalSize(hDIB));

   GlobalUnlock (hDIB);
   return TRUE;
}

HBITMAP CDIBitmap::DIBToBitmap()
{
 LPSTR    lpDIBHdr, lpDIBBits;
  HDC      hDC;
  HPALETTE hOldPal = NULL;

  if (!hDIB)
     return NULL;

  lpDIBHdr  = lpbi = (LPSTR) GlobalLock (hDIB);

  lpDIBBits = FindDIBBits ();
  hDC       = GetDC (NULL);

  if (!hDC)
     {
     GlobalUnlock (hDIB);
     return NULL;
     }

  if (hPal)
     hOldPal = SelectPalette (hDC, hPal, FALSE);

  RealizePalette (hDC);

  hBitmap = CreateDIBitmap (hDC,
                            (LPBITMAPINFOHEADER) lpDIBHdr,
                            CBM_INIT,
                            lpDIBBits,
                            (LPBITMAPINFO) lpDIBHdr,
                            DIB_RGB_COLORS);

//   if (!hBitmap)
//      DIBError (ERR_CREATEDDB);

  if (hOldPal)
     SelectPalette (hDC, hOldPal, FALSE);

  ReleaseDC (NULL, hDC);
  GlobalUnlock (hDIB);

  return hBitmap;
}


BOOL CDIBitmap::Draw(CDC&dc, CRect& rc)

{
  HDC      hMemDC;
  HBITMAP  hOldBitmap;
  HPALETTE hOldPal1 = NULL;
  HPALETTE hOldPal2 = NULL;


  hMemDC = CreateCompatibleDC (dc.m_hDC);

  if (!hMemDC)
     return FALSE;

  if (hPal)
     {
     hOldPal1   = SelectPalette (hMemDC, hPal, FALSE);
     hOldPal2   = SelectPalette (dc.m_hDC, hPal, FALSE);
     // Assume the palette's already been realized (no need to
     //  call RealizePalette().  It should have been realized in
     //  our WM_QUERYNEWPALETTE or WM_PALETTECHANGED messages...
     }

  hOldBitmap = (HBITMAP)SelectObject (hMemDC, hBitmap);

  SetStretchBltMode (dc.m_hDC, COLORONCOLOR);

  BitBlt (dc.m_hDC,
             rc.left,
             rc.top,
             rc.right - rc.left,
             rc.bottom - rc.top,
             hMemDC,
             0,0,
             SRCCOPY);

  SelectObject (hMemDC, hOldBitmap);

  if (hOldPal1)
     SelectPalette (hMemDC, hOldPal1, FALSE);

  if (hOldPal2)
     SelectPalette (dc.m_hDC, hOldPal2, FALSE);

  DeleteDC (hMemDC);
  return TRUE;
}

CDIBitmap::CDIBitmap()

{
     hPal = NULL;
     hDIB = NULL;
     hBitmap = NULL;
     lpbi = NULL;
     wDIBBits = wDIBHeight = wDIBType = wDIBWidth = 0;
}

CDIBitmap::~CDIBitmap()
{
     if (hPal)
          DeleteObject(hPal);
     if (hBitmap)
          DeleteObject(hBitmap);
     if (hDIB)
          GlobalFree(hDIB);
}

CDIBitmap::CDIBitmap(HBITMAP hbm)

{
}

BOOL CDIBitmap::AssignDDP(HBITMAP hBmp)
{
     if (!hBmp)
          return NULL;

     ResetDIB();
     /* get the current palette */
     hPal = GetSystemPalette();
     BitmapToDIB(hBmp);
     hBitmap = DIBToBitmap();
return TRUE;
}

void CDIBitmap::ResetDIB()
{
     if (hPal)
          DeleteObject(hPal);
     if (hBitmap)
          DeleteObject(hBitmap);
     if (hDIB)
          GlobalFree(hDIB);
}

HPALETTE CDIBitmap::GetSystemPalette ()
{
  HDC           hDC;
  HPALETTE      hPal = NULL;
  HANDLE        hLogPal;
  LPLOGPALETTE  lpLogPal;
  int           i, nColors;


     // Find out how many palette entries we want.

  hDC = GetDC (NULL);
  if (!hDC)
     {
//      DIBError (ERR_GETDC);
     return NULL;
     }

     // Find out the number of palette entries on this
     //  defice.

  nColors = GetDeviceCaps (hDC, SIZEPALETTE);

     // For non-palette devices, we'll use the # of system
     //  colors for our palette size.

  if (!nColors)
     nColors = GetDeviceCaps (hDC, NUMCOLORS);

  ReleaseDC (NULL, hDC);

     // Allocate room for the palette and lock it.

  hLogPal = GlobalAlloc (GHND, sizeof (LOGPALETTE) +
                          nColors * sizeof (PALETTEENTRY));

  if (!hLogPal)
     {
//      DIBError (ERR_CREATEPAL);
     return NULL;
     }

  lpLogPal = (LPLOGPALETTE) GlobalLock (hLogPal);

  lpLogPal->palVersion    = PALVERSION;
  lpLogPal->palNumEntries = nColors;

  for (i = 0;  i < nColors;  i++)
     {
     lpLogPal->palPalEntry[i].peBlue  = 0;
     *((LPWORD) (&lpLogPal->palPalEntry[i].peRed)) = i;
     lpLogPal->palPalEntry[i].peFlags = PC_EXPLICIT;
     }

     // Go ahead and create the palette.  Once it's created,
     //  we no longer need the LOGPALETTE, so free it.

  hPal = CreatePalette (lpLogPal);

  GlobalUnlock (hLogPal);
  GlobalFree (hLogPal);

  return hPal;
}

//get handle to bitmap from your device context of the view
HBITMAP GetViewBitmap(CWnd* pWnd, int x, int y, int w, int h)
{
      CDC* pDC;
      CDC tDC;
      HBITMAP Bitmap, oBitmap;

      pDC = pWnd->GetDC();
      tDC.CreateCompatibleDC(pDC);

      Bitmap = CreateCompatibleBitmap(pDC->m_hDC, w, h);
      oBitmap = (HBITMAP)SelectObject(tDC.m_hDC, Bitmap);
      tDC.BitBlt(0, 0, w, h, pDC, x, y, SRCCOPY);

      SelectObject(tDC.m_hDC, oBitmap);
      pWnd->ReleaseDC(pDC);

      return Bitmap;
}

//finally the function which uses all the above
void CSpectraAnalisysGuiView::OnFileSaveAsImage()
{
      // configure dialog
      CFileDialog dlgFile( false );
      dlgFile.m_ofn.lpstrTitle  = "Save Spectrum as an Image";

      // set directory
      CString strPath = GetDocument()->GetPathName();
      int start = strPath.ReverseFind('\\') + 1;
      CString strDir( strPath.Left(start) );
      dlgFile.m_ofn.lpstrInitialDir = strDir;

      // set type
      dlgFile.m_ofn.lpstrDefExt = "";
      dlgFile.m_ofn.lpstrFilter = "Bitmap File (*.bmp)\0*.bmp\0Tiff File (*.tif)\0*.tif\0Gif File (*.gif)\0*.gif\0Jpeg File(*.jpg)\0*.jpg\0\0";
      dlgFile.m_ofn.nFilterIndex = 1;

      // show dialog
      if ( dlgFile.DoModal() != IDOK )
            return;

      // get file name; if no extension then add one
      CString strFileName = dlgFile.GetPathName();
      if (strFileName.Find('.') < 0) { // no extension
            switch ( dlgFile.m_ofn.nFilterIndex ) {
            case 1:
                  strFileName += "bmp";
                  break;
            case 2:
                  strFileName += "tif";
                  break;
            case 3:
                  strFileName += "gif";
                  break;
            case 4:
                  strFileName += "jpg";
                  break;
            }      
      }

      BeginWaitCursor();
      
      CRect rect;
      GetClientRect(&rect);
      HBITMAP hBitmap = APP->GetViewBitmap(GetParent(), rect.TopLeft().x, rect.TopLeft().y,
                                                                  rect.Width(), rect.Height());
      CFile file((LPCTSTR)strFileName, CFile::modeCreate|CFile::modeWrite);
      CDIBitmap DIBitmap;
      DIBitmap.AssignDDP(hBitmap);
      ASSERT(DIBitmap.Save(file));
      file.Close();

      EndWaitCursor();
}

good luck


0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.