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
22 Aug

Bootstrap Panel Samples

This example shows how to create a panel using bootstrap framework.

Firstly, you should add the following code to the head section in html:

  http://csharpexamples.com
  
  
  
  

Sample Usage :

    
Simple panel without heading
Sample 1
Panel Content 1
Sample 2
Panel Content 2
Sample 3
Panel Content 3
Sample 4
Panel Content 4
Sample 5
Panel Content 5
Sample 6
Panel Content 6

RESULT :
bootstrap panel samples