有没有比 GDI GetPixel() 更快的替代方法?
我在 .NET 应用程序中使用 gdi32.dll 中的 GetPixel()
对屏幕上任意位置的像素颜色进行采样。它工作正常,但对我来说这是一个主要的性能瓶颈。
有没有更快的方法?
I'm using GetPixel()
from gdi32.dll in a .NET app to sample the colour of a pixel anywhere on the screen. It works ok but it is a major performance bottleneck for me.
Is there a faster way of doing it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
使用
Bitmap
的LockBits()
方法可以快速访问像素。这将返回一个对象,其中包含指向像素数据开头的指针,并且您可以使用不安全的代码来访问内存。https://web.archive.org/web/ 20150330113356/http://bobpowell.net/lockingbits.aspx
Fast access to pixels are possible using
LockBits()
method of theBitmap
. This will return to you an object containing a pointer to the start of the pixel data and you can use unsafe code to access the memory.https://web.archive.org/web/20150330113356/http://bobpowell.net/lockingbits.aspx
GetPixel
速度较慢有两个原因:由于您正在轮询屏幕 - 每次调用
GetPixel
都会导致视频驱动程序发生事务,而视频驱动程序又需要来自视频内存的像素数据。相比之下,在 DIB 上使用
GetPixel
速度要快得多。无论如何,
GetPixel
可以做几件事,包括坐标剪切/转换等。因此,如果您用于一次查询许多像素值 - 您应该尝试将其安排在 GDI / 视频的单个事务中司机。
使用 GDI,您应该创建一个足够大小的 DIB(请参阅
CreateDIBSection
)。创建后,您将获得一个指向图像位数据的直接指针。然后将图像部分复制到您的 DIB 上(请参阅BitBlt
)。另外,在实际检查 DIB 的内容之前,不要忘记调用 GdiFlush(因为视频驱动程序可能会进行异步绘制)。使用 GD+,您实际上可以做同样的事情,但语法更简单一些。
GetPixel
is slow for two reasons:Since you're polling the screen - every call to
GetPixel
leads to a transaction to the video driver, which in turn takes the pixel data from the video memory.In constrast using
GetPixel
on DIBs is very much faster.Anyway
GetPixel
does several things, including coordinates clipping/transformations and etc.So that if you're using to query many pixel values at once - you should try to arrange this in a single transaction to GDI / video driver.
Using GDI you should create a DIB of the adequate size (see
CreateDIBSection
). After creation you'll be given a direct pointer to the image bits data. Then copy the image part onto your DIB (seeBitBlt
). Also don't forget to callGdiFlush
before you actually check the contents of the DIB (since video drivers may do asynchronous drawing).Using GD+ you may actually do the same, with a bit simpler syntax.