?
Solved

How to stitch two bitmaps together

Posted on 2007-10-12
1
Medium Priority
?
995 Views
Last Modified: 2013-12-14
Hello experts,
  I got a hard question here. I am programming with MFC in VS6. I have three different .bmp files. Based on the input of the user, I want to concatinate(or stitch) two together, or mabey all three, and display the newly constructed bitmap to the user. Any ideas how to do that?
0
Comment
Question by:v3203
1 Comment
 
LVL 23

Accepted Solution

by:
Roshan Davis earned 2000 total points
ID: 20076219
1. Load bitmaps into a memory DC
2. Combine the bitmaps using BitBlt function by giving different destination points based on image width/hieght
3. Save combined image to file

You can take reference of following functions to do that

   BOOL LoadBitmapFromBMPFile( LPTSTR szFileName, HBITMAP *phBitmap,
   HPALETTE *phPalette )
   {

   BITMAP  bm;

   *phBitmap = NULL;
   *phPalette = NULL;

   // Use LoadImage() to get the image loaded into a DIBSection
   *phBitmap = (HBITMAP)LoadImage( NULL, szFileName, IMAGE_BITMAP, 0, 0,
               LR_CREATEDIBSECTION | LR_DEFAULTSIZE | LR_LOADFROMFILE );
   if( *phBitmap == NULL )
     return FALSE;

   // Get the color depth of the DIBSection
   GetObject(*phBitmap, sizeof(BITMAP), &bm );
   // If the DIBSection is 256 color or less, it has a color table
   if( ( bm.bmBitsPixel * bm.bmPlanes ) <= 8 )
   {
   HDC           hMemDC;
   HBITMAP       hOldBitmap;
   RGBQUAD       rgb[256];
   LPLOGPALETTE  pLogPal;
   WORD          i;

   // Create a memory DC and select the DIBSection into it
   hMemDC = CreateCompatibleDC( NULL );
   hOldBitmap = (HBITMAP)SelectObject( hMemDC, *phBitmap );
   // Get the DIBSection's color table
   GetDIBColorTable( hMemDC, 0, 256, rgb );
   // Create a palette from the color tabl
   pLogPal = (LOGPALETTE *)malloc( sizeof(LOGPALETTE) + (256*sizeof(PALETTEENTRY)) );
   pLogPal->palVersion = 0x300;
   pLogPal->palNumEntries = 256;
   for(i=0;i<256;i++)
   {
     pLogPal->palPalEntry[i].peRed = rgb[i].rgbRed;
     pLogPal->palPalEntry[i].peGreen = rgb[i].rgbGreen;
     pLogPal->palPalEntry[i].peBlue = rgb[i].rgbBlue;
     pLogPal->palPalEntry[i].peFlags = 0;
   }
   *phPalette = CreatePalette( pLogPal );
   // Clean up
   free( pLogPal );
   SelectObject( hMemDC, hOldBitmap );
   DeleteDC( hMemDC );
   }
   else   // It has no color table, so use a halftone palette
   {
   HDC    hRefDC;

   hRefDC = GetDC( NULL );
   *phPalette = CreateHalftonePalette( hRefDC );
   ReleaseDC( NULL, hRefDC );
   }
   return TRUE;

   }


//or we can save the dc to diskfile formatted .bmp
int SaveBitmapToFile(HBITMAP hBitmap ,
                               LPSTR lpFileName) // hBitmap we got it above ,remember
{
      //lpFileName the filename
      HDC hDC;

      int iBits;
      //the bytes every pixle hold in the current resolution
      WORD wBitCount;
      WORD dwPaletteSize=0,
      dwBmBitsSize,
      dwDIBSize, dwWritten;
      BITMAP Bitmap;
      BITMAPFILEHEADER bmfHdr;

      BITMAPINFOHEADER bi;

      LPBITMAPINFOHEADER lpbi;

      HANDLE fh, hDib, hPal,hOldPal=NULL;

      hDC = CreateDC("DISPLAY",NULL,NULL,NULL);
      iBits = GetDeviceCaps(hDC, BITSPIXEL) *
      GetDeviceCaps(hDC, PLANES);
      DeleteDC(hDC);

      if (iBits < = 1) wBitCount = 1;
      else if (iBits < = 4) wBitCount = 4;
      else if (iBits < = 8) wBitCount = 8;
      else if (iBits < = 24) wBitCount = 24;
      if (wBitCount < = 8) dwPaletteSize = (1 < < wBitCount) * sizeof(RGBQUAD);

      GetObject(hBitmap, sizeof(BITMAP), (LPSTR)&Bitmap);
      bi.biSize = sizeof(BITMAPINFOHEADER);
      bi.biWidth = Bitmap.bmWidth;
      bi.biHeight = Bitmap.bmHeight;
      bi.biPlanes = 1;
      bi.biBitCount = wBitCount;
      bi.biCompression = BI_RGB;
      bi.biSizeImage = 0;
      bi.biXPelsPerMeter = 0;
      bi.biYPelsPerMeter = 0;
      bi.biClrUsed = 0;
      bi.biClrImportant = 0;

      dwBmBitsSize = ((Bitmap.bmWidth * wBitCount+31)/32)* 4 *Bitmap.bmHeight ;
      
      hDib = GlobalAlloc(GHND,dwBmBitsSize + dwPaletteSize+sizeof(BITMAPINFOHEADER));
      lpbi = (LPBITMAPINFOHEADER)GlobalLock(hDib);
      *lpbi = bi;

      // handle the palette
      hPal = GetStockObject(DEFAULT_PALETTE);

      if (hPal)
      {
            hDC = GetDC(NULL);
            hOldPal = SelectPalette(hDC, hPal, FALSE);
            RealizePalette(hDC);
      }

      GetDIBits(hDC,
                    hBitmap,
                    0,
                    (UINT) Bitmap.bmHeight,
                    (LPSTR)lpbi + sizeof(BITMAPINFOHEADER) + dwPaletteSize,
                    (BITMAPINFOHEADER *)lpbi, DIB_RGB_COLORS);
      
      if (hOldPal)
      {
            SelectPalette(hDC, hOldPal, TRUE);
            RealizePalette(hDC);
            ReleaseDC(NULL, hDC);
      }

      //create the bmp file
      fh = CreateFile(lpFileName,
                              GENERIC_WRITE,
                              0,
                              NULL,
                              CREATE_ALWAYS,
                              FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
                              NULL);

      
      if (fh == INVALID_HANDLE_VALUE) return FALSE;

      //set bmp fileheader
      bmfHdr.bfType = 0x4D42; // "BM"
      dwDIBSize = sizeof(BITMAPFILEHEADER) +
                        sizeof(BITMAPINFOHEADER) +
                        dwPaletteSize +
                        dwBmBitsSize;

      bmfHdr.bfSize = dwDIBSize;
      bmfHdr.bfReserved1 = 0;
      bmfHdr.bfReserved2 = 0;

      bmfHdr.bfOffBits = (DWORD)sizeof(BITMAPFILEHEADER) +
                                 (DWORD)sizeof(BITMAPINFOHEADER) +
                                 dwPaletteSize;

      // write the bmp header into file
      WriteFile(fh, (LPSTR)&bmfHdr, sizeof(BITMAPFILEHEADER), &dwWritten, NULL);

      // writhe content
      WriteFile(fh, (LPSTR)lpbi, dwDIBSize, &dwWritten, NULL);

      //clear
      GlobalUnlock(hDib);
      GlobalFree(hDib);
      CloseHandle(fh);
}

void CaptureScreen(LPCTSTR lpszFilePathName)
{
      BITMAPFILEHEADER      bmfHeader;
      BITMAPINFO                  *pbminfo;
      HBITMAP                        hBMP;
      CFile                        oFile;
      
      CDC            *pDC            = GetWindowDC();
      INT            nSizeImage      = 1024 * 768 * 3;
      CHAR      *pBuff            = new CHAR[sizeof(BITMAPINFOHEADER) + nSizeImage];
      pbminfo                        = (BITMAPINFO *)pBuff;
      hBMP                        = (HBITMAP)pDC->GetCurrentBitmap()->m_hObject;

      ZeroMemory(pbminfo, sizeof(BITMAPINFO));
      
      pbminfo->bmiHeader.biSize            = sizeof(BITMAPINFOHEADER);
      
      GetDIBits(pDC->m_hDC,
                    hBMP,
                    0,
                    1,
                    NULL,
                    pbminfo,
                    DIB_RGB_COLORS);

      GetDIBits(pDC->m_hDC,
                    hBMP,
                    0,
                    pbminfo->bmiHeader.biHeight,
                    pBuff + sizeof(BITMAPINFOHEADER),
                    pbminfo,
                    DIB_RGB_COLORS);
      
      ReleaseDC(pDC);

      bmfHeader.bfType            = 0x4d42; /*"BM"*/
      bmfHeader.bfSize            = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + nSizeImage;
      bmfHeader.bfReserved1      = 0;
      bmfHeader.bfReserved2      = 0;
      bmfHeader.bfOffBits            = (DWORD) sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);

      oFile.Open(lpszFilePathName, CFile::modeWrite | CFile::modeCreate);

      oFile.Write(&bmfHeader, sizeof(BITMAPFILEHEADER));
      oFile.Write(pBuff, sizeof(BITMAPINFOHEADER) + pbminfo->bmiHeader.biSizeImage);
      delete []pBuff;
      oFile.Close();
}
0

Featured Post

Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

Question has a verified solution.

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

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 …
Introduction: Dialogs (2) modeless dialog and a worker thread.  Handling data shared between threads.  Recursive functions. Continuing from the tenth article about sudoku.   Last article we worked with a modal dialog to help maintain informat…
The viewer will learn how to use and create keystrokes in Netbeans IDE 8.0 for Windows.
The viewer will learn how to synchronize PHP projects with a remote server in NetBeans IDE 8.0 for Windows.

616 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