MFC 显示位图 缩放与拖动的矛盾
MFC多文档视图类,使用SetDIBitsToDevice显示位图,并实现拖动和缩放的功能。对于缩放,1.如果是一次性对整张图进行重采样,计算获得的lpvBits存储了整...
MFC多文档视图类,使用SetDIBitsToDevice显示位图,并实现拖动和缩放的功能。
对于缩放,1.如果是一次性对整张图进行重采样,计算获得的lpvBits存储了整张图缩放后的图像数据,然后完成缩放操作后,对其进行拖动显示会相当流畅,但是如果影像尺寸大(如10000*10000的图像放大到500%)整个缩放计算的过程就久;2.如果是只针对当前将要显示的部分进行缩放,即首先确定缩放后屏幕显示的范围,lpvBits只存储这个范围的数据,则当拖动的时候(即不断执行OnDraw),则lpvBits都重新计算一次,这样的话,每次缩放都很快,即使图像再大,缩放比例再大,循环次数也一样,因为不必一次性完成全图的缩放,只是计算缩放当前部分,而每当拖动的时候,都要重新计算lpvBits存储的值,这样就会导致拖动的时候比较卡,不像一次性完成全图缩放计算之后再拖动时那么流畅。
总结一下就是:1.缩放计算针对全图,则计算时间长,但计算之后拖动流畅;2.缩放计算针对当前要显示的区域,则计算时间短,但拖动时不流畅(即每次执行OnDraw都要重新计算一次lpvBits的值)。
请问一般怎么解决这个问题?因为我看到很多软件,缩放速度块,缩放后拖动也流畅。
是否除了SetDIBitsToDevice、StretchDIBits,还有其它用于位图显示的函数?能够便于处理上述问题?
PS:1.是缩放显示,不是对原图大小进行改变,只是显示,重采样的只是用于显示的数据;2.StretchDIBits能指定目标矩阵和源矩阵,然后该函数能完成拉伸,但是更卡,不考虑。 展开
对于缩放,1.如果是一次性对整张图进行重采样,计算获得的lpvBits存储了整张图缩放后的图像数据,然后完成缩放操作后,对其进行拖动显示会相当流畅,但是如果影像尺寸大(如10000*10000的图像放大到500%)整个缩放计算的过程就久;2.如果是只针对当前将要显示的部分进行缩放,即首先确定缩放后屏幕显示的范围,lpvBits只存储这个范围的数据,则当拖动的时候(即不断执行OnDraw),则lpvBits都重新计算一次,这样的话,每次缩放都很快,即使图像再大,缩放比例再大,循环次数也一样,因为不必一次性完成全图的缩放,只是计算缩放当前部分,而每当拖动的时候,都要重新计算lpvBits存储的值,这样就会导致拖动的时候比较卡,不像一次性完成全图缩放计算之后再拖动时那么流畅。
总结一下就是:1.缩放计算针对全图,则计算时间长,但计算之后拖动流畅;2.缩放计算针对当前要显示的区域,则计算时间短,但拖动时不流畅(即每次执行OnDraw都要重新计算一次lpvBits的值)。
请问一般怎么解决这个问题?因为我看到很多软件,缩放速度块,缩放后拖动也流畅。
是否除了SetDIBitsToDevice、StretchDIBits,还有其它用于位图显示的函数?能够便于处理上述问题?
PS:1.是缩放显示,不是对原图大小进行改变,只是显示,重采样的只是用于显示的数据;2.StretchDIBits能指定目标矩阵和源矩阵,然后该函数能完成拉伸,但是更卡,不考虑。 展开
展开全部
看了你的描述,我有几点想法看能不能帮到你吧。
第一,关于缩放。像ACDSee,缩放只支持固定的几种大小,50,75,100,125,150,300……如果你对缩放大小没有要求的话,可以像他这样,只支持几种固定的大小,然后在加载的时候,把你算好的位图数据提前存入相关的内存中,缩放到相应的大小直接显示就行。
第二,如果你想实现精确的缩比(比如1%比例的),你可以试一下使用GDI+,使用GDI的库,运行速度要快很多,具体能达到什么效果因为没实现过你这类的功能所以不敢确定。
第三,如果你不想用GDI的库,还想实现精确控制的话,你可以试试做一下多线程缓冲。比如你启动的时候另启一个缓冲线程,这个线程用来计算全部的lpvBits数据。当你第一次放大至很大时,只计算当前的缩放,而同时,使用消息也好还是事件也好,让缓冲线程计算当前放大页面的全部数据,计算完成后,使用标志位之类的随你,总之,OnDraw就不用再次计算lpvBits中的值了,直接使用缓冲线程的数据就可以了。大体这么个流程,具体实现个人感觉没什么太复杂的地方,理论上也是可行的。
PS:对bitmap只算是用过几次,发表一下个人的想法,能帮上最好,要是觉得我的想法不可行,可以继续交流。
第一,关于缩放。像ACDSee,缩放只支持固定的几种大小,50,75,100,125,150,300……如果你对缩放大小没有要求的话,可以像他这样,只支持几种固定的大小,然后在加载的时候,把你算好的位图数据提前存入相关的内存中,缩放到相应的大小直接显示就行。
第二,如果你想实现精确的缩比(比如1%比例的),你可以试一下使用GDI+,使用GDI的库,运行速度要快很多,具体能达到什么效果因为没实现过你这类的功能所以不敢确定。
第三,如果你不想用GDI的库,还想实现精确控制的话,你可以试试做一下多线程缓冲。比如你启动的时候另启一个缓冲线程,这个线程用来计算全部的lpvBits数据。当你第一次放大至很大时,只计算当前的缩放,而同时,使用消息也好还是事件也好,让缓冲线程计算当前放大页面的全部数据,计算完成后,使用标志位之类的随你,总之,OnDraw就不用再次计算lpvBits中的值了,直接使用缓冲线程的数据就可以了。大体这么个流程,具体实现个人感觉没什么太复杂的地方,理论上也是可行的。
PS:对bitmap只算是用过几次,发表一下个人的想法,能帮上最好,要是觉得我的想法不可行,可以继续交流。
展开全部
你这样的两种方式都有缺点,我不清场你怎样使用的内存DC。提供你两个优化办法:
1·其实你第二种方法,我认为通过两个处理可以很好的优化,一个是以当前视口为中心,做3*3一共9个视口大小的区域图进行缩放计算,这样在移动的时候根本不需要重新计算,只需要松开鼠标后再做一次3*3的运算就可以了;另外一个下面一起解释。
2·StretchDIBits并非不可取,你在内存中建立第二个内存DC,将原图通过StretchDIBits缩放到第二内存DC中,这样每次刷新只需要内存DC到设备DC的BitBlt就可以了,会很快(同样最好是3*3);另外就是和1里面一样,你每次拖动比较卡的原因还有一个就是界面刷新问题,CScrollView有一个优化,就是对于BitBlt,滚动的时候不是全屏刷新,而是只刷新更新区域,这样显示就快,如果你在做自定义滚动的时候是全屏刷新,那么显示的闪烁和卡就是必然的。
1·其实你第二种方法,我认为通过两个处理可以很好的优化,一个是以当前视口为中心,做3*3一共9个视口大小的区域图进行缩放计算,这样在移动的时候根本不需要重新计算,只需要松开鼠标后再做一次3*3的运算就可以了;另外一个下面一起解释。
2·StretchDIBits并非不可取,你在内存中建立第二个内存DC,将原图通过StretchDIBits缩放到第二内存DC中,这样每次刷新只需要内存DC到设备DC的BitBlt就可以了,会很快(同样最好是3*3);另外就是和1里面一样,你每次拖动比较卡的原因还有一个就是界面刷新问题,CScrollView有一个优化,就是对于BitBlt,滚动的时候不是全屏刷新,而是只刷新更新区域,这样显示就快,如果你在做自定义滚动的时候是全屏刷新,那么显示的闪烁和卡就是必然的。
本回答被提问者采纳
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
您一些参考方案,我直接写:的
CBitmap的位图; / /自定义位图变量的
bitmap.LoadBitmap的(IDB_BITMAP1); / /获取位图的ID
的bmp位图;
bitmap.GetBitmap(BMP);
CDC直流;
dc.CreateCompatibleDC(PDC); / /创建一个DC
dc.SelectObject(位图) / /选择
了CRect矩形
GetClientRect(正确);
PDC->的StretchBlt(0,0,rect.Width(),rect.Height(的直流设备描述表)直流,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
/ /显示位图
CBitmap的位图; / /自定义位图变量的
bitmap.LoadBitmap的(IDB_BITMAP1); / /获取位图的ID
的bmp位图;
bitmap.GetBitmap(BMP);
CDC直流;
dc.CreateCompatibleDC(PDC); / /创建一个DC
dc.SelectObject(位图) / /选择
了CRect矩形
GetClientRect(正确);
PDC->的StretchBlt(0,0,rect.Width(),rect.Height(的直流设备描述表)直流,0,0,bmp.bmWidth,bmp.bmHeight,SRCCOPY);
/ /显示位图
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
CDC类的BitBlt()来显示
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
展开全部
CDC类的BitBlt()来显示
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询