How to save MFC CImage in .WMF file? - c++

How to save MFC CImage in a .WMF file? If I use CImage.Save method to save it in .WMF format I am getting the error "save failed:80004005 - Unspecified error".
Is there any other way to save MFC CImage in .WMF format?
Thanks in advance.

The CImage does not support vector graphics like Enhanced Metafile Format (EMF) and Windows Metafile Format (WMF) by design. It is just a wrapper class around Image class from GDI+ that does support raster image formats only: JPEG, GIF, BMP, and Portable Network Graphics (PNG) formats.
Here is the way to save EMF/WMF files based on GDI+:
Bitmap* pBitmap;
...
// do some paintings on pBitmap
...
CStringW sFileName = L"c:\\Files\Image.emf";
CDC* pDC = GetDC();
Metafile* pMetaFile = new Metafile(sFileName, pDC->m_hDC);
Graphics graphics(pMetaFile);
graphics.DrawImage(pBitmap, 0, 0, pBitmap->GetWidth(),
pBitmap->GetHeight());

Related

Transfer image from CDC to Windows Imaging Component (WIC)?

I have some old C++/MFC code which uses GDI to create an image in a device context (CDC), using functions like Rectangle. The image is then painted to the screen, by the destructor of CPaintDC. Everything works as expected.
Now I want to store the image in a PNG file. For this, I am using Windows Imaging Component (WIC). I can create an image in WIC by creating a bitmap frame, storing pixels in a buffer, and copying the pixels into it using WritePixels. Then WIC stores the image as a PNG file via Commit. All this also works.
The question is, how can I transfer the image I created using GDI, which is in a CDC, to something WIC recognizes? I'm looking for something more efficient than a CDC::GetPixel loop storing into a buffer followed by WritePixels.
Windows 7, Visual Studio 2015, C++.
Update: I'm trying to get the CImage method suggested by #Andrew Komiagin. My code is
CDC memdc;
memdc.CreateCompatibleDC(nullptr);
myControl.RenderToDC(memdc); // this draws the image onto the dc
CBitmap bmp;
BOOL ok=bmp.CreateCompatibleBitmap(&memdc, w, h); // w=h=292 defined elsewhere
CBitmap *pOldBitmap=memdc.SelectObject(&bmp);
ok=memdc.BitBlt(0, 0, w, h, &memdc, 0, 0, SRCCOPY);
CImage tempImageObj;
tempImageObj.Attach((HBITMAP)bmp.Detach());
CString outputFilename("outputImage.png");
HRESULT hr=tempImageObj.Save(outputFilename);
This produces a PNG image file with an all-black square, w x h pixels, rather than the image I drew. I know the image is being drawn correctly by RenderToDC (see below).
For comparison, this is in MyControl::OnPaint for the control (derived from CStatic):
CPaintDC dc(this); // device context for painting
RenderToDC(dc); // this draws the image onto the dc
// Painted to screen by CPaintDC's destructor
The image appears correctly.
I'd suggest using standard CImage class from ATL/MFC that works just great with GDI device context and natively supports the ability to load and save images in JPEG, GIF, BMP, and Portable Network Graphics (PNG) formats.
Here is an example on how to use it:
CDC MemDC;
MemDC.CreateCompatibleDC(&dc);
CBitmap Bmp;
Bmp.CreateCompatibleBitmap(&dc,ClientRect.Width(),ClientRect.Height());
MemDC.SelectObject(&Bmp);
MemDC.BitBlt(0,0,ClientRect.Width(),ClientRect.Height(),&dc,0,0,SRCCOPY);
CImage TempImageObj;
TempImageObj.Attach((HBITMAP)Bmp.Detach());
TempImageObj.Save(sFilePath);

LoadImage() with QRCode bitmap failing unless file is opened/saved with MS Paint first

I am trying to read a bmp file using below function in c++
HANDLE hBmp = LoadImage(0, L"C:\\Users\\abhinay\\Desktop\\Sample.bmp", IMAGE_BITMAP, 0, 0, LR_CREATEDIBSECTION | LR_LOADFROMFILE);
In my scenario the sample.bmp is a QRCode which is generated by a 3rd part QRCode library. When i try to read QRCode generated with above "LoadImage" function i get hBmp as "NULL".
I opened QRCode image "sample.bmp" with MS paint and saved it as .bmp in 24-bit Bitmap and now i am able to load the file using the same "LoadImage" function above.
Can you please help why the bmp file was not loaded in the first case and how can i make the the generated QRCode image to be loaded properly loaded using "LoadImage" function without the need of converting into 24-bit Bitmap image using MS Paint. Also let me know if its easy to print a .jpg or .png image instead of a .bmp file.
Thanks
Abhinay
Edit
I have tried using "GetLastError()" as mentioned below
HANDLE hBmp = LoadImage(NULL, bmpfile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE);
if (hBmp == NULL)
{
DWORD dw = GetLastError();
if (dw == NULL)
{
MessageBoxA(NULL, "get last error is null", "ABHINAY", MB_OK | MB_TOPMOST);
}
else
{
MessageBoxA(NULL, "get last error is not null", "ABHINAY", MB_OK | MB_TOPMOST);
}
}
And i get the error message "get last error is null".
Can you please help why the bmp file was not loaded in the first case?
There are lots of variations of BMP format. It's quite possible that the original image was in a variant that LoadImage cannot directly convert to a DIB. So you converted it in Paint to a BMP variant that it could open.
In particular, there are variants where raw PNG of JPG data can be packed into a BMP container. This is typically used to pass the compressed image data directly to a printer that can decompress itself. (In my experience, only a few printers actually support this.) I don't think the GDI API can actually do much else with BMPs of this type. Paint, on the other hand, has codecs for PNG and JPG, so I'd expect its repertoire might include those formats, even when they're packed in a BMP header.
how can i make the the generated QRCode image to be loaded properly loaded using "LoadImage" function without the need of converting into 24-bit Bitmap image using MS Paint.
I don't think you'll be able to do it with LoadImage without converting the file. Modern versions of Windows have other APIs that can load BMPs (and PNG and JPG), so you might try one of these.
GDI+ (probably the simplest)
WIC
OLE (probably the most complex, especially if you're not used to COM)
Also let me know if its easy to print a .jpg or .png image instead of a .bmp file.
If you use one of the APIs I listed to load the image, printing it should be pretty straightforward.

is it possible to set jpeg(or png) types of images to exe(C++)?

Now I'm writing an open source project(C++/MFC) and find a beautiful image which is Jpeg type, in Windows API it's easy to change icon with function: SetIcon, but I don't want to convert my jpeg file into icon type.
My question: is there a way to set an application's icon using a .jpeg file?
This should do the trick for you:
Bitmap* icon = new Bitmap("myfile.jpg", TRUE);
HICON hIcon;
icon->GetHICON(&hIcon);
SendMessage(hWnd, WM_SETICON, ICON_BIG, (LPARAM)hIcon);
This is of course ignoring error checking, which you might want to add, but otherwise I think this should work. According to Microsoft this should support the following formats: BMP, GIF, JPEG, PNG, TIFF, Exif, WMF, and EMF.

Display IPLimage/ MAT (opencv) in MFC picture box

I want to display an IPLimage / MAT (opencv) formats on a MFC picture box in Visual C++
Here is a complete solution describing how to display an IplImage in a MCF/C++ form application using OpenCV http://ac-it.pl/display-an-iplimage-in-a-mcfc-form-application-using-opencv
Picture boxes can only display bitmaps I think. You'll need to convert IPLimage to a bitmap.
Assuming you can first convert IPLimage to a buffer of RGB values, see Creating HBITMAP from memory buffer
Then when you get the HBITMAP, you'll need to load it in the Picture Box. Assuming by picture box you mean a static control, add SS_BITMAP to its styles, and then load the HBITMAP using
SendMessage(hStatic, STM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)hBitmap);

Show Win32 popup menu with PNG icons from resources

It's been a long time since I've had to deal with Win32 menus. I need to add some PNG icons to a Win32 context popup menu. Naturally, I want to preserve PNG transparency and all the per-pixel-alpha in the process. Is this possible?
I was thinking on using SetMenuItemBitmaps. Is that the way to go?
I imported my PNGs as "PNG" resources but I can't seem to load them neither with LoadBitmap nor with LoadImage. I found some suggestions about using Gdi+ but obviously I won't be drawing the menu - the system will.
There seems to be a way to get a HBITMAP from a Gdi+ Bitmap but it looks as if all the alpha is getting lost in the process. AFAIK, a HBITMAP can happily host alpha information.
You need GDI+ to load a PNG. Then you need to create a 32-bit alpha bitmap of the correct size, create a Graphics on the bitmap, and use DrawImage to copy the PNG to the bitmap. That gives you a bitmap with an alpha channel.
Something like this:
Image* pimgSrc = Image::FromFile("MyIcon.png"L, FALSE);
Bitmap* pbmpImage = new Bitmap(
iWidth, iHeight,
PixelFormat32bppARGB
);
Graphics* pgraphics = Graphics::FromImage(bmpImage))
{
// This draws the PNG onto the bitmap, scaling it if necessary.
// You may want to set the scaling quality
graphics->DrawImage(
imageSrc,
Rectangle(0,0, bmpImage.Width, bmpImage.Height),
Rectangle(0,0, imgSrc.Width, imgSrc.Height),
GraphicsUnitPixel
);
}
// You can now get the HBITMAP from the Bitmap object and use it.
// Don't forget to delete the graphics, image and bitmap when done.
Perhaps you could use icon instead?
Here are my reasons for using icons instead of PNGs:
The Win32 API has good support icons, and it relatively much easier to draw icons, since GDI+ is not required.
Icons also support 8-bit transparency (just like PNGs).
Icons can be any size in pixels (just like PNGs).
Icons can easily be embedded in the executable as a resource.
Icons can be edited via Visual Studio.
To load an icon from a resource or a file use:
LoadImage()
To draw the icon, use:
DrawIcon() or DrawIconEx()