Two image compare using win32 api c#

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
i have two images and i want to compare two image and want to get difference. i search google and found a link from where i copy paste the code for image comparison using win32 api. so this is the url http://blog.bobcravens.com/2009/04/create-a-remote-desktop-viewer-using-c-and-wcf/<br/>
<br/>
here i am pasting the code.<br/>
<br/>
private void button1_Click(object sender, EventArgs e)<br/>
{<br/>
Bitmap _prevBitmap = new Bitmap(@"d:prev.jpg");<br/>
Bitmap _newBitmap = new Bitmap(@"d:current.jpg");<br/>
<br/>
Rectangle bounds = GetBoundingBoxForChanges(_prevBitmap, _newBitmap);<br/>
if (bounds == Rectangle.Empty)<br/>
{<br/>
}<br/>
<br/>
Bitmap diff = new Bitmap(bounds.Width, bounds.Height);<br/>
Graphics g = Graphics.FromImage(diff);<br/>
g.DrawImage(_newBitmap, 0, 0, bounds, GraphicsUnit.Pixel);<br/>
g.Dispose();<br/>
<br/>
// Set the current bitmap as the previous to prepare<br/>
// for the next screen capture.<br/>
//<br/>
diff.Save(@"d:diff.bmp");<br/>
<br/>
//return diff;<br/>
}<br/>
<br/>
private Rectangle GetBoundingBoxForChanges(Bitmap _prevBitmap, Bitmap _newBitmap)<br/>
{<br/>
// The search algorithm starts by looking<br/>
// for the top and left bounds. The search<br/>
// starts in the upper-left corner and scans<br/>
// left to right and then top to bottom. It uses<br/>
// an adaptive approach on the pixels it<br/>
// searches. Another pass is looks for the<br/>
// lower and right bounds. The search starts<br/>
// in the lower-right corner and scans right<br/>
// to left and then bottom to top. Again, an<br/>
// adaptive approach on the search area is used.<br/>
//<br/>
<br/>
// Note: The GetPixel member of the Bitmap class<br/>
// is too slow for this purpose. This is a good<br/>
// case of using unsafe code to access pointers<br/>
// to increase the speed.<br/>
//<br/>
<br/>
// Validate the images are the same shape and type.<br/>
//<br/>
if (_prevBitmap.Width != _newBitmap.Width ||<br/>
_prevBitmap.Height != _newBitmap.Height ||<br/>
_prevBitmap.PixelFormat != _newBitmap.PixelFormat)<br/>
{<br/>
// Not the same shape...cant do the search.<br/>
//<br/>
return Rectangle.Empty;<br/>
}<br/>
<br/>
// Init the search parameters.<br/>
//<br/>
int width = _newBitmap.Width;<br/>
int height = _newBitmap.Height;<br/>
int left = width;<br/>
int right = 0;<br/>
int top = height;<br/>
int bottom = 0;<br/>
<br/>
BitmapData bmNewData = null;<br/>
BitmapData bmPrevData = null;<br/>
try<br/>
{<br/>
// Lock the bits into memory.<br/>
//<br/>
bmNewData = _newBitmap.LockBits(<br/>
new Rectangle(0, 0, _newBitmap.Width, _newBitmap.Height),<br/>
ImageLockMode.ReadOnly, _newBitmap.PixelFormat);<br/>
bmPrevData = _prevBitmap.LockBits(<br/>
new Rectangle(0, 0, _prevBitmap.Width, _prevBitmap.Height),<br/>
ImageLockMode.ReadOnly, _prevBitmap.PixelFormat);<br/>
<br/>
// The images are ARGB (4 bytes)<br/>
//<br/>
int numBytesPerPixel = 4;<br/>
<br/>
// Get the number of integers (4 bytes) in each row<br/>
// of the image.<br/>
//<br/>
int strideNew = bmNewData.Stride / numBytesPerPixel;<br/>
int stridePrev = bmPrevData.Stride / numBytesPerPixel;<br/>
<br/>
// Get a pointer to the first pixel.<br/>
//<br/>
// Note: Another speed up implemented is that I dont<br/>
// need the ARGB elements. I am only trying to detect<br/>
// change. So this algorithm reads the 4 bytes as an<br/>
// integer and compares the two numbers.<br/>
//<br/>
System.IntPtr scanNew0 = bmNewData.Scan0;<br/>
System.IntPtr scanPrev0 = bmPrevData.Scan0;<br/>
<br/>
// Enter the unsafe code.<br/>
//<br/>
unsafe<br/>
{<br/>
// Cast the safe pointers into unsafe pointers.<br/>
//<br/>
int* pNew = (int*)(void*)scanNew0;<br/>
int* pPrev = (int*)(void*)scanPrev0;<br/>
<br/>
// First Pass - Find the left and top bounds<br/>
// of the minimum bounding rectangle. Adapt the<br/>
// number of pixels scanned from left to right so<br/>
// we only scan up to the current bound. We also<br/>
// initialize the bottom & right. This helps optimize<br/>
// the second pass.<br/>
//<br/>
// For all rows of pixels (top to bottom)<br/>
//<br/>
for (int y = 0; y < _newBitmap.Height; ++y)<br/>
{<br/>
// For pixels up to the current bound (left to right)<br/>
//<br/>
for (int x = 0; x < left; ++x)<br/>
{<br/>
// Use pointer arithmetic to index the<br/>
// next pixel in this row.<br/>
//<br/>
if ((pNew + x)[0] != (pPrev + x)[0])<br/>
{<br/>
// Found a change.<br/>
//<br/>
if (x < left)<br/>
{<br/>
left = x;<br/>
}<br/>
if (x > right)<br/>
{<br/>
right = x;<br/>
}<br/>
if (y < top)<br/>
{<br/>
top = y;<br/>
}<br/>
if (y > bottom)<br/>
{<br/>
bottom = y;<br/>
}<br/>
}<br/>
}<br/>
<br/>
// Move the pointers to the next row.<br/>
//<br/>
pNew += strideNew;<br/>
pPrev += stridePrev;<br/>
}<br/>
<br/>
// If we did not find any changed pixels<br/>
// then no need to do a second pass.<br/>
//<br/>
if (left != width)<br/>
{<br/>
// Second Pass - The first pass found at<br/>
// least one different pixel and has set<br/>
// the left & top bounds. In addition, the<br/>
// right & bottom bounds have been initialized.<br/>
// Adapt the number of pixels scanned from right<br/>
// to left so we only scan up to the current bound.<br/>
// In addition, there is no need to scan past<br/>
// the top bound.<br/>
//<br/>
<br/>
// Set the pointers to the first element of the<br/>
// bottom row.<br/>
//<br/>
pNew = (int*)(void*)scanNew0;<br/>
pPrev = (int*)(void*)scanPrev0;<br/>
pNew += (_newBitmap.Height - 1) * strideNew;<br/>
pPrev += (_prevBitmap.Height - 1) * stridePrev;<br/>
<br/>
// For each row (bottom to top)<br/>
//<br/>
for (int y = _newBitmap.Height - 1; y > top; y--)<br/>
{<br/>
// For each column (right to left)<br/>
//<br/>
for (int x = _newBitmap.Width - 1; x > right; x--)<br/>
{<br/>
// Use pointer arithmetic to index the<br/>
// next pixel in this row.<br/>
//<br/>
if ((pNew + x)[0] != (pPrev + x)[0])<br/>
{<br/>
// Found a change.<br/>
//<br/>
if (x > right)<br/>
{<br/>
right = x;<br/>
}<br/>
if (y > bottom)<br/>
{<br/>
bottom = y;<br/>
}<br/>
}<br/>
}<br/>
<br/>
// Move up one row.<br/>
//<br/>
pNew -= strideNew;<br/>
pPrev -= stridePrev;<br/>
}<br/>
}<br/>
}<br/>
}<br/>
catch (Exception ex)<br/>
{<br/>
int xxx = 0;<br/>
}<br/>
finally<br/>
{<br/>
// Unlock the bits of the image.<br/>
//<br/>
if (bmNewData != null)<br/>
{<br/>
_newBitmap.UnlockBits(bmNewData);<br/>
}<br/>
if (bmPrevData != null)<br/>
{<br/>
_prevBitmap.UnlockBits(bmPrevData);<br/>
}<br/>
}<br/>
<br/>
// Validate we found a bounding box. If not<br/>
// return an empty rectangle.<br/>
//<br/>
int diffImgWidth = right - left + 1;<br/>
int diffImgHeight = bottom - top + 1;<br/>
if (diffImgHeight < 0 || diffImgWidth < 0)<br/>
{<br/>
// Nothing changed<br/>
return Rectangle.Empty;<br/>
}<br/>
<br/>
// Return the bounding box.<br/>
//<br/>
return new Rectangle(left, top, diffImgWidth, diffImgHeight);<br/>
}<br/>
<br/>
when GetBoundingBoxForChanges() call then i am getting error and error message is Attempted to read or write protected memory. This is often an indication that other memory is corrupt.<br/>
<br/>
error occur at this code if ((pNew + x)[0] != (pPrev + x)[0])<br/>
<br/>
so i am not being able to find out the reason. how to fix this error. please guide. thanks<br/>

View the full article
 

Similar threads

Back
Top