Пример #1
0
    //Scan-line flood fill, much faster
    //https://lodev.org/cgtutor/floodfill.html#Scanline_Floodfill_Algorithm_With_Stack
    public static PixelMatrix FloodFillLine(PixelMatrix bmp, int x, int y, Color replacementColor)
    {
        Point pt = new Point(x, y);

        Color targetColor = bmp.GetPixel(pt.x, pt.y);

        if (targetColor == replacementColor)
        {
            return(bmp);
        }

        Stack <Point> pixels = new Stack <Point>();

        pixels.Push(pt);
        while (pixels.Count != 0)
        {
            Point temp = pixels.Pop();
            int   y1   = temp.y;

            while (y1 >= 0 && bmp.GetPixel(temp.x, y1) == targetColor)
            {
                y1--;
            }
            y1++;
            bool spanLeft  = false;
            bool spanRight = false;

            while (y1 < bmp.height && bmp.GetPixel(temp.x, y1) == targetColor)
            {
                bmp.SetPixelSafe(temp.x, y1, replacementColor);

                Color clm1 = bmp.GetPixel(temp.x - 1, y1);
                Color clp1 = bmp.GetPixel(temp.x + 1, y1);

                if (!spanLeft && temp.x > 0 && clm1 == targetColor)
                {
                    pixels.Push(new Point(temp.x - 1, y1));
                    spanLeft = true;
                }
                else if (spanLeft && temp.x - 1 >= 0 && clm1 != targetColor)
                {
                    spanLeft = false;
                }
                if (!spanRight && temp.x < bmp.width - 1 && clp1 == targetColor)
                {
                    pixels.Push(new Point(temp.x + 1, y1));
                    spanRight = true;
                }
                else if (spanRight && temp.x < bmp.width - 1 && clp1 != targetColor)
                {
                    spanRight = false;
                }
                y1++;
            }
        }

        return(bmp);
    }
        /// <summary>
        /// Calculates the best-fitting character based on Mean squared error. See <see cref="RenderOption.CalculateCharForMatrix(PixelMatrix)"/> and <see cref="https://en.wikipedia.org/wiki/Mean_squared_error"/> for more information.
        /// </summary>
        /// <param name="tile">The part of the image to be represented.</param>
        /// <returns>The best-fitting character and its corresponding PixelMatrix.</returns>
        public override KeyValuePair <char, PixelMatrix> CalculateCharForMatrix(PixelMatrix tile)
        {
            double minScore = double.MaxValue;
            KeyValuePair <char, PixelMatrix> bestFit = Font.Chars.FirstOrDefault();

            foreach (var item in Font.Chars)
            {
                double score = 0;

                for (int y = 0; y < Font.CharSize.Height; y++)
                {
                    for (int x = 0; x < Font.CharSize.Width; x += Utils.BytesPerPixel)
                    {
                        byte grayChar   = Utils.ColorToGray(item.Value.GetPixel(x, y));
                        byte grayMatrix = Utils.ColorToGray(tile.GetPixel(x, y));

                        score += (grayMatrix - grayChar) * (grayMatrix - grayChar);
                    }
                }

                if (score < minScore)
                {
                    bestFit  = item;
                    minScore = score;
                }
            }

            return(bestFit);
        }
        /// <summary>
        /// Calculates the best-fitting character based on Structural similarity index. See <see cref="RenderOption.CalculateCharForMatrix(PixelMatrix)"/> and <see cref="https://en.wikipedia.org/wiki/Structural_similarity"/> for more information.
        /// </summary>
        /// <param name="tile">The part of the image to be represented.</param>
        /// <returns>The best-fitting character and its corresponding PixelMatrix.</returns>
        public override KeyValuePair <char, PixelMatrix> CalculateCharForMatrix(PixelMatrix tile)
        {
            double maxScore = RenderingMode == RenderingMode.Default ? double.MinValue : double.MaxValue;
            KeyValuePair <char, PixelMatrix> bestFit = Font.Chars.FirstOrDefault();

            foreach (var item in Font.Chars)
            {
                double score = 0;

                double covariance = 0;
                for (int y = 0; y < Font.CharSize.Height; y++)
                {
                    for (int x = 0; x < Font.CharSize.Width; x += Utils.BytesPerPixel)
                    {
                        byte grayChar   = Utils.ColorToGray(item.Value.GetPixel(x, y));
                        byte grayMatrix = Utils.ColorToGray(tile.GetPixel(x, y));

                        covariance += (grayChar - item.Value.Mean) * (grayMatrix - tile.Mean);
                    }
                }

                covariance /= Font.CharSize.Height * Font.CharSize.Width;

                score  = (2 * Math.Sqrt(item.Value.Variance) * Math.Sqrt(tile.Variance) + C1) * (2 * covariance + C2);
                score /= (item.Value.Mean * item.Value.Mean + tile.Mean * tile.Mean + C1) * (covariance * covariance + C2);

                if (RenderingMode == RenderingMode.Default && score > maxScore)
                {
                    bestFit  = item;
                    maxScore = score;
                }
                else if (RenderingMode == RenderingMode.Inverted && score < maxScore)
                {
                    bestFit  = item;
                    maxScore = score;
                }
            }

            return(bestFit);
        }
Пример #4
0
 /// <summary>
 /// Copies the pixel values to the output image. See <see cref="Converter{T}.AddToOutput(KeyValuePair{char, PixelMatrix}, Point, PixelMatrix)"/> for more information.
 /// </summary>
 /// <param name="character">The character to be drawn.</param>
 /// <param name="point">A point that represents the coordinates of the upper left corner to be drawn.</param>
 /// <param name="tile">The PixelMatrix representing a tile of the source image.</param>
 protected override void AddToOutput(KeyValuePair <char, PixelMatrix> character, Point point, PixelMatrix tile)
 {
     for (int y = point.Y; y < point.Y + RenderOptions.TileSize.Height; y++)
     {
         for (int x = point.X * Utils.BytesPerPixel; x < (point.X + RenderOptions.TileSize.Width) * Utils.BytesPerPixel; x += Utils.BytesPerPixel)
         {
             int index = y * _size.Width * Utils.BytesPerPixel;
             System.Drawing.Color c = DrawingMode.CalculateColor(character.Value.GetPixel(x - Utils.BytesPerPixel * point.X, y - point.Y), tile.GetPixel(x - Utils.BytesPerPixel * point.X, y - point.Y));
             _pixels[index + x]     = c.B; // b
             _pixels[index + x + 1] = c.G; // g
             _pixels[index + x + 2] = c.R; // r
             _pixels[index + x + 3] = c.A; // a
         }
     }
 }