views:

220

answers:

3

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?

+1  A: 

Software blitting seems like a severe bottleneck. I would seriously suggest looking into hardware accelerated drawing for a task like this.

Sparr
At least the neck got noticably wider.
Kawa
+1  A: 

a simple Get/SetPixel loop was as fast as a DrawImageUnscaled call

Then you are definitely doing something wrong. The GetPixel and SetPixel methods has quite some overhead, using any of the DrawImage 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 the InterpolationMode property to NearestNeighbor to keep it from doing any interpolation.

An alternative to drawing on the bitmap would be to use LockBits and UnlockBits to get access to the bitmap's pixel data directly.

Guffa
+1  A: 

There is an excellent answer for this at.. http://stackoverflow.com/questions/190385/how-to-manipulate-images-at-pixel-level-in-c

If you do go the LockBits route could you post a follow-up with the speed differences.

Chris Masterton
I will look there right now, and see what I can come up with. Thanks.
Kawa