private static IImageProcessingContext DrawStats(this IImageProcessingContext source, Font header, Font body, string rank, string level, string required, DateTime lastLevelUp) { const float spacing = XpBarLength / 4f; const float y = 117.5f; source.DrawLines(Color.HotPink, 2.5f, new PointF(XpBarX + spacing, y), new PointF(XpBarX + spacing, y + 52)) .DrawLines(Color.HotPink, 2.5f, new PointF(XpBarX + spacing * 2, y), new PointF(XpBarX + spacing * 2, y + 52)) .DrawLines(Color.HotPink, 2.5f, new PointF(XpBarX + spacing * 3, y), new PointF(XpBarX + spacing * 3, y + 52)); var headerOptions = new TextGraphicsOptions { TextOptions = { HorizontalAlignment = HorizontalAlignment.Center } }; var bodyOptions = new TextGraphicsOptions { TextOptions = { HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Bottom, } }; // need to use en-US since en-CA adds a . to month abbreviation (en-US -> Jan, en-CA -> Jan.) string lastLevelUpString = lastLevelUp == DateTime.MinValue ? "Never" : lastLevelUp.ToString("MMM dd yyyy", new CultureInfo("en-US")); source.DrawText(headerOptions, "Rank", header, Color.HotPink, new PointF(301, y)) // (XpBarX + spacing) / 2 .DrawText(bodyOptions, rank, body, Color.DarkSlateGray, new PointF(301, 170)) .DrawText(headerOptions, "Level", header, Color.HotPink, new PointF(430, y)) // ((XpBarX + spacing) / 2 + (XpBarX + spacing * 2)) / 2 .DrawText(bodyOptions, level, body, Color.DarkSlateGray, new PointF(430, 170)) .DrawText(headerOptions, "Required XP", header, Color.HotPink, new PointF(558, y)) .DrawText(bodyOptions, required, body, Color.DarkSlateGray, new PointF(558, 170)) .DrawText(headerOptions, "Last Level Up", header, Color.HotPink, new PointF(695, y)) .DrawText(bodyOptions, lastLevelUpString, body, Color.DarkSlateGray, new PointF(695, 170)); return(source); }
public void AddWaterMark(Image image, string watermark) { var collection = new FontCollection(); var family = collection.Install("Font/Ganttlets.ttf"); var font = family.CreateFont(12, FontStyle.Italic); var imgSize = image.Size(); var size = TextMeasurer.Measure(watermark, new RendererOptions(font)); var scalingFactor = Math.Min(imgSize.Width / size.Width, imgSize.Height / size.Height); var scaledFont = new Font(font, scalingFactor * font.Size); var center = new PointF(imgSize.Width / 2, imgSize.Height / 2); var textGraphicOptions = new TextGraphicsOptions() { TextOptions = { HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center } }; image.Mutate(context => context.DrawText(textGraphicOptions, watermark, scaledFont, Color.Aqua, center)); }
static void Main(string[] args) { System.IO.Directory.CreateDirectory("output"); using (Image <Rgba32> img = new Image <Rgba32>(1500, 500)) { PathBuilder pathBuilder = new PathBuilder(); pathBuilder.SetOrigin(new PointF(500, 0)); pathBuilder.AddBezier(new PointF(50, 450), new PointF(200, 50), new PointF(300, 50), new PointF(450, 450)); // add more complex paths and shapes here. IPath path = pathBuilder.Build(); // For production application we would recomend you create a FontCollection // singleton and manually install the ttf fonts yourself as using SystemFonts // can be expensive and you risk font existing or not existing on a deployment // by deployment basis. var font = SystemFonts.CreateFont("Arial", 39, FontStyle.Regular); string text = "Hello World Hello World Hello World Hello World Hello World"; var textGraphicsOptions = new TextGraphicsOptions(true) // draw the text along the path wrapping at the end of the line { WrapTextWidth = path.Length }; img.Mutate(ctx => ctx .Fill(Rgba32.White) // white background image .Draw(Rgba32.Gray, 3, path) // draw the path so we can see what the text is supposed to be following .DrawText(textGraphicsOptions, text, font, Rgba32.Black, path)); img.Save("output/wordart.png"); } }
private static void CreateImage(string quote, string highlight, string footer) { var authorOptions = new TextGraphicsOptions(true) { HorizontalAlignment = HorizontalAlignment.Right, VerticalAlignment = VerticalAlignment.Bottom, WrapTextWidth = 500 }; var textGraphicOptions = new TextGraphicsOptions(true) { HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Top, WrapTextWidth = 560 }; using (Image <Rgba32> image = new Image <Rgba32>(600, 800)) { var location = new PointF(80, image.Height - 25); image.Mutate(ctx => ctx .Fill(Rgba32.White) // white background image .ApplyScalingedText(font, quote, highlight, Rgba32.Gray, Rgba32.Black, 22, 60) //.DrawText(textGraphicOptions, "Wilkins Wilkins Wilkins Wilkins Wilkins Wilkins Wilkins Wilkins Wilkins Wilkins Wilkins Wilkins Wilkins Wilkins Wilkins Wilkins Wilkins Wilkins Wilkins", font, Rgba32.Gray, new PointF(22,22)) .DrawText(authorOptions, footer, fontAuthor, Rgba32.Black, location)); image.Save(@"c:\temp\test_core.png"); } }
static void Main(string[] args) { System.IO.Directory.CreateDirectory("output"); using (Image <Rgba32> img = new Image <Rgba32>(1500, 500)) { PathBuilder pathBuilder = new PathBuilder(); pathBuilder.SetOrigin(new PointF(500, 0)); pathBuilder.AddBezier(new PointF(50, 450), new PointF(200, 50), new PointF(300, 50), new PointF(450, 450)); // add more complex paths and shapes here. IPath path = pathBuilder.Build(); SixLabors.Fonts.FontCollection fontCollection = new FontCollection(); SixLabors.Fonts.Font carlitoFont = fontCollection.Install(Directory.GetCurrentDirectory() + "/font/Carlito-Regular.ttf") .CreateFont(14, FontStyle.Regular); string text = "Hello World Hello World Hello World Hello World Hello World"; var textGraphicsOptions = new TextGraphicsOptions(true) // draw the text along the path wrapping at the end of the line { WrapTextWidth = path.Length }; var point = new PointF(100, 100); img.Mutate(ctx => ctx .Fill(Rgba32.White) // white background image .Draw(Rgba32.Gray, 3, path) // draw the path so we can see what the text is supposed to be following .DrawText(textGraphicsOptions, text, carlitoFont, Rgba32.Black, point)); img.Save("output/path.png"); } }
private static Image <T> RenderImage <T>(this FontAtlas fa, T color) where T : struct, IPixel <T> { // TODO we need the extra pixels here because ImageSharp renders out of bounds and crashes. var img = new Image <T>(Configuration.Default, fa.Width + 2, fa.Height); var tgo = new TextGraphicsOptions(true); tgo.AntialiasSubpixelDepth = 8; for (var i = 0; i < fa.MapCount; i++) { var gm = fa[i]; var font = gm.Font; foreach (var gd in gm) { // TODO lower level control to render single character? This API sucks balls for FA layout + rendering var charStr = char.ConvertFromUtf32(gd.Character); var pos = (Vector2)gd.Bounds.TopLeft; var ro = new RendererOptions(font); TextMeasurer.TryMeasureCharacterBounds(charStr.AsSpan(), ro, out var cbs); var cb = cbs[0]; img.Mutate(c => c.DrawText(tgo, charStr, font, color, pos - (Vector2)cb.Bounds.Location)); } } return(img); }
/// <summary> /// Image process and writes to <paramref name="output"/> <see cref="Stream"/>. /// </summary> /// <param name="output">The output <see cref="Stream"/> to write to.</param> /// <param name="firstName">First name to use.</param> /// <param name="lastName">Last name to use.</param> /// <param name="size">Image size.</param> /// <param name="jpeg">Specifies whether the image has .jpg extension.</param> /// <param name="background">The background color to use.</param> public void Generate(Stream output, string firstName, string lastName, int size = 192, bool jpeg = false, string background = null) { var avatarText = string.Format("{0}{1}", firstName?.Length > 0 ? firstName[0] : ' ', lastName?.Length > 0 ? lastName[0] : ' ').ToUpper().RemoveDiacritics(); var randomIndex = $"{firstName}{lastName}".ToCharArray().Sum(x => x) % _backgroundColours.Length; var accentColor = _backgroundColours[randomIndex]; if (background != null) { accentColor = new AvatarColor(background); } using (var image = new Image <Rgba32>(size, size)) { image.Mutate(x => x.Fill(accentColor.Background)); var fonts = new FontCollection(); // For production application we would recomend you create a FontCollection singleton and manually install the ttf fonts yourself as using SystemFonts can be expensive and you risk font existing or not existing on a deployment by deployment basis. var font = _openSansFont.CreateFont("Open Sans", 70, FontStyle.Regular); // for scaling water mark size is largly ignored. // Measure the text size. var textSize = TextMeasurer.Measure(avatarText, new RendererOptions(font)); // Find out how much we need to scale the text to fill the space (up or down). var scalingFactor = Math.Min(image.Width * 0.6f / textSize.Width, image.Height * 0.6f / textSize.Height); // Create a new font. var scaledFont = new Font(font, scalingFactor * font.Size); var center = new PointF(image.Width / 2, image.Height / 2); var textGraphicOptions = new TextGraphicsOptions(true) { HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; image.Mutate(x => x.DrawText(textGraphicOptions, avatarText, scaledFont, accentColor.Color, center)); image.Save(output, jpeg ? (IImageFormat)JpegFormat.Instance : PngFormat.Instance); } output.Seek(0, SeekOrigin.Begin); }
/// <summary> /// 绘制中文字符(可以绘制字母数字,但样式可能需要改) /// </summary> /// <param name="img"></param> /// <param name="text"></param> /// <param name="color"></param> /// <param name="font"></param> private void DrawingCnText(Image img, string text, Color color, Font font) { if (string.IsNullOrEmpty(text) == false) { Random random = new Random(); var textWidth = (_imageWidth / text.Length); var img2Size = Math.Min(textWidth, _imageHeight); var fontMiniSize = (int)(img2Size * 0.6); var fontMaxSize = (int)(img2Size * 0.95); for (int i = 0; i < text.Length; i++) { using (Image img2 = new Image <Rgba32>(img2Size, img2Size)) { Font scaledFont = new Font(font, random.Next(fontMiniSize, fontMaxSize)); var point = new Point(i * textWidth, (_imageHeight - img2.Height) / 2); var textGraphicsOptions = new TextGraphicsOptions() { TextOptions = new TextOptions() { HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Top } }; img2.Mutate(ctx => ctx.DrawText(textGraphicsOptions, text[i].ToString(), scaledFont, color, new Point(0, 0)).Rotate(random.Next(-30, 30))); img.Mutate(ctx => ctx.DrawImage(img2, point, 1)); } } } }
public Image GenerateMeme(Image image, string customPhrase = null) { var phrase = customPhrase ?? new Random().Choose(phrases.ToArray(), p => 1d / usage[p]); if (customPhrase == null) { usage[phrase]++; } var font = new Font(memeFont, 40); var imageSize = image.Size(); var size = TextMeasurer.Measure(phrase, new RendererOptions(font)); var scalingFactor = Math.Min((imageSize.Width - border * 2) / size.Width, imageSize.Height / size.Height); var scaledFont = new Font(font, scalingFactor * font.Size); var scaledSize = TextMeasurer.Measure(phrase, new RendererOptions(scaledFont)); var point = new PointF(imageSize.Width / 2, imageSize.Height - border - scaledSize.Height); var textGraphicOptions = new TextGraphicsOptions(true) { HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; var shadowPoint = new PointF(point.X + scaledFont.Size / 20, point.Y + scaledFont.Size / 20); image.Mutate(i => i .DrawText(textGraphicOptions, phrase, scaledFont, Color.Black, shadowPoint) .DrawText(textGraphicOptions, phrase, scaledFont, Color.White, point)); return(image); }
public Task <CommandResult> RunImageCommand([Implicit] Image <Rgba32> image, string text, Rgba32?color = null, float fontSize = 14, FontFamily family = null, FontStyle style = FontStyle.Regular, float?x = null, float?y = null) { color = color ?? new Rgba32(0, 0, 0); family = family ?? SystemFonts.Find("Segoe UI"); Font font = family.CreateFont(fontSize, FontStyle.Regular); SizeF bounds = TextMeasurer.Measure(text, new RendererOptions(font) { ApplyKerning = true, WrappingWidth = image.Width - 20 }); x = x ?? (image.Width - bounds.Width) / 2; y = y ?? (image.Height - bounds.Height) / 2; TextGraphicsOptions options = new TextGraphicsOptions(true) { ApplyKerning = true, WrapTextWidth = image.Width - 20, Antialias = true, AntialiasSubpixelDepth = 4 }; image.Mutate(m => m.DrawText(text, font, color.Value, new PointF(x.Value, y.Value), options)); return(Task.FromResult(image.ToResult(Context))); }
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); }
// Colors: Red,Blue,Purple,#006666 private static IImageProcessingContext DrawWatermark(this IImageProcessingContext context, WatermarkSettings settings) { var imgSize = context.GetCurrentSize(); // measure the text size var size = TextMeasurer.Measure(settings.Text, new RendererOptions(settings.TextFont)); //find out how much we need to scale the text to fill the space (up or down) var scalingFactor = Math.Min(imgSize.Width / size.Width, imgSize.Height / size.Height) / 3; //create a new settings.TextFont var scaledFont = new Font(settings.TextFont, scalingFactor * settings.TextFont.Size); var center = settings.Position switch { WatermarkPosition.Top => new PointF(imgSize.Width / 2, (imgSize.Height / 9)), WatermarkPosition.TopLeft => new PointF(imgSize.Width / 2, (imgSize.Height / 9)), WatermarkPosition.TopRight => new PointF(imgSize.Width / 2, (imgSize.Height / 9)), _ => new PointF(imgSize.Width / 2, imgSize.Height - (imgSize.Height / 9)), }; var textGraphicOptions = new TextGraphicsOptions(true) { HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, }; // Apply Banner context.DrawBanner(settings) .DrawText(textGraphicOptions, settings.Text, scaledFont, settings.TextColor, center); return(context); }
static void Main(string[] args) { var squareSize = 512; var backgroundColor = Rgba32.Salmon; var font = SystemFonts.CreateFont("Arial", 300); var text = "KS"; var textSize = TextMeasurer.Measure(text, new RendererOptions(font, 72)); Console.WriteLine($"Measured size: {textSize.Width}, {textSize.Height}, Text: {text}"); using (var img = new Image <Rgba32>(squareSize, squareSize)) { var textGraphicsOptions = new TextGraphicsOptions(true); var textPosition = new PointF(squareSize / 2f - textSize.Width / 2, squareSize / 2f - textSize.Height / 2f); img.Mutate(ctx => ctx .Fill(backgroundColor) .DrawText(text, font, Rgba32.White, textPosition)); byte[] buffer; using (var ms = new MemoryStream()) { img.SaveAsPng(ms); ms.Seek(0, SeekOrigin.Begin); buffer = ms.ToArray(); } var base64Image = Convert.ToBase64String(buffer); Console.WriteLine("\x1b]1337;File=inline=1;width=100px;height=100px:" + base64Image + "\a\n"); File.WriteAllBytes("result.png", buffer); } }
public static IImageProcessingContext <TPixel> ApplyScalingWaterMarkSimple <TPixel>(this IImageProcessingContext <TPixel> processingContext, Font font, string text, TPixel color, float padding) where TPixel : struct, IPixel <TPixel> { return(processingContext.Apply(img => { float targetWidth = img.Width - (padding * 2); float targetHeight = img.Height - (padding * 2); // measure the text size SizeF size = TextMeasurer.Measure(text, new RendererOptions(font)); //find out how much we need to scale the text to fill the space (up or down) float scalingFactor = Math.Min(img.Width / size.Width, img.Height / size.Height); //create a new font Font scaledFont = new Font(font, scalingFactor * font.Size); var center = new PointF(img.Width / 2, img.Height / 2); var textGraphicOptions = new TextGraphicsOptions(true) { HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; img.Mutate(i => i.DrawText(textGraphicOptions, text, scaledFont, color, center)); })); }
static void Main(string[] args) { if (args.Length < 1) { return; } FontCollection fonts = new FontCollection(); var actionManFont = fonts.Install("/home/peter/Pictures/captai/Action_Man.ttf"); var font = new Font(actionManFont, 39, FontStyle.Regular); FontRectangle s = new FontRectangle(369, 80, 506, 302); var textGraphicOptions = new TextGraphicsOptions() { TextOptions = { HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, WrapTextWidth = 164.0f } }; var result = "output.jpg"; using (Image <Rgba32> image = (Image <Rgba32>)Image.Load("/home/peter/Pictures/captai/template.png")) { image.Mutate(x => x .DrawText(textGraphicOptions, args[0], font, Color.Black, new PointF(362.0f, 171.0f)) ); image.Save(result); } }
/// <summary> /// 绘制中文字符(可以绘制字母数字,但样式可能需要改) /// </summary> /// <typeparam name="TPixel"></typeparam> /// <param name="processingContext"></param> /// <param name="containerWidth"></param> /// <param name="containerHeight"></param> /// <param name="text"></param> /// <param name="color"></param> /// <param name="font"></param> /// <returns></returns> public static IImageProcessingContext <TPixel> DrawingCnText <TPixel>(this IImageProcessingContext <TPixel> processingContext, int containerWidth, int containerHeight, string text, Rgba32 color, Font font) where TPixel : struct, IPixel <TPixel> { return(processingContext.Apply(img => { if (string.IsNullOrEmpty(text) == false) { Random random = new Random(); var textWidth = (img.Width / text.Length); var img2Size = Math.Min(textWidth, img.Height); var fontMiniSize = (int)(img2Size * 0.6); var fontMaxSize = (int)(img2Size * 0.95); for (int i = 0; i < text.Length; i++) { using (Image <Rgba32> img2 = new Image <Rgba32>(img2Size, img2Size)) { Font scaledFont = new Font(font, random.Next(fontMiniSize, fontMaxSize)); var point = new Point(i * textWidth, (containerHeight - img2.Height) / 2); var textGraphicsOptions = new TextGraphicsOptions(true) { HorizontalAlignment = HorizontalAlignment.Left, VerticalAlignment = VerticalAlignment.Top }; img2.Mutate(ctx => ctx .DrawText(textGraphicsOptions, text[i].ToString(), scaledFont, color, new Point(0, 0)) .Rotate(random.Next(-45, 45)) ); img.Mutate(ctx => ctx.DrawImage(img2, point, 1)); } } } })); }
public void CanDrawWithoutMemoryException() { int width = 768; int height = 438; // Creates a new image with empty pixel data. using (var image = new Image <Rgba32>(width, height)) { FontFamily family = SystemFonts.Find("verdana"); Font font = family.CreateFont(48, FontStyle.Bold); // The options are optional var options = new TextGraphicsOptions() { TextOptions = new TextOptions() { ApplyKerning = true, TabWidth = 8, // a tab renders as 8 spaces wide WrapTextWidth = width, // greater than zero so we will word wrap at 100 pixels wide HorizontalAlignment = HorizontalAlignment.Center // right align } }; IBrush brush = Brushes.Solid(Color.White); IPen pen = Pens.Solid(Color.White, 1); string text = "sample text"; // Draw the text image.Mutate(x => x.DrawText(options, text, font, brush, pen, new PointF(0, 100))); } }
public bool Render(IImageProcessingContext <Rgba32> context, Rectangle area, object input) { if (!(input is string text)) { return(false); } var width = area.Width; var height = area.Height; var x = area.X; var y = area.Y; var scaledFont = GetAdjustedFont(width, height, text); var textGraphicOptions = new TextGraphicsOptions(true) { HorizontalAlignment = HorizontalAlignment, VerticalAlignment = VerticalAlignment, WrapTextWidth = width }; var renderY = VerticalAlignment == VerticalAlignment.Center ? height / 2 + y : y; context.DrawText(textGraphicOptions, text, scaledFont, Brush, Pen, new PointF(x, renderY)); return(true); }
public MemoryStream DrawLevelUp(string name, int level) { MemoryStream outputStream = new MemoryStream(); var backgroundImage = _cacheService.GetOrAddImage(Path.Combine(AppContext.BaseDirectory, "Resources", "RabbotThemeNeon", "assets", "img", "NeonLevelUp", "LevelUp.png")); var levelIcon = _cacheService.GetOrAddImage(Path.Combine(AppContext.BaseDirectory, "Resources", "RabbotThemeNeon", "assets", "img", "XeroLevelIcons", $"{level}.png")); FontCollection fonts = new FontCollection(); FontFamily notoSansRegular = fonts.Install(Path.Combine(AppContext.BaseDirectory, "Resources", "RabbotThemeNeon", "assets", "fonts", "NotoSans-Regular.ttf")); var centerOptions = new TextGraphicsOptions { HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; var nameFont = new Font(notoSansRegular, 26, FontStyle.Regular); using var image = new Image <Rgba32>(300, 100); int fontSize = (int)nameFont.Size; //Reduce font size if name is too long nameFont = ResizeFont(nameFont, name, 180); levelIcon.Mutate(x => x.Resize(80, 80)); image.Mutate(x => x .DrawImage(backgroundImage, new Point(0, 0), 1f) .DrawImage(levelIcon, new Point(10, 10), 1f) .DrawText(centerOptions, name, nameFont, Color.FromHex("#00FFFF"), new PointF(200, 25)) ); image.SaveAsPng(outputStream); outputStream.Position = 0; return(outputStream); }
public void DoesntThrowExceptionWhenOverlappingRightEdge_Issue688 <TPixel>(TestImageProvider <TPixel> provider) where TPixel : struct, IPixel <TPixel> { Font font = CreateFont("OpenSans-Regular.ttf", 36); Color color = Color.Black; float padding = 5; var text = "A short piece of text"; using (var img = provider.GetImage()) { float targetWidth = img.Width - (padding * 2); float targetHeight = img.Height - (padding * 2); // measure the text size SizeF size = TextMeasurer.Measure(text, new RendererOptions(font)); //find out how much we need to scale the text to fill the space (up or down) float scalingFactor = Math.Min(img.Width / size.Width, img.Height / size.Height); //create a new font Font scaledFont = new Font(font, scalingFactor * font.Size); var center = new PointF(img.Width / 2, img.Height / 2); var textGraphicOptions = new TextGraphicsOptions(true) { HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; img.Mutate(i => i.DrawText(textGraphicOptions, text, scaledFont, color, center)); } }
private static IImageProcessingContext ApplyScalingWaterMarkSimple(IImageProcessingContext processingContext, Font font, string text, Color color, float padding) { Size imgSize = processingContext.GetCurrentSize(); float targetWidth = imgSize.Width - (padding * 2); float targetHeight = imgSize.Height - (padding * 2); // measure the text size FontRectangle size = TextMeasurer.Measure(text, new RendererOptions(font)); //find out how much we need to scale the text to fill the space (up or down) float scalingFactor = Math.Min(imgSize.Width / size.Width, imgSize.Height / size.Height); //create a new font Font scaledFont = new Font(font, scalingFactor * font.Size); var center = new PointF(imgSize.Width / 2, imgSize.Height / 2); var textGraphicOptions = new TextGraphicsOptions() { TextOptions = { HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center } }; return(processingContext.DrawText(textGraphicOptions, text, scaledFont, color, center)); }
private string GetBase64StringOfImageWithText(string base64Image, string text) { string str = ""; var bytes = Convert.FromBase64String(base64Image); // Creates a new image with all the pixels set as transparent. using (var image = Image.Load(bytes)) { image.Mutate(context => { var textGraphicsOptions = new TextGraphicsOptions(true) { HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center }; //Pick any font size, since it will be replaced later var initialFont = SystemFonts.CreateFont("Arial", 10); var size = TextMeasurer.Measure(text, new RendererOptions(initialFont)); var scalingFactor = Math.Min(image.Width / 2 / size.Width, image.Height / 2 / size.Height); var font = new Font(initialFont, scalingFactor * initialFont.Size, FontStyle.Bold); var textColor = GetContrastColorBW(image); var center = new PointF(image.Width / 2, image.Height / 2); context.DrawText(textGraphicsOptions, text, font, textColor, center); }); str = image.ToBase64String <Rgba32>(PngFormat.Instance); } return(str); }
public void TextPositioningIsRobust <TPixel>(TestImageProvider <TPixel> provider, string fontName) where TPixel : struct, IPixel <TPixel> { Font font = CreateFont(fontName, 30); string text = Repeat("Beware the Jabberwock, my son! The jaws that bite, the claws that catch! Beware the Jubjub bird, and shun The frumious Bandersnatch!\n", 20); var textOptions = new TextGraphicsOptions(true) { WrapTextWidth = 1000 }; string details = fontName.Replace(" ", ""); // Based on the reported 0.1755% difference with AccuracyMultiple = 8 // We should avoid quality regressions leading to higher difference! var comparer = ImageComparer.TolerantPercentage(0.2f); provider.RunValidatingProcessorTest( x => x.DrawText(textOptions, text, font, Color.Black, new PointF(10, 50)), details, comparer, appendPixelTypeToFileName: false, appendSourceFileOrDescription: false); }
public void CloneIsDeep() { var expected = new TextGraphicsOptions(); TextGraphicsOptions actual = expected.DeepClone(); actual.AlphaCompositionMode = PixelAlphaCompositionMode.DestAtop; actual.Antialias = false; actual.AntialiasSubpixelDepth = 23; actual.ApplyKerning = false; actual.BlendPercentage = .25F; actual.ColorBlendingMode = PixelColorBlendingMode.HardLight; actual.DpiX = 46F; actual.DpiY = 52F; actual.HorizontalAlignment = HorizontalAlignment.Center; actual.TabWidth = 3F; actual.VerticalAlignment = VerticalAlignment.Bottom; actual.WrapTextWidth = 42F; Assert.NotEqual(expected.AlphaCompositionMode, actual.AlphaCompositionMode); Assert.NotEqual(expected.Antialias, actual.Antialias); Assert.NotEqual(expected.AntialiasSubpixelDepth, actual.AntialiasSubpixelDepth); Assert.NotEqual(expected.ApplyKerning, actual.ApplyKerning); Assert.NotEqual(expected.BlendPercentage, actual.BlendPercentage); Assert.NotEqual(expected.ColorBlendingMode, actual.ColorBlendingMode); Assert.NotEqual(expected.DpiX, actual.DpiX); Assert.NotEqual(expected.DpiY, actual.DpiY); Assert.NotEqual(expected.HorizontalAlignment, actual.HorizontalAlignment); Assert.NotEqual(expected.TabWidth, actual.TabWidth); Assert.NotEqual(expected.VerticalAlignment, actual.VerticalAlignment); Assert.NotEqual(expected.WrapTextWidth, actual.WrapTextWidth); }
public IActionResult GenerateImage(string text) { using (Image <Rgba32> image = new Image <Rgba32>(1280, 720)) { PathBuilder pathBuilder = new PathBuilder(); pathBuilder.SetOrigin(new PointF(0, 0)); pathBuilder.AddLine(new PointF(350, 350), new PointF(1000, 300)); IPath path = pathBuilder.Build(); Font font = SystemFonts.CreateFont("Arial", 60, FontStyle.Regular); string text2 = $"{text}{Environment.NewLine}{DateTime.Now}"; var textGraphicsOptions = new TextGraphicsOptions(true) { WrapTextWidth = path.Length }; image.Mutate(ctx => ctx .Fill(Rgba32.LightGray) .DrawText(textGraphicsOptions, text2, font, Rgba32.DarkGreen, path) ); using (MemoryStream ms = new MemoryStream()) { image.SaveAsPng(ms); return(File(ms.ToArray(), "image/png")); } } }
public void NonDefaultClone() { var expected = new TextGraphicsOptions { AlphaCompositionMode = PixelAlphaCompositionMode.DestAtop, Antialias = false, AntialiasSubpixelDepth = 23, ApplyKerning = false, BlendPercentage = .25F, ColorBlendingMode = PixelColorBlendingMode.HardLight, DpiX = 46F, DpiY = 52F, HorizontalAlignment = HorizontalAlignment.Center, TabWidth = 3F, VerticalAlignment = VerticalAlignment.Bottom, WrapTextWidth = 42F }; TextGraphicsOptions actual = expected.DeepClone(); Assert.Equal(expected.AlphaCompositionMode, actual.AlphaCompositionMode); Assert.Equal(expected.Antialias, actual.Antialias); Assert.Equal(expected.AntialiasSubpixelDepth, actual.AntialiasSubpixelDepth); Assert.Equal(expected.ApplyKerning, actual.ApplyKerning); Assert.Equal(expected.BlendPercentage, actual.BlendPercentage); Assert.Equal(expected.ColorBlendingMode, actual.ColorBlendingMode); Assert.Equal(expected.DpiX, actual.DpiX); Assert.Equal(expected.DpiY, actual.DpiY); Assert.Equal(expected.HorizontalAlignment, actual.HorizontalAlignment); Assert.Equal(expected.TabWidth, actual.TabWidth); Assert.Equal(expected.VerticalAlignment, actual.VerticalAlignment); Assert.Equal(expected.WrapTextWidth, actual.WrapTextWidth); }
public static void DrawTextAnySize(this IImageProcessingContext context, TextGraphicsOptions op, string?text, FontFamily font, Color color, Rectangle bounds) { if (string.IsNullOrEmpty(text)) { return; } int fontSize = 64; bool fits = false; Font currentFont = font.CreateFont(fontSize); while (!fits) { currentFont = font.CreateFont(fontSize); SizeF size = TextMeasurer.Measure(text, new RendererOptions(currentFont)); fits = size.Height <= bounds.Height && size.Width <= bounds.Width; if (!fits) { fontSize -= 2; } if (fontSize <= 2) { return; } } context.DrawText(op, text, currentFont, color, new Point(bounds.X, bounds.Y)); }
public static void DrawText(this IImageProcessingContext context, TextGraphicsOptions op, string?text, Font font, Color color, Rectangle bounds) { if (string.IsNullOrEmpty(text)) { return; } op.WrapTextWidth = bounds.Width; RendererOptions rOp = new RendererOptions(font); rOp.WrappingWidth = bounds.Width; bool fits = false; while (!fits) { SizeF size = TextMeasurer.Measure(text, rOp); fits = size.Height <= bounds.Height && size.Width <= bounds.Width; if (!fits) { text = text.Truncate(text.Length - 5); } } context.DrawText(op, text, font, color, new Point(bounds.X, bounds.Y)); }
public void EmojiFontRendering <TPixel>(TestImageProvider <TPixel> provider, bool enableColorFonts) where TPixel : unmanaged, IPixel <TPixel> { Font font = CreateFont("OpenSans-Regular.ttf", 70); FontFamily emjoiFontFamily = CreateFont("TwemojiMozilla.ttf", 36).Family; var color = Color.Black; var text = "A short piece of text 😀 with an emoji"; var textGraphicOptions = new TextGraphicsOptions { TextOptions = { HorizontalAlignment = HorizontalAlignment.Center, VerticalAlignment = VerticalAlignment.Center, FallbackFonts = { emjoiFontFamily }, RenderColorFonts = enableColorFonts } }; provider.VerifyOperation( TextDrawingComparer, img => { var center = new PointF(img.Width / 2, img.Height / 2); img.Mutate(i => i.DrawText(textGraphicOptions, text, font, color, center)); }, $"ColorFontsEnabled-{enableColorFonts}"); }
/// <summary> /// 生成指定字符的验证码图片。 /// </summary> /// <param name="code">验证码。</param> /// <param name="width">图片的宽度。</param> /// <param name="height">图片的高度。</param> /// <returns></returns> public static byte[] GenerateImage(string code, int width, int height) { var ran = new Random(); #if !NETSTANDARD2_0 using (var bmp = new Bitmap(width, height)) using (var graphics = Graphics.FromImage(bmp)) { graphics.TextRenderingHint = TextRenderingHint.AntiAlias; graphics.SmoothingMode = SmoothingMode.AntiAlias; var x = 2; foreach (var c in code) { graphics.RotateTransform(ran.Next(-5, 5)); var color = Color.FromArgb(255, 255, 255); var bursh = new SolidBrush(color); graphics.DrawString(c.ToString(), new Font("Consolas", 18), bursh, x, 0); x += 18; graphics.ResetTransform(); bursh.Dispose(); } using (var memory = new MemoryStream()) { bmp.Save(memory, ImageFormat.Png); return(memory.ToArray()); } } #else using (var img = new Image <Rgba32>(width, height)) //画布大小 { var fontFamily = new FontCollection().Install(Path.Combine(Directory.GetCurrentDirectory(), "wwwroot/fonts", "CONSOLA.TTF")); var option = new TextGraphicsOptions() { Antialias = true }; img.Mutate(p => { var x = 2; foreach (var c in code) { var color = Rgba32.White; p.Rotate(ran.Next(-5, 5)); p.DrawText(option, c.ToString(), new Font(fontFamily, 22), color, new Vector2(x, 0)); p.Rotate(RotateMode.None); x += 18; } }); using (var memory = new MemoryStream()) { img.SaveAsPng(memory); return(memory.ToArray()); } } #endif }