Solved

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

Posted on 2001-08-07
3
583 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
ID: 6358805
0
 
LVL 6

Expert Comment

by:MichaelS
ID: 6358811
0
 
LVL 42

Expert Comment

by:sedgwick
ID: 6358828
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

Is Your AD Toolbox Looking More Like a Toybox?

Managing Active Directory can get complicated.  Often, the native tools for managing AD are just not up to the task.  The largest Active Directory installations in the world have relied on one tool to manage their day-to-day administration tasks: Hyena. Start your trial today.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
not able to insert into temp table 68 162
VBA "SendKeys" Syntax for Multiple Keystrokes 7 108
Modbus - whats the maximum I can store in one register? 4 80
changeXy challenge 13 82
Introduction: Ownerdraw of the grid button.  A singleton class implentation and usage. Continuing from the fifth article about sudoku.   Open the project in visual studio. Go to the class view – CGridButton should be visible as a class.  R…
Introduction: Database storage, where is the exe actually on the disc? Playing a game selected randomly (how to generate random numbers).  Error trapping with try..catch to help the code run even if something goes wrong. Continuing from the seve…
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.
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…

810 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