Here's your "original" source:
Code:
#region UICode
int Amount1=20; //[0,100]Tolerance
int Amount2=1; //[1,8]Matching pixels
#endregion
void Render(Surface dst, Surface src, Rectangle rect)
{
ColorBgra CurrentPixel;
byte B, G, R;
int totalB, totalG, totalR;
int matches;
double lowerLimitR, lowerLimitG, lowerLimitB;
double upperLimitR, upperLimitG, upperLimitB;
double percent, percentInverse;
ColorBgra[] pixels = new ColorBgra[8]; // Array for containing surrounding pixels. Indices:
// 0 1 2
// 3 x 4 (x is the current pixel)
// 5 6 7
percent = (100-Amount1)/100;
percentInverse = 1/percent;
for (int y = rect.Top; y < rect.Bottom; y++)
{
for (int x = rect.Left; x < rect.Right; x++)
{
//Set limits:
lowerLimitR = src[x,y].R * percent;
lowerLimitG = src[x,y].G * percent;
lowerLimitB = src[x,y].B * percent;
upperLimitR = src[x,y].R * percentInverse;
upperLimitG = src[x,y].G * percentInverse;
upperLimitB = src[x,y].B * percentInverse;
//Clear the loop variables
totalB = 0;
totalG = 0;
totalR = 0;
matches = 0;
// Get our pixels. Technically, you could use a kernel here,
// But it's not worth it for 8 pixels.
CurrentPixel = src[x,y];
pixels[0] = src.GetBilinearSampleClamped(x-1, y-1);
pixels[1] = src.GetBilinearSampleClamped(x , y-1);
pixels[2] = src.GetBilinearSampleClamped(x+1, y-1);
pixels[3] = src.GetBilinearSampleClamped(x-1, y );
pixels[4] = src.GetBilinearSampleClamped(x+1, y );
pixels[5] = src.GetBilinearSampleClamped(x-1, y+1);
pixels[6] = src.GetBilinearSampleClamped(x , y+1);
pixels[7] = src.GetBilinearSampleClamped(x+1, y+1);
// Loop through the array and...
foreach(ColorBgra s in pixels)
{
// Test if the pixel matches,
if (s.B < upperLimitB && s.B > lowerLimitB &&
s.G < upperLimitG && s.G > lowerLimitG &&
s.R < upperLimitR && s.R > lowerLimitR)
matches++;
// and add to our total that we will average if needed.
totalB += s.B;
totalG += s.G;
totalR += s.R;
}
// Test for matches
if (matches >= Amount2)
dst[x,y] = CurrentPixel;
else // Average if needed. Using src[,].A so stuff doesn't look goofy if it is antialiased.
dst[x,y] = ColorBgra.FromBgra(Int32Util.ClampToByte(totalB/8), Int32Util.ClampToByte(totalG/8), Int32Util.ClampToByte(totalR/8), CurrentPixel.A);
}
}
}
Now, notice the effect of this--it leaves a ring around any noise that is of the noise's intensity averaged with 7 pixels surrounding it. To combat this, you could, for example, make a public (technically static but codelab assumes static) boolean array (outside the Render function so that all instances of Render() can access it) of the dimensions of the selection and set that array[x,y] to true if you found noise, and then make sure that you don't repeat the dst[x,y] = ColorBgra.FromBgra(...) line if any of the surrounding pixels are true.
Edit:
Also.. you had wonderful bits about null. Remember always that null and not defined are two different things--you can define a variable as null if its type has support for a null value, however, attempting to access a variable that isn't in memory (such as something outside the bounds of an array) directly will crash the program. GetBilinearSampleClamped saves you any of the mess that is testing for constraints by simply returning the pixel closest to the point you're trying to access that exists on the given surface (think of lines going out from the defined surface that are the same pixel value as where they start on the edge).