GDI+画图时,可以通过调用Image::FromIstream获取Image* 指针,而该还是的参数IStream* 我是通过CreateStreamOnHGlobal获取到的。
CreateStreamOnHGlobal
hGlobal:由GlobalAlloc函数分配的内存句柄。 fDeleteOnRelease:该参数指明上一个参数制定的内存在该对象被释放后是否也自动释放。如果该参数设定为FALSE,那么调用者必须显示的释放hGlobal。如果该参数设置为TRUE,则hGlobal最终会自动释放。 ppstm:IStream指针的地址,该指针在该函数执行后指向新创建的流对象。该参数不能未NULL。 如果函数创建流对象成功则返回S_OK。我在第二个参数
fDeleteOnRelease 传入了TRUE,接着就GlobalFree掉了hGlobal,使得在最后IStream在调用Release释放内存时出现异常。 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
在内存中 玩 图片格式
//了解下面这个例子,就可以通过GDI+实现把bmp图片转换JPEG格式(在内存中),然后通过网络发送到另一端,
//另一端接收再显示,
//大概步骤是,先用Image加载图片,然后创建流,通过Image类的Save函数以JPEG格式把图片数据保存到
//流中,之后读取数据,再用Image类的FromStream从流中加载(还原)
#include<windows.h>
#define ULONG_PTR ULONG
#include<gdiplus.h>
using namespace Gdiplus;
#pragma comment(lib,"gdiplus.lib")
//获取图片格式CLSID的自定义函数
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid);
int main()
{
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR pGdiToken;
GdiplusStartup(&pGdiToken,&gdiplusStartupInput,NULL);//初始GDI+
Image image(L"d:\\abc.bmp");//加载图片
CLSID encoderClsid;
//1. 获取JPEG图片格式CLSID
GetEncoderClsid(L"image/jpeg",&encoderClsid);
//2.创建流
IStream *pStream;
CreateStreamOnHGlobal(NULL,TRUE,&pStream);
//以JPEG图片格式储存数据到流中
image.Save(pStream,&encoderClsid);
//获得与流对应的内存句柄
HGLOBAL hMem;
GetHGlobalFromStream(pStream,&hMem);
//获得内存块大小
DWORD dwSize=GlobalSize(hMem);
//再创建一块内存句柄,用于目标流
HGLOBAL hDesMem=GlobalAlloc(GMEM_MOVEABLE,dwSize);
IStream *pDesStream;
CreateStreamOnHGlobal(hDesMem,TRUE,&pDesStream);
//获得内存块首地址
BYTE *pImgData=(BYTE *)GlobalLock(hMem);
BYTE *pDesData=(BYTE *)GlobalLock(hDesMem);
//3.复制内存,如果通过网络,就把pImgData里的数据发送过去。
CopyMemory(pDesData,pImgData,dwSize);
::GlobalUnlock(hMem);
GlobalUnlock(hDesMem);
// 4. 重建Image
Image *pImg=Image::FromStream(pDesStream);
HWND hWnd=FindWindow(NULL,"无标题.txt - 记事本");
HDC hDC=GetDC(hWnd);
Graphics graphics(hDC);
while(TRUE)
{
//绘制图片,测试是否正确
graphics.DrawImage(pImg,0,0,300,300);
Sleep(500);
}
//GdiplusShutdown(pGdiToken);//关闭GDI+
}
int GetEncoderClsid(const WCHAR* format, CLSID* pClsid)
{
UINT num= 0;
UINT size= 0;
ImageCodecInfo* pImageCodecInfo= NULL;
GetImageEncodersSize(&num, &size);
if(size== 0)
{
return -1;
}
pImageCodecInfo= (ImageCodecInfo*)(malloc(size));
if(pImageCodecInfo== NULL)
{
return -1;
}
GetImageEncoders(num, size, pImageCodecInfo);
for(UINT j=0; j< num; ++j)
{
if(wcscmp(pImageCodecInfo[j].MimeType, format)== 0)
{
*pClsid= pImageCodecInfo[j].Clsid;
free(pImageCodecInfo);
return j;
}
}
free(pImageCodecInfo);
return -1;
}