using ImageMagick; using PosterMaker.Interfaces.Services; using PosterMaker.Models; using PosterMaker.Models.Enums; namespace PosterMaker.Services; public class MoviePosterMakerService : IMoviePosterMakerService { private static readonly string RefDir = Path.Combine("Resources", "Movies"); private static readonly string RefDirectory = Path.Combine(Directory.GetCurrentDirectory(), RefDir); private static readonly string Font = Path.Combine(RefDirectory, "Arial Bold.ttf"); private static readonly string Frame = Path.Combine(RefDirectory, "frame.png"); private static readonly string Gradient = Path.Combine(RefDirectory, "gradient.png"); private const string FontColor = "white"; private const float FontSize = 1.0F; private const string IndexFontColor = "rgb(154,154,154)"; private readonly IMovieLogoService _movieLogoService; public MoviePosterMakerService(IMovieLogoService movieLogoService) { _movieLogoService = movieLogoService; } public byte[] CreatePoster(string file, ImageProperties imageProperties) { using var image = new MagickImage(file); var resizeGeometry = new MagickGeometry(1892, 2892) { FillArea = true }; image.Resize(resizeGeometry); image.Extent(2000, 3000, Gravity.Center); ApplyGradient(image); using var frame = new MagickImage(Frame); frame.BackgroundColor = new MagickColor("transparent"); image.Composite(frame, Gravity.Center, CompositeOperator.Over); AddLogo(image, imageProperties.Logo, imageProperties.LogoOption); AddIndex(image, imageProperties.Index); AddTitle(image, imageProperties); return image.ToByteArray(); } private static void ApplyGradient(MagickImage image) { using var gradient = new MagickImage(Gradient); image.Composite(gradient, Gravity.Center, CompositeOperator.Multiply); } private static void AddIndex(MagickImage image, string? input) { if (string.IsNullOrEmpty(input)) return; var readSettings = new MagickReadSettings { Font = Font, FillColor = new MagickColor(IndexFontColor), FontPointsize = 598, TextGravity = Gravity.Center, BackgroundColor = MagickColors.Transparent, }; var index = new MagickImage($"label:{(input)}", readSettings); image.Composite(index, Gravity.South, 0, 50, CompositeOperator.Atop); } private void AddLogo(MagickImage image, MovieLogoEnum? logo, LogoOptionEnum? logoOptionEnum) { if (logo == null) return; var logoFile = _movieLogoService.GetMovieLogo(logo); var gravity = _movieLogoService.GetLogoGravity(logo); var readSettings = new MagickReadSettings { TextGravity = Gravity.Center, BackgroundColor = MagickColors.Transparent }; using var logoImage = new MagickImage(logoFile, readSettings); logoImage.Resize(_movieLogoService.GetLogoGeometry(logo)); if (logoOptionEnum == LogoOptionEnum.White) { logoImage.Colorize(MagickColors.White, new Percentage(100)); } if (logoOptionEnum == LogoOptionEnum.Black) { logoImage.Colorize(MagickColors.Black, new Percentage(100)); } var shadow = new MagickImage(logoImage); shadow.Shadow(3, 3,3, new Percentage(80)); var offset = gravity == Gravity.Northwest ? 100 : 0; image.Composite(shadow, gravity, offset, 100, CompositeOperator.Atop); image.Composite(logoImage, gravity, offset, 100, CompositeOperator.Atop); } private void AddTitle(MagickImage image, ImageProperties properties) { if (string.IsNullOrEmpty(properties.TopSubtitle) && string.IsNullOrEmpty(properties.Title) && string.IsNullOrEmpty(properties.Subtitle)) return; var readSettings = new MagickReadSettings { BackgroundColor = MagickColors.Transparent, FillColor = new MagickColor(FontColor), Font = Font, Debug = true }; var labelImages = new MagickImageCollection(); if (!string.IsNullOrEmpty(properties.TopSubtitle)) { readSettings.FontPointsize = 95 * FontSize; readSettings.TextGravity = Gravity.Center; labelImages.Add(new MagickImage($"label:{properties.TopSubtitle.ToUpper()}", readSettings)); } if (!string.IsNullOrEmpty(properties.Title)) { readSettings.FontPointsize = 190 * FontSize; readSettings.TextKerning = 0.7; readSettings.TextInterlineSpacing = -44.5; readSettings.TextInterwordSpacing = 55; readSettings.TextGravity = Gravity.Center; labelImages.Add(new MagickImage($"label:{properties.Title.ToUpper()}", readSettings)); } if (!string.IsNullOrEmpty(properties.Title2)) { readSettings.FontPointsize = 190 * FontSize; readSettings.TextKerning = 0.7; readSettings.TextInterlineSpacing = -44.5; readSettings.TextInterwordSpacing = 55; readSettings.TextGravity = Gravity.Center; labelImages.Add(new MagickImage($"label:{properties.Title2.ToUpper()}", readSettings)); } if (!string.IsNullOrEmpty(properties.Subtitle)) { readSettings.FontPointsize = 95 * FontSize; readSettings.TextInterwordSpacing = 18; readSettings.TextKerning = 0.5; readSettings.TextGravity = Gravity.Center; labelImages.Add(new MagickImage($"label:{properties.Subtitle.ToUpper()}", readSettings)); } using var labels = labelImages.SmushVertical(30); var titleHeight = !string.IsNullOrEmpty(properties.Subtitle) ? 182 : 262; image.Composite(labels, Gravity.South, 0, titleHeight, CompositeOperator.Atop); } }