using System.Drawing.Imaging;
using System.Collections.Generic;
public static void Main()
Bitmap bitmapToTest = new Bitmap(800,600);
using(Graphics g = Graphics.FromImage(bitmapToTest))
g.FillRectangle(Brushes.White, 0,0,800,600);
g.FillRectangle(Brushes.Black, 100, 100, 100, 100);
BoundingBoxCalculator boundingBoxCalc = new BoundingBoxCalculator(bitmapToTest, new Point(100,100));
Rectangle rectangleOfObject = boundingBoxCalc.CalculateBoundingBox();
Console.WriteLine(rectangleOfObject.X);
Console.WriteLine(rectangleOfObject.Y);
Console.WriteLine(rectangleOfObject.Width);
Console.WriteLine(rectangleOfObject.Height);
internal class BoundingBoxCalculator
Bitmap bitmapToCalculateBoundingBoxFor;
Point[] neighborOffsets =
public BoundingBoxCalculator(Bitmap bitmapContainingObject, Point borderPoint)
this.bitmapToCalculateBoundingBoxFor = bitmapContainingObject;
this.startingPoint = borderPoint;
public Rectangle CalculateBoundingBox()
List<Point> edgePoints = CalculateEdge();
int minX = edgePoints.Min(p => p.X);
int maxX = edgePoints.Max(p => p.X);
int minY = edgePoints.Min(p => p.Y);
int maxY = edgePoints.Max(p => p.Y);
return new Rectangle(minX, minY, maxX - minX, maxY - minY);
List<Point> CalculateEdge()
List<Point> edgePoints = new List<Point>();
Point currentPoint = startingPoint;
IEnumerable<Point> neighboringEdgePoints = GetNeighboringEdgePoints(currentPoint);
IEnumerable<Point> neighboringEdgePointsNotVisited = from p in neighboringEdgePoints where !edgePoints.Contains(p) select p;
edgePoints.Add(currentPoint);
if(neighboringEdgePointsNotVisited.Count() == 0
&& neighboringEdgePoints.Contains(startingPoint))
currentPoint = startingPoint;
else if(neighboringEdgePointsNotVisited.Count() == 1)
Point nextPoint = neighboringEdgePointsNotVisited.First();
currentPoint = nextPoint;
else if(neighboringEdgePointsNotVisited.Count() > 1)
Point nextPoint = GetPointWithMinDistance(currentPoint, neighboringEdgePointsNotVisited);
currentPoint = nextPoint;
} while(currentPoint != startingPoint);
Point GetPointWithMinDistance(Point origin, IEnumerable<Point> pointsToTest)
double minDistance = double.MaxValue;
Point pointWithMinDistance = new Point(0,0);
foreach(Point pointToTest in pointsToTest)
double currentDistance = GetPointsDistance(origin, pointToTest);
if(currentDistance < minDistance)
minDistance = currentDistance;
pointWithMinDistance = pointToTest;
return pointWithMinDistance;
double GetPointsDistance(Point p1, Point p2)
return Math.Sqrt((p1.X - p2.X) * (p1.X - p2.X) + (p1.Y - p2.Y) * (p1.Y - p2.Y));
IEnumerable<Point> GetNeighboringEdgePoints(Point currentPoint)
IEnumerable<Point> neighboringPoints = GetNeighboringPoints(currentPoint);
List<Point> neighboringEdgePoints = new List<Point>();
foreach(Point pointToTest in neighboringPoints)
if(GetNeighboringPoints(pointToTest).Count() < 8)
neighboringEdgePoints.Add(pointToTest);
return neighboringEdgePoints;
IEnumerable<Point> GetNeighboringPoints(Point currentPoint)
List<Point> neighbors = new List<Point>();
for(int offsetsCount = 0; offsetsCount < neighborOffsets.Length; offsetsCount++)
Point currentPointWithOffset = AddPointOffset(currentPoint, neighborOffsets[offsetsCount]);
if(IsInImage(currentPointWithOffset) &&
IsInObject(currentPointWithOffset))
neighbors.Add(currentPointWithOffset);
bool IsInImage(Point pointToTest)
return pointToTest.X >= 0
&& pointToTest.X < bitmapToCalculateBoundingBoxFor.Width
&& pointToTest.Y < bitmapToCalculateBoundingBoxFor.Height;
bool IsInObject(Point pointToTest)
Color colorInPointPosition = bitmapToCalculateBoundingBoxFor.GetPixel(pointToTest.X, pointToTest.Y);
return colorInPointPosition.R != 255
|| colorInPointPosition.G != 255
|| colorInPointPosition.B != 255;
Point AddPointOffset(Point point, Point offset)
return new Point(point.X + offset.X, point.Y + offset.Y);