这个瓷砖碎片能变得更快吗?
当我用 C# 制作基于图块的地图编辑器时,我倾向于迭代 X、Y 轴并调用 Graphics.DrawImage() 将单个图块从图块集位图位图传输到地图位图上。 这个过程需要几秒钟才能完成,所以我只在加载新地图或更改其图块集时执行一次。 此后的任何编辑都是仅编辑过的图块的相对快速的位图传输。
现在,我今天早些时候坐下来思考我的选择。 Graphics.DrawImage() 是三个中唯一一个(其他的是 DrawImageUnscaled 和 DrawImageUnscaledAndCropped(?)),它允许指定源原点。 DrawImageUnscaled() 速度快得多,但总是从源位图的左上角进行位图传输。
与 QuickBasic PSET 与 POKEing 视频内存的速度,或者 VB6 的 PSet 与 WinAPI 的 SetPixel 的速度形成鲜明对比,一个简单的 Get/SetPixel 循环与 DrawImageUnscaled 调用一样快,但只进行了 DrawImage 的裁剪操作否则会这样做。
目前这已经足够快了,但我想知道直接图像处理之类的东西如何能够加快速度? 也许是 LockBits 的一些东西,一个我几乎一无所知的函数?
When I make a tile-based map editor in C#, I tend to iterate over the X,Y axes and call Graphics.DrawImage() to blit a single tile in place, from a tileset Bitmap onto a map Bitmap. This process takes several seconds to complete, so I only do it once when loading a new map or changing its tileset. Any edits from there on are relatively fast blits of only the edited tile.
Now, I sat back earlier today and thought about my options. Graphics.DrawImage() is the only one of the three (the others being DrawImageUnscaled and DrawImageUnscaledAndCropped(?)) that allows the specification of a source origin. DrawImageUnscaled() was much, much faster, but always blitted from the top-left of the source bitmap.
In sharp contrast with the speeds of QuickBasic PSET versus POKEing the video memory, or VB6's PSet versus WinAPI's SetPixel, a simple Get/SetPixel loop was as fast as a DrawImageUnscaled call, but did the cropping that only DrawImage would otherwise do.
This is fast enough for now, but I was wondering how something like direct image manipulation could speed it up even more? Something with LockBits perhaps, a function I know next to nothing about?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
软件位块传送似乎是一个严重的瓶颈。 我强烈建议您研究硬件加速绘图来完成这样的任务。
Software blitting seems like a severe bottleneck. I would seriously suggest looking into hardware accelerated drawing for a task like this.
那么你肯定做错了什么。
GetPixel
和SetPixel
方法有相当大的开销,使用任何DrawImage
方法应该快 100 倍左右(除非你的图块非常小,如 2x2 像素)。与它的名称相反,DrawImageUnscaled 方法不会在不调整大小的情况下进行绘制。 相反,它使用图像的 PPI 设置将它们缩放到相同的尺寸。 这意味着,如果您有一个设置为 100 PPI 的位图,并在其上绘制一个设置为 50 PPI 的位图,则它将调整为双倍大小。
如果您以不变的尺寸绘制图像,则可以更改
Graphics
对象中的质量设置来调整速度。 例如,您可以将InterpolationMode
属性设置为NearestNeighbor
以防止其进行任何插值。在位图上绘图的另一种方法是使用
LockBits
和UnlockBits
直接访问位图的像素数据。Then you are definitely doing something wrong. The
GetPixel
andSetPixel
methods has quite some overhead, using any of theDrawImage
methods should be somehting like 100 times faster (unless perhaps if your tiles are very small, like 2x2 pixels).Contrary to it's name, the DrawImageUnscaled method doesn't draw without resizing. Instead it uses the PPI settings of the images to scale them to the same measurements. That means that if you have a bitmap with the setting 100 PPI, and draw on it a bitmap with the setting 50 PPI, it will be resized to the double size.
If you are drawing the images at unchanged size, you can change the quality settings in the
Graphics
object to tweak the speed. You can for example set theInterpolationMode
property toNearestNeighbor
to keep it from doing any interpolation.An alternative to drawing on the bitmap would be to use
LockBits
andUnlockBits
to get access to the bitmap's pixel data directly.