RSS Feed

Manipulating Bitmaps in .Net – Performance comparison, LockBits vs Get Pixel Set Pixel

When using GDI+ method you can optimize the process of bitmap manipulation  seven  times.I am implementing an image scaling algorithm at my University Seam Carving . While working on this project I realized that simply accessing pixels by the GetPixel and SetPixel methods is too slow.

 

GetPixel , SetPixel

This is a really easy solution. We have two functions GetPixel and SetPixel both  have x and y coordinate as argument. GetPixel returns a color and SetPixel sets a color on the coordinate.

 

1 GetPixel(int x,int y) 2 SetPixel(int x,int y,Color color) 3

With the use of those functions, we can easily iterate through all the pixels in the image by simply modifying the x and y variable.

 

1 for (int y = 0; y < _bmp.Height; y++) 2 { 3 for (int x = 0; x < _bmp.Width; x++) 4 { 5 _bmp.SetPixel(x,y,color); 6 Color c = _bmp.GetPixel(x,y); 7 } 8 }

 

Pros:

– Code is more readable.

– Easy to implement and use.

Cons:

-Low efficiency.

 

This method is really great for simple graphical operations when speed isn’t important. In my scenario with the Seam Carving algorithm, I had an efficiency problem using this method. Seam Carving algorithm is making a lot of calculations in order to find seams. The time is growing exponentially with the size of the image.

 

GDI+ and LockBits.

Bitmap class contains two methods LockBits and UnlockBits , with them, we can get access and work directly on the memory. LockBits method returns BitmapData object, which is used to describe the memory sector. In this method, we have to use the pointers. That’s why our class should have an unsafe keyword.

 

1 BitmapData _bmd = _bmp.LockBits(new Rectangle(0, 0, _bmp.Width,_bmp.Height) , ImageLockMode ReadWrite, _bmp.PixelFormat);

 

With BitmapData object we need to define some variables.

 

1 int _pixelSize = 3; 2 byte* _current =(byte*)(void*)_bmd.Scan0; 3 int _nWidth = _bmp.Width * _pixelSize; 4 int _nHeight = _bmp.Height;

 
– ScanO  memory address which defines the beginning of our Bitmap
_nWidth how many bots in one row
With this we can iterate through the image.
1 for (int y = 0; y < _nHeight; y++) 2 { 3 for (int x = 0; x < _nWidth;x++ ) 4 { 5 if (x % _pixelSize == 0 || x == 0) 6 { 7 SetColor(new Color.Black); 8 } 9 _current++; 10 } 11 }

We have to remember that current variable is only a pointer  to a memory address

1 if (x % _pixelSize == 0 || x == 0)

This condition ensures that the current will always point to the beginning of the next pixel. In my example pixel is represented by  three bytes, this value is stored in the _pixelSize variable.
With _current pointer we can access pixel values by using the indexer.

1 void SetColor(,Color color) 2 { 3 _current[0]= color.R; 4 _current [1] = color.G; 5 _current [2] = color.B; 6 }

 

Pros:

– Speed

Cons:

-Code is confusing but we can wrap the logic in readable functions

– Implementation is complicated in the beginning

– unmanaged code

 

Comparision between Gdi+ Lockbits and GetPixel SetPixel



GetPixelSetPixel:

Getting one pixel (30k) ————- 157 ms

Setting one pixel 30k) ————-153 ms

iterating through image (100 times100x100) ————1496 ms

GDI:

Getting one pixel(30k ) ————- 21 ms

Setting one pixel (30k ) ————- 15ms

iterating through image(100 100×100) ———— 226ms

As you can see the GDI+ Lockbits are almost seven times faster than GetPixel SetPixel method

 

Link to the project.

Advertisements

3 Comments on “Manipulating Bitmaps in .Net – Performance comparison, LockBits vs Get Pixel Set Pixel”

  1. Pimpirimpi says:

    Bogdanie, korzystając z sytuacji chciałbym nadmienić tudzież zauważyć, iż onegdaj przemierzając mroczną otchłań internetowego nieładu natknąłem się na stronę http://msdn.microsoft.com/en-us/library/ms229672.aspx . Która jasno precyzuje, że nie jest koniecznością używanie znienawidzonych przez ogół wskaźników, a co za tym idzie używanie trybu unsafe przy LockBits’ie. Pozdro Zio0Oo0m 😛

    p.s. IntPtr


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s