CBitmap and CImage interchangeable? - c++

I'd like to know how something like this can be done
CBitmap bmp;
CImage img;
///
bmp=img;
//use bmp here
In my program I have to use CBitmap at some point but from the start I am only around with CImage.

Sort of CImage is GdiPlus and CBitmap is MFC. You can do something like this:
CBitmap bmp;
CImage img;
bmp = CBitmap::FromHandle(img.Detach());
Edit: Actually CBitmap has an attach so might be more efficient to do this:
bmp.Attach(img.Detach());

Related

How to create pattern brush using PNG image

I have image with black dots in a white background, which i use to create a patten brush and change the color of the black dots using SetTextColor. So I created a CBitmap using PNG image(i used CPngImage to get HBITMAP and attached it to CBitmap ). Now i created PatternBrush using(CreatePatternBrush) with that bitmap, the problem is that the color of the brush doesn't change if i use PNG image. But it changes when i use image in bmp format.
here is some code
CBitmap bmp;
if (bmp.LoadBitmap(IDB_BITMAP1))
{
if (brush.CreatePatternBrush(&bmp))
pOldBrush = pDC->SelectObject(&brush);
}
pDC->SetTextColor(color);
This Works
CBitmap bmp;
CPngImage pngImage;
HBITMAP hBitmap = NULL;
if ( pngImage.Load(MAKEINTRESOURCE(IDB_PNG1)) )
{
hBitmap = (HBITMAP)pngImage.Detach();
}
if ( hBitmap )
bmp.Attach(hBitmap);
if (brush.CreatePatternBrush(&bmp))
pOldBrush = pDC->SelectObject(&brush);
pDC->SetTextColor(color);
This Doesn't work

Screen capture only returns a black image

I'm trying to take a screen capture of the main dialog in my MFC application and save it as an image file. I tried about every example I could find online and always end up with the same result: the image file has the correct dimensions (I tried this with dialogs other than the main one just to be sure), but it is all black. My most recent solution is using the CBitmap class to transfer the main dialog handle to a CImage. Here is my code:
CWnd* mainWindow;
CDC* mainWindowDC;
CBitmap bitmapToSave;
CImage imageToSave;
CRect windowRect;
//Get main window context and create bitmap from it
mainWindow = AfxGetMainWnd();
mainWindowDC = mainWindow->GetWindowDC();
mainWindow->GetWindowRect(&windowRect);
bitmapToSave.CreateCompatibleBitmap(mainWindowDC, windowRect.Width(), windowRect.Height());
imageToSave.Attach(bitmapToSave);
imageToSave.Save("C:\\Capture\\image.bmp", Gdiplus::ImageFormatBMP);
Here is the way to do it:
HRESULT CaptureScreen(const CString& sImageFilePath)
{
CWnd* pMainWnd = AfxGetMainWnd();
CRect rc;
pMainWnd->GetWindowRect(rc);
CImage img;
img.Create(rc.Width(), rc.Height(), 24);
CDC memdc;
CDC* pDC = pMainWnd->GetWindowDC();
memdc.CreateCompatibleDC(pDC);
CBitmap* pOldBitmap = memdc.SelectObject(CBitmap::FromHandle((HBITMAP)img));
memdc.BitBlt(0, 0, rc.Width(), rc.Height(), pDC, 0, 0, SRCCOPY);
memdc.SelectObject(pOldBitmap);
return img.Save(sImageFilePath, Gdiplus::ImageFormatPNG);
}
Please also take a look at this nice implementation: http://www.codeguru.com/cpp/article.php/c18347/C-Programming-Easy-Screen-Capture-Using-MFCATL.htm
You created the bitmap, but you didn't put anything into it. You need to blit from one DC to another to make a copy of what's on the screen.
// ...
CMemDC dcMem;
dcMem.CreateCompatibleDC(&mainWindowDC);
CBitmap * pOld = dcMem.SelectObject(&bitmapToSave);
dcMem.BitBlt(0, 0, windowRect.Width(), windowRect.Height(), &mainWindowDC, windowRect.left, windowRect.top, SRCCOPY);
dcMem.SelectObject(pOld);
// ...

GDI+ GetHBITMAP memory error?

So I was trying to learn some GDI basics and my code breaks when I try to get the HBITMAP for a png image I want to display...
HBITMAP SplashScreen::LoadPng(WCHAR* path)
{
HBITMAP bmp;
fstream f;
f.open(path);
if(!f.good())
{
throw std::exception("Can't find/read file.");
}
f.close();
Gdiplus::Bitmap* img = Gdiplus::Bitmap::FromFile(path, FALSE);
Gdiplus::Color bg(0,0,0,0);
img->GetHBITMAP(bg, &bmp); // <--- Breaks here! Memory access exception!
return bmp;
}
The code is already so simple, I can't think of anything wrong with it, except maybe I just didn't set something up beforehand??
Thoughts?
Not sure what your problem is, though, I do note that you've got a memory leak.
img is never deleted - you should call delete img; after the call to GetHBITMAP
I use the following (less thorough code) in quick test projects.
// BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF
HBITMAP mLoadImg(WCHAR *szFilename)
{
HBITMAP result=NULL;
Gdiplus::Bitmap* bitmap = new Gdiplus::Bitmap(szFilename,false);
bitmap->GetHBITMAP(0, &result);
delete bitmap;
return result;
}
I didn't initialize GDI correctly. After fixing my init code, it works fine. That was annoying. Now I know.

Load a CBitmap dynamically

I have a Bitmap image that i want to load dynamically. But I am unable to load it.
CBitmap bmp;
bmp.LoadBitmap("c:\\aeimg");
it does not seem to be working.
Can someone please help me.
Thanks.
You can also try something like this:
CImage image;
image.Load(_T("C:\\image.png"));
CBitmap bitmap;
bitmap.Attach(image.Detach());
According to CBitmap documentation: LoadBitmap() function takes resource identifier of the bitmap or resource id of the bitmap.
You can't specify the path of the bitmap file.
E.g.
MyProject.rc
------------
MYBMP BITMAP "res\myimage.bmp"
and make sure that resource.h does not have any entry of MYBMP otherwise during preprocessing its replaced by id and ultimately LoadBitmap() will fail since application can't locate the resource as FindResource() fails.
Now do this :
CBitmap bmp;
bmp.LoadBitmap(L"MYBMP");
It will definitely load the bitmap.
To load a bitmap from a file, you want to use LoadImage with the LR_LOADFROMFILE flag.
CBitmap doesn't support directly reading from a .bmp file. You can instead make use of CImage class as suggested in other answers. You'll need to include atlimage.h in your code to make CImage work:
#include <atlimage.h>
:
CImage img;
img.Load (_T("C:\\image.bmp"));
CBitmap bitmap;
bitmap.Attach(img.Detach());
Another way is to load the image using LoadImage Win32 API and then attaching CBitmap to that:
HBITMAP hBitmap = (HBITMAP)LoadImage(NULL,"c:\\image.bmp",
IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
if (hBitmap != NULL)
bitmap.Attach(hBitmap);
CImage doesn't work with png last time I tried / checked. Have a look at CxImage - http://www.codeproject.com/KB/graphics/cximage.aspx .
It could be as simple as you forgetting to escape the backslash.
Instead of
bmp.LoadBitmap("c:\aeimg");
use
bmp.LoadBitmap("c:\\aeimg");
Otherwise you're passing an invalid path to the LoadBitmap method.
CString filename;
TCHAR szFilter[] = _T("Bitmap (*.bmp)|*.bmp|PNG (*.png)|*.png||");
CFileDialog selDlg(TRUE, NULL, NULL, OFN_OVERWRITEPROMPT | OFN_EXTENSIONDIFFERENT, szFilter, this);
if (selDlg.DoModal() == IDOK)
{
filename = selDlg.GetPathName();
CImage image;
HBITMAP hBitmap = (HBITMAP)LoadImage(NULL,filename, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
if (hBitmap)
{
// Delete the current bitmap
if (m_bmpBitmap.DeleteObject())
m_bmpBitmap.Detach(); // If there was a bitmap, detach it
// Attach the currently loaded bitmap to the bitmap object
m_bmpBitmap.Attach(hBitmap);
Invalidate();
}
}
When using the solutions mentioned to date, with a member variable of CBitmap I kept getting memory leaking every time I loaded the CImage onto the CBitmap. I solved this with the following code:
CString _fileName(/*Path to image*/);
CImage _image;
HRESULT hr = _image.Load(_fileName);
if (SUCCEEDED(hr)) {
if (m_Display.m_bmpImage.DeleteObject())
m_Display.m_bmpImage.Detach();
m_bmpImage.Attach(_image->Detach());
}

Bitmap manipulation in C++ on Windows

I have myself a handle to a bitmap, in C++, on Windows:
HBITMAP hBitmap;
On this image I want to do some Image Recognition, pattern analysis, that sort of thing. In my studies at University, I have done this in Matlab, it is quite easy to get at the individual pixels based on their position, but I have no idea how to do this in C++ under Windows - I haven't really been able to understand what I have read so far. I have seen some references to a nice looking Bitmap class that lets you setPixel() and getPixel() and that sort of thing, but I think this is with .net .
How should I go about turning my HBITMAP into something I can play with easily? I need to be able to get at the RGBA information. Are there libraries that allow me to work with the data without having to learn about DCs and BitBlt and that sort of thing?
You can use OpenCV library as a full image processing tool.
You can also use MFC's CImage or VCL's TBitmap just to extract pixel values from HBITMAP.
Gdiplus::Bitmap* pBitmap = Gdiplus::Bitmap::FromHBITMAP( hBitmap, NULL );
Gdiplus::Color pixel_color;
pBitmap->GetPixel( x, y, &pixel_color ); // read pixel at x,y into pixel_color
// ...
delete pBitmap; // do not forget to delete
Try this using GetPixel from GDI:
COLORREF GetBitmapBixel(HBITMAP hBitmap, int xPos, int yPos)
{
HDC hDC = GetDC(NULL);
HDC hMemDC = CreateCompatibleDC(hDC);
COLORREF pixelColor;
HBITMAP hOld = (HBITMAP)SelectObject(hMemDC, hBitmap);
pixelColor = ::GetPixel(hMemDC, xPos, yPos);
SelectObject(hMemDC, hOld);
DeleteDC(hMemDC);
ReleaseDC(NULL, hDC);
return pixelColor;
}
With:
DIBSECTION ds;
::GetObject(hbmp/*your HBITMAP*/, sizeof DIBSECTION, &ds);
you will get all you need (including pixel format and pixel buffer adress) in ds.dsBm.
see the doc