Archive for January, 2008

Fast rendering images in c# – part 2

As I reported in  previous part (fast drawing images using bitblt function), using this technique you actually can draw images about 8 times faster than using standard Graphics.DrawImage method. However, if you tried to do that, you probably noticed that the image is copied with its background, as is. Sometimes this result is not desired. For example when you have some symbol and string near it, moving the whole bitmap from memory to screen will move also all not used space between picture and string. Even if you not specified any background color, still blue color (default background) will be copied. Is it possible to avoid that? The good news are – you can. As my friend Michael Kogan pointed, there is another WINAPI function, called TransparentBlt. Its definition in C# look as the following:

[DllImport("Msimg32.dll")]
public static extern bool TransparentBlt(IntPtr hdcDest, // handle to destination DC
int nXOriginDest, // x-coord of destination upper-left corner
int nYOriginDest, // y-coord of destination upper-left corner
int nWidthDest, // width of destination rectangle
int hHeightDest, // height of destination rectangle
IntPtr hdcSrc, // handle to source DC
int nXOriginSrc, // x-coord of source upper-left corner
int nYOriginSrc, // y-coord of source upper-left corner
int nWidthSrc, // width of source rectangle
int nHeightSrc, // height of source rectangle
int crTransparent // color to make transparent
);

This function looks very similiar to BitBlt, and you should use it in the same way exactly (selectObject and all the other staff). You have working example to that in the previous part. There are 2 important differences between these functions: first, there is no raster operation here. It always using SourceCopy operation – just coping from DC to DC. Maybe you can use SetROP2 function – didn’t tryed yet, please let me know if it works. Second, last argument is crTransparent. That is exactly the color, which will be NOT copied from source. You should provide here Win32 color representation (COLORREF) structure. To convert Color object to COLORREF, use this:
int transparentColor = ColorTranslator.ToWin32(Color.Black);

Of cause, the color argument should be as the background color of the source image. As I mentioned before, it works and that is the good news. The bad news is that TransparentBlt slower than BitBlt. For 10000 drawings, BitBlt takes about 1100ms, when TransparentBlt takes about 1700ms. I will write here in case I discover something faster.

1 comment January 22, 2008

Key’s Equality in Hashtables (or who equal to who?)

Consider the following simple class:

public class SomeClass
{
uint _id = 125;public SomeClass(uint id)
  {
  _id = id;
  }
public override int GetHashCode()
  {
return (int)_id;
  }
}

We want to add instance of this class to hashtable, where the key is object’s ID, and the value is object itself. If we doing the following, it works:

SomeClass someClass = new SomeClass(125);
//1.

//========
hashTable[someClass.GetHashCode()] = someClass;
object returnValue = hashTable[125];
 

The returnValue is exactly our someClass instance. However, using value types as keys as bad, due to boxing each time key is passed to the hashtable. How we can improve this? Well, as known, inside hashtable ‘GetHashCode’ method is being called to determine the key. Therefore we can pass as a key the object itself, and override the ‘GetHashCode’ method (which is exactly what we did). Let’s try this code:

//2.
//===========
hashTable[someClass] = someClass;
SomeClass key =
new SomeClass(125);
returnValue = hashTable[key];

If you will run this code, you will see the returnValue is null. So what is wrong? When you trying to retrieve your object from hashtable and passing the key, hashtable using ‘Equals’ method, to find the right key. By default, after confirming the hashcode is the same, it comparing references, so in the code above the result is false. Obvious, the solution is to override the ‘Equals’ method (here is the one possible solution):

public override bool Equals(object obj)
{
return (_id == obj.GetHashCode());
}

If we run this code, that works ok. Now, we want to retrieve the object by passing the ID directly, without creating wrapper around it (as I said before, this is bad because of boxing – don’t do that in production code):

hashTable[someClass] = someClass;
returnValue = hashTable[125];

We overrided the Equals method, so this will work? No, it will not. You see, the hashtable comparing the passed key to the stored keys, and not storing keys to passed one. As a result, the ‘Equals’ method is invoked on the passed key – in our example it’s an integer – and it never equal to SomeClass, ofc. The conlcusion is: if you using your custom classes as hashtable keys, always override ‘GetHashCode’ and ‘Equals’ methods. And remember to use only your classes for the lookup inside the hashtable.

2 comments January 15, 2008

Converting CString to integer (VS 2005)

Well, today I got another reason to abandon MFC (this one added to very long list I already have). Consider this very simple task: convertion of CString to integer. Is can something be more basic than this?? Doing this in .NET takes, in worst case, 5 seconds? I took me about a hour to discover how to do that in MFC. In the VS 2003, the following code does works:

CString someText;
int value = atoi(someText);

However, in VS 2005 it doesn’t. atoi function assepts only const char*, and if you casting CString to const char*, you got only first digit of the number. Finally, I found some solution (God bless Internet) that works:

CString someText;
int value = _ttoi(static_cast<LPCTSTR>(someText));

I don’t know, how an average programmer supposed to discover this on his own. From my own experience, I saw string representation in about 10 different forms (in c++, ofc), and this is not trivial at all to convert from one form to other. Pfff…

6 comments January 14, 2008

Fast rendering images in c#

I will start this article with example: let say, we have some kind of GPS application. Our goal is to draw object’s current position on map. We represent object by symbol and maybe by some string near it. The symbol and its related text not changing, the only thing changing is position of the object on the map. We have to update object position very frequently, let say once at 500 ms.

Obvious, this is waste of CPU time to draw the symbol and text again and again each 500 ms. One way to improve performance is to store our object representation image (symbol or/and text, whatever) in memory, and each time copy its bits to different place on the map. At this point, everyone who claims to be Windows programmer should flash in his head word “BitBlt”. If you didn’t, I suggest you to review Windows programming basics, start from reading ‘Programming Windows’ by Charles Petzold. In short, BitBlt is Windows API function, which is copying bits from one Device Context (DC) to other. The common use of this function is implementation of Double Buffering – well known techniques to draw without “flickering”.

In demo application I prepared (download link here – hosted by RapidShare), I drawing text “Test string” using 3 ways:

  • Graphics.DrawString
  • Graphics.DrawImageUnscaled (which is fastest method in DrawImageXXX series)
  • Calling directly to unmanaged BitBlt function

To see differences in performance, I call each way 10000 times, and mesuring start and end times. Here are results (Athlon 64 bit dual core):

  • Calling Graphics.DrawString – 3984.375 ms
  • Calling Graphics.DrawImageUnscaled – 7765.625 ms
  • Calling BitBlt – 1015.ms

Copying bits from memory is x8 times faster than drawing image directly!!! And x4 times faster rendering text. In additional, you have in your desposal all raster operations, which you can use inside BitBlt method, such as invert colors – very useful staff. By the way, .NET framework do provide one method which is wraps BitBlt – Graphics.CopyFromSceen method. As expected, inside it Microsoft guys calling BitBlt with 2 DCs: current graphics and Desktop hwnd (hwnd = NULL).

As far I know, this is the best you can do using GDI. Still, you can notice that my application even using BitBlt consuming very high CPU (on my machine – 50%). In case you need better performance, consider to use XNA (managed DirectX).

2 comments January 5, 2008


Categories

Top Posts

Tags

.NET addin app.config ArrayList bug CAB Configuration ConfigurationManager ConfigurationSection ContentControl ContextMenu CTime; DateTime custom keys DataBinding DataContext Data templates debugging equals gethashcode GUI Hashtable interlocked Invoke lock lock free memcpy MFC multithreading multithreading; lock free override performance SCSF serialization Smart Client Software Factory Styles System.Configuration unsafe virtual functions Visual Studio wait free WinAPI WinForms WinForms\WPF Integration World of Warcraft World of Warcraft; Addon

Archives