예제 #1
0
        /// <summary>
        /// Finds the bounding rectangle based on the first instance of any color component other
        /// than the given one.
        /// </summary>
        /// <typeparam name="TColor">The pixel format.</typeparam>
        /// <param name="bitmap">The <see cref="Image"/> 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 <TColor>(ImageBase <TColor> bitmap, float componentValue, RgbaComponent channel = RgbaComponent.B)
            where TColor : struct, IPixel <TColor>
        {
            int   width       = bitmap.Width;
            int   height      = bitmap.Height;
            Point topLeft     = default(Point);
            Point bottomRight = default(Point);

            Func <PixelAccessor <TColor>, 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;
            }

            Func <PixelAccessor <TColor>, int> getMinY = 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);
            };

            Func <PixelAccessor <TColor>, int> getMaxY = 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);
            };

            Func <PixelAccessor <TColor>, int> getMinX = 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);
            };

            Func <PixelAccessor <TColor>, int> getMaxX = 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);
            };

            using (PixelAccessor <TColor> bitmapPixels = bitmap.Lock())
            {
                topLeft.Y     = getMinY(bitmapPixels);
                topLeft.X     = getMinX(bitmapPixels);
                bottomRight.Y = (getMaxY(bitmapPixels) + 1).Clamp(0, height);
                bottomRight.X = (getMaxX(bitmapPixels) + 1).Clamp(0, width);
            }

            return(GetBoundingRectangle(topLeft, bottomRight));
        }
예제 #2
0
        /// <summary>
        /// Finds the bounding rectangle based on the first instance of any color component other
        /// than the given one.
        /// </summary>
        /// <param name="bitmap">
        /// The <see cref="Image"/> 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(ImageBase bitmap, float componentValue, RgbaComponent channel = RgbaComponent.B)
        {
            const float Epsilon = .00001f;
            int width = bitmap.Width;
            int height = bitmap.Height;
            Point topLeft = new Point();
            Point bottomRight = new Point();

            Func<ImageBase, int, int, float, bool> delegateFunc;

            // Determine which channel to check against
            switch (channel)
            {
                case RgbaComponent.R:
                    delegateFunc = (imageBase, x, y, b) => Math.Abs(imageBase[x, y].R - b) > Epsilon;
                    break;

                case RgbaComponent.G:
                    delegateFunc = (imageBase, x, y, b) => Math.Abs(imageBase[x, y].G - b) > Epsilon;
                    break;

                case RgbaComponent.A:
                    delegateFunc = (imageBase, x, y, b) => Math.Abs(imageBase[x, y].A - b) > Epsilon;
                    break;

                default:
                    delegateFunc = (imageBase, x, y, b) => Math.Abs(imageBase[x, y].B - b) > Epsilon;
                    break;
            }

            Func<ImageBase, int> getMinY = imageBase =>
            {
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        if (delegateFunc(imageBase, x, y, componentValue))
                        {
                            return y;
                        }
                    }
                }

                return 0;
            };

            Func<ImageBase, int> getMaxY = imageBase =>
            {
                for (int y = height - 1; y > -1; y--)
                {
                    for (int x = 0; x < width; x++)
                    {
                        if (delegateFunc(imageBase, x, y, componentValue))
                        {
                            return y;
                        }
                    }
                }

                return height;
            };

            Func<ImageBase, int> getMinX = imageBase =>
            {
                for (int x = 0; x < width; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        if (delegateFunc(imageBase, x, y, componentValue))
                        {
                            return x;
                        }
                    }
                }

                return 0;
            };

            Func<ImageBase, int> getMaxX = imageBase =>
            {
                for (int x = width - 1; x > -1; x--)
                {
                    for (int y = 0; y < height; y++)
                    {
                        if (delegateFunc(imageBase, 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);
        }
예제 #3
0
        /// <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));
        }
예제 #4
0
        /// <summary>
        /// Finds the bounding rectangle based on the first instance of any color component other
        /// than the given one.
        /// </summary>
        /// <param name="bitmap">
        /// The <see cref="Image"/> 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(Image bitmap, byte componentValue, RgbaComponent channel = RgbaComponent.B)
        {
            int   width       = bitmap.Width;
            int   height      = bitmap.Height;
            Point topLeft     = new Point();
            Point bottomRight = new Point();

            Func <FastBitmap, int, int, byte, bool> delegateFunc;

            // Determine which channel to check against
            switch (channel)
            {
            case RgbaComponent.R:
                delegateFunc = (fastBitmap, x, y, b) => fastBitmap.GetPixel(x, y).R != b;
                break;

            case RgbaComponent.G:
                delegateFunc = (fastBitmap, x, y, b) => fastBitmap.GetPixel(x, y).G != b;
                break;

            case RgbaComponent.A:
                delegateFunc = (fastBitmap, x, y, b) => fastBitmap.GetPixel(x, y).A != b;
                break;

            default:
                delegateFunc = (fastBitmap, x, y, b) => fastBitmap.GetPixel(x, y).B != b;
                break;
            }

            Func <FastBitmap, int> getMinY = fastBitmap =>
            {
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        if (delegateFunc(fastBitmap, x, y, componentValue))
                        {
                            return(y);
                        }
                    }
                }

                return(0);
            };

            Func <FastBitmap, int> getMaxY = fastBitmap =>
            {
                for (int y = height - 1; y > -1; y--)
                {
                    for (int x = 0; x < width; x++)
                    {
                        if (delegateFunc(fastBitmap, x, y, componentValue))
                        {
                            return(y);
                        }
                    }
                }

                return(height);
            };

            Func <FastBitmap, int> getMinX = fastBitmap =>
            {
                for (int x = 0; x < width; x++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        if (delegateFunc(fastBitmap, x, y, componentValue))
                        {
                            return(x);
                        }
                    }
                }

                return(0);
            };

            Func <FastBitmap, int> getMaxX = fastBitmap =>
            {
                for (int x = width - 1; x > -1; x--)
                {
                    for (int y = 0; y < height; y++)
                    {
                        if (delegateFunc(fastBitmap, x, y, componentValue))
                        {
                            return(x);
                        }
                    }
                }

                return(height);
            };

            using (FastBitmap fastBitmap = new FastBitmap(bitmap))
            {
                topLeft.Y     = getMinY(fastBitmap);
                topLeft.X     = getMinX(fastBitmap);
                bottomRight.Y = getMaxY(fastBitmap) + 1;
                bottomRight.X = getMaxX(fastBitmap) + 1;
            }

            return(GetBoundingRectangle(topLeft, bottomRight));
        }
예제 #5
0
        /// <summary>
        /// Finds the bounding rectangle based on the first instance of any color component other
        /// than the given one.
        /// </summary>
        /// <typeparam name="T">The pixel format.</typeparam>
        /// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
        /// <param name="bitmap">The <see cref="Image"/> 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 <T, TP>(ImageBase <T, TP> bitmap, float componentValue, RgbaComponent channel = RgbaComponent.B)
            where T : IPackedVector <TP>
            where TP : struct
        {
            const float Epsilon     = .00001f;
            int         width       = bitmap.Width;
            int         height      = bitmap.Height;
            Point       topLeft     = new Point();
            Point       bottomRight = new Point();

            Func <IPixelAccessor <T, TP>, int, int, float, bool> delegateFunc;

            // Determine which channel to check against
            switch (channel)
            {
            case RgbaComponent.R:
                delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToBytes()[0] - b) > Epsilon;
                break;

            case RgbaComponent.G:
                delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToBytes()[1] - b) > Epsilon;
                break;

            case RgbaComponent.B:
                delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToBytes()[2] - b) > Epsilon;
                break;

            default:
                delegateFunc = (pixels, x, y, b) => Math.Abs(pixels[x, y].ToBytes()[3] - b) > Epsilon;
                break;
            }

            Func <IPixelAccessor <T, TP>, int> getMinY = 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);
            };

            Func <IPixelAccessor <T, TP>, int> getMaxY = 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);
            };

            Func <IPixelAccessor <T, TP>, int> getMinX = 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);
            };

            Func <IPixelAccessor <T, TP>, int> getMaxX = 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);
            };

            using (IPixelAccessor <T, TP> bitmapPixels = bitmap.Lock())
            {
                topLeft.Y     = getMinY(bitmapPixels);
                topLeft.X     = getMinX(bitmapPixels);
                bottomRight.Y = (getMaxY(bitmapPixels) + 1).Clamp(0, height);
                bottomRight.X = (getMaxX(bitmapPixels) + 1).Clamp(0, width);
            }

            return(GetBoundingRectangle(topLeft, bottomRight));
        }