예제 #1
0
        public static Stream GetImage(string astronaut1, string astronaut2, string messageContent, bool debugRectangle = false)
        {
            MemoryStream   stream = new MemoryStream();
            FontCollection fonts  = new FontCollection();

            fonts.Install(Path.Combine(assetsFolder, "fonts", "arial.ttf"));
            Font      captionFont             = fonts.CreateFont("arial", 8);
            Rectangle messageContentRectangle = new Rectangle(150, 50, 450, 165);
            Font      astronaut1Font          = fonts.CreateFont("arial", 7);
            Rectangle astronaut1Rectangle     = new Rectangle(350, 225, 150, 75);
            Font      astronaut2Font          = fonts.CreateFont("arial", 8);
            Rectangle astronaut2Rectangle     = new Rectangle(625, 50, 250, 125);
            Font      alwaysHasBeenFont       = fonts.CreateFont("arial", 9);
            Rectangle alwaysHasBeenRectangle  = new Rectangle(400, 0, 475, 50);

            using (Image img = Image.Load(Path.Combine(assetsFolder, "images", "wait-its-all-ohio.png")))
            {
                img.Mutate(ctx => ctx.DrawBoxedText(astronaut1Font, astronaut1, Color.White, Color.Black, astronaut1Rectangle, VerticalAlignment.Center, debugRectangle));
                img.Mutate(ctx => ctx.DrawBoxedText(astronaut2Font, astronaut2, Color.White, Color.Black, astronaut2Rectangle, VerticalAlignment.Center, debugRectangle));
                img.Mutate(ctx => ctx.DrawBoxedText(captionFont, messageContent, Color.White, Color.Black, messageContentRectangle, VerticalAlignment.Bottom, debugRectangle));
                img.Mutate(ctx => ctx.DrawBoxedText(alwaysHasBeenFont, "Always has been", Color.White, Color.Black, alwaysHasBeenRectangle, VerticalAlignment.Center, debugRectangle));
                img.SaveAsPng(stream);
            }
            stream.Position = 0;
            return(stream);
        }
예제 #2
0
        public async Task <RuntimeResult> ProfileAsync(SocketUser user = null)
        {
            //User Data
            var targetUser = user ?? Context.User;
            var record     = await UserRepository.GetOrCreateProfileAsync(targetUser).ConfigureAwait(false);

            using (var profileBase = Image.Load("Resources/Profile/base.png"))
                using (var avatarFrame = Image.Load("Resources/Profile/avatarFrame.png"))
                    using (var badge = Image.Load("Resources/Profile/badge.png"))
                        using (var avatarStream = await WebHelper.GetFileStreamAsync(HttpClient, new Uri(targetUser.GetAvatarUrl())).ConfigureAwait(false))
                            using (var finalImage = new MemoryStream())
                                using (var avatar = Image.Load(avatarStream))
                                {
                                    //Fonts & text rendering
                                    var robotoItalic = new FontCollection().Install("Resources/Profile/Fonts/Roboto-Italic.ttf");
                                    var roboto       = new FontCollection().Install("Resources/Profile/Fonts/Roboto-Regular.ttf");
                                    var textOptions  = new TextGraphicsOptions {
                                        HorizontalAlignment = HorizontalAlignment.Center
                                    };

                                    //Actual Image
                                    var final = profileBase.DrawImage(avatar.Resize(540, 540), new Size(), new Point(935, 134),
                                                                      GraphicsOptions.Default)
                                                .DrawImage(avatarFrame, new Size(), new Point(0, 0), GraphicsOptions.Default)
                                                .DrawText(targetUser.Username, robotoItalic.CreateFont(130), new Rgba32(106, 161, 196),
                                                          new Point(profileBase.Width / 2, 690), textOptions)
                                                .DrawText($"Member Since {targetUser.CreatedAt:M/d/yy}", robotoItalic.CreateFont(73),
                                                          new Rgba32(138, 145, 153),
                                                          new Point(profileBase.Width / 2, 840), textOptions)
                                                .DrawText($"Balance: {record.Balance}", roboto.CreateFont(82), new Rgba32(138, 145, 153),
                                                          new Point(profileBase.Width / 2, 930), textOptions)
                                                .DrawText("About Me:", robotoItalic.CreateFont(90), new Rgba32(106, 161, 196), new Point(340, 1130),
                                                          TextGraphicsOptions.Default)
                                                .DrawText(Regex.Replace(record.Summary, ".{55}", "$0\n"), roboto.CreateFont(70), new Rgba32(138, 145, 153), new Point(340, 1250),
                                                          TextGraphicsOptions.Default);

                                    //Verified Badge
                                    //TODO: Add some kind of verification system/reputation system?
                                    if (Config.Owners.Contains(targetUser.Id))
                                    {
                                        final.DrawImage(badge, new Size(), new Point(0, 0), GraphicsOptions.Default).Resize(500, 500).SaveAsPng(finalImage);
                                    }
                                    else
                                    {
                                        final.Resize(500, 500).SaveAsPng(finalImage);
                                    }

                                    //Sending the image
                                    finalImage.Seek(0, SeekOrigin.Begin);
                                    await Context.Channel.SendFileAsync(finalImage, "profile.png", $"Profile card for `{targetUser}`").ConfigureAwait(false);
                                }
            return(CommandRuntimeResult.FromSuccess());
        }
예제 #3
0
        public void Draw(Image image, FontCollection fonts, ICommandContext context, IMessage repliedMessage)
        {
            var    font      = fonts.CreateFont(FontName, FontSize);
            string labelText = GetLabelText(context, repliedMessage);

            image.Mutate(ctx => ctx.DrawBoxedText(font, labelText, MainColor, OutlineColor, Rectangle, VerticalAlignment, ShowRectangle));
        }
예제 #4
0
        /// <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);
        }
예제 #5
0
        /// <summary>
        /// Transforms an image to add a watermark.
        /// </summary>
        /// <param name="input"></param>
        /// <param name="output"></param>
        /// <param name="waterMarkText"></param>
        public void TransformDownloadImage(string input, Stream output, string waterMarkText = null)
        {
            Logging.Log($" Running image transform for Watermark: {waterMarkText}");

            using var img = Image.Load(input, out IImageFormat fmt);

            var opts = new ResizeOptions {
                Mode = ResizeMode.Max, Size = new Size {
                    Height = 1600, Width = 1600
                }
            };

            // First rotate and resize.
            img.Mutate(x => x.AutoOrient().Resize(opts));

            if (!string.IsNullOrEmpty(waterMarkText))
            {
                // Apply the watermark if one's been specified.
                Font font = fontCollection.CreateFont("Arial", 10);

                if (!string.IsNullOrEmpty(waterMarkText))
                {
                    img.Mutate(context => ApplyWaterMark(context, font, waterMarkText, Color.White));
                }
            }

            img.Save(output, fmt);
        }
예제 #6
0
        public void DrawText(PointF position, string text, Font font, string color, int penWidth)
        {
            var p = ToPointF(position, world);

            commandQueue.Enqueue(ctx =>
            {
                ctx.DrawText(text, fontCollection.CreateFont(font.Name, font.Size), Rgba32.FromHex(color), p, currentOption);
            });
        }
        public Function(ILogger <Function> logger)
        {
            _logger = logger;
            var configReader = new ConfigReader(logger);

            _outputBucket  = configReader.Read("BUCKET");
            _requestReader = new HttpRequestReader(logger);

            var fontCollection = new FontCollection();

            fontCollection.Install("Arial.ttf");
            _font = fontCollection.CreateFont("Arial", 10);
        }
예제 #8
0
        private async Task DrawWelcomeScreen()
        {
            Image <Rgba32> image = new Image <Rgba32>(400, 300);
            FontCollection fc    = new FontCollection();

            fc.Install("DigitalDream.ttf");
            var             f       = fc.CreateFont("Digital Dream", 18);
            GraphicsOptions options = new GraphicsOptions(false);

            image.Mutate((ctx) =>
            {
                ctx.Fill(Rgba32.White);
                ctx.DrawText($"{GetCurrentIpv4Address()}:8800", f, Rgba32.Black, new PointF(0, 0), options);
                ctx.DrawText($"{DateTime.Now.ToString()}", f, Rgba32.Black, new PointF(0, 100), options);
                ctx.Dither(new SixLabors.ImageSharp.Dithering.FloydSteinbergDiffuser(), 0.5f);
            });
            await Renderer.RenderAsync(image, Task.Factory.CancellationToken);
        }
예제 #9
0
        public KomiPaperMemeGen(BotState state)
        {
            _botState = state;
            var fontCollection = new FontCollection();

            fontCollection.Install(@"Fonts\mangat.ttf", out var fontDescription);
            _template = new MemeTemplate("KomiPaper.png",
                                         new TextBoundingBox()
            {
                TopLeft      = new PointF(245, 479),
                TopRight     = new PointF(708, 558),
                BottomLeft   = new PointF(168, 728),
                BottomRight  = new PointF(632, 810),
                CenterHeight = false,
                CenterWidth  = false,
                Font         = fontCollection.CreateFont(fontDescription.FontFamily, 20)
            },
                                         new MultiBoundingBox(new ImageBoundingBox()
            {
                TopLeft              = new PointF(245, 479),
                TopRight             = new PointF(708, 558),
                BottomLeft           = new PointF(94, 988),
                BottomRight          = new PointF(557, 1067),
                LandscapeScalingMode = ImageScalingMode.FitWithLetterbox,
                PortraitScalingMode  = ImageScalingMode.FillFit
            })
            {
                Padding = 10,
                Masks   = new List <Rectangle>
                {
                    new Rectangle(0, 631, 186, 446),
                    new Rectangle(666, 552, 50, 150),
                    new Rectangle(0, 1065, 557, 205)
                }
            });
        }
예제 #10
0
파일: Banner.cs 프로젝트: mscloud/devBanner
        public static async Task <string> GenerateAsync(BannerOptions options, Profile profile, string subtext)
        {
            if (profile == null)
            {
                throw new ArgumentNullException(nameof(profile));
            }

            // Avatar base url + avatar meta = rendered avatar url
            var avatarURL = $"{DevrantAvatarBaseURL}/{profile.Avatar.Image}";

            const string outputDir  = "generated";
            const string avatarsDir = "avatars";

            var outputFileName = $"{profile.Username}.png";

            var workingDir = Directory.GetCurrentDirectory();
            var outputPath = Path.Combine(workingDir, outputDir);

            var avatarPath = Path.Combine(workingDir, avatarsDir);

            Directory.CreateDirectory(outputPath);
            Directory.CreateDirectory(avatarPath);

            var avatarFile = Path.Combine(avatarPath, outputFileName);
            var outputFile = Path.Combine(outputPath, outputFileName);

            byte[] data;

            if (options.CacheAvatars && File.Exists(avatarFile))
            {
                data = await File.ReadAllBytesAsync(avatarFile);
            }
            else
            {
                // Download rendered avatar
                var httpClient = new HttpClient();

                using (var response = await httpClient.GetAsync(avatarURL))
                {
                    if (response.StatusCode == HttpStatusCode.NotFound)
                    {
                        throw new AvatarNotFoundException(profile.Username);
                    }

                    response.EnsureSuccessStatusCode();

                    data = await response.Content.ReadAsByteArrayAsync();

                    if (options.CacheAvatars)
                    {
                        await File.WriteAllBytesAsync(avatarFile, data);
                    }
                }
            }

            using (var avatarImage = Image.Load(data))
                using (var banner = new Image <Rgba32>(800, 192))
                {
                    var fontCollection = new FontCollection();
                    fontCollection.Install("fonts/Comfortaa-Regular.ttf");

                    var fontSizeUsername = 64;
                    var fontSizeSubtext  = fontSizeUsername / 2;
                    var fontSizeDevrant  = 16;

                    var fontUsername = fontCollection.CreateFont("Comfortaa", fontSizeUsername, FontStyle.Bold);
                    var fontSubtext  = fontCollection.CreateFont("Comfortaa", fontSizeSubtext, FontStyle.Regular);
                    var fontDevrant  = fontCollection.CreateFont("Comfortaa", fontSizeDevrant, FontStyle.Regular);

                    var avatarHeight = banner.Height;
                    var avatarWidth  = avatarHeight;
                    var avatarSize   = new Size(avatarWidth, avatarHeight);

                    var avatarTargetX = 15;
                    var avatarTargetY = 0;
                    var avatarTarget  = new Point(avatarTargetX, avatarTargetY);

                    var usernameTargetX  = banner.Width / 3;
                    var usernameTartgetY = banner.Height / 4;
                    var usernameTarget   = new Point(usernameTargetX, usernameTartgetY);

                    var subtextTargetX  = usernameTarget.X;
                    var subtextTartgetY = usernameTarget.Y + fontSizeUsername;
                    var subtextTarget   = new Point(subtextTargetX, subtextTartgetY);
                    var subTextWidth    = banner.Width - subtextTargetX - 15;
                    var subTextHeight   = fontSizeSubtext;

                    var devrantTargetX = banner.Width - 108;
                    var devrantTargetY = banner.Height - 4 - fontSizeDevrant;
                    var devrantTarget  = new Point(devrantTargetX, devrantTargetY);

                    // Draw background
                    banner.SetBGColor(Rgba32.FromHex(profile.Avatar.Background));

                    // Draw avatar
                    banner.DrawImage(avatarImage, avatarSize, avatarTarget);

                    // Draw username
                    banner.DrawText(profile.Username, fontUsername, Rgba32.White, usernameTarget);

                    // Scale font size to subtext
                    fontSubtext = fontSubtext.ScaleToText(subtext, new SizeF(subTextWidth, subTextHeight));

                    // Draw subtext
                    banner.DrawText(subtext, fontSubtext, Rgba32.White, subtextTarget);

                    // Draw devrant text
                    banner.DrawText("devrant.com", fontDevrant, Rgba32.White, devrantTarget, HorizontalAlignment.Left, VerticalAlignment.Top);

                    banner.Save(outputFile, new PngEncoder());
                }

            return(outputFile);
        }
예제 #11
0
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger <Startup> logger)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            logger.LogInformation("Service is starting...");

            app.UseRouting();

            var eventReader = new CloudEventReader(logger);

            var configReader = new ConfigReader(logger);
            var outputBucket = configReader.Read("BUCKET");

            var fontCollection = new FontCollection();

            fontCollection.Install("Arial.ttf");
            var font = fontCollection.CreateFont("Arial", 10);

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapPost("/", async context =>
                {
                    try
                    {
                        var(bucket, name) = await eventReader.ReadCloudStorageData(context);

                        using (var inputStream = new MemoryStream())
                        {
                            var client = await StorageClient.CreateAsync();
                            await client.DownloadObjectAsync(bucket, name, inputStream);
                            logger.LogInformation($"Downloaded '{name}' from bucket '{bucket}'");

                            using (var outputStream = new MemoryStream())
                            {
                                inputStream.Position = 0; // Reset to read
                                using (var image = Image.Load(inputStream))
                                {
                                    using (var imageProcessed = image.Clone(ctx => ApplyScalingWaterMarkSimple(ctx, font, Watermark, Color.DeepSkyBlue, 5)))
                                    {
                                        logger.LogInformation($"Added watermark to image '{name}'");
                                        imageProcessed.SaveAsJpeg(outputStream);
                                    }
                                }

                                var outputObjectName = $"{Path.GetFileNameWithoutExtension(name)}-watermark.jpeg";
                                await client.UploadObjectAsync(outputBucket, outputObjectName, "image/jpeg", outputStream);
                                logger.LogInformation($"Uploaded '{outputObjectName}' to bucket '{outputBucket}'");
                            }
                        }
                    }
                    catch (Exception e)
                    {
                        logger.LogError($"Error processing: " + e.Message);
                        throw e;
                    }
                });
            });
        }
예제 #12
0
        public static MemoryStream GenerateXpBar(Stream avatar, XpLevel xp, string rank,
                                                 string username, string discriminator, DateTime date, bool doubleXp, bool fastXp)
        {
            using Image image = Image.Load("data/xp/roki_xp_half.png");

            var transparentGray = new Rgba32(211, 211, 211, 220);

            var grayBackground = new RectangleF(PfpOutlineX + (PfpLength + 10) / 2, 7.5f, 680, 185);

            var pfpBackground = new RectangleF(PfpOutlineX, PfpOutlineY, PfpLength + 10, PfpLength + 10);
            var pfpOutline    = new RectangleF(PfpOutlineX, PfpOutlineY, PfpLength + 10, PfpLength + 10);

            var xpBarOutline = new RectangleF(XpBarX, XpBarY, XpBarLength, XpBarHeight);

            image.Mutate(x => x
                         .Fill(new Color(transparentGray), grayBackground)
                         // profile pic
                         .Fill(Color.White, pfpBackground)
                         .Draw(Color.WhiteSmoke, 3.5f, pfpOutline)
                         .Fill(Color.HotPink, new RectangleF(37, 25, 150, 150)) // profile pic

                                                                                // xp bar
                         .Draw(Color.HotPink, 2.5f, xpBarOutline));

            if (xp.TotalXp != 0)
            {
                var xpBarProgress = new RectangleF(XpBarX + 2.5f, XpBarY + 2.5f, (XpBarLength - 5) * ((float)xp.ProgressXp / xp.RequiredXp), XpBarHeight - 5);
                image.Mutate(x => x.Fill(Color.HotPink, xpBarProgress));
            }

            using (Image pfp = Image.Load(avatar))
            {
                pfp.Mutate(x => x.Resize(new Size(PfpLength, PfpLength)));
                image.Mutate(x => x.DrawImage(pfp, new Point(PfpOutlineX + 5, PfpOutlineY + 5), 1));
            }

            var fonts = new FontCollection();

            fonts.Install("data/xp/DIN_REG.ttf");
            fonts.Install("data/xp/DIN_MED.ttf");
            Font usernameFont      = fonts.CreateFont("DIN", 30);
            Font discriminatorFont = fonts.CreateFont("DIN", 21);
            Font xpFont            = fonts.CreateFont("DIN", 30);
            Font headerFont        = fonts.CreateFont("DIN Medium", 20);
            Font bodyFont          = fonts.CreateFont("DIN", 25);

            image.Mutate(x => x
                         .DrawUsername(usernameFont, discriminatorFont, username, $"#{discriminator}", new PointF(XpBarX, 50)) // username + discrim
                         .DrawText(new TextGraphicsOptions {
                TextOptions = { HorizontalAlignment = HorizontalAlignment.Center }
            },
                                   $"XP: {xp.TotalXp:N0} / {xp.TotalRequiredXp:N0}", xpFont, Color.DarkSlateGray, new PointF(XpBarX + XpBarLength / 2, 66)) // xp progress
                         .DrawStats(headerFont, bodyFont, $"#{rank}", xp.Level.ToString("N0"), (xp.TotalRequiredXp - xp.TotalXp).ToString("N0"), date)
                         .DrawBoosts(doubleXp, fastXp));

            var stream = new MemoryStream();

            image.SaveAsPng(stream);
            stream.Position = 0;
            return(stream);
        }
예제 #13
0
 public int GetFont(string family, float size)
 {
     return(add <Font>(fc.CreateFont(family, size)));
 }
예제 #14
0
        /// <summary>
        /// Loads necesarry resouces for rendering
        /// </summary>
        /// <returns>true loading succeeded</returns>
        static bool LoadResources()
        {
            if (!String.IsNullOrWhiteSpace(Options.SystemFont))
            {
                if (!SystemFonts.TryFind(Options.SystemFont, out var family))
                {
                    Log.Error("font '" + Options.SystemFont + " not found");
                    return(false);
                }
                SelectedFont = new Font(family, Options.FontSize, Options.StyleOfFont);
                //Log.Debug("FontInfo: "
                //	+"\n\tAscender\t"+SelectedFont.Ascender
                //	+"\n\tBold\t"+SelectedFont.Bold
                //	+"\n\tDescender\t"+SelectedFont.Descender
                //	+"\n\tEmSize\t"+SelectedFont.EmSize
                //	+"\n\tFamily.Name\t"+SelectedFont.Family.Name
                //	+"\n\tItalic\t"+SelectedFont.Italic
                //	+"\n\tLineGap\t"+SelectedFont.LineGap
                //	+"\n\tLineHeight\t"+SelectedFont.LineHeight
                //	+"\n\tName\t"+SelectedFont.Name
                //	+"\n\tSize\t"+SelectedFont.Size
                //);
            }
            else if (!String.IsNullOrWhiteSpace(Options.FontFile))
            {
                if (!File.Exists(Options.FontFile))
                {
                    Log.Error("Cannot find font file '" + Options.FontFile + "'");
                    return(false);
                }
                var col = new FontCollection().Install(Options.FontFile);
                SelectedFont = col.CreateFont(Options.FontSize, Options.StyleOfFont);
            }
            else
            {
                Log.Error("no font specified");
                return(false);
            }

            //Log.Debug("Options.WhichSet = "+Options.WhichSet);
            if (Options.WhichSet != CharSets.Set.None)
            {
                SelectedCharSet = CharSets.Get(Options.WhichSet);
            }
            else if (!String.IsNullOrWhiteSpace(Options.CharFile))
            {
                if (!File.Exists(Options.CharFile))
                {
                    Log.Error("cannot find file " + Options.CharFile);
                    return(false);
                }
                var       uniqChars = new HashSet <char>();
                const int buffLen   = 256;
                using (var fs = File.Open(Options.CharFile, FileMode.Open, FileAccess.Read, FileShare.Read))
                    using (var sr = new StreamReader(fs)) {
                        char[] buff  = new char[buffLen];
                        int    count = int.MaxValue;
                        while (count >= buffLen)
                        {
                            count = sr.Read(buff, 0, buffLen);
                            uniqChars.UnionWith(buff);
                        }
                    }
                SelectedCharSet = new char[uniqChars.Count];
                uniqChars.CopyTo(SelectedCharSet);
            }
            else
            {
                Log.Error("char set not specified");
                return(false);
            }

            if (!String.IsNullOrWhiteSpace(Options.InputName))
            {
                if (!File.Exists(Options.InputName))
                {
                    Log.Error("cannot find file " + Options.InputName);
                    return(false);
                }
                var data = File.ReadAllBytes(Options.InputName);
                SourceImage = Image.Load(data);
            }

            return(true);
        }
예제 #15
0
        public static async Task <string> GenerateAsync(BannerOptions options, Profile profile, string subtext, int width = 800, int height = 192)
        {
            if (profile == null)
            {
                throw new ArgumentNullException(nameof(profile));
            }

            var checkedWidth = CheckWidth(options, width);

            height = (int)(checkedWidth / options.WidthToHeightRatio);

            // Avatar base url + avatar meta = rendered avatar url
            var avatarURL = $"{DevrantAvatarBaseURL}/{profile.Avatar.Image}";

            const string outputDir  = "generated";
            const string avatarsDir = "avatars";

            var outputFileName = $"{profile.Username}.png";

            var workingDir = Directory.GetCurrentDirectory();
            var outputPath = Path.Combine(workingDir, outputDir);

            var avatarPath = Path.Combine(workingDir, avatarsDir);

            Directory.CreateDirectory(outputPath);
            Directory.CreateDirectory(avatarPath);

            var avatarFile = Path.Combine(avatarPath, outputFileName);
            var outputFile = Path.Combine(outputPath, outputFileName);

            byte[] data;

            if (options.CacheAvatars && File.Exists(avatarFile) && File.GetCreationTime(avatarFile) > DateTime.Now.AddMinutes(-options.MaxCacheAvatarAge))
            {
                data = await File.ReadAllBytesAsync(avatarFile);
            }
            else
            {
                // Download rendered avatar
                var httpClient = new HttpClient();

                using (var response = await httpClient.GetAsync(avatarURL))
                {
                    if (response.StatusCode == HttpStatusCode.NotFound)
                    {
                        throw new AvatarNotFoundException(profile.Username);
                    }

                    response.EnsureSuccessStatusCode();

                    data = await response.Content.ReadAsByteArrayAsync();

                    if (options.CacheAvatars)
                    {
                        await File.WriteAllBytesAsync(avatarFile, data);
                    }
                }
            }

            using (var avatarImage = Image.Load(data))
                using (var banner = new Image <Rgba32>(checkedWidth, height))
                {
                    var fontCollection = new FontCollection();
                    fontCollection.Install("fonts/Comfortaa-Regular.ttf");

                    var fontSizeUsername = (int)(banner.Width * 0.07); // original : 0.08
                    var fontSizeSubtext  = (int)(banner.Width * 0.04);
                    var fontSizeDevrant  = (int)(banner.Width * 0.02);

                    var fontUsername = fontCollection.CreateFont("Comfortaa", fontSizeUsername, FontStyle.Bold);
                    var fontSubtext  = fontCollection.CreateFont("Comfortaa", fontSizeSubtext, FontStyle.Regular);
                    var fontDevrant  = fontCollection.CreateFont("Comfortaa", fontSizeDevrant, FontStyle.Regular);

                    var avatarHeight = banner.Height;
                    var avatarWidth  = avatarHeight;
                    var avatarSize   = new Size(avatarWidth, avatarHeight);

                    var avatarTargetX = (int)(banner.Width * 0.01875);
                    var avatarTargetY = 0;
                    var avatarTarget  = new Point(avatarTargetX, avatarTargetY);

                    var usernameTargetX = banner.Width / 3;
                    var usernameTargetY = (banner.Height / 4f) - (fontSizeUsername / 2f);
                    var usernameTarget  = new PointF(usernameTargetX, usernameTargetY);

                    var subtextTargetX = usernameTarget.X;
                    var subtextTargetY = usernameTarget.Y + fontSizeUsername;
                    var subtextTarget  = new PointF(subtextTargetX, subtextTargetY + (fontSizeSubtext / 2f));
                    var subTextWidth   = banner.Width - subtextTargetX - (int)(banner.Width * 0.01875);
                    var subTextHeight  = fontSizeSubtext;

                    var devrantTargetX = banner.Width - (int)(banner.Width * 0.130);
                    var devrantTargetY = banner.Height - (int)(banner.Width * 0.03);
                    var devrantTarget  = new Point(devrantTargetX, devrantTargetY);

                    var backgroundColor = Rgba32.FromHex(profile.Avatar.Background);
                    var foregroundColor = GetForegroundColor(backgroundColor);

                    // Draw background
                    banner.SetBGColor(backgroundColor);

                    // Draw avatar
                    banner.DrawImage(avatarImage, avatarSize, avatarTarget);

                    // Draw username
                    banner.DrawText(profile.Username, fontUsername, foregroundColor, usernameTarget, verticalAlignment: VerticalAlignment.Top);

                    // Scale font size to subtext
                    fontSubtext = fontSubtext.ScaleToText(subtext, new SizeF(subTextWidth, subTextHeight), subTextWidth);

                    // Add subtext word wrapping
                    subtext = subtext.AddWrap(fontSubtext, subTextWidth, options.MaxSubtextWraps);

                    // Draw subtext
                    banner.DrawText(subtext, fontSubtext, foregroundColor, subtextTarget, verticalAlignment: VerticalAlignment.Top);

                    // Draw devrant text
                    banner.DrawText("devrant.com", fontDevrant, foregroundColor, devrantTarget, HorizontalAlignment.Left, VerticalAlignment.Top);

                    banner.Save(outputFile, new PngEncoder());
                }

            return(outputFile);
        }
예제 #16
0
        public static string Generate(string avatarURL, string avatarBGColor, string username, string subtext)
        {
            var workingDir = Directory.GetCurrentDirectory();
            var outputPath = $"{workingDir}/generated/{username}.png";

            // Download rendered avatar
            var httpClient     = new HttpClient();
            var responseStream = httpClient.GetStreamAsync(avatarURL).Result;

            var avatarImage = Image.Load(responseStream);

            System.IO.Directory.CreateDirectory("generated");
            using (Image <Rgba32> banner = new Image <Rgba32>(800, 192))
            {
                var fontCollection = new FontCollection();
                fontCollection.Install("fonts/Comfortaa-Regular.ttf");

                var fontSizeUsername = 64;
                var fontSizeSubtext  = fontSizeUsername / 2;
                var fontSizeDevrant  = 16;

                var fontUsername = fontCollection.CreateFont("Comfortaa", fontSizeUsername, FontStyle.Bold);
                var fontSubtext  = fontCollection.CreateFont("Comfortaa", fontSizeSubtext, FontStyle.Regular);
                var fontDevrant  = fontCollection.CreateFont("Comfortaa", fontSizeDevrant, FontStyle.Regular);

                var avatarHeight = banner.Height;
                var avatarWidth  = avatarHeight;
                var avatarSize   = new Size(avatarWidth, avatarHeight);

                var avatarTargetX = 0;
                var avatarTargetY = 0;
                var avatarTarget  = new Point(avatarTargetX, avatarTargetY);

                var usernameTargetX  = banner.Width / 3;
                var usernameTartgetY = banner.Height / 4;
                var usernameTarget   = new Point(usernameTargetX, usernameTartgetY);

                var subtextTargetX  = usernameTarget.X;
                var subtextTartgetY = usernameTarget.Y + fontSizeUsername;
                var subtextTarget   = new Point(subtextTargetX, subtextTartgetY);

                var devrantTargetX = banner.Width - 108;
                var devrantTargetY = banner.Height - 4 - fontSizeDevrant;
                var devrantTarget  = new Point(devrantTargetX, devrantTargetY);

                // Draw background
                banner.Mutate(i => i.BackgroundColor(Rgba32.FromHex(avatarBGColor)));

                // Draw avatar
                banner.Mutate(i => i.DrawImage(avatarImage, 1, avatarSize, avatarTarget));

                // Draw username
                banner.Mutate(i => i.DrawText(username, fontUsername, Rgba32.White, usernameTarget, new TextGraphicsOptions(true)
                {
                    HorizontalAlignment = HorizontalAlignment.Left,
                    VerticalAlignment   = VerticalAlignment.Center
                }));

                // Draw subtext
                banner.Mutate(i => i.DrawText(subtext, fontSubtext, Rgba32.White, subtextTarget, new TextGraphicsOptions(true)
                {
                    HorizontalAlignment = HorizontalAlignment.Left,
                    VerticalAlignment   = VerticalAlignment.Center
                }));

                // Draw devrant text
                banner.Mutate(i => i.DrawText("devrant.com", fontDevrant, Rgba32.White, devrantTarget, new TextGraphicsOptions(true)
                {
                    HorizontalAlignment = HorizontalAlignment.Left,
                    VerticalAlignment   = VerticalAlignment.Top
                }));

                banner.Save(outputPath);
            }

            responseStream.Close();
            return(outputPath);
        }
예제 #17
0
        /// <summary>
        /// Create a font atlas with all registered <see cref="FontAtlasEntry"/> instances.
        /// </summary>
        /// <param name="dpi">Dots per inch to use. Usually 96 (Windows) or 72 (MacOS).</param>
        public FontAtlas CreateAtlas(Vector2?dpi = null)
        {
            var dpiVal          = dpi ?? new Vector2(DefaultDpi);
            var characterSizes  = new Size[_atlasEntries.Count][];
            var characterRanges = new CharacterRange[_atlasEntries.Count][];
            var characterBounds = new Rectangle[_atlasEntries.Count][];
            var fonts           = new Font[_atlasEntries.Count];

            var packer = new MaxRectsBin(64, 64);

            // pad 1 pixel at all borders
            packer.PaddingWidth  = 1;
            packer.PaddingHeight = 1;

            var sb = new StringBuilder();

            for (var i = 0; i < _atlasEntries.Count; i++)
            {
                var e = _atlasEntries[i];

                characterSizes[i]  = new Size[e.GetCharacterCount()];
                characterRanges[i] = new CharacterRange[e.CharacterRanges.Count];

                Font font;
                if (e.IsSystemFont)
                {
                    font = SystemFonts.CreateFont(e.Font.FamilyName, e.Font.Size, e.Font.Style);
                }
                else
                {
                    font = _fontCollection.CreateFont(e.Font.FamilyName, e.Font.Size, e.Font.Style);
                }

                fonts[i] = font;

                var renderOptions  = new RendererOptions(font, dpiVal.X, dpiVal.Y);
                var characterIndex = 0;
                for (var characterRangeIndex = 0; characterRangeIndex < e.CharacterRanges.Count; characterRangeIndex++)
                {
                    // TODO reduce allocations
                    var cr = e.CharacterRanges[characterRangeIndex];
                    characterRanges[i][characterRangeIndex] = new CharacterRange(cr, characterIndex);

                    sb.Clear();
                    for (var c = cr.Start; c <= cr.End; c++)
                    {
                        sb.Append(char.ConvertFromUtf32(c));
                    }

                    if (!TextMeasurer.TryMeasureCharacterBounds(sb.ToString().AsSpan(), renderOptions, out var glyphMetrics))
                    {
                        continue;
                    }

                    foreach (var gm in glyphMetrics)
                    {
                        // we should round the size up so nothing gets lost
                        characterSizes[i][characterIndex] = new Size((int)(gm.Bounds.Width + .9999f), (int)(gm.Bounds.Height + .9999f));
                        characterIndex++;
                    }
                }
            }

            for (var i = 0; i < _atlasEntries.Count; i++)
            {
                characterBounds[i] = packer.Insert(characterSizes[i]);
            }

            var uw = (float)packer.UsedWidth;
            var uh = (float)packer.UsedHeight;

            var glyphMaps = new PixelGlyphMap[_atlasEntries.Count];

            for (var i = 0; i < _atlasEntries.Count; i++)
            {
                var glyphData = new GlyphData[characterSizes[i].Length];
                var gi        = 0;
                foreach (var cr in characterRanges[i])
                {
                    foreach (var c in cr)
                    {
                        var rect = characterBounds[i][gi];
                        glyphData[gi] = new GlyphData(c, rect);
                        gi++;
                    }
                }

                glyphMaps[i] = new PixelGlyphMap(fonts[i], characterRanges[i], glyphData);
            }

            return(new FontAtlas(packer.UsedWidth, packer.UsedHeight, dpiVal, glyphMaps));
        }