/// <summary> /// Finds the bounding rectangle based on the first instance of any color component other /// than the given one. /// </summary> /// <typeparam name="TPixel">The pixel format.</typeparam> /// <param name="bitmap">The <see cref="Image{TPixel}"/> to search within.</param> /// <param name="componentValue">The color component value to remove.</param> /// <param name="channel">The <see cref="RgbaComponent"/> channel to test against.</param> /// <returns> /// The <see cref="Rectangle"/>. /// </returns> public static Rectangle GetFilteredBoundingRectangle <TPixel>(ImageFrame <TPixel> bitmap, float componentValue, RgbaComponent channel = RgbaComponent.B) where TPixel : struct, IPixel <TPixel> { int width = bitmap.Width; int height = bitmap.Height; Point topLeft = default; Point bottomRight = default; Func <ImageFrame <TPixel>, int, int, float, bool> delegateFunc; // Determine which channel to check against switch (channel) { case RgbaComponent.R: delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().X - b) > Constants.Epsilon; break; case RgbaComponent.G: delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().Y - b) > Constants.Epsilon; break; case RgbaComponent.B: delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().Z - b) > Constants.Epsilon; break; default: delegateFunc = (pixels, x, y, b) => MathF.Abs(pixels[x, y].ToVector4().W - b) > Constants.Epsilon; break; } int GetMinY(ImageFrame <TPixel> pixels) { for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { if (delegateFunc(pixels, x, y, componentValue)) { return(y); } } } return(0); } int GetMaxY(ImageFrame <TPixel> pixels) { for (int y = height - 1; y > -1; y--) { for (int x = 0; x < width; x++) { if (delegateFunc(pixels, x, y, componentValue)) { return(y); } } } return(height); } int GetMinX(ImageFrame <TPixel> pixels) { for (int x = 0; x < width; x++) { for (int y = 0; y < height; y++) { if (delegateFunc(pixels, x, y, componentValue)) { return(x); } } } return(0); } int GetMaxX(ImageFrame <TPixel> pixels) { for (int x = width - 1; x > -1; x--) { for (int y = 0; y < height; y++) { if (delegateFunc(pixels, x, y, componentValue)) { return(x); } } } return(height); } topLeft.Y = GetMinY(bitmap); topLeft.X = GetMinX(bitmap); bottomRight.Y = (GetMaxY(bitmap) + 1).Clamp(0, height); bottomRight.X = (GetMaxX(bitmap) + 1).Clamp(0, width); return(GetBoundingRectangle(topLeft, bottomRight)); }