Solved

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

Posted on 2001-08-07
3
555 Views
Last Modified: 2013-11-20
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...
0
Comment
Question by:Esmond071901
  • 2
3 Comments
 
LVL 6

Accepted Solution

by:
MichaelS earned 100 total points
Comment Utility
0
 
LVL 6

Expert Comment

by:MichaelS
Comment Utility
0
 
LVL 42

Expert Comment

by:sedgwick
Comment Utility
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

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Expand LInux Boot partition remotly 3 78
bigDiff challenge 17 74
mapBully challenge 6 88
Thin secure Windows 10 5 46
Introduction: Dynamic window placements and drawing on a form, simple usage of windows registry as a storage place for information. Continuing from the first article about sudoku.  There we have designed the application and put a lot of user int…
Introduction: Dialogs (1) modal - maintaining the database. Continuing from the ninth article about sudoku.   You might have heard of modal and modeless dialogs.  Here with this Sudoku application will we use one of each type: a modal dialog …
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now