求MFC中高效显示jpeg图片的方法?

chenzhenghui_hw 2016-08-09 11:42:50
各位大神,本人要在MFC的对话框中显示本地硬盘的一幅jpeg图片,用的是如下代码。问题是,如果一个文件夹下有多幅图片,要想在一个界面上依次显示,则会非常耗时。我检查了下主要是调用 OleLoadPicture() 时消耗的时间最长(长达数百ms)。请问有什么方法能够高效显示jpeg图片啊?本人是菜鸟,这个又要得比较急,如果有哪位大神知道,希望能附上能直接使用的源代码,如果经本人测试能够使读取显示一幅图片的时间降低到几十ms甚至几ms,本人不甚感激哈!!原理性的指导现在本人短时间还消化不了的,最好附上高效显示的代码。100分就是他的了!谢谢~
/**************************************************************   代码开始    **********************************************/
int CAllPoleDiglog::ShowThumbNail(int nId)
{
char strTmp[MAX_PARA_LEN];
CString strPath;
LPVOID pvData;
IStream *pStm;
IPicture *pPic;
OLE_XSIZE_HIMETRIC hmWidth;
OLE_YSIZE_HIMETRIC hmHeight;
CDC* pDC;
int s32PicWidth;
int s32PicHeight;
int x = 0;
int y = 0;
CFileStatus fstatus;
CFile file;
ULONGLONG cb;
HGLOBAL hGlobal;


/************************************************
step2: 打开 jpeg 文件 m_apFileName[nId]
*************************************************/
strPath.Format(m_apFileName[nId]);
if (!file.Open(strPath,CFile::modeRead))
{
MessageBox("file has not found");
return -1;
}
if (!file.GetStatus(strPath, fstatus))
{
MessageBox("file status is not right");
return -1;
}
if ((cb =fstatus.m_size)<=0)
{
MessageBox("file size is error");
return -1;
}

/************************************************
step3: 根据文件大小分配内存空间,记得释放内存
*************************************************/
hGlobal = GlobalAlloc(GMEM_MOVEABLE, (unsigned int)cb);
if (hGlobal == NULL)
{
return -1;
}

/************************************************
step4: 锁定刚才分配的内存空间
*************************************************/
pvData = GlobalLock(hGlobal);
if (pvData == NULL)
{
GlobalFree(hGlobal); // 记得释放内存
return -1;
}

/************************************************
step5: 将文件放到流中
*************************************************/
file.Read(pvData,(unsigned int)cb);
GlobalUnlock(hGlobal);
CreateStreamOnHGlobal(hGlobal, TRUE, &pStm);

/************************************************
step6: 从流中加载图片 (能显示jpeg图片和gif图片的一帧)
*************************************************/
if(OleLoadPicture(pStm,(LONG)fstatus.m_size,TRUE,IID_IPicture,(LPVOID*)&pPic)!=S_OK)
{
GlobalFree(hGlobal); // 记得释放内存
return -1;
}

/************************************************
step7: 获取图像宽和高,注意这里的宽和高不是图像的分辨率
*************************************************/
pPic->get_Width(&hmWidth);
pPic->get_Height(&hmHeight);

/************************************************
step8: use render function display image
*************************************************/
x = m_aCRectThumbNail[nId].left;
y = m_aCRectThumbNail[nId].top;
s32PicWidth = m_aCRectThumbNail[nId].right - m_aCRectThumbNail[nId].left;
s32PicHeight = m_aCRectThumbNail[nId].bottom - m_aCRectThumbNail[nId].top;

pDC = GetDC();
if(FAILED(pPic->Render(*pDC, x, y, s32PicWidth, s32PicHeight, 0, hmHeight, hmWidth, -hmHeight, NULL)))
{
pPic->Release();
GlobalFree(hGlobal); // 记得释放内存
return -1;
}

if (NULL != hGlobal)
{
GlobalFree(hGlobal); // 记得释放内存
}
ReleaseDC(pDC);
pPic->Release();

return 0;
}

/************************************************************** 代码结束 **********************************************/
...全文
381 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2016-08-12
  • 打赏
  • 举报
回复
ACDSee真的已经落伍到“当年的”了吗?
  • 打赏
  • 举报
回复
引用 2 楼 boylafong 的回复:
我正好做过多张大图片的显示 先遍历文件夹下面所有图片,记下文件路径,存到一个结构里面 用3个缓存区在初始化的时候存下三张图片内容 缓存好了之后开始显示图片,一拖动后,线程马上重新读取一张(因为已经有三张缓存,所以在显示或者滑动的时候不会卡)
可以试着模拟jpg2000的方式,缓存全部的小图,然后显示的时候如果正在读取大图,就先显示出来放大的小图(当然质量)不行,等大图加载完成之后,显示大图。有不少网页都是这样做的。当年的ACDSee也是这样做的。
xiaohuh421 2016-08-12
  • 打赏
  • 举报
回复
为什么不使用GDI+ Image img( "d:\\img\\phto.jpg"); CDC *pDC = GetDC(); Graphics gp(pDC->m_hDC); gp.DrawImage(&img,0,0); ReleaseDC(pDC);
  • 打赏
  • 举报
回复
引用 11 楼 zhao4zhong1 的回复:
ACDSee真的已经落伍到“当年的”了吗?
引用 12 楼 dongycumt 的回复:
现在还很普遍ACDSee Plus
唉,我已经很少用这个了。。。 好吧,其实是不需要了。用不到了。。。
雪狼__ 2016-08-12
  • 打赏
  • 举报
回复
现在还很普遍ACDSee Plus
chenzhenghui_hw 2016-08-11
  • 打赏
  • 举报
回复
引用 4 楼 shenyi0106 的回复:
首先,IO问题的优化,需要建立缓存机制和预读取机制,没有其他更好的办法。 其次,就刷图而言,如果不牵涉到缩放的话,CImage效率还是挺不错的,而且是MFC自带的类,用起来没负担。 亲测,载入一张内存的1080P的JPG,然后画到HDC上,用时在30ms左右。 如果要放大的话,就不要用它了,效率很差的。建议用libjpeg-turbo先处理成YUV12,然后用direcXt的surface来画,整套下来,平均大概在40ms左右 只提供思路,不提供代码
谢谢哈。有时间我试试。
chenzhenghui_hw 2016-08-11
  • 打赏
  • 举报
回复
引用 6 楼 boylafong 的回复:
[quote=引用 5 楼 chenzhenghui_hw 的回复:] [quote=引用 2 楼 boylafong 的回复:] 我正好做过多张大图片的显示 先遍历文件夹下面所有图片,记下文件路径,存到一个结构里面 用3个缓存区在初始化的时候存下三张图片内容 缓存好了之后开始显示图片,一拖动后,线程马上重新读取一张(因为已经有三张缓存,所以在显示或者滑动的时候不会卡)
有很多不同的文件夹下都有图片,而不是一个文件夹下哈。所以,这种方法不好使哈。还是谢谢你[/quote] 这有关系吗?只要提前把文件路径存起来就可以了啊?你要显示的图片预先知道吧[/quote] 要显示的图片分放在不同的文件夹下,路径都存到一个文件中了。但下个时候要显示哪个文件夹下的图片却不知道(每个文件夹下有几十张图片,都要在一张界面上显示)。鼠标点击滑动条控件这个动作是随机的,可能拖到任意位置哈。
  • 打赏
  • 举报
回复
用Gdiplus
boylafong 2016-08-11
  • 打赏
  • 举报
回复
引用 5 楼 chenzhenghui_hw 的回复:
[quote=引用 2 楼 boylafong 的回复:] 我正好做过多张大图片的显示 先遍历文件夹下面所有图片,记下文件路径,存到一个结构里面 用3个缓存区在初始化的时候存下三张图片内容 缓存好了之后开始显示图片,一拖动后,线程马上重新读取一张(因为已经有三张缓存,所以在显示或者滑动的时候不会卡)
有很多不同的文件夹下都有图片,而不是一个文件夹下哈。所以,这种方法不好使哈。还是谢谢你[/quote] 这有关系吗?只要提前把文件路径存起来就可以了啊?你要显示的图片预先知道吧
shenyi0106 2016-08-10
  • 打赏
  • 举报
回复
首先,IO问题的优化,需要建立缓存机制和预读取机制,没有其他更好的办法。 其次,就刷图而言,如果不牵涉到缩放的话,CImage效率还是挺不错的,而且是MFC自带的类,用起来没负担。 亲测,载入一张内存的1080P的JPG,然后画到HDC上,用时在30ms左右。 如果要放大的话,就不要用它了,效率很差的。建议用libjpeg-turbo先处理成YUV12,然后用direcXt的surface来画,整套下来,平均大概在40ms左右 只提供思路,不提供代码
  • 打赏
  • 举报
回复
刚刚开学习MFC,前来围观学习
chenzhenghui_hw 2016-08-10
  • 打赏
  • 举报
回复
引用 2 楼 boylafong 的回复:
我正好做过多张大图片的显示 先遍历文件夹下面所有图片,记下文件路径,存到一个结构里面 用3个缓存区在初始化的时候存下三张图片内容 缓存好了之后开始显示图片,一拖动后,线程马上重新读取一张(因为已经有三张缓存,所以在显示或者滑动的时候不会卡)
有很多不同的文件夹下都有图片,而不是一个文件夹下哈。所以,这种方法不好使哈。还是谢谢你
boylafong 2016-08-10
  • 打赏
  • 举报
回复
我正好做过多张大图片的显示 先遍历文件夹下面所有图片,记下文件路径,存到一个结构里面 用3个缓存区在初始化的时候存下三张图片内容 缓存好了之后开始显示图片,一拖动后,线程马上重新读取一张(因为已经有三张缓存,所以在显示或者滑动的时候不会卡)
zgl7903 2016-08-10
  • 打赏
  • 举报
回复
如果文件很大的话, 可能光读文件就需要很长时间 可以考虑后台多线程加载, 显示第一个的时候,后台就加载后面的图片,这样也就第一个有些迟钝,后续的就感觉不出来了

15,979

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧