From e7dc6e659db7aaf4b19bca76100ec00a936089fb Mon Sep 17 00:00:00 2001 From: James South Date: Tue, 6 May 2014 19:01:10 +0100 Subject: [PATCH] Adding Tint Former-commit-id: dee84652a23ad506edd06c701fe1119bf6e89cae --- .../NuSpecs/ImageProcessor.Web.Config.nuspec | 2 +- build/NuSpecs/ImageProcessor.Web.nuspec | 2 +- build/NuSpecs/ImageProcessor.nuspec | 2 +- .../RegularExpressionUnitTests.cs | 26 ++- .../NET45/Config/Resources/processing.config | 1 + src/ImageProcessor/ImageFactory.cs | 20 ++ src/ImageProcessor/ImageProcessor.csproj | 1 + src/ImageProcessor/Processors/Tint.cs | 183 ++++++++++++++++++ src/ImageProcessorConsole/Program.cs | 2 +- .../images/output/120430.gif.REMOVED.git-id | 2 +- .../images/output/nLpfllv .gif.REMOVED.git-id | 1 - .../images/output/nLpfllv.gif.REMOVED.git-id | 1 + .../Views/Home/Index.cshtml | 12 ++ .../config/imageprocessor/processing.config | 1 + 14 files changed, 248 insertions(+), 8 deletions(-) create mode 100644 src/ImageProcessor/Processors/Tint.cs delete mode 100644 src/ImageProcessorConsole/images/output/nLpfllv .gif.REMOVED.git-id create mode 100644 src/ImageProcessorConsole/images/output/nLpfllv.gif.REMOVED.git-id diff --git a/build/NuSpecs/ImageProcessor.Web.Config.nuspec b/build/NuSpecs/ImageProcessor.Web.Config.nuspec index f476eff88..5c0d60d5e 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 4ec86c131..61d01bbc4 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 5066af328..f05c30c21 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 40f00bb63..6c188e749 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 0cb384b96..a091e72db 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 3875ce72c..dcfae8000 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 45ad36bc2..cf27f6c1d 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 000000000..37341552e --- /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 7c95ad1ce..b5f0abdb3 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 361dec973..0d2234d4e 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 3e0788875..000000000 --- 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 000000000..e57ebffe4 --- /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 fad22dfba..d1378da35 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 6b4b482fa..d81783805 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 @@ +