コード例 #1
0
        public Bitmap ToGrayscale(Bitmap originalBmp, bool parallel)
        {
            FastBitmap fastOriginal = new FastBitmap(originalBmp);
            int        h = originalBmp.Height, w = originalBmp.Width;

            if (parallel)
            {
                Parallel.For(0, h, (y) =>
                {
                    Parallel.For(0, w, (x) =>
                    {
                        Color c  = fastOriginal.GetColor(x, y);
                        int gray = (byte)(c.R * 0.11 + c.G * 0.59 + c.R * 0.3);

                        fastOriginal.SetColor(x, y, Color.FromArgb(gray, gray, gray));
                    });
                });
            }
            else
            {
                for (int y = 0; y < originalBmp.Height; y++)
                {
                    for (int x = 0; x < originalBmp.Width; x++)
                    {
                        Color c    = fastOriginal.GetColor(x, y);
                        int   gray = (byte)(c.R * 0.11 + c.G * 0.59 + c.R * 0.3);

                        fastOriginal.SetColor(x, y, Color.FromArgb(gray, gray, gray));
                    }
                }
            }
            fastOriginal.Dispose();
            return(originalBmp);
        }
コード例 #2
0
        public Bitmap convertToGray(Bitmap originalBmp)
        {
            FastBitmap fastOriginal = new FastBitmap(originalBmp);
            int        h = originalBmp.Height, w = originalBmp.Width;

            for (int y = 0; y < originalBmp.Height; y++)
            {
                for (int x = 0; x < originalBmp.Width; x++)
                {
                    Color c    = fastOriginal.GetColor(x, y);
                    int   gray = (byte)(c.R * 0.11 + c.G * 0.59 + c.R * 0.3);

                    fastOriginal.SetColor(x, y, Color.FromArgb(gray, gray, gray));
                }
            }
            fastOriginal.Dispose();
            return(originalBmp);
        }
コード例 #3
0
        /// <summary>Implements a b&w + hue-based transformation for an image.</summary>
        /// <param name="original">The original image.</param>
        /// <param name="selectedPixels">The location in the original image of the selected pixels for hue
        /// comparison.</param>
        /// <param name="epsilon">Allowed hue variation from selected pixels.</param>
        /// <param name="paths">GraphicPath instances demarcating regions containing possible pixels to be
        /// left in color.</param>
        /// <param name="parallel">Whether to run in parallel.</param>
        /// <returns>The new Bitmap.</returns>
        public Bitmap Colorize(Bitmap original, List <Point> selectedPixels, int epsilon, List <GraphicsPath> paths, bool parallel)
        {
            // Create a new bitmap with the same size as the original
            int    width = original.Width, height = original.Height;
            Bitmap colorizedImage = new Bitmap(width, height);

            // Optimization: For every GraphicsPath, get a bounding rectangle.  This allows for quickly
            // ruling out pixels that are definitely not containing within the selected region.
            Rectangle [] pathsBounds = null;
            if (paths != null && paths.Count > 0)
            {
                pathsBounds = new Rectangle[paths.Count];
                for (int i = 0; i < pathsBounds.Length; i++)
                {
                    pathsBounds[i] = Rectangle.Ceiling(paths[i].GetBounds());
                }
            }

            // Optimization: Hit-testing against GraphicPaths is relatively slow.  Hit testing
            // against rectangles is very fast.  As such, appromixate the area of the GraphicsPath
            // with rectangles which can be hit tested against instead of the paths.  Not quite
            // as accurate, but much faster.
            List <RectangleF[]> compositions = null;

            if (paths != null && paths.Count > 0)
            {
                compositions = new List <RectangleF[]>(paths.Count);
                using (Matrix m = new Matrix())
                {
                    for (int i = 0; i < paths.Count; i++)
                    {
                        using (Region r = new Region(paths[i])) compositions.Add(r.GetRegionScans(m));
                    }
                }
            }

            // Use FastBitmap instances to provide unsafe/faster access to the pixels
            // in the original and in the new images
            using (FastBitmap fastColorizedImage = new FastBitmap(colorizedImage))
                using (FastBitmap fastOriginalImage = new FastBitmap(original))
                {
                    // Extract the selected hues from the selected pixels
                    List <float> selectedHues = new List <float>(selectedPixels.Count);
                    foreach (Point p in selectedPixels)
                    {
                        selectedHues.Add(fastOriginalImage.GetColor(p.X, p.Y).GetHue());
                    }

                    // For progress update purposes, figure out how many pixels there
                    // are in total, and how many constitute 1% so that we can raise
                    // events after every additional 1% has been completed.
                    long totalPixels             = height * width;
                    long pixelsPerProgressUpdate = totalPixels / 100;
                    if (pixelsPerProgressUpdate == 0)
                    {
                        pixelsPerProgressUpdate = 1;
                    }
                    long pixelsProcessed = 0;

                    // Pixels close to the selected hue but not close enough may be
                    // left partially desaturated.  The saturation window determines
                    // what pixels fall into that range.
                    const int maxSaturationWindow = 10;
                    int       saturationWindow    = Math.Min(maxSaturationWindow, epsilon);

                    // Separated out the body of the loop just to make it easier
                    // to switch between sequential and parallel for demo purposes
                    Action <int> processRow = y =>
                    {
                        for (int x = 0; x < width; x++)
                        {
                            // Get the color/hue of th epixel
                            Color c        = fastOriginalImage.GetColor(x, y);
                            float pixelHue = c.GetHue();

                            // Use hit-testing to determine if the pixel is in the selected region.
                            bool pixelInSelectedRegion = false;

                            // First, if there are no paths, by definition it is in the selected
                            // region, since the whole image is then selected
                            if (paths == null || paths.Count == 0)
                            {
                                pixelInSelectedRegion = true;
                            }
                            else
                            {
                                // For each path, first see if the pixel is within the bounding
                                // rectangle; if it's not, it's not in the selected region.
                                Point p = new Point(x, y);
                                for (int i = 0; i < pathsBounds.Length && !pixelInSelectedRegion; i++)
                                {
                                    if (pathsBounds[i].Contains(p))
                                    {
                                        // The pixel is within a bounding rectangle, so now
                                        // see if it's within the composition rectangles
                                        // approximating the region.
                                        foreach (RectangleF bound in compositions[i])
                                        {
                                            if (bound.Contains(x, y))
                                            {
                                                // If it is, it's in the region.
                                                pixelInSelectedRegion = true;
                                                break;
                                            }
                                        }
                                    }
                                }
                            }

                            // Now that we know whether a pixel is in the region,
                            // we can figure out what to do with it.  If the pixel
                            // is not in the selected region, it needs to be converted
                            // to grayscale.
                            bool useGrayscale = true;
                            if (pixelInSelectedRegion)
                            {
                                // If it is in the selected region, get the color hue's distance
                                // from each target hue.  If that distance is less than the user-selected
                                // hue variation limit, leave it in color.  If it's greater than the
                                // variation limit, but within the saturation window of the limit,
                                // desaturate it proportionally to the distance from the limit.
                                foreach (float selectedHue in selectedHues)
                                {
                                    // A hue wheel is 360 degrees. If you pick two points on a wheel, there
                                    // will be two distances between them, depending on which way you go around
                                    // the wheel from one to the other (unless they're exactly opposite from
                                    // each other on the wheel, the two distances will be different).  We always
                                    // want to do our work based on the smaller of the two distances (e.g. a hue
                                    // with the value 359 is very, very close to a hue with the value 1).  So,
                                    // we take the absolute value of the difference between the two hues.  If that
                                    // distance is 180 degrees, then both distances are the same, so it doesn't
                                    // matter which we go with. If that difference is less than 180 degrees,
                                    // we know this must be the smaller of the two distances, since the sum of the
                                    // two distances must add up to 360.  If, however, it's larger than 180, it's the
                                    // longer distance, so to get the shorter one, we have to subtract it from 360.
                                    float distance = Math.Abs(pixelHue - selectedHue);
                                    if (distance > 180)
                                    {
                                        distance = 360 - distance;
                                    }

                                    if (distance <= epsilon)
                                    {
                                        useGrayscale = false;
                                        break;
                                    }
                                    else if ((distance - epsilon) / saturationWindow < 1.0f)
                                    {
                                        useGrayscale = false;
                                        c            = ColorFromHsb(
                                            pixelHue,
                                            c.GetSaturation() * (1.0f - ((distance - epsilon) / maxSaturationWindow)),
                                            c.GetBrightness());
                                        break;
                                    }
                                }
                            }

                            // Set the pixel color into the new image
                            if (useGrayscale)
                            {
                                c = ToGrayscale(c);
                            }
                            fastColorizedImage.SetColor(x, y, c);
                        }

                        // Notify any listeners of our progress, if enough progress has been made
                        Interlocked.Add(ref pixelsProcessed, width);
                        OnProgressChanged((int)(100 * pixelsProcessed / (double)totalPixels));
                    };

                    // Copy over every single pixel, and possibly transform it in the process
                    if (parallel)
                    {
                        Parallel.For(0, height, processRow);
                    }
                    else
                    {
                        for (int y = 0; y < height; y++)
                        {
                            processRow(y);
                        }
                    }
                }

            // We're done creating the image.  Return it.
            return(colorizedImage);
        }
コード例 #4
0
ファイル: ImageManipulation.cs プロジェクト: Farouq/semclone
        /// <summary>Implements a b&w + hue-based transformation for an image.</summary>
        /// <param name="original">The original image.</param>
        /// <param name="selectedPixels">The location in the original image of the selected pixels for hue
        /// comparison.</param>
        /// <param name="epsilon">Allowed hue variation from selected pixels.</param>
        /// <param name="paths">GraphicPath instances demarcating regions containing possible pixels to be
        /// left in color.</param>
        /// <param name="parallel">Whether to run in parallel.</param>
        /// <returns>The new Bitmap.</returns>
        public Bitmap Colorize(Bitmap original, List<Point> selectedPixels, int epsilon, List<GraphicsPath> paths, bool parallel)
        {
            // Create a new bitmap with the same size as the original
            int width = original.Width, height = original.Height;
            Bitmap colorizedImage = new Bitmap(width, height);

            // Optimization: For every GraphicsPath, get a bounding rectangle.  This allows for quickly
            // ruling out pixels that are definitely not containing within the selected region.
            Rectangle [] pathsBounds = null;
            if (paths != null && paths.Count > 0) 
            {
                pathsBounds = new Rectangle[paths.Count];
                for(int i=0; i<pathsBounds.Length; i++)
                {
                    pathsBounds[i] = Rectangle.Ceiling(paths[i].GetBounds());
                }
            }

            // Optimization: Hit-testing against GraphicPaths is relatively slow.  Hit testing
            // against rectangles is very fast.  As such, appromixate the area of the GraphicsPath
            // with rectangles which can be hit tested against instead of the paths.  Not quite
            // as accurate, but much faster.
            List<RectangleF[]> compositions = null;
            if (paths != null && paths.Count > 0)
            {
                compositions = new List<RectangleF[]>(paths.Count);
                using (Matrix m = new Matrix())
                {
                    for(int i=0; i<paths.Count; i++)
                    {
                        using (Region r = new Region(paths[i])) compositions.Add(r.GetRegionScans(m));
                    }
                }
            }

            // Use FastBitmap instances to provide unsafe/faster access to the pixels
            // in the original and in the new images
            using (FastBitmap fastColorizedImage = new FastBitmap(colorizedImage))
            using (FastBitmap fastOriginalImage = new FastBitmap(original))
            {
                // Extract the selected hues from the selected pixels
                List<float> selectedHues = new List<float>(selectedPixels.Count);
                foreach (Point p in selectedPixels)
                {
                    selectedHues.Add(fastOriginalImage.GetColor(p.X, p.Y).GetHue());
                }

                // For progress update purposes, figure out how many pixels there
                // are in total, and how many constitute 1% so that we can raise
                // events after every additional 1% has been completed.
                long totalPixels = height * width;
                long pixelsPerProgressUpdate = totalPixels / 100;
                if (pixelsPerProgressUpdate == 0) pixelsPerProgressUpdate = 1;
                long pixelsProcessed = 0;

                // Pixels close to the selected hue but not close enough may be
                // left partially desaturated.  The saturation window determines
                // what pixels fall into that range.
                const int maxSaturationWindow = 10;
                int saturationWindow = Math.Min(maxSaturationWindow, epsilon);

                // Separated out the body of the loop just to make it easier
                // to switch between sequential and parallel for demo purposes
                Action<int> processRow = y =>
                {
                    for (int x = 0; x < width; x++)
                    {
                        // Get the color/hue of th epixel
                        Color c = fastOriginalImage.GetColor(x, y);
                        float pixelHue = c.GetHue();

                        // Use hit-testing to determine if the pixel is in the selected region.
                        bool pixelInSelectedRegion = false;

                        // First, if there are no paths, by definition it is in the selected
                        // region, since the whole image is then selected
                        if (paths == null || paths.Count == 0) pixelInSelectedRegion = true;
                        else
                        {
                            // For each path, first see if the pixel is within the bounding
                            // rectangle; if it's not, it's not in the selected region.
                            Point p = new Point(x, y);
                            for (int i = 0; i < pathsBounds.Length && !pixelInSelectedRegion; i++)
                            {
                                if (pathsBounds[i].Contains(p))
                                {
                                    // The pixel is within a bounding rectangle, so now
                                    // see if it's within the composition rectangles
                                    // approximating the region.
                                    foreach (RectangleF bound in compositions[i])
                                    {
                                        if (bound.Contains(x, y))
                                        {
                                            // If it is, it's in the region.
                                            pixelInSelectedRegion = true;
                                            break;
                                        }
                                    }
                                }
                            }
                        }

                        // Now that we know whether a pixel is in the region,
                        // we can figure out what to do with it.  If the pixel
                        // is not in the selected region, it needs to be converted
                        // to grayscale.
                        bool useGrayscale = true;
                        if (pixelInSelectedRegion)
                        {
                            // If it is in the selected region, get the color hue's distance 
                            // from each target hue.  If that distance is less than the user-selected
                            // hue variation limit, leave it in color.  If it's greater than the
                            // variation limit, but within the saturation window of the limit,
                            // desaturate it proportionally to the distance from the limit.
                            foreach (float selectedHue in selectedHues)
                            {
                                // A hue wheel is 360 degrees. If you pick two points on a wheel, there
                                // will be two distances between them, depending on which way you go around
                                // the wheel from one to the other (unless they're exactly opposite from
                                // each other on the wheel, the two distances will be different).  We always
                                // want to do our work based on the smaller of the two distances (e.g. a hue
                                // with the value 359 is very, very close to a hue with the value 1).  So,
                                // we take the absolute value of the difference between the two hues.  If that
                                // distance is 180 degrees, then both distances are the same, so it doesn't
                                // matter which we go with. If that difference is less than 180 degrees, 
                                // we know this must be the smaller of the two distances, since the sum of the 
                                // two distances must add up to 360.  If, however, it's larger than 180, it's the
                                // longer distance, so to get the shorter one, we have to subtract it from 360.
                                float distance = Math.Abs(pixelHue - selectedHue);
                                if (distance > 180) distance = 360 - distance;

                                if (distance <= epsilon)
                                {
                                    useGrayscale = false;
                                    break;
                                }
                                else if ((distance - epsilon) / saturationWindow < 1.0f)
                                {
                                    useGrayscale = false;
                                    c = ColorFromHsb(
                                        pixelHue,
                                        c.GetSaturation() * (1.0f - ((distance - epsilon) / maxSaturationWindow)),
                                        c.GetBrightness());
                                    break;
                                }
                            }
                        }

                        // Set the pixel color into the new image
                        if (useGrayscale) c = ToGrayscale(c);
                        fastColorizedImage.SetColor(x, y, c);
                    }

                    // Notify any listeners of our progress, if enough progress has been made
                    Interlocked.Add(ref pixelsProcessed, width);
                    OnProgressChanged((int)(100 * pixelsProcessed / (double)totalPixels));
                };

                // Copy over every single pixel, and possibly transform it in the process
                if (parallel)
                {
                    Parallel.For(0, height, processRow);
                }
                else
                {
                    for (int y = 0; y < height; y++) processRow(y);
                }
            }

            // We're done creating the image.  Return it.
            return colorizedImage;
        }
コード例 #5
0
ファイル: Processor.cs プロジェクト: makht/PicMaster
        double MeasureError(Rectangle blockRect, FastBitmap block)
        {
            double error = 0;

            for (int y = 0; y < blockRect.Height; y++)
            {
                for (int x = 0; x < blockRect.Width; x++)
                {
                    Color m = _main.GetColor(blockRect.X + x, blockRect.Y + y);
                    Color b = block.GetColor(x, y);
                    double dist = Math.Sqrt(
                        (m.R - b.R) * (m.R - b.R) +
                        (m.G - b.G) * (m.G - b.G) +
                        (m.B - b.B) * (m.B - b.B));
                    error += dist;
                }
            }

            return error;
        }
コード例 #6
0
ファイル: PixelMask.cs プロジェクト: alexhanh/Botting-Library
        public bool IsMatch(FastBitmap bitmap, int tolerance)
        {
            Color c1 = bitmap.GetColor(X, Y);
            Color c2 = this.ToColor();

            if (Math.Abs(c1.R - c2.R) > tolerance || Math.Abs(c1.G - c2.G) > tolerance || Math.Abs(c1.B - c2.B) > tolerance)
                return false;

            return true;
        }
コード例 #7
0
        /// <summary>
        /// Matches until difference is more than total tolerance.
        /// </summary>
        /// <param name="fast_bitmap"></param>
        /// <param name="sub_rect"></param>
        /// <returns></returns>
        public bool IsIn(FastBitmap fast_bitmap, Point basepoint, int tolerance)
        {
            int total = 0;
            for (int y = 0; y < this.Height; y++)
            {
                for (int x = 0; x < this.Width; x++)
                {
                    total += BitmapAnalyzer.AbsoluteDiff(this.GetColor(x, y), fast_bitmap.GetColor(basepoint.X + x, basepoint.Y + y));
                    if (total > tolerance)
                        return false;
                }
            }

            return true;
        }
コード例 #8
0
        public static bool IsMatch(FastBitmap fast_bitmap1, FastBitmap fast_bitmap2, int total_tolerance)
        {
            if (fast_bitmap1.Width != fast_bitmap2.Width || fast_bitmap1.Height != fast_bitmap2.Height)
                return false;

            int total = 0;
            for (int y = 0; y < fast_bitmap1.Height; y++)
            {
                for (int x = 0; x < fast_bitmap1.Width; x++)
                {
                    total += BitmapAnalyzer.AbsoluteDiff(fast_bitmap1.GetColor(x, y), fast_bitmap2.GetColor(x, y));

                    if (total > total_tolerance)
                        return false;
                }
            }

            return true;
        }