Skip to content

Instantly share code, notes, and snippets.

@VisualMelon
Created December 14, 2017 11:46
Show Gist options
  • Save VisualMelon/f6a8679e633e347ec32006fbc128dd24 to your computer and use it in GitHub Desktop.
Save VisualMelon/f6a8679e633e347ec32006fbc128dd24 to your computer and use it in GitHub Desktop.
public static Rectangle GetBrightestRectangle(this Bitmap bitmap, int width, int height)
{
// Each rectangle's value is its average pixel color.
var rectangles = new Dictionary<Rectangle, float>();
// Iterate through all possible rectangle points.
for (var x = 0; x < bitmap.Width - width; x++)
for (var y = 0; y < bitmap.Height - height; y++)
{
var brightnesses = new List<float>();
// Iterate through all rectangle pixels.
for (var w = x; w < x + width; w++)
for (var h = y; h < y + height; h++)
{
brightnesses.Add(bitmap.GetPixel(w, h).GetBrightness());
}
rectangles.Add(new Rectangle(x, y, width, height), brightnesses.Average());
}
// The brightness ranges from 0.0 through 1.0, where 0.0 represents black and 1.0 represents white.
return rectangles.OrderByDescending(pair => pair.Value).First().Key;
}
public static Rectangle GetBrightestRectangle2(this Bitmap bitmap, int rectWidth, int rectHeight)
{
int hSumWidth = bitmap.Width - rectWidth + 1;
int hSumHeight = bitmap.Height;
float[,] hSums = new float[hSumWidth, hSumHeight];
Queue<float> queue = new Queue<float>(rectWidth);
// I would never use `var` in a for-loop; makes it immediately obvious we are using ints and not floats
for (int y = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x++)
{
// this is the only time we call bitmap.GetPixel(,)
queue.Enqueue(bitmap.GetPixel(x, y).GetBrightness());
if (x >= rectWidth)
{
hSums[x - rectWidth, y] = queue.Sum();
// if the ring-buffer isn't fixed size, we may have to manually evict the old value at this point
queue.Dequeue();
}
}
queue.Clear(); // we don't need to do this, but it is much clearer if we do
}
queue = new Queue<float>(rectHeight);
float bestAverage = float.NegativeInfinity;
Rectangle bestRectangle = default(Rectangle);
for (int x = 0; x < hSumWidth; x++)
{
for (int y = 0; y < bitmap.Height; y++)
{
queue.Enqueue(hSums[x, y]);
if (y >= rectHeight)
{
float rectangleAverage = queue.Average();
if (rectangleAverage > bestAverage)
{
bestRectangle = new Rectangle(x, y - rectHeight, rectWidth, rectHeight);
bestAverage = rectangleAverage;
}
// if the ring-buffer isn't fixed size, we may have to manually evict the old value at this point
queue.Dequeue();
}
}
queue.Clear();
}
return bestRectangle;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment