GDI 显示已有的像素数组,用什么方法最高效
1、像素数组是程序计算好的,已经行4字节对齐
2、像素数据被修改后需要重新显示,即一个像素数组会被多次使用
[最优解释]
如果你的数据完全符合BMP的标准,使用SetDIBitsToDevice(不缩放显示) 和 StretchDIBits(缩放)子哦最为快捷方便。
[其他解释]
我是支持1楼的2个函数的DIB这个最高效了。不信楼主可以继续等高手。
[其他解释]
那就楼主的这个问题本身来说 CreateDIBSection + BitBLt就绝对不会比 SetDIBitsToDevice这个函数来的快了。
我想我在也不会怀疑我自己的想法了。
[其他解释]
CreateDIBSection不是显示函数。如果已经有数据了,用这个函数来显示,还要把原始数据复制过来,然后再通过bitblt或strechblt函数来显示到DC上,不可能比SetDIBitsToDevice 和 StretchDIBits来的快。
如果楼主的数据部不符合BMP规范,那就需要CreateDIBSection发挥作用了。
楼主既然关心显示的速度问题,那就应该是要做动态的效果,屏幕就那么大,如果设计的合理,最多也就只需要输出屏幕大小的图,用SetDIBitsToDevice或StretchDIBits 这样的函数显示这么大的图,实时性根本不用担心。
[其他解释]
关于CreateDIBSection的使用我解释如下:
1)CreateDIBSection会返回一个指针,我们可以直接使用这个指针指向的空间(就如同FrameBuffer一样),然后使用BitBlt将画面直接输出到设备上,注意BitBlt的速度要比StretchDIBits快(否则Adobe也不至于滥到不知道用StretchDIBits了吧 --- 尽管我不喜欢Adobe)
2)StretchDIBits有个Buffer指针,CreateDIBSection也有个Buffer指针,我不理解CreateDIBSection为什么不能用这个Buffer,而StretchDIBits就可以呢?为什么CreateDIBSection就要傻傻的复制,而StretchDIBits就不需要呢?注意:CreateDIBSection虽不是直接的显示函数,但它提供了一种渠道可以使用户直接操作显示缓冲区 ---- 这是任何DC操作所无法比拟的;所以似乎只有DirectX可以这样;
3)如果您的图形有缩放,那还是使用StretchDIBits了;
在Windows 95刚出现时,那个时候DirectX(第一版本实际叫GameSDK)还没有出现时,我们写PC游戏都是用CreateDIBSection:那其中多数图形并非是直接在这个Buffer上绘制的,而是所有动画实际先准备在若干的BackBuffer中 ----- 及LZ所说的数据是准备好的;
[其他解释]
tomsoft: 有个问题想请教一下:
我非常喜欢CreateDIBSection这个函数,不过这个函数是否能从已经分配好的内存中 创—IBSECTION,似乎我一直都没试验成功。如果能,那就太好了,不知能否给出这样的调用示例。
另外,似乎不能拿BitBlt和StretchDIBits来比较,两者功效不一样。
当然,如果我是楼主,我就会先直接创建好DIBSECTION,然后往这个DIBSECTION分配好的BUFFER中写数据,最后通过bltblt或者 StrechBlt来显示。
[其他解释]
限于GDI的话,肯定是SetDIBitsToDevice快,这个API相当于把一个BITMAP(像素数组由CONST VOID *lpvBits指出,格式由CONST BITMAPINFO *lpbmi指出)直接BitBlt到某个DC。
CreateDIBSection只是建立一个BITMAP,允许用户直接写到它的内存数据,不用SelectObject到某个DC再绘制,但这只是直接读写BITMAP,你要显示这个BITMAP,还得先SelectObject,然后BitBlt。
[其他解释]
用VFW的话,直接写入显存,不依赖任何GDI机制。以前的XingPlayer之类的VCD播放器普遍用的这种方式绘图。不过呢,VFW是很老很老的东西了(GDI也一样老),如果你要写主要在Win7/Vista上跑的程序,还是建议你用OpenGL/DirectX,将其作为纹理渲染到立方体上,这种方式可以有更多的操纵方式,比如写Shader程序利用GPU运算实现一些特效什么的,和Win7/Vista的DWM显卡驱动兼容性也更好,当然了,程序也要麻烦复杂很多。
[其他解释]
当然有了,有比GDI更高效的绘制位图的方法。CreateDIBSection的复制的确挺多余的。
Win95引入的Video For Windows(VFW)提供了DrawDib功能,这个是直接利用显卡驱动绘制功能,是DirectX出现之前最快的绘图方法了,而且它支持快速褪色功能,就是在低色深的显示器上绘制高色深的位图。使用它也需要构造一个BitmapInfoHeader头,但是并不需要复制数据,直接用指针给出数据位置就可以了。当然了,用VFW需要安装Windows SDK。
看看这个:http://msdn.microsoft.com/en-us/library/windows/desktop/dd797892.aspx
[其他解释]
为什么肯定呢?和CreateDIBSection配合的是BitBlt,任何有Windows编程经验的都知道BitBlt是最快的
[其他解释]
这个您错了,是用BitBlt,人人有编程经验都知道BitBlt比您说的那个函数快。
[其他解释]
CreateDIBSection的正确用法是利用它返回的缓冲区直接作为FrameBuffer使用,然后使用BitBlt(配合DirtyRect就更好了)这样的效率是最高的---直接硬件传输;
DrawDib确实比广泛使用的StretchDIBits快,但我印象中DrawDib似乎不是标准GDI的函数,应该是vfw的,如果是这样我道建议使用DirectX。
[其他解释]
但是用DirectX比较麻烦啊。在Direct2D已经被遗弃的时候,现在只有使用Direct3D进行开发,我也说了,Direct3D要求将你的图像转换为纹理贴图到立方体的表面,所以需要一定的3D开发经验。由于显卡的硬件限制,往往只支持512x512这样的2的整数幂的乘积的形式贴图,还需要对你的图像进行修改。总之程序会麻烦很多。
所以最简单又快的方法就是DrawDib,我也说了DrawDib根本不依赖任何GDI机制,是直接通过显卡驱动向显存写入数据的。这个是得到设计上保证的。而GDI的方法,总是要涉及位图数据在内存和DC中的拷贝,而Bitblt的硬件加速不是被保证的,也就是说GDI不一定会直接写显存。
回帖的时候请先看清楚好不好?
[其他解释]
用内存DC bitblt 或stretchBlt到响应设备DC中。
CDC memDC;
memDC.CreateCompatibleDC(pdc);
memDC.SelectObject(m_pBitmap);
ret = pdc->StretchBlt(m_display_x,m_display_y, m_displaySize.cx, m_displaySize.cy,
&memDC,0,0,m_ImageSize.cx, m_ImageSize.cy, SRCCOPY);
[其他解释]
GDI就是1楼说的,当然directshow更快
[其他解释]
CreateDIBSection应该是效能最高的 ---- 在DirectX没有出现时,这个函数是替代DirectDraw
[其他解释]
刚在微软的文档中看到:"The CreateDIBSection function creates a DIB that applications can write to directly. "
因为是直接写,所以应该是CreateDIBSection最快,他提供了类似嵌入系统直接操作FrameBuffer的方式。
[其他解释]
最后为了证明我说的是对的,我刚刚反向了一下Adobe的FlashPlayer 10,我找到了其显示部分,用的就是CreateDIBSection;
[其他解释]
有些地方需要更正,对于多数显示屏幕,显示分辨率都会超过1280 x 800(我不清楚现在主流是多少,反正我现在用的一个老爷显示器是1680 x 1050),这样分辨率使用StretchDIBits全屏刷新,我相信除非你的CPU足够强悍,想要流畅还有问题 ---- 更不要说期间进行与图形变换有关的操作;所以除显示函数的选择和使用技巧,刷新技巧是关键 ---- 如DirtyRect技术的使用;
[其他解释]
我需要的是执行效率高的方法
[其他解释]
1、数据时像素数组,不是 HBITMAP
2、用的是GDI,不是MFC环境
[其他解释]
谢谢,可是我的像素数据是已经计算好的,CreateDIBSection是自己申请缓存
[其他解释]
不了解.
[其他解释]
测试结果: CreateDIBSection + BitBLt 和 SetDIBitsToDevice 速度相当
SetDIBitsToDevice 更加便捷,因此使用这个函数
[其他解释]
SetDIBitsToDevice 更加方便,可以直接用来显示放在buf里的数据(位图)