Conversion from MFC CImage to Opencv IPlImage - c++

I am having a camera application using opencv where I am using MFC GUI.I need to convert the CImage to IplImage for the Opencv modules for image processing and convert it back to CImage for displaying in the window again.
I researched in this topic but not enough examples and solutions.Anybody have some suggestions.Thanks
This is my code...
void CChildView::OnFileOpenimage(void)
{
// TODO: Add your command handler code here
CString strFilter;
CSimpleArray<GUID> aguidFileTypes;
HRESULT hResult;
hResult = imgOriginal.GetExporterFilterString(strFilter,aguidFileTypes);
if (FAILED(hResult)) {
CString fmt;
fmt.Format("GetExporterFilter failed:\n%x - %s", hResult, _com_error(hResult).ErrorMessage());
::AfxMessageBox(fmt);
return;
}
CFileDialog dlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, strFilter);
dlg.m_ofn.nFilterIndex = m_nFilterLoad;
hResult = (int)dlg.DoModal();
if(FAILED(hResult)) {
return;
}
m_nFilterLoad = dlg.m_ofn.nFilterIndex;
imgOriginal.Destroy();
CString pathval = dlg.GetPathName();
hResult = imgOriginal.Load(dlg.GetPathName());
if (FAILED(hResult)) {
CString fmt;
fmt.Format("Load image failed:\n%x - %s", hResult, _com_error(hResult).ErrorMessage());
::AfxMessageBox(fmt);
return;
}
// IplImage *img from imgOriginal; want to convert here for further processing.
m_nImageSize = SIZE_ORIGINAL;
Invalidate();
UpdateWindow();
}

Had this problem for quite a while myself. I found this code here which I ended up using that worked quite well. Instead of researching "CImage to IplImage" you should search "HBITMAP to IplImage"
IplImage* hBitmap2Ipl(HBITMAP hBmp, bool flip)
{
BITMAP bmp;
::GetObject(hBmp,sizeof(BITMAP),&bmp);
int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel/8;
int depth = bmp.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U;
IplImage *img=cvCreateImageHeader(cvSize(bmp.bmWidth, bmp.bmHeight), depth, nChannels);
img->imageData = (char*)malloc(bmp.bmHeight*bmp.bmWidth*nChannels*sizeof(char));
memcpy(img->imageData,(char*)(bmp.bmBits),bmp.bmHeight*bmp.bmWidth*nChannels);
return img;
}
Usage:
ATL::CImage image;
//whatever code you use to generate the image goes here
IplImage *convertedImage=hBitmap2Ipl(image.Detach());
image.Destroy();

I searched half the night for my copy-and-paste memory leak and finally found it!
So here is an updated code snippet of the original answer. The important thing for me was to use cvCreateImage instead of cvCreateImageHeader because I did use cvReleaseImage after the call to hBitmap2IplImage. Also flipping was neccessary in my case. Cheers!
IplImage* hBitmap2IplImage(HBITMAP hBmp, bool flip)
{
BITMAP bmp;
::GetObject(hBmp,sizeof(BITMAP),&bmp);
int nChannels = bmp.bmBitsPixel == 1 ? 1 : bmp.bmBitsPixel/8;
int depth = bmp.bmBitsPixel == 1 ? IPL_DEPTH_1U : IPL_DEPTH_8U;
IplImage *img=cvCreateImage(cvSize(bmp.bmWidth, bmp.bmHeight), depth, nChannels);
size_t imgSize = bmp.bmHeight*bmp.bmWidth*nChannels;
memcpy_s(img->imageData, imgSize, (char*)(bmp.bmBits), imgSize);
if (flip)
cvFlip(img, NULL, 0);
return img;
}
Usage:
ATL::CImage image;
HBITMAP hBitmap = image.Detach(); // some handle to your bitmap
bool flip = true;
IplImage* pSomeIplImage = hBitmap2IplImage(hBitmap, flip);
image.Destroy();
//
// use "pSomeIplImage"
//
cvReleaseImage( &pSomeIplImage ); // don't forget

If a bitmap image is on a view you can use the device context(CDC dcBuffer ) to copy it.
IplImage *pCapture = cvCreateImage(cvSize(U16_IMAGE_WIDTH/2,U16_IMAGE_HEIGHT/2),8, 3);
::GetDIBits(dcBuffer.GetSafeHdc(), bitmapBuffer, 0, U16_IMAGE_HEIGHT/2, pCapture->imageData, &bitmapInfo, DIB_RGB_COLORS);
cvSaveImage("temp.bmp", pCapture);
cvReleaseImage(&pCapture);

Related

how to convert CBitmap to cv::Mat?

How to convert CBitmap to cv::Mat? Maybe there are some libs or something else...
like...
CBitmap bitmap;
bitmap.CreateBitmap(128, 128, 1, 24, someData);
cv::Mat outBitmap(128,128,someData,1,24);
but that code is incorrect.
thanks!
There is another way around, you can convert your CBitmap to HBitmap, then convert HBitmap to GdiPlus::Bitmap, then convert it to cv::Mat.
Here's what you can do, but beware, this solution only works for RGB24 pixel format :
Step 1: CBitmap to HBITMAP
HBITMAP hBmp = (HBITMAP)yourCBitmap.GetSafeHandle();
Step 2: HBITMAP to Gdiplus::Bitmap (copied from this question)
#include <GdiPlus.h>
#include <memory>
Gdiplus::Status HBitmapToBitmap( HBITMAP source, Gdiplus::PixelFormat pixel_format, Gdiplus::Bitmap** result_out )
{
BITMAP source_info = { 0 };
if( !::GetObject( source, sizeof( source_info ), &source_info ) )
return Gdiplus::GenericError;
Gdiplus::Status s;
std::auto_ptr< Gdiplus::Bitmap > target( new Gdiplus::Bitmap( source_info.bmWidth, source_info.bmHeight, pixel_format ) );
if( !target.get() )
return Gdiplus::OutOfMemory;
if( ( s = target->GetLastStatus() ) != Gdiplus::Ok )
return s;
Gdiplus::BitmapData target_info;
Gdiplus::Rect rect( 0, 0, source_info.bmWidth, source_info.bmHeight );
s = target->LockBits( &rect, Gdiplus::ImageLockModeWrite, pixel_format, &target_info );
if( s != Gdiplus::Ok )
return s;
if( target_info.Stride != source_info.bmWidthBytes )
return Gdiplus::InvalidParameter; // pixel_format is wrong!
CopyMemory( target_info.Scan0, source_info.bmBits, source_info.bmWidthBytes * source_info.bmHeight );
s = target->UnlockBits( &target_info );
if( s != Gdiplus::Ok )
return s;
*result_out = target.release();
return Gdiplus::Ok;
}
Call this function and pass your HBITMAP to it.
Step 3: Gdiplus::Bitmap to cv::Mat
cv::Mat GdiPlusBitmapToCvMat(Gdiplus::Bitmap* bmp)
{
auto format = bmp->GetPixelFormat();
if (format != PixelFormat24bppRGB)
return cv::Mat();
int width = bmp->GetWidth();
int height = bmp->GetHeight();
Gdiplus::Rect rcLock(0, 0, width, height);
Gdiplus::BitmapData bmpData;
if (!bmp->LockBits(&rcLock, Gdiplus::ImageLockModeRead, format, &bmpData) == Gdiplus::Ok)
return cv::Mat();
cv::Mat mat = cv::Mat(height, width, CV_8UC3, static_cast<unsigned char*>(bmpData.Scan0), bmpData.Stride).clone();
bmp->UnlockBits(&bmpData);
return mat;
}
Pass the Gdiplus::Bitmap that you created in last step to this function and you will get your cv:Mat. As I said before this function just works with RGB24 pixel format.

C++ GDI+ memory leak in own class

I am searching for the memory leak(s) in this code.
I am new to GDI+ and I am not sure what I am doing wrong.
The class you see below gets called in a loop in my main function.
Each loop iteration I push an other vector to the function.
Everything is working fine except there is a memory leak.
I tried the program cppCheck to find the leak but it found no memory leaks :/
My last chance to fix the problem is to ask someone who has more experience than me with GDI+
Thank you very much for the help and sorry for the long code :)
#include "helper.h"
Gui::Gui(const TCHAR* fileName) {
this->fileName = fileName;
}
void Gui::drawGui(Gdiplus::Bitmap* image, std::vector<std::wstring> &vec) {
// Init graphics
Gdiplus::Graphics* graphics = Gdiplus::Graphics::FromImage(image);
Gdiplus::Pen penWhite (Gdiplus::Color::White);
Gdiplus::Pen penRed (Gdiplus::Color::Red);
Gdiplus::SolidBrush redBrush(Gdiplus::Color(255, 255, 0, 0));
penRed.SetWidth(8);
unsigned short marginTop = 15;
unsigned short marginLeft = 5;
unsigned short horizontalBarsizeStart = marginLeft + 60;
for (unsigned short iter = 0; iter < 8; iter++) {
// Draw text
std::wstring coreLabel = L"Core " + std::to_wstring(iter) + L':';
Gdiplus::Font myFont(L"Arial", 12);
Gdiplus::PointF origin(marginLeft, marginTop - 10);
graphics->DrawString(coreLabel.c_str(), coreLabel.length(), &myFont, origin, &redBrush);
// Draw CPU lines
unsigned short horizontalBarsizeEnd = horizontalBarsizeStart + std::stoi(vec.at(iter)); // 100 == Max cpu load
graphics->DrawLine(&penRed, horizontalBarsizeStart, marginTop, horizontalBarsizeEnd, marginTop);
// Draw border
Gdiplus::Rect rect(horizontalBarsizeStart, marginTop - 5, 100, 8);
graphics->DrawRectangle(&penWhite, rect);
// Next element
marginTop += 17;
}
}
bool Gui::SetColorBackgroundFromFile(std::vector<std::wstring> &vec) {
Gdiplus::GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
// Initialize GDI+.
Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
HDC hdc = GetDC(NULL);
// Load the image. Any of the following formats are supported: BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF
Gdiplus::Bitmap* image = Gdiplus::Bitmap::FromFile(this->fileName, false);
if (image == NULL) {
return false;
}
// Draw the gui
this->drawGui(image, vec);
// Get the bitmap handle
HBITMAP hBitmap = NULL;
Gdiplus::Status status = image->GetHBITMAP(RGB(0, 0, 0), &hBitmap);
if (status != Gdiplus::Ok) {
return false;
}
BITMAPINFO bitmapInfo = { 0 };
bitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
// Check what we got
int ret = GetDIBits(hdc, hBitmap, 0, 0, NULL, &bitmapInfo, DIB_RGB_COLORS);
if (LOGI_LCD_COLOR_WIDTH != bitmapInfo.bmiHeader.biWidth || LOGI_LCD_COLOR_HEIGHT != bitmapInfo.bmiHeader.biHeight) {
std::cout << "Oooops. Make sure to use a 320 by 240 image for color background." << std::endl;
return false;
}
bitmapInfo.bmiHeader.biCompression = BI_RGB;
bitmapInfo.bmiHeader.biHeight = -bitmapInfo.bmiHeader.biHeight; // this value needs to be inverted, or else image will show up upside/down
BYTE byteBitmap[LOGI_LCD_COLOR_WIDTH * LOGI_LCD_COLOR_HEIGHT * 4]; // we have 32 bits per pixel, or 4 bytes
// Gets the "bits" from the bitmap and copies them into a buffer
// which is pointed to by byteBitmap.
ret = GetDIBits(hdc, hBitmap, 0,
-bitmapInfo.bmiHeader.biHeight, // height here needs to be positive. Since we made it negative previously, let's reverse it again.
&byteBitmap,
(BITMAPINFO *)&bitmapInfo, DIB_RGB_COLORS);
LogiLcdColorSetBackground(byteBitmap); // Send image to LCD
// delete the image when done
if (image) {
delete image;
image = NULL;
Gdiplus::GdiplusShutdown(gdiplusToken); // Shutdown GDI+
}
return true;
}
In drawGui() you're leaking the graphics object. This line creates a new Gdiplus::Graphics object:
Gdiplus::Graphics* graphics = Gdiplus::Graphics::FromImage(image);
But nowhere do you call delete graphics to delete it once you're done with it.
In SetColorBackgroundFromFile, you're leaking the DC.
HDC hdc = GetDC(NULL);
This gets a DC for the screen, but nowhere do you call ReleaseDC(NULL, hdc); to free it.
In the same function, you are creating an HBITMAP using the following call:
Gdiplus::Status status = image->GetHBITMAP(RGB(0, 0, 0), &hBitmap);
But nowhere do you call DeleteObject(hBitmap); to free it.
You also have the problem that in case of errors, your code can return without doing necessary cleanup. E.g. if the GetHBITMAP call fails, you return immediately and will leak the image object that you created a few lines above.

How to convert cv::Mat to MFC CBitmap

how can I convert an OpenCV image to an Microsoft Foundation Classes (MFC) CBitmap object?
I tried the following, which failed,
cv::Mat tmp;
(Load opencv image ...)
cv::Size size = tmp.size();
CBitmap bitmap;
// 3 colors (RGB), 24bits (8bits*3channels)
if (!bitmap.CreateBitmap(128, 128, 1, 24, (void *)tmp.data)) {
TRACE0("Failed to create bitmap for image display\n");
return;
}
this results in a black image..
This post shares the method of converting an IplImage to CBitmap:
CBitmap* IplImageToCBitmap(IplImage* img)
{
CDC dc;
CDC memDC;
if (!dc.CreateDC("DISPLAY", NULL, NULL, NULL))
return NULL;
if (!memDC.CreateCompatibleDC(&dc))
return NULL;
CBitmap* bmp = new CBitmap();
CBitmap* pOldBitmap;
bmp->CreateCompatibleBitmap(&dc, img->width, img->height);
pOldBitmap = memDC.SelectObject(bmp);
CvvImage cvImage; // you will need OpenCV_2.2.0- to use CvvImage
cvImage.CopyOf(img);
cvImage.Show(memDC.m_hDC, 0, 0, img->width, img->height, 0, 0);
cvImage.Destroy();
memDC.SelectObject(pOldBitmap);
memDC.DeleteDC();
dc.DeleteDC();
return bmp;
}
Based on this, you can achieve your goal by calling it as follows:
cv::Mat aMat;
CBitmap *aCBitmap = IplImageToCBitmap((IplImage*) &aMat);

OpenCV 2.4 : Displaying a cv::Mat in MFC

I am updating an existing code base from IplImage* to the newer cv::Mat. I was wondering how to display my cv::Mat object to MFC. The current solution we are using is based on the old CvvImage class:
void DrawPicToHDC(IplImage *img, UINT ID, bool bOnPaint)
{
CDC *pDC = GetDlgItem(ID)->GetDC();
HDC hDC= pDC->GetSafeHdc();
CRect rect;
GetDlgItem(ID)->GetClientRect(&rect);
CvvImage cimg;
cimg.CopyOf( img );
cimg.DrawToHDC( hDC, &rect );
ReleaseDC( pDC );
}
I came across this thread but unfortunately the answer provided doesn't meet my needs because the answers still require you to convert the Mat to an IplImage* before displaying.
Is there any way to do this using cv::Mat only? Any help is much appreciated.
UPDATE:
I adapted the above function to using cv::Mat with the help from Kornel's answer. I now do not need to include the CvvImage class:
void DrawPicToHDC(cv::Mat cvImg, UINT ID, bool bOnPaint)
{
// Get the HDC handle information from the ID passed
CDC *pDC = GetDlgItem(ID)->GetDC();
HDC hDCDst = pDC->GetSafeHdc();
CRect rect;
GetDlgItem(ID)->GetClientRect(&rect);
cv::Size winSize(rect.right, rect.bottom);
// Resize the source to the size of the destination image if necessary
cv::Mat cvImgTmp(winSize, CV_8UC3);
if (cvImg.size() != winSize)
{
cv::resize(cvImg, cvImgTmp, winSize);
}
else
{
cvImgTmp = cvImg;
}
// Rotate the image
cv::flip(cvImgTmp,cvImgTmp,0);
// Initialize the BITMAPINFO structure
BITMAPINFO bitInfo;
bitInfo.bmiHeader.biBitCount = 24;
bitInfo.bmiHeader.biWidth = winSize.width;
bitInfo.bmiHeader.biHeight = winSize.height;
bitInfo.bmiHeader.biPlanes = 1;
bitInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitInfo.bmiHeader.biCompression = BI_RGB;
bitInfo.bmiHeader.biClrImportant = 0;
bitInfo.bmiHeader.biClrUsed = 0;
bitInfo.bmiHeader.biSizeImage = 0;
bitInfo.bmiHeader.biXPelsPerMeter = 0;
bitInfo.bmiHeader.biYPelsPerMeter = 0;
// Add header and OPENCV image's data to the HDC
StretchDIBits(hDCDst, 0, 0,
winSize.width, winSize.height, 0, 0,
winSize.width, winSize.height,
cvImgTmp.data, &bitInfo, DIB_RGB_COLORS, SRCCOPY);
ReleaseDC( pDC );
}
Suppose we have an OpenCV image cv::Mat cvImg which one should be converted to CImage* mfcImg.
Of course the MFC image should be displayed on an MFC window i.e. in CStatic winImg
So the following transformations should be performed in order to display an OpenCV image in an MFC window:
cv::Mat -> CImage -> CStatic
Define MFC window size:
RECT r;
winImg.GetClientRect(&r);
cv::Size winSize(r.right, r.bottom);
The size of cvImg is not always the same as an MFC window’s:
cv::Mat cvImgTmp(winSize, CV_8UC3);
if (cvImg.size() != winSize)
{
cv::resize(cvImg, cvImgTmp, winSize);
}
else
{
cvImgTmp = cvImg.clone();
}
Rotate the image:
cv::flip(cvImgTmp, cvImgTmp, 0);
Create an MFC image:
if (mfcImg)
{
mfcImg->ReleaseDC();
delete mfcImg; mfcImg = nullptr;
}
mfcImg = new CImage();
mfcImg->Create(winSize.width, winSize.height, 24);
For mfcImg you need a header. Create it by using BITMAPINFO structure
BITMAPINFO bitInfo;
bitInfo.bmiHeader.biBitCount = 24;
bitInfo.bmiHeader.biWidth = winSize.width;
bitInfo.bmiHeader.biHeight = winSize.height;
bitInfo.bmiHeader.biPlanes = 1;
bitInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitInfo.bmiHeader.biCompression = BI_RGB;
bitInfo.bmiHeader.biClrImportant = 0;
bitInfo.bmiHeader.biClrUsed = 0;
bitInfo.bmiHeader.biSizeImage = 0;
bitInfo.bmiHeader.biXPelsPerMeter = 0;
bitInfo.bmiHeader.biYPelsPerMeter = 0;
Add header and OpenCV image’s data to mfcImg
StretchDIBits(mfcImg->GetDC(), 0, 0,
winSize.width, winSize.height, 0, 0,
winSize.width, winSize.height,
cvImgTmp.data, &bitInfo, DIB_RGB_COLORS, SRCCOPY
);
Display mfcImg in MFC window
mfcImg->BitBlt(::GetDC(winImg.m_hWnd), 0, 0);
Release mfcImg, if you will not use it:
if (mfcImg)
{
mfcImg->ReleaseDC();
delete mfcImg; mfcImg = nullptr;
}

Merging two Gdiplus::Bitmap into one c++

I have two bitmaps:
Gdiplus::Bitmap *pbmBitmap, pbmBitmap1;
They contains two images. How i can merge them into one image?
I was trying something like that:
Bitmap* dstBitmap = new Bitmap(pbmBitmap->GetWidth(), pbmBitmap->GetHeight() + pbmBitmap1->GetHeight()); //create dst bitmap
HDC dcmem = CreateCompatibleDC(NULL);
SelectObject(dcmem, pbmBitmap); //select first bitmap
HDC dcmemDst = CreateCompatibleDC(NULL);
SelectObject(dcmem1, dstBitmap ); //select destination bitmap
BitBlt(dcmemDst em1, 0, 0, pbmBitmap->GetWidth(), pbmBitmap->GetHeight(), dcmem, 0, 0, SRCCOPY); //copy first bitmap into destination bitmap
HBITMAP CreatedBitmap = CreateCompatibleBitmap(dcmem, pbmBitmap->GetWidth(), pbmBitmap->GetHeight() + pbmBitmap1->GetHeight());
dstBitmap = new Bitmap(CreatedBitmap, NULL);
dstBitmap ->Save(L"omg.bmp", &pngClsid, 0); //pngClsid i took from msdn
I know - ugly code, but i need to do it in C++.
I'm getting black image. Why?
//EDIT
After two hours googling and reading i got this:
HBITMAP bitmapSource;
pbmBitmap->GetHBITMAP(Color::White, &bitmapSource); //create HBITMAP from Gdiplus::Bitmap
HDC dcDestination = CreateCompatibleDC(NULL); //create device contex for our destination bitmap
HBITMAP HBitmapDestination = CreateCompatibleBitmap(dcDestination, pbmBitmap->GetWidth(), pbmBitmap->GetHeight()); //create HBITMAP with correct size
SelectObject(dcDestination, dcDestination); //select created hbitmap on our destination dc
HDC dcSource = CreateCompatibleDC(NULL); //create device contex for our source bitmap
SelectObject(dcSource, bitmapSource); //select source bitmap on our source dc
BitBlt(dcDestination, 0, 0, pbmBitmap->GetWidth(), pbmBitmap->GetHeight(), dcSource, 0, 0, SRCCOPY); //copy piece of bitmap with correct size
SaveBitmap(dcDestination, HBitmapDestination, "OMG.bmp"); //not working i get 24kb bitmap
//SaveBitmap(dcSource, bitmapSource, "OMG.bmp"); //works like a boss, so it's problem with SaveBitmap function
It should work, but i get 24kb bitmap.
SaveBitmap is my custom function, it works when i try save source bitmap.
Why i can't copy one bitmap to another??
Use a Graphics object to combine them. Here's some sample working code... Of course, you should use smart ptrs like unique_ptr<> instead of new/delete but I did not want to assume you're using VS 2012 or newer.
void CombineImages()
{
Status rc;
CLSID pngClsid;
GetEncoderClsid(L"image/png", &pngClsid);
Bitmap* bmpSrc1 = Bitmap::FromFile(L"Image1.JPG");
assert(bmpSrc1->GetLastStatus() == Ok);
Bitmap* bmpSrc2 = Bitmap::FromFile(L"Image2.JPG");
assert(bmpSrc2->GetLastStatus() == Ok);
Bitmap dstBitmap(bmpSrc1->GetWidth(), bmpSrc1->GetHeight() + bmpSrc2->GetHeight());
assert(dstBitmap.GetLastStatus() == Ok);
Graphics* g = Graphics::FromImage(&dstBitmap);
rc = g->DrawImage(bmpSrc1, 0, 0 );
assert(rc == Ok);
rc = g->DrawImage(bmpSrc2, 0, bmpSrc1->GetHeight());
assert(rc == Ok);
rc = dstBitmap.Save(L"Output.png", &pngClsid, NULL);
assert(rc == Ok);
delete g;
delete bmpSrc1;
delete bmpSrc2;
}
main fn..
int _tmain(int argc, _TCHAR* argv[])
{
ULONG_PTR token;
GdiplusStartupInput input;
GdiplusStartup(&token, &input, nullptr);
CombineImages();
GdiplusShutdown(token);
return 0;
}
Here is my own function that receives a vector of image files and merge them vercially.
wstring CombineBitmaps(vector files)
{
wstring NewFile{ L"Output.png" };
Gdiplus::Status rc;
CLSID pngClsid;
GetEncoderClsid(L"image/png", &pngClsid);
vector< Gdiplus::Bitmap*> bmpSrc;
int Height{ 0 };
for (int i = 0; i < files.size(); i++)
{
bmpSrc.push_back (Gdiplus::Bitmap::FromFile(files[i].c_str()));
Height += bmpSrc[0]->GetHeight();
}
Gdiplus::Bitmap dstBitmap(bmpSrc[0]->GetWidth(), Height);
Gdiplus::Graphics* g = Gdiplus::Graphics::FromImage(&dstBitmap);
for (int i = 0; i < files.size(); i++)
{
rc = g->DrawImage(bmpSrc[i], 0, i*bmpSrc[i]->GetHeight());
}
rc = dstBitmap.Save(NewFile.c_str(), &pngClsid, NULL);
delete g;
return NewFile;
}
You would call it as shown below:
vector<wstring> screens;
screens.push_back(L"screenshot1");
screens.push_back(L"screenshot2");
screens.push_back(L"screenshot3");
screens.push_back(L"screenshot4");
screens.push_back(L"screenshot5");
CombineBitmaps(screens);