diff --git a/build/NuSpecs/ImageProcessor.Web.Config.nuspec b/build/NuSpecs/ImageProcessor.Web.Config.nuspec index f476eff885..5c0d60d5e1 100644 --- a/build/NuSpecs/ImageProcessor.Web.Config.nuspec +++ b/build/NuSpecs/ImageProcessor.Web.Config.nuspec @@ -18,7 +18,7 @@ Feedback is always welcome James South en-GB - Image Imaging ASP Performance Processing HttpModule Cache Resize Rotate RoundedCorners Flip Crop Filter Effects Quality Watermark Alpha Vignette Saturation Brightness Contrast Gif Jpg Jpeg Bitmap Png Fluent GDI Gaussian Blur Sharpen + Image Imaging ASP Performance Processing HttpModule Cache Resize Rotate RoundedCorners Flip Crop Filter Effects Quality Watermark Alpha Vignette Saturation Brightness Contrast Gif Jpg Jpeg Bitmap Png Fluent GDI Gaussian Blur Sharpen Tint Quantizer Animated diff --git a/build/NuSpecs/ImageProcessor.Web.nuspec b/build/NuSpecs/ImageProcessor.Web.nuspec index 4ec86c131f..61d01bbc48 100644 --- a/build/NuSpecs/ImageProcessor.Web.nuspec +++ b/build/NuSpecs/ImageProcessor.Web.nuspec @@ -22,7 +22,7 @@ Feedback is always welcome James South en-GB - Image Imaging ASP Performance Processing HttpModule Cache Resize Rotate RoundedCorners Flip Crop Filter Effects Quality Watermark Alpha Vignette Saturation Brightness Contrast Gif Jpg Jpeg Bitmap Png Fluent GDI Gaussian Blur Sharpen + Image Imaging ASP Performance Processing HttpModule Cache Resize Rotate RoundedCorners Flip Crop Filter Effects Quality Watermark Alpha Vignette Saturation Brightness Contrast Gif Jpg Jpeg Bitmap Png Fluent GDI Gaussian Blur Sharpen Tint Quantizer Animated diff --git a/build/NuSpecs/ImageProcessor.nuspec b/build/NuSpecs/ImageProcessor.nuspec index 5066af328e..f05c30c217 100644 --- a/build/NuSpecs/ImageProcessor.nuspec +++ b/build/NuSpecs/ImageProcessor.nuspec @@ -21,7 +21,7 @@ Feedback is always welcome. James South en-GB - Image Imaging ASP Performance Processing Resize Rotate RoundedCorners Flip Crop Filter Effects Quality Watermark Alpha Vignette Saturation Brightness Contrast Gif Jpg Jpeg Bitmap Png Fluent GDI Gaussian Blur Sharpen + Image Imaging ASP Performance Processing Resize Rotate RoundedCorners Flip Crop Filter Effects Quality Watermark Alpha Vignette Saturation Brightness Contrast Gif Jpg Jpeg Bitmap Png Fluent GDI Gaussian Blur Sharpen Tint Quantizer Animated diff --git a/src/ImageProcessor.Tests/RegularExpressionUnitTests.cs b/src/ImageProcessor.Tests/RegularExpressionUnitTests.cs index 40f00bb635..6c188e749a 100644 --- a/src/ImageProcessor.Tests/RegularExpressionUnitTests.cs +++ b/src/ImageProcessor.Tests/RegularExpressionUnitTests.cs @@ -149,12 +149,12 @@ namespace ImageProcessor.Tests public void TestResizeRegex() { const string Querystring = "width=300"; - Size expected = new Size(300, 0); + ResizeLayer expected = new ResizeLayer(new Size(300, 0)); Resize resize = new Resize(); resize.MatchRegexIndex(Querystring); - Size actual = resize.DynamicParameter; + ResizeLayer actual = resize.DynamicParameter; Assert.AreEqual(expected, actual); } @@ -192,6 +192,28 @@ namespace ImageProcessor.Tests Assert.AreEqual(expected, actual); } + + /// + /// The rounded corners regex unit test. + /// + [TestMethod] + public void TestTintRegex() + { + const string HexQuerystring = "tint=6aa6cc"; + const string RgbaQuerystring = "tint=106,166,204,255"; + Color expectedHex = ColorTranslator.FromHtml("#" + "6aa6cc"); + Color expectedRgba = Color.FromArgb(255, 106, 166, 204); + + Tint tint = new Tint(); + tint.MatchRegexIndex(HexQuerystring); + Color actualHex = tint.DynamicParameter; + Assert.AreEqual(expectedHex, actualHex); + + tint = new Tint(); + tint.MatchRegexIndex(RgbaQuerystring); + Color actualRgba = tint.DynamicParameter; + Assert.AreEqual(expectedRgba, actualRgba); + } #endregion } } diff --git a/src/ImageProcessor.Web/NET45/Config/Resources/processing.config b/src/ImageProcessor.Web/NET45/Config/Resources/processing.config index 0cb384b96d..a091e72dbf 100644 --- a/src/ImageProcessor.Web/NET45/Config/Resources/processing.config +++ b/src/ImageProcessor.Web/NET45/Config/Resources/processing.config @@ -33,6 +33,7 @@ + diff --git a/src/ImageProcessor/ImageFactory.cs b/src/ImageProcessor/ImageFactory.cs index 3875ce72c8..dcfae80004 100644 --- a/src/ImageProcessor/ImageFactory.cs +++ b/src/ImageProcessor/ImageFactory.cs @@ -743,6 +743,26 @@ namespace ImageProcessor return this; } + /// + /// Tints the current image with the given color. + /// + /// + /// The to tint the image with. + /// + /// + /// The current instance of the class. + /// + public ImageFactory Tint(Color color) + { + if (this.ShouldProcess) + { + Tint tint = new Tint { DynamicParameter = color }; + this.ApplyProcessor(tint.ProcessImage); + } + + return this; + } + /// /// Adds a vignette image effect to the current image. /// diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj index 45ad36bc29..cf27f6c1da 100644 --- a/src/ImageProcessor/ImageProcessor.csproj +++ b/src/ImageProcessor/ImageProcessor.csproj @@ -111,6 +111,7 @@ + diff --git a/src/ImageProcessor/Processors/Tint.cs b/src/ImageProcessor/Processors/Tint.cs new file mode 100644 index 0000000000..37341552e8 --- /dev/null +++ b/src/ImageProcessor/Processors/Tint.cs @@ -0,0 +1,183 @@ +// -------------------------------------------------------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// +// Tints an image with the given colour. +// +// -------------------------------------------------------------------------------------------------------------------- + +namespace ImageProcessor.Processors +{ + using System; + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Drawing2D; + using System.Drawing.Imaging; + using System.Text.RegularExpressions; + using ImageProcessor.Extensions; + + /// + /// Tints an image with the given colour. + /// + public class Tint : IGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"tint=(\d+,\d+,\d+,\d+|([0-9a-fA-F]{3}){1,2})", RegexOptions.Compiled); + + #region IGraphicsProcessor Members + + /// + /// 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; + this.DynamicParameter = this.ParseColor(match.Value); + } + + 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 + { + Color tintColour = (Color)this.DynamicParameter; + float[][] colorMatrixElements = + { + new[] { tintColour.R / 255f, 0, 0, 0, 0 }, // Red + new[] { 0, tintColour.G / 255f, 0, 0, 0 }, // Green + new[] { 0, 0, tintColour.B / 255f, 0, 0 }, // Blue + new[] { 0, 0, 0, tintColour.A / 255f, 0 }, // Alpha + new float[] { 0, 0, 0, 0, 1 } + }; + + ColorMatrix colorMatrix = new ColorMatrix(colorMatrixElements); + newImage = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppPArgb); + + using (Graphics graphics = Graphics.FromImage(newImage)) + { + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighQuality; + + using (ImageAttributes attributes = new ImageAttributes()) + { + attributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap); + graphics.DrawImage(image, new Rectangle(0, 0, image.Width, image.Height), 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes); + + image.Dispose(); + image = newImage; + } + } + + return image; + } + catch + { + if (newImage != null) + { + newImage.Dispose(); + } + } + + return image; + } + #endregion + + /// + /// Returns the correct for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct + /// + private Color ParseColor(string input) + { + foreach (Match match in QueryRegex.Matches(input)) + { + string value = match.Value.Split('=')[1]; + + if (value.Contains(",")) + { + int[] split = value.ToPositiveIntegerArray(); + byte red = split[0].ToByte(); + byte green = split[1].ToByte(); + byte blue = split[2].ToByte(); + byte alpha = split[3].ToByte(); + + return Color.FromArgb(alpha, red, green, blue); + } + + // Split on color-hex + return ColorTranslator.FromHtml("#" + value); + } + + return Color.Transparent; + } + } +} diff --git a/src/ImageProcessorConsole/Program.cs b/src/ImageProcessorConsole/Program.cs index 7c95ad1ce6..b5f0abdb33 100644 --- a/src/ImageProcessorConsole/Program.cs +++ b/src/ImageProcessorConsole/Program.cs @@ -43,7 +43,7 @@ namespace ImageProcessorConsole // Load, resize, set the format and quality and save an image. imageFactory.Load(inStream) .Constrain(size) - .Filter(MatrixFilters.Comic) + .Tint(Color.FromArgb(255, 106, 166, 204)) .Format(format) .Save(Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), @"..\..\images\output", fileInfo.Name))); } diff --git a/src/ImageProcessorConsole/images/output/120430.gif.REMOVED.git-id b/src/ImageProcessorConsole/images/output/120430.gif.REMOVED.git-id index 361dec9732..0d2234d4e7 100644 --- a/src/ImageProcessorConsole/images/output/120430.gif.REMOVED.git-id +++ b/src/ImageProcessorConsole/images/output/120430.gif.REMOVED.git-id @@ -1 +1 @@ -7880376ac9108d4e74412efb31f544484079ce16 \ No newline at end of file +17e154964bfb4da80c1e0aec623cd2486d493b47 \ No newline at end of file diff --git a/src/ImageProcessorConsole/images/output/nLpfllv .gif.REMOVED.git-id b/src/ImageProcessorConsole/images/output/nLpfllv .gif.REMOVED.git-id deleted file mode 100644 index 3e07888758..0000000000 --- a/src/ImageProcessorConsole/images/output/nLpfllv .gif.REMOVED.git-id +++ /dev/null @@ -1 +0,0 @@ -673e6c6d9223e0906fe342a17496168b8d9017fb \ No newline at end of file diff --git a/src/ImageProcessorConsole/images/output/nLpfllv.gif.REMOVED.git-id b/src/ImageProcessorConsole/images/output/nLpfllv.gif.REMOVED.git-id new file mode 100644 index 0000000000..e57ebffe44 --- /dev/null +++ b/src/ImageProcessorConsole/images/output/nLpfllv.gif.REMOVED.git-id @@ -0,0 +1 @@ +069f8472ed7b83ea57f4cf511f83396e1a0b8877 \ No newline at end of file diff --git a/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Index.cshtml b/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Index.cshtml index fad22dfba9..d1378da353 100644 --- a/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Index.cshtml +++ b/src/TestWebsites/NET45/Test_Website_NET45/Views/Home/Index.cshtml @@ -186,6 +186,18 @@ +
+
+
+

Tint rgba

+ +
+
+

Tint Hex

+ +
+
+

Color Profiles

diff --git a/src/TestWebsites/NET45/Test_Website_NET45/config/imageprocessor/processing.config b/src/TestWebsites/NET45/Test_Website_NET45/config/imageprocessor/processing.config index 6b4b482faf..d817838051 100644 --- a/src/TestWebsites/NET45/Test_Website_NET45/config/imageprocessor/processing.config +++ b/src/TestWebsites/NET45/Test_Website_NET45/config/imageprocessor/processing.config @@ -36,6 +36,7 @@ +