09 Sep

Dynamic Type in C# 4.0

This example shows how to use dynamic type in C#.

C# 4.0 allows a new static type called “dynamic”. Any operation on the object of type dynamic resolve at runtime. So, it gets escaped from compile type checking. But if any error, it caught at runtime. Also, the dynamic type allows us to access the object, without knowing type of the object at compile time. It causes no intelli-sense support.

Sample Usage :

            dynamic dynamicObj = "This is a dynamic type";
            Type dynObjType = dynamicObj.GetType();
            Console.WriteLine(dynObjType);
            Console.WriteLine(dynamicObj);
            
            //Result:
            //System.String
            //This is a dynamic type

In above code, a variable of type dynamic is defined. This type is resolved in type string at runtime. We are printing the string value, and type.

09 Sep

C# Regular Expressions

This page contains regular expressions metacharacters, operators, quantifiers etc.

Character
Description
\

Marks the next character as either a special character or escapes a literal. For example, “n” matches the character “n”. “\n” matches a newline character. The sequence “\\” matches “\” and “\(” matches “(“.

Note: double quotes may be escaped by doubling them: “<a href=””…>”

^ Depending on whether the MultiLine option is set, matches the position before the first character in a line, or the first character in the string.
$ Depending on whether the MultiLine option is set, matches the position after the last character in a line, or the last character in the string.
* Matches the preceding character zero or more times. For
example, “zo*” matches either “z” or “zoo”.
+ Matches the preceding character one or more times. For
example, “zo+” matches “zoo” but not “z”.
? Matches the preceding character zero or one time. For
example, “a?ve?” matches the “ve” in “never”.
. Matches any single character except a newline character.
(pattern) Matches pattern and remembers the match. The matched substring can be retrieved from the resulting Matches collection, using Item [0]…[n]. To match parentheses characters
( ), use “\(” or “\)”.
(?<name>pattern) Matches pattern and gives the match a name.
(?:pattern) A non-capturing group
(?=…) A positive lookahead
(?!…) A negative lookahead
(?<=…) A positive lookbehind .
(?<!…) A negative lookbehind .
x|y Matches either x or y. For example, “z|wood” matches “z” or “wood”. “(z|w)oo” matches “zoo” or “wood”.
{n} n is a non-negative integer. Matches exactly n times.
For example, “o{2}” does not match the “o” in “Bob,” but matches the
first two o’s in “foooood”.
{n,} n is a non-negative integer. Matches at least n times.
For example, “o{2,}” does not match the “o” in “Bob” and matches all
the o’s in “foooood.” “o{1,}” is equivalent to “o+”. “o{0,}” is equivalent
to “o*”.
{n,m} m and n are non-negative integers. Matches
at least n and at most m times. For example, “o{1,3}” matches
the first three o’s in “fooooood.” “o{0,1}” is equivalent to “o?”.
[xyz] A character set. Matches any one of the enclosed characters.
For example, “[abc]” matches the “a” in “plain”.
[^xyz] A negative character set. Matches any character not enclosed.
For example, “[^abc]” matches the “p” in “plain”.
[a-z] A range of characters. Matches any character in the specified
range. For example, “[a-z]” matches any lowercase alphabetic character
in the range “a” through “z”.
[^m-z] A negative range characters. Matches any character not
in the specified range. For example, “[m-z]” matches any character not
in the range “m” through “z”.
\b Matches a word boundary, that is, the position between
a word and a space. For example, “er\b” matches the “er” in “never” but
not the “er” in “verb”.
\B Matches a non-word boundary. “ea*r\B” matches the “ear” in “never
early”.
\d Matches a digit character. Equivalent to [0-9].
\D Matches a non-digit character. Equivalent to [^0-9].
\f Matches a form-feed character.
\k A back-reference to a named group.
\n Matches a newline character.
\r Matches a carriage return character.
\s Matches any white space including space, tab, form-feed,
etc. Equivalent to “[ \f\n\r\t\v]”.
\S Matches any nonwhite space character. Equivalent to “[^ \f\n\r\t\v]”.
\t Matches a tab character.
\v Matches a vertical tab character.
\w Matches any word character including underscore. Equivalent
to “[A-Za-z0-9_]”.
\W Matches any non-word character. Equivalent to “[^A-Za-z0-9_]”.
\num Matches num, where num is a positive integer. A reference back to remembered matches.
For example, “(.)\1” matches two consecutive identical characters.
\n Matches n, where n is an octal escape value. Octal escape values must be 1, 2, or 3 digits long.
For example, “\11” and “\011” both match a tab character. “\0011” is the equivalent of “\001” & “1”. Octal escape values must not exceed 256. If they do, only the first two digits comprise the expression. Allows ASCII codes to be used in regular expressions.
\xn Matches n, where n is a hexadecimal escape value. Hexadecimal escape values must be exactly two digits long.
For example, “\x41” matches “A”. “\x041” is equivalent to “\x04” & “1”.
Allows ASCII codes to be used in regular expressions.
\un Matches a Unicode character expressed in hexadecimal notation with exactly four numeric digits. “\u0200” matches a space character.
\A Matches the position before the first character in a string. Not affected by the MultiLine setting
\Z Matches the position after the last character of a string. Not affected by the MultiLine setting.
\G Specifies that the matches must be consecutive, without any intervening non-matching characters.
08 Sep

Taking Screenshots with C#

This examples show how to take screenshot using C#.

Sample Usage:

            Bitmap bmp = TakingScreenshotEx1();
            bmp.Save("Screenshot1.png", ImageFormat.Png);

            bmp = TakingScreenshotEx2();
            bmp.Save("Screenshot2.png", ImageFormat.Png);

This method shows you a simple method of capturing screenshots using C# and .NET 2.0( CopyFromScreen() method. )

        private Bitmap TakingScreenshotEx1()
        {
            //Create a new bitmap.
            var bmpScreenshot = new Bitmap(Screen.PrimaryScreen.Bounds.Width,
                                           Screen.PrimaryScreen.Bounds.Height,
                                           PixelFormat.Format32bppArgb);

            // Create a graphics object from the bitmap.
            var g = Graphics.FromImage(bmpScreenshot);

            // Take the screenshot from the upper left corner to the right bottom corner.
            g.CopyFromScreen(Screen.PrimaryScreen.Bounds.X,
                             Screen.PrimaryScreen.Bounds.Y,
                             0,
                             0,
                             Screen.PrimaryScreen.Bounds.Size,
                             CopyPixelOperation.SourceCopy);

            return bmpScreenshot;
        }

This method uses GDI in C#.NET to draw the primary screen onto a bitmap.

        private Bitmap TakingScreenshotEx2()
        {
            int screenWidth = Screen.PrimaryScreen.Bounds.Width;
            int screenHeight = Screen.PrimaryScreen.Bounds.Height;

            Bitmap bmpScreenshot = new Bitmap(screenWidth, screenHeight);
            Graphics g = Graphics.FromImage(bmpScreenshot);

            IntPtr dc1 = WinAPI.GetDC(WinAPI.GetDesktopWindow());
            IntPtr dc2 = g.GetHdc();

            //Main drawing, copies the screen to the bitmap
            //last number is the copy constant
            WinAPI.BitBlt(dc2, 0, 0, screenWidth, screenHeight, dc1, 0, 0, 13369376);

            //Clean up
            WinAPI.ReleaseDC(WinAPI.GetDesktopWindow(), dc1);
            g.ReleaseHdc(dc2);
            g.Dispose();

            return bmpScreenshot;
        }
    public class WinAPI
    {
        [DllImport("user32.dll", ExactSpelling = true, SetLastError = true)]
        public static extern IntPtr GetDC(IntPtr hWnd);

        [DllImport("user32.dll", ExactSpelling = true)]
        public static extern IntPtr ReleaseDC(IntPtr hWnd, IntPtr hDC);

        [DllImport("gdi32.dll", ExactSpelling = true)]
        public static extern IntPtr BitBlt(IntPtr hDestDC, int x, int y, int nWidth, int nHeight, IntPtr hSrcDC, int xSrc, int ySrc, int dwRop);

        [DllImport("user32.dll", EntryPoint = "GetDesktopWindow")]
        public static extern IntPtr GetDesktopWindow();
    }
03 Sep

Fast Image Processing in C#

This example shows how to process the images in C# comparatively. Users often use GetPixel/SetPixel methods in System.Drawing.Bitmap class but these methods have bad performance, especially for big images. It is the simplest approach and it does not require you to know anything about pixel format(number of bits per pixel) of processed picture. If we use the memory access and parallel programming(using threads), image processing time is less than PixelGet and PixelSet methods.

Following samples show how to use comparatively.

Sample Usages :

            Stopwatch sw = new Stopwatch();

            sw.Start();
            ProcessUsingGetPixelSetPixel(bmp);
            sw.Stop();
            Console.WriteLine(string.Format("Processed using ProcessUsingGetPixel method in {0} ms.", sw.ElapsedMilliseconds));

            sw.Restart();
            ProcessUsingLockbits(bmp);
            sw.Stop();
            Console.WriteLine(string.Format("Processed using ProcessUsingLockbits method in {0} ms.", sw.ElapsedMilliseconds));

            sw.Restart();
            ProcessUsingLockbitsAndUnsafe(bmp);
            sw.Stop();
            Console.WriteLine(string.Format("Processed using ProcessUsingLockbitsAndUnsafe method in {0} ms.", sw.ElapsedMilliseconds));

            sw.Restart();
            ProcessUsingLockbitsAndUnsafeAndParallel(bmp);
            sw.Stop();
            Console.WriteLine(string.Format("Processed using ProcessUsingLockbitsAndUnsafeAndParallel method in {0} ms.", sw.ElapsedMilliseconds));

            //Result: (For ~7500x5000 pixel)
            //Processed using ProcessUsingGetPixel method in 87118 ms.
            //Processed using ProcessUsingLockbits method in 333 ms.
            //Processed using ProcessUsingLockbitsAndUnsafe method in 177 ms.
            //Processed using ProcessUsingLockbitsAndUnsafeAndParallel method in 78 ms.

Processing using GetPixel and SetPixel :

        private void ProcessUsingGetPixelSetPixel(Bitmap processedBitmap)
        {
            int width = processedBitmap.Width;
            int height = processedBitmap.Height;
            for (int x = 0; x < width; x++)
            {
                for (int y = 0; y < height; y++)
                {
                    Color oldPixel = processedBitmap.GetPixel(x, y);
                    
                    // calculate new pixel value
                    Color newPixel = oldPixel;

                    processedBitmap.SetPixel(x, y, newPixel);
                }
            }
        }

Processing using Bitmap.Lockbits and Marshal.Copy :

        private void ProcessUsingLockbits(Bitmap processedBitmap)
        {
            BitmapData bitmapData = processedBitmap.LockBits(new Rectangle(0, 0, processedBitmap.Width, processedBitmap.Height), ImageLockMode.ReadWrite, processedBitmap.PixelFormat);
            
            int bytesPerPixel = Bitmap.GetPixelFormatSize(processedBitmap.PixelFormat) / 8;
            int byteCount = bitmapData.Stride * processedBitmap.Height;
            byte[] pixels = new byte[byteCount];
            IntPtr ptrFirstPixel = bitmapData.Scan0;
            Marshal.Copy(ptrFirstPixel, pixels, 0, pixels.Length);
            int heightInPixels = bitmapData.Height;
            int widthInBytes = bitmapData.Width * bytesPerPixel;

            for (int y = 0; y < heightInPixels; y++)
            {
                int currentLine = y * bitmapData.Stride;
                for (int x = 0; x < widthInBytes; x = x + bytesPerPixel)
                {
                    int oldBlue = pixels[currentLine + x];
                    int oldGreen = pixels[currentLine + x + 1];
                    int oldRed = pixels[currentLine + x + 2];
                    
                    // calculate new pixel value
                    pixels[currentLine + x] = (byte)oldBlue;
                    pixels[currentLine + x + 1] = (byte)oldGreen;
                    pixels[currentLine + x + 2] = (byte)oldRed;
                }
            }

            // copy modified bytes back
            Marshal.Copy(pixels, 0, ptrFirstPixel, pixels.Length);
            processedBitmap.UnlockBits(bitmapData);
        }

Processing using Bitmap.LockBits and direct memory access in unsafe context :

        private void ProcessUsingLockbitsAndUnsafe(Bitmap processedBitmap)
        {
            unsafe
            {
                BitmapData bitmapData = processedBitmap.LockBits(new Rectangle(0, 0, processedBitmap.Width, processedBitmap.Height), ImageLockMode.ReadWrite, processedBitmap.PixelFormat);
                int bytesPerPixel = System.Drawing.Bitmap.GetPixelFormatSize(processedBitmap.PixelFormat) / 8;
                int heightInPixels = bitmapData.Height;
                int widthInBytes = bitmapData.Width * bytesPerPixel;
                byte* ptrFirstPixel = (byte*)bitmapData.Scan0;
                
                for (int y = 0; y < heightInPixels; y++)
                {
                    byte* currentLine = ptrFirstPixel + (y * bitmapData.Stride);
                    for (int x = 0; x < widthInBytes; x = x + bytesPerPixel)
                    {
                        int oldBlue = currentLine[x];
                        int oldGreen = currentLine[x + 1];
                        int oldRed = currentLine[x + 2];

                        // calculate new pixel value
                        currentLine[x] = (byte)oldBlue;
                        currentLine[x + 1] = (byte)oldGreen;
                        currentLine[x + 2] = (byte)oldRed;
                    }
                }
                processedBitmap.UnlockBits(bitmapData);
            }
        }

Processing using Bitmap.LockBits and direct memory access in unsafe context with System.Threading.Tasks.Parallel class :

        private void ProcessUsingLockbitsAndUnsafeAndParallel(Bitmap processedBitmap)
        {
            unsafe
            {
                BitmapData bitmapData = processedBitmap.LockBits(new Rectangle(0, 0, processedBitmap.Width, processedBitmap.Height), ImageLockMode.ReadWrite, processedBitmap.PixelFormat);

                int bytesPerPixel = System.Drawing.Bitmap.GetPixelFormatSize(processedBitmap.PixelFormat) / 8;
                int heightInPixels = bitmapData.Height;
                int widthInBytes = bitmapData.Width * bytesPerPixel;
                byte* PtrFirstPixel = (byte*)bitmapData.Scan0;

                Parallel.For(0, heightInPixels, y =>
                {
                    byte* currentLine = PtrFirstPixel + (y * bitmapData.Stride);
                    for (int x = 0; x < widthInBytes; x = x + bytesPerPixel)
                    {
                        int oldBlue = currentLine[x];
                        int oldGreen = currentLine[x + 1];
                        int oldRed = currentLine[x + 2];

                        currentLine[x] = (byte)oldBlue;
                        currentLine[x + 1] = (byte)oldGreen;
                        currentLine[x + 2] = (byte)oldRed;
                    }
                });
                processedBitmap.UnlockBits(bitmapData);
            }
        }
Image Size (MP) GetPixel/SetPixel (ms) LockBits + Marshal.Copy (ms) LockBits + unsafe context (ms) Lockbits + unsafe context + Parallel.For (ms)
~10 22314 82 31 19
~38 87118 333 117 78