How to load .png , .jpeg images using MFC? - mfc

Hi i want to load png images and jpeg images.
can anyone help me?

CImage image;
image.Load(_T("C:\\image.png")); // just change extension to load jpg
CBitmap bitmap;
bitmap.Attach(image.Detach());

//----- load png into CImage from resource
bool Load( CImage * pimage, LPCTSTR lpszResourceName, HINSTANCE hinstRes)
{
if (hinstRes == NULL)
{
hinstRes = AfxFindResourceHandle(lpszResourceName, _T("PNG") );
}
HRSRC hRsrc = ::FindResource(hinstRes, lpszResourceName, _T("PNG") );
if (hRsrc == NULL)
{
return false;
}
HGLOBAL hGlobal = LoadResource(hinstRes, hRsrc);
if (hGlobal == NULL)
{
return false;
}
LPBYTE lpBuffer = (LPBYTE) ::LockResource(hGlobal);
if (lpBuffer == NULL)
{
FreeResource(hGlobal);
return false;
}
bool bRes = false;
{
UINT uiSize = ::SizeofResource(hinstRes, hRsrc);
HGLOBAL hRes = ::GlobalAlloc(GMEM_MOVEABLE, uiSize);
if (hRes != NULL)
{
IStream* pStream = NULL;
LPVOID lpResBuffer = ::GlobalLock(hRes);
ASSERT (lpResBuffer != NULL);
memcpy(lpResBuffer, lpBuffer, uiSize);
HRESULT hResult = ::CreateStreamOnHGlobal(hRes, TRUE, &pStream);
if( hResult == S_OK)
{
pimage->Load(pStream);
pStream->Release();
bRes= true;
}
}
}
UnlockResource(hGlobal);
FreeResource(hGlobal);
return bRes;
}

You can use CImage class which supports the following formats: JPEG, GIF, BMP, and PNG.
http://msdn.microsoft.com/en-us/library/bwea7by5%28VS.80%29.aspx
Use Load function to load file from disk:
http://msdn.microsoft.com/en-us/library/tf4bytf8%28VS.80%29.aspx

For PNGs that come from resources
CPngImage pngImage;
pngImage.Load(YOUR_RESOURCE_ID, AfxGetResourceHandle());
CBitmap bitmap;
bitmap.Attach(pngImage.Detach());
will make you happy. bitmap can also be added to an CImageList.

use CPictureCtrl, it's opensource.
http://www.codeproject.com/Articles/24969/An-MFC-picture-control-to-dynamically-show-picture

CString pngPath=L"D:\\k.png";
CImage pngImage;
CBitmap pngBmp;
CDC bmDC;
CBitmap *pOldbmp;
BITMAP bi;
//UINT xPos=450,yPos=300;
UINT xPos=10,yPos=10;
CClientDC dc(this);
pngImage.Load(pngPath);
// new code
pngBmp.Attach(pngImage.Detach());
bmDC.CreateCompatibleDC(&dc);
pOldbmp= bmDC.SelectObject(&pngBmp);
pngBmp.GetBitmap(&bi);
dc.BitBlt(xPos,yPos,bi.bmWidth,bi.bmHeight,&bmDC,0,0,SRCCOPY);
bmDC.SelectObject(pOldbmp);

There is a simple CPngImage in the MFC. It is derived from CBitmap and allows to load a PNG as a CBitmap.
AFAIK this class is available since VS-2010.

Related

Trying to display a CImage on a CDialog in OnPaint handler [duplicate]

Hi i want to load png images and jpeg images.
can anyone help me?
CImage image;
image.Load(_T("C:\\image.png")); // just change extension to load jpg
CBitmap bitmap;
bitmap.Attach(image.Detach());
//----- load png into CImage from resource
bool Load( CImage * pimage, LPCTSTR lpszResourceName, HINSTANCE hinstRes)
{
if (hinstRes == NULL)
{
hinstRes = AfxFindResourceHandle(lpszResourceName, _T("PNG") );
}
HRSRC hRsrc = ::FindResource(hinstRes, lpszResourceName, _T("PNG") );
if (hRsrc == NULL)
{
return false;
}
HGLOBAL hGlobal = LoadResource(hinstRes, hRsrc);
if (hGlobal == NULL)
{
return false;
}
LPBYTE lpBuffer = (LPBYTE) ::LockResource(hGlobal);
if (lpBuffer == NULL)
{
FreeResource(hGlobal);
return false;
}
bool bRes = false;
{
UINT uiSize = ::SizeofResource(hinstRes, hRsrc);
HGLOBAL hRes = ::GlobalAlloc(GMEM_MOVEABLE, uiSize);
if (hRes != NULL)
{
IStream* pStream = NULL;
LPVOID lpResBuffer = ::GlobalLock(hRes);
ASSERT (lpResBuffer != NULL);
memcpy(lpResBuffer, lpBuffer, uiSize);
HRESULT hResult = ::CreateStreamOnHGlobal(hRes, TRUE, &pStream);
if( hResult == S_OK)
{
pimage->Load(pStream);
pStream->Release();
bRes= true;
}
}
}
UnlockResource(hGlobal);
FreeResource(hGlobal);
return bRes;
}
You can use CImage class which supports the following formats: JPEG, GIF, BMP, and PNG.
http://msdn.microsoft.com/en-us/library/bwea7by5%28VS.80%29.aspx
Use Load function to load file from disk:
http://msdn.microsoft.com/en-us/library/tf4bytf8%28VS.80%29.aspx
For PNGs that come from resources
CPngImage pngImage;
pngImage.Load(YOUR_RESOURCE_ID, AfxGetResourceHandle());
CBitmap bitmap;
bitmap.Attach(pngImage.Detach());
will make you happy. bitmap can also be added to an CImageList.
use CPictureCtrl, it's opensource.
http://www.codeproject.com/Articles/24969/An-MFC-picture-control-to-dynamically-show-picture
CString pngPath=L"D:\\k.png";
CImage pngImage;
CBitmap pngBmp;
CDC bmDC;
CBitmap *pOldbmp;
BITMAP bi;
//UINT xPos=450,yPos=300;
UINT xPos=10,yPos=10;
CClientDC dc(this);
pngImage.Load(pngPath);
// new code
pngBmp.Attach(pngImage.Detach());
bmDC.CreateCompatibleDC(&dc);
pOldbmp= bmDC.SelectObject(&pngBmp);
pngBmp.GetBitmap(&bi);
dc.BitBlt(xPos,yPos,bi.bmWidth,bi.bmHeight,&bmDC,0,0,SRCCOPY);
bmDC.SelectObject(pOldbmp);
There is a simple CPngImage in the MFC. It is derived from CBitmap and allows to load a PNG as a CBitmap.
AFAIK this class is available since VS-2010.

How to apply masking for mouse cursor while writing in to icon(.ico)

I using GetCursorInfo to capture cursor but while saving the cursor as icon getting some black rectangle over on icon.
For windows default cursors are fine but few custom cursor I facing this issue http://www.cursors-4u.com/
Placed one example cursor icon in link https://www.google.com/search?q=cursor+icon&rlz=1C1CHBD_enIN789IN789&source=lnms&tbm=isch&sa=X&ved=0ahUKEwix9aj_gq_iAhWCXCsKHcusD0oQ_AUIDigB&biw=1366&bih=657#imgrc=rOxlbRoBfnKs8M:
HRESULT SaveIcon(HICON hIcon, const char* path)
{
// Create the IPicture intrface
PICTDESC desc = { sizeof(PICTDESC) };
desc.picType = PICTYPE_ICON;
desc.icon.hicon = hIcon;
IPicture* pPicture = 0;
HRESULT hr = OleCreatePictureIndirect(&desc, IID_IPicture, FALSE, (void**)&pPicture);
if (FAILED(hr)) return hr;
// Create a stream and save the image
IStream* pStream = 0;
CreateStreamOnHGlobal(0, TRUE, &pStream);
LONG cbSize = 0;
hr = pPicture->SaveAsFile(pStream, TRUE, &cbSize);
// Write the stream content to the file
if (!FAILED(hr))
{
HGLOBAL hBuf = 0;
GetHGlobalFromStream(pStream, &hBuf);
void* buffer = GlobalLock(hBuf);
HANDLE hFile = CreateFileA(path, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
if (!hFile)
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
DWORD written = 0;
WriteFile(hFile, buffer, cbSize, &written, 0);
CloseHandle(hFile);
}
GlobalUnlock(buffer);
}
// Cleanup
pStream->Release();
pPicture->Release();
return hr;
}
//Capture cursor.
CURSORINFO getHCursor()
{
CURSORINFO cursorInfo;
cursorInfo.cbSize = sizeof(CURSORINFO);
if (GetCursorInfo(&cursorInfo) == 0)
{
MessageBox(NULL, _T("Exception : GetCursorInfo creation failed"),_T("message"),MB_OK|MB_SYSTEMMODAL);
cursorInfo.hCursor = NULL;
return cursorInfo;
}
return cursorInfo;
}
//Main Call
int _tmain(int argc, _TCHAR* argv[])
{
while (true)
{
CURSORINFO CursorInfo = getHCursor();
if (CursorInfo.hCursor == NULL)
{
::Sleep(MinSleep);
continue;
}
SaveIcon((HICON)CursorInfo.hCursor, "C:\\Users\\Desktop\\myicon.ico");
Sleep(MaxSleep);
}
return 0;
}
My agenda is to capture cursor and save cursor in to icon(.ico) file or load in to buffer.
Is any other way I can write cursor data in to icon file or buffer ?
The ICONINFO struct contains two members, hbmMask and hbmColor, that contain the mask and color bitmaps, respectively, for the cursor (see the MSDN page for ICONINFO for the official documentation).
When you call GetIconInfo() for the default cursor, the ICONINFO struct contains both valid mask and color bitmaps.
There is probably a better way to render the cursor that the
BitBlt() - BitBlt() - MakeTransparent() combination of method
calls.
Refer to the #Tarsier approach, although it's C #, but the idea is the same.
Link: Capturing the Mouse cursor image

C++ raw HBITMAP to png struct data [duplicate]

I'm trying to send a screenshot of a window over tcp to a server.
Getting the screenshot is no problem (using GDIplus). The networking is also easy for me. The problem is trying to convert the gdi+ Bitmap to a png (in memory) to get the data out of it and send it to the server.
Can anyone help me please?
Gdiplus can save to file, or save to memory using IStream. See Gdiplus::Image::Save method
//get gdi+ bitmap
Gdiplus::Bitmap bitmap(hbitmap, nullptr);
//write to IStream
IStream* istream = nullptr;
HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, &istream);
CLSID clsid_png;
CLSIDFromString(L"{557cf406-1a04-11d3-9a73-0000f81ef32e}", &clsid_png);
bitmap.Save(istream, &clsid_png);
The memory size is small enough that you can copy from IStream to a single buffer (see "Minimum example" for more detail)
//get memory handle associated with istream
HGLOBAL hg = NULL;
GetHGlobalFromStream(istream, &hg);
//copy IStream to buffer
int bufsize = GlobalSize(hg);
char *buffer = new char[bufsize];
//lock & unlock memory
LPVOID ptr = GlobalLock(hg);
memcpy(buffer, ptr, bufsize);
GlobalUnlock(hg);
//release will automatically free the memory allocated in CreateStreamOnHGlobal
istream->Release();
PNG is now available in buffer, its size is bufsize. You can work directly with the binary data, or convert to Base64 to send over the network.
Minimum example:
#include <iostream>
#include <fstream>
#include <vector>
#include <Windows.h>
#include <gdiplus.h>
bool save_png_memory(HBITMAP hbitmap, std::vector<BYTE>& data)
{
Gdiplus::Bitmap bmp(hbitmap, nullptr);
//write to IStream
IStream* istream = nullptr;
if (CreateStreamOnHGlobal(NULL, TRUE, &istream) != 0)
return false;
CLSID clsid_png;
if (CLSIDFromString(L"{557cf406-1a04-11d3-9a73-0000f81ef32e}", &clsid_png)!=0)
return false;
Gdiplus::Status status = bmp.Save(istream, &clsid_png);
if (status != Gdiplus::Status::Ok)
return false;
//get memory handle associated with istream
HGLOBAL hg = NULL;
if (GetHGlobalFromStream(istream, &hg) != S_OK)
return 0;
//copy IStream to buffer
int bufsize = GlobalSize(hg);
data.resize(bufsize);
//lock & unlock memory
LPVOID pimage = GlobalLock(hg);
if (!pimage)
return false;
memcpy(&data[0], pimage, bufsize);
GlobalUnlock(hg);
istream->Release();
return true;
}
int main()
{
CoInitialize(NULL);
ULONG_PTR token;
Gdiplus::GdiplusStartupInput tmp;
Gdiplus::GdiplusStartup(&token, &tmp, NULL);
//take screenshot
RECT rc;
GetClientRect(GetDesktopWindow(), &rc);
auto hdc = GetDC(0);
auto memdc = CreateCompatibleDC(hdc);
auto hbitmap = CreateCompatibleBitmap(hdc, rc.right, rc.bottom);
auto oldbmp = SelectObject(memdc, hbitmap);
BitBlt(memdc, 0, 0, rc.right, rc.bottom, hdc, 0, 0, SRCCOPY);
SelectObject(memdc, oldbmp);
DeleteDC(memdc);
ReleaseDC(0, hdc);
//save as png
std::vector<BYTE> data;
if(save_png_memory(hbitmap, data))
{
//write from memory to file for testing:
std::ofstream fout("test.png", std::ios::binary);
fout.write((char*)data.data(), data.size());
}
DeleteObject(hbitmap);
Gdiplus::GdiplusShutdown(token);
CoUninitialize();
return 0;
}

C++ gdi::Bitmap to PNG Image in memory

I'm trying to send a screenshot of a window over tcp to a server.
Getting the screenshot is no problem (using GDIplus). The networking is also easy for me. The problem is trying to convert the gdi+ Bitmap to a png (in memory) to get the data out of it and send it to the server.
Can anyone help me please?
Gdiplus can save to file, or save to memory using IStream. See Gdiplus::Image::Save method
//get gdi+ bitmap
Gdiplus::Bitmap bitmap(hbitmap, nullptr);
//write to IStream
IStream* istream = nullptr;
HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, &istream);
CLSID clsid_png;
CLSIDFromString(L"{557cf406-1a04-11d3-9a73-0000f81ef32e}", &clsid_png);
bitmap.Save(istream, &clsid_png);
The memory size is small enough that you can copy from IStream to a single buffer (see "Minimum example" for more detail)
//get memory handle associated with istream
HGLOBAL hg = NULL;
GetHGlobalFromStream(istream, &hg);
//copy IStream to buffer
int bufsize = GlobalSize(hg);
char *buffer = new char[bufsize];
//lock & unlock memory
LPVOID ptr = GlobalLock(hg);
memcpy(buffer, ptr, bufsize);
GlobalUnlock(hg);
//release will automatically free the memory allocated in CreateStreamOnHGlobal
istream->Release();
PNG is now available in buffer, its size is bufsize. You can work directly with the binary data, or convert to Base64 to send over the network.
Minimum example:
#include <iostream>
#include <fstream>
#include <vector>
#include <Windows.h>
#include <gdiplus.h>
bool save_png_memory(HBITMAP hbitmap, std::vector<BYTE>& data)
{
Gdiplus::Bitmap bmp(hbitmap, nullptr);
//write to IStream
IStream* istream = nullptr;
if (CreateStreamOnHGlobal(NULL, TRUE, &istream) != 0)
return false;
CLSID clsid_png;
if (CLSIDFromString(L"{557cf406-1a04-11d3-9a73-0000f81ef32e}", &clsid_png)!=0)
return false;
Gdiplus::Status status = bmp.Save(istream, &clsid_png);
if (status != Gdiplus::Status::Ok)
return false;
//get memory handle associated with istream
HGLOBAL hg = NULL;
if (GetHGlobalFromStream(istream, &hg) != S_OK)
return 0;
//copy IStream to buffer
int bufsize = GlobalSize(hg);
data.resize(bufsize);
//lock & unlock memory
LPVOID pimage = GlobalLock(hg);
if (!pimage)
return false;
memcpy(&data[0], pimage, bufsize);
GlobalUnlock(hg);
istream->Release();
return true;
}
int main()
{
CoInitialize(NULL);
ULONG_PTR token;
Gdiplus::GdiplusStartupInput tmp;
Gdiplus::GdiplusStartup(&token, &tmp, NULL);
//take screenshot
RECT rc;
GetClientRect(GetDesktopWindow(), &rc);
auto hdc = GetDC(0);
auto memdc = CreateCompatibleDC(hdc);
auto hbitmap = CreateCompatibleBitmap(hdc, rc.right, rc.bottom);
auto oldbmp = SelectObject(memdc, hbitmap);
BitBlt(memdc, 0, 0, rc.right, rc.bottom, hdc, 0, 0, SRCCOPY);
SelectObject(memdc, oldbmp);
DeleteDC(memdc);
ReleaseDC(0, hdc);
//save as png
std::vector<BYTE> data;
if(save_png_memory(hbitmap, data))
{
//write from memory to file for testing:
std::ofstream fout("test.png", std::ios::binary);
fout.write((char*)data.data(), data.size());
}
DeleteObject(hbitmap);
Gdiplus::GdiplusShutdown(token);
CoUninitialize();
return 0;
}

Get bytes/char* from hIcon/hBitmap

I'm working on a C/S application, Server in C++ and Client in C#, I need to send some information about current running processes and related icon.
I get icon file thanks to EnumWindows with this code inside the callback...
// Get the window icon
HICON hIcon = (HICON)(::SendMessageW(hWnd, WM_GETICON, ICON_SMALL, 0));
if (hIcon == 0) {
// Alternative method. Get from the window class
hIcon = reinterpret_cast<HICON>(::GetClassLongPtrW(hWnd, GCLP_HICONSM));
}
// Alternative: get the first icon from the main module
if (hIcon == 0) {
hIcon = ::LoadIcon(GetModuleHandleW(0), MAKEINTRESOURCE(0));
}
// Alternative method. Use OS default icon
if (hIcon == 0) {
hIcon = ::LoadIcon(0, IDI_APPLICATION);
}
OK, now I have the Icon and I can "print" it (simply for check) with DrawIcon().
My question is: How to get bytes starting from this?
I need a buffer to send this data to my Client and CONVERT the same data to display icon in a list (icon + process_name). So, I need to get bytes of this icon/hIcon (or bitmap/hBitmap, etc.)
(Of course I need help for server side.)
I think is good to copy the icon in a temp buffer to get bytes but nothing works.
Any help would be appreciated.
EDIT:
#DavidHeffernan thank you for reply. I found this: Converting-DDB-to-DIB through StackOverflow's past questions (sorry if is bad to post external links).
Now, with GetDIBits() I have in the fifth param the LPVOID lpvBits , that is "A pointer to a buffer to receive the bitmap data msdn - GetDIBits()"
Now, How Should I send from lpvBits? What's about Bitmap Size?
I've found something on MSDN and StackOverflow and it helped me: link;
#include "stdafx.h"
#include <windows.h>
#include <olectl.h>
#pragma comment(lib, "oleaut32.lib")
HRESULT SaveIcon(HICON hIcon, const wchar_t* path) {
// Create the IPicture intrface
PICTDESC desc = { sizeof(PICTDESC) };
desc.picType = PICTYPE_ICON;
desc.icon.hicon = hIcon;
IPicture* pPicture = 0;
HRESULT hr = OleCreatePictureIndirect(&desc, IID_IPicture, FALSE, (void**)&pPicture);
if (FAILED(hr)) return hr;
// Create a stream and save the image
IStream* pStream = 0;
CreateStreamOnHGlobal(0, TRUE, &pStream);
LONG cbSize = 0;
hr = pPicture->SaveAsFile(pStream, TRUE, &cbSize);
// Write the stream content to the file
if (!FAILED(hr)) {
HGLOBAL hBuf = 0;
GetHGlobalFromStream(pStream, &hBuf);
void* buffer = GlobalLock(hBuf);
HANDLE hFile = CreateFile(path, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0);
if (!hFile) hr = HRESULT_FROM_WIN32(GetLastError());
else {
DWORD written = 0;
WriteFile(hFile, buffer, cbSize, &written, 0);
CloseHandle(hFile);
}
GlobalUnlock(buffer);
}
// Cleanup
pStream->Release();
pPicture->Release();
return hr;
}
int _tmain(int argc, _TCHAR* argv[])
{
HICON hIcon = (HICON)LoadImage(0, L"c:\\windows\\system32\\perfcentercpl.ico", IMAGE_ICON, 32, 32, LR_LOADFROMFILE);
if (!hIcon) return GetLastError();
HRESULT hr = SaveIcon(hIcon, L"c:\\temp\\test.ico");
return hr;
}
Thanks to SaveIcon() I can save it and after, when needed, I can open it as binary file and send it via socket.