VC下显示JPG,GIF图象的一种简便方法

来源:互联网 发布:淘宝卖家退货率怎么看 编辑:程序博客网 时间:2024/04/30 02:37

作者:jiaohe2000

转自:http://blog.csdn.net/jiaohe2000/article/details/1884756


一、 引言 
  JPEG图像压缩标准随然是一种有损图像压缩标准,但由于人眼视觉的不敏感,经压缩后的画质基本没有发生变化,很快便以较高的压缩率得到了广泛的认可。GIF格式虽然仅支持256色但它对于颜色较少的图像有着很高的压缩率,甚至超过JPEG标准,也得到了广泛的认同。但作为众多程序员的一个重要的开发工具--Microsoft Visual C++ 6.0的MFC库却仅对没有经过任何压缩的BMP位图文件有着良好的支持,可以读取、显示、存储甚至在内存中创建一块内存位图。由于BMP格式的图像没有经过任何的压缩,不论是作为程序的外部文件,还是作为程序的内部资源都要占据大量的空间,尤其是后者会大大增加可执行文件的长度。可以看出,如果能用经过压缩、具有较好的压缩率的JPEG或GIF格式的图像来取代BMP文件在VC中的应用,无疑还是很有吸引力的。 
二、 设计思路 
  虽然有一些操作、处理JPEG、GIF等其他格式图像的Active X控件,但总的来说使用起来并不太方便,笔者经过实验摸索,总结出了一种借助于COM接口的OLE方法来实现上述功能的一种简便方法,现介绍如下以飨广大读者: 
下面我们要使用IPicture 的COM接口,有必要对该图像接口做些了解:该接口主要管理图像对象及其属性,图像对象为位图、图标和图元等提供一种与语言无关的抽象。和标准的字体对象一样,系统也提供了对图像对象的标准实现。其主要的接口是IPicture和IPictureDisp,后者是由IDispatch接口派生以便通过自动化对图像的属性进行访问。图像对象也支持外部接口IPropertyNotifySink,以便用户能在图像属性发生改变时作出决定。图像对象也支持IPersistStream接口,所以它能从一个IStream接口的实例对象保存、装载自己,而IStream接口也支持对流对象的数据读写。 
  我们可以用函数OleLoadPicture从包含有图像数据的流中装载图像。该函数简化了基于流的图像对象的创建过程,可以创建一个新的图像对象并且用流中的内容对它进行初始化。其函数原型为: 
STDAPI OleLoadPicture( IStream * pStream, //指向包含有图像数据的流的指针LONG lSize, //从流中读取的字节数BOOL fRunmode, //图像属性对应的初值REFIID riid, //涉及到的接口标识,描述要返回的接口指针的类型VOID ppvObj // 在rrid中用到的接口指针变量的地址); 

 

三、 具体的实现 
  在显示图像之前,首先要获取到图像文件的存放路径,这里采用标准的文件打开对话框来选取图像文件,文件名存放在CString型的变量m_sPath中: 
CFileDialog dlg(TRUE,"jpg","*.jpg", 
OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT, 
"JPEG文件(*.jpg)|*.jpg|GIF文件(*.gif)|*.gif||",NULL); 
if(dlg.DoModal()==IDOK) 

m_sPath=dlg.GetPathName(); 
Invalidate(); 

为简单计,图形显示的代码直接在视类中的OnDraw中编写,首先打开文件并判断文件的可用性,并把文件内容放到流接口IStream的对象pStm中: 
IStream *pStm; 
CFileStatus fstatus; 
CFile file; 
LONG cb; 
…… 
if (file.Open(m_Path,CFile::modeRead)&&file.GetStatus(m_Path,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); 





  然后,就直接调用OleLoadPicture函数从流中装载图像:
IPicture *pPic; 
…… 
OleLoadPicture(pStm,fstatus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic)); 


  由于该函数有时会导致失败,所以应当用SUCCEEDED宏来做一些适当的保护工作,只有在数据装载成功的前提下才能继续下面的图像显示工作: 
if(SUCCEEDED(OleLoadPicture(pStm,fstatus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic))) 

OLE_XSIZE_HIMETRIC hmWidth; 
OLE_YSIZE_HIMETRIC hmHeight; 
pPic->get_Width(&hmWidth); 
pPic->get_Height(&hmHeight); 
double fX,fY; 
…… 
fX = (double)pDC->GetDeviceCaps(HORZRES)*(double)hmWidth/((double)pDC->GetDeviceCaps(HORZSIZE)*100.0); 
fY = (double)pDC->GetDeviceCaps(VERTRES)*(double)hmHeight/((double)pDC->GetDeviceCaps(VERTSIZE)*100.0); 
if(FAILED(pPic->Render(*pDC,0,0,(DWORD)fX,(DWORD)fY,0,hmHeight,hmWidth,-hmHeight,NULL))) 
AfxMessageBox("渲染图像失败!"); 
pPic->Release(); 

else 
AfxMessageBox("从流中装载图像失败!"); 



  其中,显示工作主要是由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 //指向目标图元设备环境句柄的指针); 


  小结:到此为止,通过上述代码已经能够在程序的客户区内显示JPEG、GIF等标准的图像了,但对于有多帧图片(即有动画)的GIF格式的图像,目前还只能显示第一帧,如要完整的显示GIF 动画的全过程,还需要外部Active X控件的支持。


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 怀孕痔疮老脱出怎么办 顺产后浑身酸疼怎么办 爬山后肌肉酸疼怎么办 手上打针胳膊疼怎么办 狗 打针后疼痛怎么办 流产后浑身酸疼怎么办 屋子里潮湿有味怎么办 墙潮湿发霉有味怎么办 当兵体检没有过怎么办 航空面试有纹身怎么办 儿童眼睛外斜视怎么办 大疆imu异常怎么办 新生儿血液回流不好怎么办 灌肠温度高了怎么办 炎症引起的咳嗽怎么办 90岁老人肠梗阻怎么办 84岁老人肠梗阻怎么办 婴儿开塞露后大便肚子疼怎么办 孕早期用开塞露肚子疼怎么办 冰点脱毛后刺痛怎么办 医院建不上档怎么办 dnf输入变繁体怎么办 机械钟表不走了怎么办 火柴枪卡住了怎么办 dnf卖掉的东西怎么办 mac恢复备份失败怎么办 割的双眼皮凹陷怎么办 公司聚餐不想去怎么办 左前分支阻滞怎么办 新电脑特别卡怎么办 夜神安卓模拟器网络没有怎么办 电脑磁盘占用率100怎么办 逆战没有语音怎么办 qt语音登陆不了怎么办 电脑无法识别键盘怎么办 金立f106耗电快怎么办 移动网络速度慢怎么办 手机wifi网络不稳定怎么办 试管取卵腹水怎么办 取卵术后便秘怎么办 基础卵泡3个怎么办