Ejemplo n.º 1
0
        public static string GenerateFront(string name, Roles role, string filePath)
        {
            string hexcode = "#0B1133";
            string border  = "Cards/hero_frontoverlay.png";

            if (role == Roles.Villain)
            {
                border  = "Cards/villain_frontoverlay.png";
                hexcode = "#670000";
            }
            else if (role == Roles.Rogue)
            {
                border  = "Cards/rogue_frontoverlay.png";
                hexcode = "#350022";
            }

            var fontCollection = new FontCollection();
            var parentFont     = fontCollection.Install("Cards/front.tff").CreateFont(50, FontStyle.Bold);

            var childFont = parentFont;

            using (Image <Rgba32> backgroundImage = Image.Load(filePath))
            {
                using (Image <Rgba32> borderImage = Image.Load(border))
                {
                    int   fontSize   = 50;
                    float textOffset = 0;
                    while (true)
                    {
                        var size = TextMeasurer.Measure(name, new RendererOptions(childFont));
                        if (size.Width > 350)
                        {
                            fontSize -= 5;
                            childFont = new Font(parentFont, fontSize);
                            continue;
                        }

                        textOffset = 250 - size.Width / 2;
                        break;
                    }
                    backgroundImage.Mutate(x => x.Resize(new ResizeOptions()
                    {
                        Mode = ResizeMode.Crop, Size = new Size(500, 700), Position = AnchorPositionMode.Top
                    }).DrawImage(borderImage, 1).DrawText(name, childFont, Brushes.Solid(Rgba32.FromHex("#FFFFFF")), Pens.Solid(Rgba32.FromHex(hexcode), 8), new PointF(textOffset, 630)).DrawText(name, childFont, Brushes.Solid(Rgba32.FromHex("#FFFFFF")), new PointF(textOffset, 630)));

                    backgroundImage.Save($"Cards/Done/front-{name}.png");
                    return($"Cards/Done/front-{name}.png");
                }
            }
        }
Ejemplo n.º 2
0
        public void Draw()
        {
            if (ImageWrapper != null)
            {
                var width  = (int)ImageWrapper.ActualWidth;
                var height = (int)ImageWrapper.ActualHeight;

                using (image = new Image <Rgba32>(width, height))
                {
                    // Draw triangle
                    image.Mutate((x) =>
                    {
                        // Define pens and inks
                        var sss = new Pen(Rgba32.ParseHex("#FFC0CB"), 10, new float[] { 2f, 6f, 8f });

                        var pinkPen   = Pens.Solid(Rgba32.ParseHex("#FFC0CB"), 10);
                        var greenPen  = Pens.Solid(Rgba32.ParseHex("#228B22"), 10);
                        var blackPen  = Pens.Solid(Rgba32.ParseHex("#000000"), 10);
                        var pinkBrush = Brushes.Solid(Rgba32.ParseHex("#C71585"));


                        Image img = Image.Load("Resources\\cat.jpg");
                        img.Mutate((x) =>
                        {
                            x.Resize(
                                128,
                                (x.GetCurrentSize().Height / x.GetCurrentSize().Width) * 128);
                        });
                        var CatBrush = new ImageBrush(img);


                        // Draw a Line
                        x.DrawLines(pinkPen, new PointF[] {
                            new PointF(30, 30),
                            new PointF(100, 30)
                        });

                        // Draw a Triangle
                        x.FillPolygon(CatBrush, new PointF[] {
                            new PointF(50, 50),
                            new PointF(500, 30),
                            new PointF(555, 555),
                        });

                        // Draw a star x y numberofcorners innerradius outerradius
                        Star star       = new Star(50, 50, 5, 50, 100);
                        var staroutline = Outliner.GenerateOutline(star, 2, JointStyle.Round);
                        x.Fill(CatBrush, star);

                        // Draw an arc
                        var arc = new Polygon(new CubicBezierLineSegment(new PointF[] {
                            new PointF(10, 400),
                            new PointF(30, 10),
                            new PointF(240, 30),
                            new PointF(300, 400)
                        }));
                        x.Draw(blackPen, arc);

                        // Draw some Ellipse
                        var sector = new EllipsePolygon(200, 200, 10, 20).Scale(5);
                        x.Draw(blackPen, sector);
                    });

                    // Set the source
                    ImageControl.Source = Helpers.ImageToBitmap(image);
                }
            }
        }
Ejemplo n.º 3
0
        public static Stream Render(string text, Image <Rgba32> image)
        {
            var words = text.Split(' ');

            var font = Arial.CreateFont(2, FontStyle.Regular);

            var canvasPoint = new PointF(image.Width * 0.125F, image.Height * 0.70F);
            var canvasSize  = new SizeF(image.Width * 0.75F, image.Height * 0.3F);

            font = GetLargestFont(canvasSize, font, text);

            var render = new RendererOptions(font);

            foreach (var line in SplitTextForMaxWidth(canvasSize.Width, font, text))
            {
                var textSize = TextMeasurer.Measure(line, render);
                var point    = new PointF(canvasPoint.X + (canvasSize.Width - textSize.Width) / 2, canvasPoint.Y);
                image.Mutate(cl => cl.DrawText(line, font, Brushes.Solid(Color.WhiteSmoke), Pens.Solid(Color.Black, 1), point));
                canvasPoint.Y += textSize.Height;
            }

            var str = new MemoryStream();

            image.SaveAsJpeg(str);
            str.Seek(0, SeekOrigin.Begin);
            return(str);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Process the filter on the specified image.
        /// </summary>
        ///
        /// <param name="source">Source image data.</param>
        /// <param name="destination">Destination image data.</param>
        /// <param name="rect">Image rectangle for processing by the filter.</param>
        ///
        protected override void ProcessFilter(Image <Rgb24> source, Image <L8> destination, Rectangle rect)
        {
            // processing start and stop X,Y positions
            int startX = rect.Left + 1;
            int startY = rect.Top + 1;
            int stopX  = startX + rect.Width - 2;
            int stopY  = startY + rect.Height - 2;

            int width  = rect.Width - 2;
            int height = rect.Height - 2;

            int dstOffset = rect.Width + 2;
            int srcOffset = rect.Width + 2;

            // pixel's value and gradients
            int gx, gy;

            double orientation, toAngle = 180.0 / System.Math.PI;
            float  leftPixel = 0, rightPixel = 0;

            // STEP 1 - blur image
            source.Mutate(x => x.ApplyProcessor(this.gaussianFilter));
            var src = source.CloneAs <L8>();

            // orientation array
            byte[] orients = new byte[width * height];

            // gradients array
            float[,] gradients = new float[source.Width, source.Height];
            float maxGradient = float.NegativeInfinity;

            // STEP 2 - calculate magnitude and edge orientation
            int p = 0;

            // for each line
            for (int y = startY; y < stopY; y++)
            {
                // for each pixel
                for (int x = startX; x < stopX; x++, p++)
                {
                    gx = src[y - 1, x + 1].PackedValue + src[y, x + 1].PackedValue
                         - src[y - 1, x - 1].PackedValue - src[y, x - 1].PackedValue
                         + (2 * (src[y + 1, x].PackedValue - src[y - 1, x].PackedValue));

                    gy = src[y - 1, x - 1].PackedValue + src[y - 1, x + 1].PackedValue
                         - src[y, x - 1].PackedValue - src[y, x + 1].PackedValue
                         + (2 * (src[y - 1, x].PackedValue - src[y + 1, x].PackedValue));

                    // get gradient value
                    gradients[x, y] = (float)Math.Sqrt((gx * gx) + (gy * gy));
                    if (gradients[x, y] > maxGradient)
                    {
                        maxGradient = gradients[x, y];
                    }

                    // --- get orientation
                    if (gx == 0)
                    {
                        // can not divide by zero
                        orientation = (gy == 0) ? 0 : 90;
                    }
                    else
                    {
                        double div = (double)gy / gx;

                        // handle angles of the 2nd and 4th quads
                        if (div < 0)
                        {
                            orientation = 180 - (Math.Atan(-div) * toAngle);
                        }

                        // handle angles of the 1st and 3rd quads
                        else
                        {
                            orientation = System.Math.Atan(div) * toAngle;
                        }

                        // get closest angle from 0, 45, 90, 135 set
                        if (orientation < 22.5)
                        {
                            orientation = 0;
                        }
                        else if (orientation < 67.5)
                        {
                            orientation = 45;
                        }
                        else if (orientation < 112.5)
                        {
                            orientation = 90;
                        }
                        else if (orientation < 157.5)
                        {
                            orientation = 135;
                        }
                        else
                        {
                            orientation = 0;
                        }
                    }

                    // save orientation
                    orients[p] = (byte)orientation;
                }
            }

            // STEP 3 - suppres non maximums

            p = 0;

            // for each line
            for (int y = startY; y < stopY; y++)
            {
                // for each pixel
                for (int x = startX; x < stopX; x++, p++)
                {
                    // get two adjacent pixels
                    switch (orients[p])
                    {
                    case 0:
                        leftPixel  = gradients[x - 1, y];
                        rightPixel = gradients[x + 1, y];
                        break;

                    case 45:
                        leftPixel  = gradients[x - 1, y + 1];
                        rightPixel = gradients[x + 1, y - 1];
                        break;

                    case 90:
                        leftPixel  = gradients[x, y + 1];
                        rightPixel = gradients[x, y - 1];
                        break;

                    case 135:
                        leftPixel  = gradients[x + 1, y + 1];
                        rightPixel = gradients[x - 1, y - 1];
                        break;
                    }

                    // compare current pixels value with adjacent pixels
                    if ((gradients[x, y] < leftPixel) || (gradients[x, y] < rightPixel))
                    {
                        destination[startY, startX] = new L8(0);
                    }
                    else
                    {
                        var result = (byte)(gradients[x, y] / maxGradient * 255);
                        destination[startY, startX] = new L8(result);
                    }
                }
            }

            // STEP 4 - hysteresis

            // for each line
            for (int y = startY; y < stopY; y++)
            {
                // for each pixel
                for (int x = startX; x < stopX; x++)
                {
                    if (destination[startY, startX].PackedValue < this.HighThreshold)
                    {
                        if (destination[startY, startX].PackedValue < this.LowThreshold)
                        {
                            // non edge
                            destination[startY, startX] = new L8(0);
                        }
                        else
                        {
                            // check 8 neighboring pixels
                            if ((destination[startY - 1, startX].PackedValue < this.HighThreshold) &&
                                (destination[startY + 1, startX].PackedValue < this.HighThreshold) &&
                                (destination[startY - 1, startX - 1].PackedValue < this.HighThreshold) &&
                                (destination[startY - 1, startX].PackedValue < this.HighThreshold) &&
                                (destination[startY - 1, startX + 1].PackedValue < this.HighThreshold) &&
                                (destination[startY + 1, startX - 1].PackedValue < this.HighThreshold) &&
                                (destination[startY + 1, startX].PackedValue < this.HighThreshold) &&
                                (destination[startY + 1, startX + 1].PackedValue < this.HighThreshold))
                            {
                                destination[startY, startX] = new L8(0);
                            }
                        }
                    }
                }
            }

            // STEP 5 - draw black rectangle to remove those pixels, which were not processed
            // (this needs to be done for those cases, when filter is applied "in place" -
            //  source image is modified instead of creating new copy)
            RectangleF r = rect;

            destination.Mutate(x => x.Draw(Pens.Solid(Color.Black, 1), r));
        }
Ejemplo n.º 5
0
        private static void DrawWorld(World world)
        {
            var map    = world.Map;
            var output = "cellmap.png";

            var e = map.MapCells.Values.ElementAt(10);

            var highlight = new List <uint>()
            {
                e.Id
            };

            highlight.AddRange(e.AdjacentMapCellIds);

            using (var image = new Image <Rgba32>(map.Width, map.Height))
            {
                // Draw edges first to ensure any pixel gaps between polygons
                // will be filled in
                foreach (var cell in map.MapCells.Values)
                {
                    if (cell.MapPoints.Count > 2)
                    {
                        var color = GetColor(cell, map.LandThreshold);

                        image.Mutate(x => x
                                     .DrawLines(new Pen(color, 3f), cell.MapPoints.Select(p => new PointF(p.X, p.Y)).ToArray())
                                     );
                    }
                }

                // Now draw map cell polygons
                foreach (var cell in map.MapCells.Values)
                {
                    if (cell.MapPoints.Count > 2)
                    {
                        var color = GetColor(cell, map.LandThreshold);

                        image.Mutate(x => x
                                     .FillPolygon(color, cell.MapPoints.Select(p => new PointF(p.X, p.Y)).ToArray())
                                     );
                    }
                }

                var colors = new List <Color>()
                {
                    Color.Red,
                    Color.Orange,
                    Color.Yellow,
                    Color.GreenYellow,
                    Color.Green,
                    Color.DarkGreen,
                    Color.DarkBlue,
                    Color.Blue,
                    Color.BlueViolet,
                    Color.Violet,
                    Color.PaleVioletRed
                };

                colors.AddRange(Color.WebSafePalette.ToArray());

                // Regions
                foreach (var territory in world.Territories.Values)
                {
                    var color = colors.RemoveRandom();

                    if (color == null)
                    {
                        color = Color.White;
                    }

                    /*
                     * foreach (var cell in territory.MapCells)
                     * {
                     *  if (cell.MapPoints.Count > 2)
                     *  {
                     *      var centerX = cell.X;
                     *      var centerY = cell.Y;
                     *
                     *      image.Mutate(x => x
                     *          .FillPolygon(color, cell.MapPoints.Select(p => new PointF(p.X, p.Y)).ToArray()));
                     *  }
                     * }/**/

                    /*
                     * image.Mutate(x => x
                     *  .DrawLines(new Pen(color, 2f), territory.ContainingMapPointIds.Select(id => new PointF(world.Map.MapPoints[id].X, world.Map.MapPoints[id].Y)).ToArray()));
                     */
                }

                // Now draw population centers

                foreach (var pop in world.PopulationCenters.Values)
                {
                    image.Mutate(x => x
                                 .DrawLines(new Pen(Color.LightGray, 10f), new PointF(pop.MapCell.X, pop.MapCell.Y), new PointF(pop.MapCell.X, pop.MapCell.Y))
                                 .DrawText(pop.Name, SmallFont, Color.White, new PointF(pop.MapCell.X + 10, pop.MapCell.Y + 10))
                                 );
                }

                // Show names of landmasses
                var textOptions = new TextOptions()
                {
                    HorizontalAlignment = HorizontalAlignment.Center,
                    VerticalAlignment   = VerticalAlignment.Center,
                };

                var drawingOptions = new DrawingOptions()
                {
                    TextOptions = textOptions
                };


                foreach (var landmass in world.Landmasses.Values.Where(x => x.MapCells.Count > 2))
                {
                    if (landmass.MapCells.Count > 100)
                    {
                        image.Mutate(x => x
                                     .DrawText(drawingOptions, landmass.Name, BigFont, Brushes.Solid(Color.White), Pens.Solid(Color.Black, 2.5f), new PointF(landmass.X, landmass.Y))
                                     );
                    }
                    else if (landmass.MapCells.Count < 20)
                    {
                        /*
                         * drawingOptions.TextOptions.VerticalAlignment = VerticalAlignment.Bottom;
                         *
                         * image.Mutate(x => x
                         *  .DrawText(drawingOptions, landmass.Name, SmallFont, Brushes.Solid(Color.Black), Pens.Solid(Color.Black, 1), new PointF(landmass.Center.X, landmass.Center.Y))
                         * );
                         * /**/
                    }
                    else
                    {
                        image.Mutate(x => x
                                     .DrawText(drawingOptions, landmass.Name, NormalFont, Brushes.Solid(Color.Black), Pens.Solid(Color.Black, 0.5f), new PointF(landmass.X, landmass.Y))
                                     );
                    }
                }

                using (var filestream = new FileStream(output, FileMode.Create))
                {
                    image.SaveAsPng(filestream);
                }
            }

            try
            {
                var process = new ProcessStartInfo(output)
                {
                    UseShellExecute = true, Verb = "open"
                };
                Process.Start(process);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Renderes the given historic coverages as PNG image.
        /// </summary>
        /// <param name="historicCoverages">The historic coverages.</param>
        /// <returns>The image in PNG format.</returns>
        public static byte[] RenderHistoryChart(IReadOnlyList <HistoricCoverage> historicCoverages)
        {
            using (Image <Rgba32> image = new Image <Rgba32>(1450, 150))
                using (MemoryStream output = new MemoryStream())
                {
                    var grayPen = Pens.Dash(Color.LightGray, 1);
                    var redPen  = Pens.Solid(Color.ParseHex("cc0000"), 2);
                    var bluePen = Pens.Solid(Color.ParseHex("1c2298"), 2);

                    var redBrush  = Brushes.Solid(Color.ParseHex("cc0000"));
                    var blueBrush = Brushes.Solid(Color.ParseHex("1c2298"));

                    int numberOfLines = historicCoverages.Count;

                    if (numberOfLines == 1)
                    {
                        numberOfLines = 2;
                    }

                    float totalWidth = 1445 - 50;
                    float width      = totalWidth / (numberOfLines - 1);

                    float totalHeight = 115 - 15;

                    image.Mutate(ctx =>
                    {
                        ctx.Fill(Color.White);

                        ctx.DrawLines(grayPen, new PointF(50, 115), new PointF(1445, 115));
                        ctx.DrawLines(grayPen, new PointF(50, 90), new PointF(1445, 90));
                        ctx.DrawLines(grayPen, new PointF(50, 65), new PointF(1445, 65));
                        ctx.DrawLines(grayPen, new PointF(50, 40), new PointF(1445, 40));
                        ctx.DrawLines(grayPen, new PointF(50, 15), new PointF(1445, 15));

                        for (int i = 0; i < numberOfLines; i++)
                        {
                            ctx.DrawLines(grayPen, new PointF(50 + (i * width), 15), new PointF(50 + (i * width), 115));
                        }

                        for (int i = 1; i < historicCoverages.Count; i++)
                        {
                            float x1 = 50 + ((i - 1) * width);
                            float y1 = 15 + (((100 - (float)historicCoverages[i - 1].CoverageQuota.GetValueOrDefault()) * totalHeight) / 100);

                            float x2 = 50 + (i * width);
                            float y2 = 15 + (((100 - (float)historicCoverages[i].CoverageQuota.GetValueOrDefault()) * totalHeight) / 100);

                            ctx.DrawLines(redPen, new PointF(x1, y1), new PointF(x2, y2));
                        }

                        if (historicCoverages.Any(h => h.BranchCoverageQuota.HasValue))
                        {
                            for (int i = 1; i < historicCoverages.Count; i++)
                            {
                                float x1 = 50 + ((i - 1) * width);
                                float y1 = 15 + (((100 - (float)historicCoverages[i - 1].BranchCoverageQuota.GetValueOrDefault()) * totalHeight) / 100);

                                float x2 = 50 + (i * width);
                                float y2 = 15 + (((100 - (float)historicCoverages[i].BranchCoverageQuota.GetValueOrDefault()) * totalHeight) / 100);

                                ctx.DrawLines(bluePen, new PointF(x1, y1), new PointF(x2, y2));
                            }
                        }

                        for (int i = 0; i < historicCoverages.Count; i++)
                        {
                            float x1 = 50 + (i * width);
                            float y1 = 15 + (((100 - (float)historicCoverages[i].CoverageQuota.GetValueOrDefault()) * totalHeight) / 100);

                            ctx.Fill(redBrush, new EllipsePolygon(x1, y1, 3));
                        }

                        if (historicCoverages.Any(h => h.BranchCoverageQuota.HasValue))
                        {
                            for (int i = 0; i < historicCoverages.Count; i++)
                            {
                                float x1 = 50 + (i * width);
                                float y1 = 15 + (((100 - (float)historicCoverages[i].BranchCoverageQuota.GetValueOrDefault()) * totalHeight) / 100);

                                ctx.Fill(blueBrush, new EllipsePolygon(x1, y1, 3));
                            }
                        }

                        try
                        {
                            var font = SystemFonts.CreateFont("Arial", 11, FontStyle.Regular);
                            var textGraphicsOptions = new TextGraphicsOptions();
                            textGraphicsOptions.TextOptions.HorizontalAlignment = HorizontalAlignment.Right;
                            ctx.DrawText(textGraphicsOptions, "100", font, Color.Gray, new PointF(38, 5));
                            ctx.DrawText(textGraphicsOptions, "75", font, Color.Gray, new PointF(38, 30));
                            ctx.DrawText(textGraphicsOptions, "50", font, Color.Gray, new PointF(38, 55));
                            ctx.DrawText(textGraphicsOptions, "25", font, Color.Gray, new PointF(38, 80));
                            ctx.DrawText(textGraphicsOptions, "0", font, Color.Gray, new PointF(38, 105));
                        }
                        catch (SixLabors.Fonts.Exceptions.FontFamilyNotFoundException)
                        {
                            // Font 'Arial' may not be present on Linux
                        }
                    });

                    image.Save(output, new PngEncoder());
                    return(output.ToArray());
                }
        }
Ejemplo n.º 7
0
        public static IImageProcessingContext DrawBoxedText(this IImageProcessingContext processingContext,
                                                            Font font,
                                                            string text,
                                                            Color mainColor,
                                                            Color outlineColor,
                                                            Rectangle rectangle,
                                                            VerticalAlignment verticalAlignment,
                                                            bool debugRectangle = false)
        {
            Size  imgSize      = processingContext.GetCurrentSize();
            float targetWidth  = rectangle.Width;
            float targetHeight = rectangle.Height;

            float targetMinHeight = (int)(targetHeight * 0.95);

            var           scaledFont = font;
            FontRectangle s          = new(0, 0, float.MaxValue, float.MaxValue);

            float scaleFactor = (scaledFont.Size / 2);
            int   trapCount   = (int)scaledFont.Size * 2;

            if (trapCount < 10)
            {
                trapCount = 10;
            }

            bool isTooSmall = false;

            while ((s.Height > targetHeight || s.Height < targetMinHeight) && trapCount > 0)
            {
                if (s.Height > targetHeight)
                {
                    if (isTooSmall)
                    {
                        scaleFactor /= 2;
                    }

                    scaledFont = new Font(scaledFont, scaledFont.Size - scaleFactor);
                    isTooSmall = false;
                }

                if (s.Height < targetMinHeight)
                {
                    if (!isTooSmall)
                    {
                        scaleFactor /= 2;
                    }
                    scaledFont = new Font(scaledFont, scaledFont.Size + scaleFactor);
                    isTooSmall = true;
                }
                trapCount--;

                s = TextMeasurer.Measure(text, new RendererOptions(scaledFont)
                {
                    WrappingWidth = targetWidth
                });
            }

            var textGraphicOptions = new TextGraphicsOptions()
            {
                TextOptions =
                {
                    HorizontalAlignment = HorizontalAlignment.Center,
                    VerticalAlignment   = verticalAlignment,
                    WrapTextWidth       = targetWidth
                }
            };
            var position = new PointF(rectangle.X, 0);

            switch (verticalAlignment)
            {
            case VerticalAlignment.Top:
                position.Y = rectangle.Y;
                break;

            case VerticalAlignment.Center:
                position.Y = rectangle.Y + rectangle.Height / 2;
                break;

            case VerticalAlignment.Bottom:
                position.Y = rectangle.Y + rectangle.Height;
                break;

            default:
                break;
            }
            if (debugRectangle)
            {
                PointF[] points = { new PointF(rectangle.X, rectangle.Y), new PointF(rectangle.X, rectangle.Y + rectangle.Height), new PointF(rectangle.X + rectangle.Width, rectangle.Y + rectangle.Height), new PointF(rectangle.X + rectangle.Width, rectangle.Y) };
                processingContext = processingContext.DrawPolygon(new Pen(Color.Red, 5), points);
            }
            return(processingContext.DrawText(textGraphicOptions, text, scaledFont, Brushes.Solid(mainColor), Pens.Solid(outlineColor, font.Size / 10), position));
        }
Ejemplo n.º 8
0
        private static async Task <Stream> DrawText(Stream stream, string text)
        {
            if (stream is null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            if (String.IsNullOrEmpty(text))
            {
                throw new ArgumentNullException(nameof(text));
            }

            var font    = SystemFonts.CreateFont("Arial", 32);
            var options = new TextGraphicsOptions(true)
            {
                VerticalAlignment   = VerticalAlignment.Center,
                HorizontalAlignment = HorizontalAlignment.Center
            };

            MemoryStream output = new MemoryStream();

            using (Image image = Image.Load(stream, new JpegDecoder()))
            {
                var position = new PointF(image.Width / 2, image.Height - 30);

                image.Mutate(x => x.DrawText(options, text, font, Brushes.Solid(Rgba32.White), Pens.Solid(Rgba32.Black, 1), position));

                image.Save(output, new JpegEncoder());
                output.Position = 0;
            }

            return(output);
        }