// ----------------------------------------------------------------------- // // TODO: Update copyright text. // // ----------------------------------------------------------------------- namespace ImageProcessor.Processors { #region Using using System.Collections.Generic; using System.Drawing; using System.Text.RegularExpressions; using ImageProcessor.Helpers.Extensions; using ImageProcessor.Imaging; #endregion /// /// Encapsulates methods to change the alpha component of the image to effect its transparency. /// public class Watermark : IGraphicsProcessor { /// /// The regular expression to search strings for. /// http://stackoverflow.com/questions/11263949/optimize-a-variable-regex /// private static readonly Regex QueryRegex = new Regex(@"watermark=(text-\w+\|position-\d+-\d+(\|color-([0-9a-fA-F]{3}){1,2}(\|size-\d+(\|style-(bold|italic|regular|strikeout|underline))?)?)?|\w+)", RegexOptions.Compiled); #region IGraphicsProcessor Members /// /// Gets the name. /// public string Name { get { return "Watermark"; } } /// /// Gets the description. /// public string Description { get { return "Adds a watermark containing text to the image."; } } /// /// Gets the regular expression to search strings for. /// public Regex RegexPattern { get { return QueryRegex; } } /// /// Gets or sets DynamicParameter. /// public dynamic DynamicParameter { get; set; } /// /// Gets the order in which this processor is to be used in a chain. /// public int SortOrder { get; private set; } /// /// Gets or sets any additional settings required by the processor. /// public Dictionary Settings { get; set; } /// /// The position in the original string where the first character of the captured substring was found. /// /// /// The query string to search. /// /// /// The zero-based starting position in the original string where the captured substring was found. /// public int MatchRegexIndex(string queryString) { int index = 0; // Set the sort order to max to allow filtering. this.SortOrder = int.MaxValue; foreach (Match match in this.RegexPattern.Matches(queryString)) { if (match.Success) { if (index == 0) { // Set the index on the first instance only. this.SortOrder = match.Index; TextLayer textLayer = new TextLayer(); // Split the string up. string[] firstPass = match.Value.Split('=')[1].Split('|'); switch (firstPass.Length) { case 1: textLayer.Text = firstPass[0]; break; case 2: textLayer.Text = firstPass[0]; textLayer.Position = this.GetPosition(firstPass[1]); break; case 3: textLayer.Text = firstPass[0]; textLayer.Position = this.GetPosition(firstPass[1]); textLayer.TextColor = this.GetColor(firstPass[2]); break; case 4: textLayer.Text = firstPass[0]; textLayer.Position = this.GetPosition(firstPass[1]); textLayer.TextColor = this.GetColor(firstPass[2]); textLayer.FontSize = this.GetFontSize(firstPass[3]); break; case 5: textLayer.Text = firstPass[0]; textLayer.Position = this.GetPosition(firstPass[1]); textLayer.TextColor = this.GetColor(firstPass[2]); textLayer.FontSize = this.GetFontSize(firstPass[3]); textLayer.Style = this.GetFontStyle(firstPass[4]); break; } this.DynamicParameter = textLayer; } index += 1; } } return this.SortOrder; } /// /// Processes the image. /// /// /// The the current instance of the class containing /// the image to process. /// /// /// The processed image from the current instance of the class. /// public Image ProcessImage(ImageFactory factory) { Bitmap newImage = null; Image image = factory.Image; try { newImage = new Bitmap(image) { Tag = image.Tag }; TextLayer textLayer = this.DynamicParameter; string text = textLayer.Text; int opacity = textLayer.Opacity; int fontSize = textLayer.FontSize; FontStyle fontStyle = textLayer.Style; using (Graphics graphics = Graphics.FromImage(newImage)) { using (Font font = this.GetFont(textLayer.Font, fontSize, fontStyle)) { using (StringFormat drawFormat = new StringFormat()) { using (Brush brush = new SolidBrush(Color.FromArgb(opacity, textLayer.TextColor))) { Point origin = textLayer.Position; // We need to ensure that there is a position set for the watermark if (origin == Point.Empty) { // Work out the size of the text. SizeF textSize = graphics.MeasureString(text, font, new SizeF(image.Width, image.Height), drawFormat); int x = (int)(image.Width - textSize.Width) / 2; int y = (int)(image.Height - textSize.Height) / 2; origin = new Point(x, y); } graphics.DrawString(text, font, brush, origin, drawFormat); } } } image.Dispose(); image = newImage; } } catch { if (newImage != null) { newImage.Dispose(); } } return image; } #endregion #region Private Methods /// /// Returns the correct for the given parameters /// /// /// The font. /// /// /// The font size. /// /// /// The font style. /// /// /// The correct /// private Font GetFont(string font, int fontSize, FontStyle fontStyle) { FontFamily fontFamily = string.IsNullOrEmpty(font) ? FontFamily.GenericSansSerif : new FontFamily(font); return new Font(fontFamily, fontSize, fontStyle, GraphicsUnit.Pixel); } /// /// Returns the correct for the given string. /// /// /// The input string containing the value to parse. /// /// /// The correct /// private Point GetPosition(string input) { int[] position = input.ToIntegerArray(); int x = position[0]; int y = position[1]; return new Point(x, y); } /// /// Returns the correct for the given string. /// /// /// The input string containing the value to parse. /// /// /// The correct /// private Color GetColor(string input) { // split on color-hex return ColorTranslator.FromHtml("#" + input.Split('-')[1]); } /// /// Returns the correct for the given string. /// /// /// The input string containing the value to parse. /// /// /// The correct /// private int GetFontSize(string input) { // split on size-value return int.Parse(input.Split('-')[1]); } /// /// Returns the correct for the given string. /// /// /// The string containing the respective fontstyle. /// /// /// The correct /// private FontStyle GetFontStyle(string input) { FontStyle fontStyle = FontStyle.Bold; switch (input.ToLowerInvariant()) { case "italic": fontStyle = FontStyle.Italic; break; case "regular": fontStyle = FontStyle.Regular; break; case "strikeout": fontStyle = FontStyle.Strikeout; break; case "underline": fontStyle = FontStyle.Underline; break; } return fontStyle; } #endregion } }