C++ 使用GDI对图像进行双缓冲+
我有一个image.png存储在GDI+图像数据类型中。有谁能告诉我如何在内存DC中获得存储在GDI+图像变量中的图像数据吗 下面是一些代码: 我们的目标是为了动画的缘故,能够加倍缓冲这个GDI+图像 我知道如何使用GDI将缓冲区加倍,但不知道如何使用GDI+。使用GDI,只需选择一个HBITMAP到内存DC中,然而,使用GDI+,图像不在HBITAP中,而是在图像变量中。有谁能告诉我如何将非HBITMAP的图像放入内存DC?谢谢。你看过位图类了吗?它继承自图像,可用于访问原始图像数据:C++ 使用GDI对图像进行双缓冲+,c++,winapi,C++,Winapi,我有一个image.png存储在GDI+图像数据类型中。有谁能告诉我如何在内存DC中获得存储在GDI+图像变量中的图像数据吗 下面是一些代码: 我们的目标是为了动画的缘故,能够加倍缓冲这个GDI+图像 我知道如何使用GDI将缓冲区加倍,但不知道如何使用GDI+。使用GDI,只需选择一个HBITMAP到内存DC中,然而,使用GDI+,图像不在HBITAP中,而是在图像变量中。有谁能告诉我如何将非HBITMAP的图像放入内存DC?谢谢。你看过位图类了吗?它继承自图像,可用于访问原始图像数据: Bit
Bitmap bmp(pStream);
BitmapData bitmapData;
Rect rect(0, 0, 200, 200);
// lock area of the image for writing
bmp.LockBits(&rect, ImageLockModeWrite, PixelFormat32bppARGB, &bitmapData);
更新以获得HBITMAP类似的内容可以使用注意:我没有测试以下代码:
HBITMAP hbmp = CreateCompatibleBitmap(hdc, width, height);
BITMAPINFO bmi;
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = height;
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 24;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = 0;
bmi.bmiHeader.biXPelsPerMeter = 0;
bmi.bmiHeader.biYPelsPerMeter = 0;
bmi.bmiHeader.biClrUsed = 0;
bmi.bmiHeader.biClrImportant = 0;
bmi.bmiColors = NULL;
SetDIBits(hdc, hbmp, 0, height, bitmapData.Scan0, &bmi, 0);
下面是我用于从磁盘加载图像的代码
// 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(NULL, &result);
delete bitmap;
return result;
}
编辑:
除了一些基本特性之外,不要自己使用GDI+。每当我使用图像时,我通常都想要尽可能最小、最快的代码——GDI在这方面做得更好
下面是从一个类中提取的代码,它将显示一个具有透明像素的图像,并带有类定义,希望能够避免类变量的任何歧义
void CStaticImg::displayImage()
{
RECT myRect;
BITMAP bm;
HDC screenDC, memDC;
HBITMAP oldBmp;
BLENDFUNCTION bf;
GetObject(mBmp, sizeof(bm), &bm);
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 0xff;
bf.AlphaFormat = AC_SRC_ALPHA;
screenDC = GetDC(mHwnd);
GetClientRect(mHwnd, &myRect);
if (mBmp == NULL)
FillRect(screenDC, &myRect, WHITE_BRUSH);
else
{
memDC = CreateCompatibleDC(screenDC);
oldBmp = (HBITMAP)SelectObject(memDC, mBmp);
AlphaBlend (screenDC, 0, 0, myRect.right,myRect.bottom, memDC, 0, 0, bm.bmWidth,bm.bmHeight, bf);
SelectObject(memDC, oldBmp);
DeleteDC(memDC);
ReleaseDC(mHwnd, screenDC);
}
}
class CStaticImg
{
public:
CStaticImg();
~CStaticImg();
void setImg(HBITMAP img);
HBITMAP getImgCopy();
void attach(HWND tgt);
void detach();
void setBkMode(bool transparent);
protected:
HWND mHwnd;
HBITMAP mBmp;
WNDPROC mOldWndProc;
void displayImage();
virtual LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
bool isBkgTransparent;
private:
// virtual LRESULT onPaint();
LRESULT onCreate();
static CStaticImg *GetObjectFromWindow(HWND hWnd);
static LRESULT CALLBACK stWinMsgHandler(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};
对不起,我是Win32新手;有没有办法将Gdiplus::Bitmap转换成HBITMAP?我已经在我的答案中发布了一种可能的方法来获得HBITMAP。你为什么还需要HBITMAP?我希望将HBITMAP加倍缓冲到内存DC中,但是,我发现HBITMAP不会保留png图像的alpha透明度:P我在我的原始帖子中发布了我的完整代码,希望有人能帮助我用我最初用来显示图像的方法来加倍缓冲我的图像..对不起。。不知怎的,我错过了你的答复!我试过你的代码,但没用?以下是我尝试过的:DrawImagehdc,0,0,mLoadImgWCHAR*myimage.png;DrawImage是一个双重缓冲hbitmap并将其绘制到屏幕的函数!无压力伴侣:我将启动编译器并检查-我认为问题在于您传递文件名的方式。与将char*强制转换为WCHAR*不同,您需要使用L或可能的TEXT宏来确保实际传递的是一个宽字符串,即每个char 2个字节。请给我几分钟时间,我将返回@JamesDiaz-是的,这将是您的问题。考虑以下两个具有相同的效果:1 MbMP=HbMMAP LoDimaGeNeURL、BITMAP32.BMP、IMAGE位图、0、0、LRYLoad文件;2 mBmp=mLoadImgLbitmap32.bmp;注意:文件名前面的L:太棒了,成功了!但是,我注意到,使用此函数,png中的alpha透明度不会保留:我在上面发布了我的完整代码,介绍了我如何使用alpha透明度显示png图像。希望有人能告诉我如何用这种方法将一个png的缓冲区加倍,谢谢。谢谢你花了这么多时间来回答这个问题。我还没有试过你的代码,但我相信它会成功的!我接受你的答案仅仅是因为你在这方面付出了巨大的努力,而你确实以不止一种方式回答了我的问题。非常感谢。
void CStaticImg::displayImage()
{
RECT myRect;
BITMAP bm;
HDC screenDC, memDC;
HBITMAP oldBmp;
BLENDFUNCTION bf;
GetObject(mBmp, sizeof(bm), &bm);
bf.BlendOp = AC_SRC_OVER;
bf.BlendFlags = 0;
bf.SourceConstantAlpha = 0xff;
bf.AlphaFormat = AC_SRC_ALPHA;
screenDC = GetDC(mHwnd);
GetClientRect(mHwnd, &myRect);
if (mBmp == NULL)
FillRect(screenDC, &myRect, WHITE_BRUSH);
else
{
memDC = CreateCompatibleDC(screenDC);
oldBmp = (HBITMAP)SelectObject(memDC, mBmp);
AlphaBlend (screenDC, 0, 0, myRect.right,myRect.bottom, memDC, 0, 0, bm.bmWidth,bm.bmHeight, bf);
SelectObject(memDC, oldBmp);
DeleteDC(memDC);
ReleaseDC(mHwnd, screenDC);
}
}
class CStaticImg
{
public:
CStaticImg();
~CStaticImg();
void setImg(HBITMAP img);
HBITMAP getImgCopy();
void attach(HWND tgt);
void detach();
void setBkMode(bool transparent);
protected:
HWND mHwnd;
HBITMAP mBmp;
WNDPROC mOldWndProc;
void displayImage();
virtual LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
bool isBkgTransparent;
private:
// virtual LRESULT onPaint();
LRESULT onCreate();
static CStaticImg *GetObjectFromWindow(HWND hWnd);
static LRESULT CALLBACK stWinMsgHandler(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
};