コード例 #1
0
        /// <summary>
        /// Looks for the brightest pixel after applying a redness filter. Narrows search first using a resampled copy of the image to eliminate edge dots. 
        /// Expects an image that is already cropped to the interested area for faster processing.
        /// </summary>
        /// <param name="img"></param>
        /// <param name="mouse"></param>
        /// <param name="maxDistanceFromMouse"></param>
        /// <returns></returns>
        public unsafe Point FindMaxPixel(UnmanagedImage img, PointF mouse, float maxDistanceFromMouse)
        {
            int width = 15;
            int height = (int)Math.Ceiling((double)img.Height / (double)img.Width * width);

            if (width <= img.Width && height <= img.Height + 1) {
                width = img.Width;
                height = img.Height;
            }

            double scale = (double)img.Width / (double)width;

            UnmanagedImage lowRed = null;
            try {
                if (width != img.Width && height != img.Height) {
                    using (Bitmap reduced = new Bitmap(width, height, PixelFormat.Format24bppRgb))
                    using (Graphics g = Graphics.FromImage(reduced))
                    using (ImageAttributes ia = new ImageAttributes()) {
                        g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
                        g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                        g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                        g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                        ia.SetWrapMode(System.Drawing.Drawing2D.WrapMode.TileFlipXY);
                        g.DrawImage(img.ToManagedImage(false), new Rectangle(0, 0, width, height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia);
                        //TODO: Not sure if ToManagedImage will stick around after the underying image is disposed. I know that the bitmap data will be gone, guess that's most of it.
                        using (UnmanagedImage rui = UnmanagedImage.FromManagedImage(reduced)) {
                            lowRed = new RedEyeFilter(2).Apply(rui); // Make an copy using the red eye filter
                        }
                    }
                } else {
                    //Don't resample unless needed
                    lowRed = new RedEyeFilter(2).Apply(img);
                }

                Point max = GetMax(lowRed, new PointF(mouse.X / (float)scale, mouse.Y / (float)scale), maxDistanceFromMouse / scale);

                //We weren't scaling things? OK, cool...
                if (scale == 0) return max;

                //Otherwise, let's get the unscaled pixel.
                //Calculate the rectangle surrounding the selected pixel, but in source coordinates.
                int tinySize = (int)Math.Ceiling(scale) + 1;
                Rectangle tinyArea = new Rectangle((int)Math.Floor(scale * (double)max.X), (int)Math.Floor(scale * (double)max.Y), tinySize, tinySize);
                if (tinyArea.Right >= img.Width) tinyArea.Width -= img.Width - tinyArea.Right + 1;
                if (tinyArea.Bottom >= img.Height) tinyArea.Height -= img.Height - tinyArea.Bottom + 1;
                //Filter it and look
                using (UnmanagedImage tiny = new Crop(tinyArea).Apply(img)) {
                    using (UnmanagedImage tinyRed = new RedEyeFilter(2).Apply(tiny)) {
                        max = GetMax(tinyRed);
                        max.X += tinyArea.X;
                        max.Y += tinyArea.Y;
                    }
                }
                return max;
            } finally {
                if (lowRed != null) lowRed.Dispose();
            }
        }
コード例 #2
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="image"></param>
        /// <param name="start"></param>
        /// <param name="maxEyeRadius">Should be 2-3 percent of max(width/height)</param>
        /// <param name="maxPointSearchDistance">In source pixels, the max distance from 'start' from which to look for the starting point. Good default: roughly 24 display pixels.</param>
        public static void MarkEye(UnmanagedImage image, Point start, int maxEyeRadius, float maxPointSearchDistance = 0)
        {
            int maxRadius = maxEyeRadius * 2 + (int)Math.Ceiling(maxPointSearchDistance);
            //Find subset
            Rectangle subset = new Rectangle(start.X - maxRadius, start.Y - maxRadius, maxRadius * 2, maxRadius * 2);

            if (subset.X < 0)
            {
                subset.Width += subset.X; subset.X = 0;
            }
            if (subset.Y < 0)
            {
                subset.Height += subset.Y; subset.Y = 0;
            }
            if (subset.Right >= image.Width)
            {
                subset.Width -= (subset.Right - image.Width + 1);
            }
            if (subset.Bottom >= image.Height)
            {
                subset.Height -= (subset.Bottom - image.Height + 1);
            }

            start.X -= subset.X;
            start.Y -= subset.Y;

            //Skip processing if we're slightly out of bounds
            if (subset.X < 0 || subset.Y < 0 || subset.Width < 0 || subset.Height < 0 || subset.Right >= image.Width || subset.Bottom >= image.Height)
            {
                return;
            }

            UnmanagedImage red = null;

            try{
                Point startAt = start;
                using (UnmanagedImage c = new Crop(subset).Apply(image)) {
                    red = new RedEyeFilter(2).Apply(c);
                    if (maxPointSearchDistance > 0)
                    {
                        startAt = new ManualSearcher().FindMaxPixel(c, start, maxPointSearchDistance);
                    }
                }

                var fill = new AdaptiveCircleFill(red, startAt, start, maxEyeRadius * 2);
                fill.FirstPass();
                fill.SecondPass();
                fill.CorrectRedEye(image, subset.X, subset.Y);
                //fill.MarkFilledPixels(image, subset.X, subset.Y, new byte[] { 0, 255, 0, 0 });

                //fill.SetPixel(image, startAt.X + subset.X, startAt.Y + subset.Y, new byte[] { 255, 255, 0, 0 });
            }finally{
                if (red != null)
                {
                    red.Dispose();
                }
            }
        }
コード例 #3
0
ファイル: ManualSearcher.cs プロジェクト: timgaunt/resizer
        /// <summary>
        /// Looks for the brightest pixel after applying a redness filter. Narrows search first using a resampled copy of the image to eliminate edge dots.
        /// Expects an image that is already cropped to the interested area for faster processing.
        /// </summary>
        /// <param name="img"></param>
        /// <param name="mouse"></param>
        /// <param name="maxDistanceFromMouse"></param>
        /// <returns></returns>
        public unsafe Point FindMaxPixel(UnmanagedImage img, PointF mouse, float maxDistanceFromMouse)
        {
            int width  = 15;
            int height = (int)Math.Ceiling((double)img.Height / (double)img.Width * width);

            if (width <= img.Width && height <= img.Height + 1)
            {
                width  = img.Width;
                height = img.Height;
            }

            double scale = (double)img.Width / (double)width;

            UnmanagedImage lowRed = null;

            try {
                if (width != img.Width && height != img.Height)
                {
                    using (Bitmap reduced = new Bitmap(width, height, PixelFormat.Format24bppRgb))
                        using (Graphics g = Graphics.FromImage(reduced))
                            using (ImageAttributes ia = new ImageAttributes()) {
                                g.CompositingMode    = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
                                g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                                g.InterpolationMode  = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                                g.PixelOffsetMode    = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                                g.SmoothingMode      = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
                                ia.SetWrapMode(System.Drawing.Drawing2D.WrapMode.TileFlipXY);
                                g.DrawImage(img.ToManagedImage(false), new Rectangle(0, 0, width, height), 0, 0, img.Width, img.Height, GraphicsUnit.Pixel, ia);
                                //TODO: Not sure if ToManagedImage will stick around after the underlying image is disposed. I know that the bitmap data will be gone, guess that's most of it.
                                using (UnmanagedImage rui = UnmanagedImage.FromManagedImage(reduced)) {
                                    lowRed = new RedEyeFilter(2).Apply(rui); // Make an copy using the red eye filter
                                }
                            }
                }
                else
                {
                    //Don't resample unless needed
                    lowRed = new RedEyeFilter(2).Apply(img);
                }


                Point max = GetMax(lowRed, new PointF(mouse.X / (float)scale, mouse.Y / (float)scale), maxDistanceFromMouse / scale);

                //We weren't scaling things? OK, cool...
                if (scale == 0)
                {
                    return(max);
                }

                //Otherwise, let's get the unscaled pixel.
                //Calculate the rectangle surrounding the selected pixel, but in source coordinates.
                int       tinySize = (int)Math.Ceiling(scale) + 1;
                Rectangle tinyArea = new Rectangle((int)Math.Floor(scale * (double)max.X), (int)Math.Floor(scale * (double)max.Y), tinySize, tinySize);
                if (tinyArea.Right >= img.Width)
                {
                    tinyArea.Width -= img.Width - tinyArea.Right + 1;
                }
                if (tinyArea.Bottom >= img.Height)
                {
                    tinyArea.Height -= img.Height - tinyArea.Bottom + 1;
                }
                //Filter it and look
                using (UnmanagedImage tiny = new Crop(tinyArea).Apply(img)) {
                    using (UnmanagedImage tinyRed = new RedEyeFilter(2).Apply(tiny)) {
                        max    = GetMax(tinyRed);
                        max.X += tinyArea.X;
                        max.Y += tinyArea.Y;
                    }
                }
                return(max);
            } finally {
                if (lowRed != null)
                {
                    lowRed.Dispose();
                }
            }
        }