在VC++上显示图片的具体思路是将jpeg、bmp文件加载到堆中,然后在堆中创建一个数据流,接着调用OleLoadPicture函数加载流中的数据到IPicture中,最后调用IPicture接口的Reader方法输出图像信息。
1. 创建单文档MFC应用程序,工程名为ShowJPEG.
2. 向视图类中添加成员变量。
IStream* m_pStream; //定义流对象
IPicture* m_pPicture; //定义接口对象
OLE_XSIZE_HIMETRIC m_JPGWidth; //图像宽度
OLE_YSIZE_HIMETRIC m_JPGHeight; //图像高度
HGLOBAL hMem; //堆句柄
3. 在视图类的构造函数中从磁盘中加载图像到流中。
CShowJPEGView::CShowJPEGView()
{
// TODO: add construction code here
CFile file; //定义文件对象
file.Open("psb.jpg",CFile::modeReadWrite); //打开文件
DWORD len=file.GetLength(); //获取文件长度
hMem=GlobalAlloc(GMEM_MOVEABLE,len); //在堆中分配内存
LPVOID pData=NULL; //定义一个指针对象
pData=GlobalLock(hMem); //锁定内存区域
file.ReadHuge(pData,len); //读取图像数据到堆中
file.Close(); //关闭文件
GlobalUnlock(hMem); //解除对堆的锁定
CreateStreamOnHGlobal(hMem,TRUE,&m_pStream); //在堆中创建流
OleLoadPicture(m_pStream,len,TRUE,IID_IPicture,(LPVOID*)&m_pPicture); //加载图像
m_pPicture->get_Height(&m_JPGHeight); //获取图像高度
m_pPicture->get_Width(&m_JPGWidth); //获取图像宽度
}
4. 在试图类的OnDraw方法中绘制JPEG图像。
void CShowJPEGView::OnDraw(CDC* pDC)
{
CShowJPEGDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
m_pPicture->Render(pDC->m_hDC,0,0,(int)(m_JPGWidth/26.45),(int)(m_JPGHeight/26.45),0,m_JPGHeight,m_JPGWidth,-m_JPGHeight,NULL);
}
5. 运行程序,显示图像。
在MFC中, 显示位图容易,但是显示JPG等格式却比较麻烦, 在此使用IPicture接口可以很方便的显示bmp,jpg,gif等格式图片 , 但此接口不支持tif png格式的图片。
void ShowImage(CString str)
{
CclientDC dc(this);
IPicture * pImg;
IStream * pStm;
CFileStatus fstatus;
CFile file;
LONG cb;
if (file.Open (str,CFile::modeRead)&&file.GetStatus (str,fstatus)&&((cb=fstatus.m_size )!=-1))
{
HGLOBAL hGlobal=GlobalAlloc(GMEM_MOVEABLE,cb);
LPVOID pvData=NULL;
if(hGlobal!=NULL)
{
if((pvData=GlobalLock(hGlobal))!=NULL)
{
file.ReadHuge (pvData,cb);
GlobalUnlock(hGlobal);
CreateStreamOnHGlobal(hGlobal,TRUE,&pStm);
if (SUCCEEDED(OleLoadPicture(pStm,fstatus.m_size ,TRUE,IID_IPicture,(LPVOID *)&pPic)))
{
pStm->Release ();
OLE_XSIZE_HIMETRIC hmWidth;
OLE_YSIZE_HIMETRIC hmHeight;
pImg->get_Width(&hmWidth);
pImg->get_Height (&hmHeight);
CRECT rect; dc.GetClientRect(&rect);
pImg->Render(dc,0,0,rect.Width(),rect.Height(),0,hmHeight,hmWidth,-hmHeight,NULL); }
else
AfxMessageBox("Error Loading Picture From Stream!");
}
}
}
else
{
AfxMessageBox("can't Open Image File!");
}
}
1. COM接口
该接口主要管理图像对象及其属性,图像对象为位图、图标和图元等提供一种与语言无关的抽象。和标准的字体对象一样,系统也提供了对图像对象的标准实现。其主要的接口是IPicture和IPictureDisp,后者是由IDispatch接口派生以便通过自动化对图像的属性进行访问。图像对象也支持外部接口IPropertyNotifySink,以便用户能在图像属性发生改变时作出决定。图像对象也支持IPersistStream接口,所以它能从一个IStream接口的实例对象保存、装载自己,而IStream接口也支持对流对象的数据读写。
2. OleLoadPicture函数
OleLoadPicture()从包含有图像数据的流中装载图像。该函数简化了基于流的图像对象的创建过程,可以创建一个新的图像对象并且用流中的内容对它进行初始化。其函数原型为:
STDAPI OleLoadPicture( IStream * pStream, //指向包含有图像数据的流的指针
LONG lSize, //从流中读取的字节数
BOOL fRunmode, //图像属性对应的初值
REFIID riid, //涉及到的接口标识,描述要返回的接口指针的类型
VOID ppvObj // 在rrid中用到的接口指针变量的地址) ;
3. Render函数
显示工作主要是由IPicture接口对象的Render函数来完成的,该函数主要用来将图片的指定部分画到指定的设备环境的指定位置。原型如下:
HRESULT Render( HDC hdc, //渲染图像用的设备环境句柄
long x, //在hdc上的水平坐标
long y, //在hdc上的垂直坐标
long cx, //图像宽度
long cy, //图像高度
OLE_XPOS_HIMETRIC xSrc, //在源图像上的水平偏移
OLE_YPOS_HIMETRIC ySrc, //在源图像上的垂直偏移
OLE_XSIZE_HIMETRIC cxSrc,//在源图像上水平拷贝的数量
OLE_YSIZE_HIMETRIC cySrc,//在源图像上垂直拷贝的数量
LPCRECT prcWBounds //指向目标图元设备环境句柄的指针);
参考: http://blog.csdn.net/shuilan0066/article/details/6623122