📄 subject_33439.htm
字号:
<p>
序号:33439 发表者:风亭雨帆 发表日期:2003-03-20 09:40:00
<br>主题:一个巨难的问题:SDK下实现jpeg的显示
<br>内容: 如何用API函数实现jpeg的显示。因为,GDI 只支持位图,所以直接显示是不可能的。<BR> 各位有什么高招,dll也行,但是,要代码呦,否则如何用!
<br><a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p>
<hr size=1>
<blockquote><p>
回复者:iwill 回复日期:2003-03-20 09:54:14
<br>内容:IPicture<BR><BR>在VC下显示JPEG、GIF格式图像的一种简便方法 <BR><BR>[ 作者: 郎锐 添加时间: 2001-7-28 0:02:47 ]<BR> <BR><BR>来源:www.ccw.com.cn<BR><BR>一、 引言 <BR>JPEG图像压缩标准随然是一种有损图像压缩标准,但由于人眼视觉的不敏感,经压缩后的画质基本没有发生变化,很快便以较高的压缩率得到了广泛的认可。GIF格式虽然仅支持256色但它对于颜色较少的图像有着很高的压缩率,甚至超过JPEG标准,也得到了广泛的认同。但作为众多程序员的一个重要的开发工具--Microsoft Visual C++ 6.0的MFC库却仅对没有经过任何压缩的BMP位图文件有着良好的支持,可以读取、显示、存储甚至在内存中创建一块内存位图。由于BMP格式的图像没有经过任何的压缩,不论是作为程序的外部文件,还是作为程序的内部资源都要占据大量的空间,尤其是后者会大大增加可执行文件的长度。可以看出,如果能用经过压缩、具有较好的压缩率的JPEG或GIF格式的图像来取代BMP文件在VC中的应用,无疑还是很有吸引力的。 <BR>二、 设计思路 <BR>虽然有一些操作、处理JPEG、GIF等其他格式图像的Active X控件,但总的来说使用起来并不太方便,笔者经过实验摸索,总结出了一种借助于COM接口的OLE方法来实现上述功能的一种简便方法,现介绍如下以飨广大读者: <BR>下面我们要使用IPicture 的COM接口,有必要对该图像接口做些了解:该接口主要管理图像对象及其属性,图像对象为位图、图标和图元等提供一种与语言无关的抽象。和标准的字体对象一样,系统也提供了对图像对象的标准实现。其主要的接口是IPicture和IPictureDisp,后者是由IDispatch接口派生以便通过自动化对图像的属性进行访问。图像对象也支持外部接口IPropertyNotifySink,以便用户能在图像属性发生改变时作出决定。图像对象也支持IPersistStream接口,所以它能从一个IStream接口的实例对象保存、装载自己,而IStream接口也支持对流对象的数据读写。 <BR>我们可以用函数OleLoadPicture从包含有图像数据的流中装载图像。该函数简化了基于流的图像对象的创建过程,可以创建一个新的图像对象并且用流中的内容对它进行初始化。其函数原型为: <BR>STDAPI OleLoadPicture( IStream * pStream, //指向包含有图像数据的流的指针LONG lSize, //从流中读取的字节数BOOL fRunmode, //图像属性对应的初值REFIID riid, //涉及到的接口标识,描述要返回的接口指针的类型VOID ppvObj // 在rrid中用到的接口指针变量的地址); <BR>三、 具体的实现 <BR>在显示图像之前,首先要获取到图像文件的存放路径,这里采用标准的文件打开对话框来选取图像文件,文件名存放在CString型的变量m_sPath中: <BR>CFileDialog dlg(TRUE,"jpg","*.jpg", <BR>OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, <BR>"JPEG文件(*.jpg)|*.jpg|GIF文件(*.gif)|*.gif||",NULL); <BR>if(dlg.DoModal()==IDOK) <BR>{ <BR>m_sPath=dlg.GetPathName(); <BR>Invalidate(); <BR>} <BR><BR>为简单计,图形显示的代码直接在视类中的OnDraw中编写,首先打开文件并判断文件的可用性,并把文件内容放到流接口IStream的对象pStm中: <BR>IStream *pStm; <BR>CFileStatus fstatus; <BR>CFile file; <BR>LONG cb; <BR>…… <BR>if (file.Open(m_Path,CFile::modeRead)&&file.GetStatus(m_Path,fstatus)&& ((cb = fstatus.m_size) != -1)) <BR>{ <BR>HGLOBAL hGlobal = GlobalAlloc(GMEM_MOVEABLE, cb); <BR>LPVOID pvData = NULL; <BR>if (hGlobal != NULL) <BR>{ <BR>if ((pvData = GlobalLock(hGlobal)) != NULL) <BR>{ <BR>file.ReadHuge(pvData, cb); <BR>GlobalUnlock(hGlobal); <BR>CreateStreamOnHGlobal(hGlobal, TRUE, &pStm); <BR>} <BR>} <BR>} <BR>然后,就直接调用OleLoadPicture函数从流中装载图像: <BR>IPicture *pPic; <BR>…… <BR>OleLoadPicture(pStm,fstatus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic)); <BR>由于该函数有时会导致失败,所以应当用SUCCEEDED宏来做一些适当的保护工作,只有在数据装载成功的前提下才能继续下面的图像显示工作: <BR>if(SUCCEEDED(OleLoadPicture(pStm,fstatus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic))) <BR>{ <BR>OLE_XSIZE_HIMETRIC hmWidth; <BR>OLE_YSIZE_HIMETRIC hmHeight; <BR>pPic->get_Width(&hmWidth); <BR>pPic->get_Height(&hmHeight); <BR>double fX,fY; <BR>…… <BR>fX = (double)pDC->GetDeviceCaps(HORZRES)*(double)hmWidth/((double)pDC->GetDeviceCaps(HORZSIZE)*100.0); <BR>fY = (double)pDC->GetDeviceCaps(VERTRES)*(double)hmHeight/((double)pDC->GetDeviceCaps(VERTSIZE)*100.0); <BR>if(FAILED(pPic->Render(*pDC,0,0,(DWORD)fX,(DWORD)fY,0,hmHeight,hmWidth,-hmHeight,NULL))) <BR>AfxMessageBox("渲染图像失败!"); <BR>pPic->Release(); <BR>} <BR>else <BR>AfxMessageBox("从流中装载图像失败!"); <BR><BR>其中,显示工作主要是由IPicture接口对象的Render函数来完成的,该函数主要用来将图片的指定部分画到指定的设备环境的指定位置。原型如下: <BR>HRESULT Render( HDC hdc, //渲染图像用的设备环境句柄 <BR>long x, //在hdc上的水平坐标 <BR>long y, //在hdc上的垂直坐标 <BR>long cx, //图像宽度 <BR>long cy, //图像高度 <BR>OLE_XPOS_HIMETRIC xSrc, //在源图像上的水平偏移 <BR>OLE_YPOS_HIMETRIC ySrc, //在源图像上的垂直偏移 <BR>OLE_XSIZE_HIMETRIC cxSrc,//在源图像上水平拷贝的数量 <BR>OLE_YSIZE_HIMETRIC cySrc,//在源图像上垂直拷贝的数量 <BR>LPCRECT prcWBounds //指向目标图元设备环境句柄的指针); <BR>小结:到此为止,通过上述代码已经能够在程序的客户区内显示JPEG、GIF等标准的图像了,但对于有多帧图片(即有动画)的GIF格式的图像,目前还只能显示第一帧,如要完整的显示GIF 动画的全过程,还需要外部Active X控件的支持。 <BR> <BR>
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:风亭雨帆 回复日期:2003-03-20 10:03:29
<br>内容:感谢<BR>我还是希望SDK的<BR>这个MFC的,是不是只有作成dll才可以使用?有没有其他比较容易的办法利用你的介绍的?<BR>谢谢!
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:iwill 回复日期:2003-03-20 10:15:01
<br>内容:mfc和sdk区别不大,部分地方改一下就可以用,学东西不要太死板 呵呵
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:风亭雨帆 回复日期:2003-03-20 10:17:56
<br>内容:收到,我会继续努力的<BR>如果成功<BR>加分给你。
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
<font color=red>答案被接受</font><br>回复者:战鹰 回复日期:2003-03-20 10:21:33
<br>内容:最新的SDK中有ICM的例子!!!!是JPEG的!!!!!!纯API的!!!!<BR><BR><BR>呵呵!!!!!!!!!1
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:风亭雨帆 回复日期:2003-03-20 10:33:40
<br>内容:really?<BR>那可是天大的好消息,简直不可思议,明明GDI只能支持位图。<BR>看来,网络的力量太大了,jpeg在网络上的大行其道使得骄傲的Mirocsoft都不得不紧紧跟随。<BR>我是多么的惊讶以及兴奋呀,当我听到这个消息的时候。<BR>但是,假如你拥有这个最新的SDK,我相信您一定可以将ICM的例子发送过来大家研究切磋,如果您果真能作到这些,我将深表感谢,并在心里祝愿您再您所从事的领域中可以象雄鹰一样大展宏图!<BR>谢谢!
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
<hr size=1>
<blockquote><p>
回复者:jackyxio 回复日期:2003-03-20 12:58:31
<br>内容:。。。。<BR><BR>太会说话了吧。。。
<br>
<a href="javascript:history.go(-1)">返回上页</a><br><a href=http://www.copathway.com/cndevforum/>访问论坛</a></p></blockquote>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -