From b03ee905f0553cfb775d1797bf96df6cebeee9f5 Mon Sep 17 00:00:00 2001 From: JimBobSquarePants Date: Sun, 23 Jun 2013 17:56:27 +0100 Subject: [PATCH] v 2.2.3 Added Rounded Corners method and fixed response type for formatted images. Former-commit-id: 1e21880106cd709ee5e4eaf5a1f5a3226d491c35 --- .../HttpModules/ImageProcessingModule.cs | 2 +- .../Properties/AssemblyInfo.cs | 4 +- src/ImageProcessor/ImageFactory.cs | 40 +- src/ImageProcessor/ImageProcessor.csproj | 2 + src/ImageProcessor/Imaging/ImageUtils.cs | 37 +- src/ImageProcessor/Imaging/RotateLayer.cs | 58 +-- .../Imaging/RoundedCornerLayer.cs | 165 +++++++++ src/ImageProcessor/Processors/Format.cs | 2 +- .../Processors/RoundedCorners.cs | 350 ++++++++++++++++++ src/ImageProcessor/Properties/AssemblyInfo.cs | 4 +- src/Nuget/ImageProcessor.1.6.0.0.nupkg | Bin 0 -> 53918 bytes ...Processor.Web.2.2.3.0.nupkg.REMOVED.git-id | 1 + 12 files changed, 597 insertions(+), 68 deletions(-) create mode 100644 src/ImageProcessor/Imaging/RoundedCornerLayer.cs create mode 100644 src/ImageProcessor/Processors/RoundedCorners.cs create mode 100644 src/Nuget/ImageProcessor.1.6.0.0.nupkg create mode 100644 src/Nuget/ImageProcessor.Web.2.2.3.0.nupkg.REMOVED.git-id diff --git a/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs b/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs index b116f0909..282216b2e 100644 --- a/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs +++ b/src/ImageProcessor.Web/HttpModules/ImageProcessingModule.cs @@ -231,7 +231,7 @@ namespace ImageProcessor.Web.HttpModules } // Store the response type in the context for later retrieval. - context.Items[CachedResponseTypeKey] = ImageUtils.GetResponseType(imageName).ToDescription(); + context.Items[CachedResponseTypeKey] = ImageUtils.GetResponseType(fullPath).ToDescription(); // The cached file is valid so just rewrite the path. context.RewritePath(cache.GetVirtualCachedPath(), false); diff --git a/src/ImageProcessor.Web/Properties/AssemblyInfo.cs b/src/ImageProcessor.Web/Properties/AssemblyInfo.cs index 6df2b8c83..5323aecf8 100644 --- a/src/ImageProcessor.Web/Properties/AssemblyInfo.cs +++ b/src/ImageProcessor.Web/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("2.2.2.0")] -[assembly: AssemblyFileVersion("2.2.2.0")] +[assembly: AssemblyVersion("2.2.3.0")] +[assembly: AssemblyFileVersion("2.2.3.0")] diff --git a/src/ImageProcessor/ImageFactory.cs b/src/ImageProcessor/ImageFactory.cs index b9f710a55..328bd4e2d 100644 --- a/src/ImageProcessor/ImageFactory.cs +++ b/src/ImageProcessor/ImageFactory.cs @@ -92,14 +92,14 @@ namespace ImageProcessor public bool ShouldProcess { get; private set; } /// - /// Gets or sets the quality of output for jpeg images as a percentile. + /// Gets the file format of the image. /// - internal int JpegQuality { get; set; } + public ImageFormat ImageFormat { get; private set; } /// - /// Gets or sets the file format of the image. + /// Gets or sets the quality of output for jpeg images as a percentile. /// - internal ImageFormat ImageFormat { get; set; } + internal int JpegQuality { get; set; } #endregion #region Methods @@ -472,6 +472,32 @@ namespace ImageProcessor return this; } + /// + /// Adds rounded corners to the current image. + /// + /// + /// The containing the properties to round corners on the image. + /// + /// + /// The current instance of the class. + /// + public ImageFactory RoundedCorners(RoundedCornerLayer roundedCornerLayer) + { + if (this.ShouldProcess) + { + if (roundedCornerLayer.Radius < 0) + { + roundedCornerLayer.Radius = 0; + } + + RoundedCorners roundedCorners = new RoundedCorners { DynamicParameter = roundedCornerLayer }; + + this.Image = roundedCorners.ProcessImage(this); + } + + return this; + } + /// /// Changes the saturation of the current image. /// @@ -561,7 +587,7 @@ namespace ImageProcessor // Fix the colour palette of gif images. this.FixGifs(); - if (object.Equals(this.ImageFormat, ImageFormat.Jpeg)) + if (this.ImageFormat.Equals(ImageFormat.Jpeg)) { // Jpegs can be saved with different settings to include a quality setting for the JPEG compression. // This improves output compression and quality. @@ -601,7 +627,7 @@ namespace ImageProcessor // Fix the colour palette of gif images. this.FixGifs(); - if (object.Equals(this.ImageFormat, ImageFormat.Jpeg)) + if (this.ImageFormat.Equals(ImageFormat.Jpeg)) { // Jpegs can be saved with different settings to include a quality setting for the JPEG compression. // This improves output compression and quality. @@ -658,7 +684,7 @@ namespace ImageProcessor // Dispose of any managed resources here. if (this.Image != null) { - // Dispose of the memorystream from Load and the image. + // Dispose of the memory stream from Load and the image. if (this.Image.Tag != null) { ((IDisposable)this.Image.Tag).Dispose(); diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj index 3d2a3f197..df2f93ff8 100644 --- a/src/ImageProcessor/ImageProcessor.csproj +++ b/src/ImageProcessor/ImageProcessor.csproj @@ -78,10 +78,12 @@ + + diff --git a/src/ImageProcessor/Imaging/ImageUtils.cs b/src/ImageProcessor/Imaging/ImageUtils.cs index 0846a1a40..8a62f2e3c 100644 --- a/src/ImageProcessor/Imaging/ImageUtils.cs +++ b/src/ImageProcessor/Imaging/ImageUtils.cs @@ -12,6 +12,7 @@ namespace ImageProcessor.Imaging using System.Drawing.Imaging; using System.IO; using System.Linq; + using System.Text.RegularExpressions; using System.Threading.Tasks; #endregion @@ -21,32 +22,36 @@ namespace ImageProcessor.Imaging public static class ImageUtils { /// - /// Returns the correct response type based on the given file extension. + /// The image format regex. /// - /// The string containing the filename to check against. - /// The correct response type based on the given file extension. - public static ResponseType GetResponseType(string fileName) + private static readonly Regex FormatRegex = new Regex(@"j(pg|peg)|bmp|png|gif", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.RightToLeft); + + /// + /// Returns the correct response type based on the given request path. + /// + /// + /// The request to match. + /// + /// + /// The correct . + /// + public static ResponseType GetResponseType(string request) { - string extension = Path.GetExtension(fileName); - if (extension != null) + foreach (Match match in FormatRegex.Matches(request)) { - string ext = extension.ToUpperInvariant(); - - switch (ext) + switch (match.Value) { - case ".PNG": + case "png": return ResponseType.Png; - case ".BMP": + case "bmp": return ResponseType.Bmp; - case ".GIF": + case "gif": return ResponseType.Gif; default: - // Should be a jpeg. return ResponseType.Jpeg; } } - // TODO: Should we call this on bad request? return ResponseType.Jpeg; } @@ -143,10 +148,10 @@ namespace ImageProcessor.Imaging } /// - /// Returns an instance of EncodingParameters for jpeg comression. + /// Returns an instance of EncodingParameters for jpeg compression. /// /// The quality to return the image at. - /// The encodingParameters for jpeg comression. + /// The encodingParameters for jpeg compression. public static EncoderParameters GetEncodingParameters(int quality) { EncoderParameters encoderParameters = null; diff --git a/src/ImageProcessor/Imaging/RotateLayer.cs b/src/ImageProcessor/Imaging/RotateLayer.cs index bce5ff1fc..0b7c956ba 100644 --- a/src/ImageProcessor/Imaging/RotateLayer.cs +++ b/src/ImageProcessor/Imaging/RotateLayer.cs @@ -8,15 +8,13 @@ namespace ImageProcessor.Imaging { #region Using - using System; - using System.Collections.Generic; using System.Drawing; #endregion /// /// Encapsulates the properties required to rotate an image. /// - public class RotateLayer : IEqualityComparer + public class RotateLayer { #region Constructors /// @@ -69,55 +67,37 @@ namespace ImageProcessor.Imaging #endregion /// - /// Returns a value indicating whether this instance is equal to another . + /// Returns a value that indicates whether the specified object is an + /// object that is equivalent to + /// this object. /// - /// - /// The other to compare to. + /// + /// The object to test. /// /// - /// True if this instance is equal to another ; otherwise, false. + /// True if the given object is an object that is equivalent to + /// this object; otherwise, false. /// - public bool Equals(RotateLayer other) + public override bool Equals(object obj) { - return this.Angle.Equals(other.Angle) && this.BackgroundColor.Equals(other.BackgroundColor); - } + RotateLayer rotate = obj as RotateLayer; - /// - /// Determines whether the specified objects are equal. - /// - /// - /// true if the specified objects are equal; otherwise, false. - /// - /// - /// The first object of type to compare. - /// - /// - /// The second object of type to compare. - /// - public bool Equals(RotateLayer x, RotateLayer y) - { - return x.Angle.Equals(y.Angle) && x.BackgroundColor.Equals(y.BackgroundColor); + if (rotate == null) + { + return false; + } + + return this.Angle == rotate.Angle && this.BackgroundColor == rotate.BackgroundColor; } /// - /// Returns a hash code for the specified object. + /// Returns a hash code value that represents this object. /// /// - /// A hash code for the specified object. + /// A hash code that represents this object. /// - /// - /// The for which a hash code is to be returned. - /// - /// - /// The type of is a reference type and is null. - /// - public int GetHashCode(RotateLayer obj) + public override int GetHashCode() { - if (obj == null) - { - throw new ArgumentNullException(); - } - return this.Angle.GetHashCode() + this.BackgroundColor.GetHashCode(); } } diff --git a/src/ImageProcessor/Imaging/RoundedCornerLayer.cs b/src/ImageProcessor/Imaging/RoundedCornerLayer.cs new file mode 100644 index 000000000..89faa8319 --- /dev/null +++ b/src/ImageProcessor/Imaging/RoundedCornerLayer.cs @@ -0,0 +1,165 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// ----------------------------------------------------------------------- + +namespace ImageProcessor.Imaging +{ + #region Using + using System.Drawing; + #endregion + + /// + /// Encapsulates the properties required to add rounded corners to an image. + /// + public class RoundedCornerLayer + { + #region Constructors + /// + /// Initializes a new instance of the class. + /// + public RoundedCornerLayer() + { + this.Radius = 10; + this.BackgroundColor = Color.Transparent; + this.TopLeft = true; + this.TopRight = true; + this.BottomLeft = true; + this.BottomRight = true; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The radius at which the corner will be done. + /// + /// + /// Set if top left is rounded + /// + /// + /// Set if top right is rounded + /// + /// + /// Set if bottom left is rounded + /// + /// + /// Set if bottom right is rounded + /// + public RoundedCornerLayer(int radius, bool topLeft, bool topRight, bool bottomLeft, bool bottomRight) + { + this.Radius = radius; + this.BackgroundColor = Color.Transparent; + this.TopLeft = topLeft; + this.TopRight = topRight; + this.BottomLeft = bottomLeft; + this.BottomRight = bottomRight; + } + + /// + /// Initializes a new instance of the class. + /// + /// + /// The radius at which the corner will be done. + /// + /// + /// The to set as the background color. + /// Used for image formats that do not support transparency + /// + /// + /// Set if top left is rounded + /// + /// + /// Set if top right is rounded + /// + /// + /// Set if bottom left is rounded + /// + /// + /// Set if bottom right is rounded + /// + public RoundedCornerLayer(int radius, Color backgroundColor, bool topLeft, bool topRight, bool bottomLeft, bool bottomRight) + { + this.Radius = radius; + this.BackgroundColor = backgroundColor; + this.TopLeft = topLeft; + this.TopRight = topRight; + this.BottomLeft = bottomLeft; + this.BottomRight = bottomRight; + } + #endregion + + #region Properties + /// + /// Gets or sets the radius of the corners. + /// + public int Radius { get; set; } + + /// + /// Gets or sets the background color. + /// + public Color BackgroundColor { get; set; } + + /// + /// Gets or sets a value indicating whether top left corners are to be added. + /// + public bool TopLeft { get; set; } + + /// + /// Gets or sets a value indicating whether top right corners are to be added. + /// + public bool TopRight { get; set; } + + /// + /// Gets or sets a value indicating whether bottom left corners are to be added. + /// + public bool BottomLeft { get; set; } + + /// + /// Gets or sets a value indicating whether bottom right corners are to be added. + /// + public bool BottomRight { get; set; } + #endregion + + /// + /// Returns a value that indicates whether the specified object is an + /// object that is equivalent to + /// this object. + /// + /// + /// The object to test. + /// + /// + /// True if the given object is an object that is equivalent to + /// this object; otherwise, false. + /// + public override bool Equals(object obj) + { + RoundedCornerLayer rounded = obj as RoundedCornerLayer; + + if (rounded == null) + { + return false; + } + + return this.Radius == rounded.Radius && this.BackgroundColor == rounded.BackgroundColor + && this.TopLeft == rounded.TopLeft && this.TopRight == rounded.TopRight + && this.BottomLeft == rounded.BottomLeft && this.BottomRight == rounded.BottomRight; + } + + /// + /// Returns a hash code value that represents this object. + /// + /// + /// A hash code that represents this object. + /// + public override int GetHashCode() + { + return this.Radius.GetHashCode() + this.BackgroundColor.GetHashCode() + + this.TopLeft.GetHashCode() + this.TopRight.GetHashCode() + + this.BottomLeft.GetHashCode() + this.BottomRight.GetHashCode(); + } + } +} diff --git a/src/ImageProcessor/Processors/Format.cs b/src/ImageProcessor/Processors/Format.cs index 30b513ed0..336e5dd4c 100644 --- a/src/ImageProcessor/Processors/Format.cs +++ b/src/ImageProcessor/Processors/Format.cs @@ -129,7 +129,7 @@ namespace ImageProcessor.Processors } // Set the internal property. - factory.ImageFormat = imageFormat; + factory.Format(imageFormat); return factory.Image; } diff --git a/src/ImageProcessor/Processors/RoundedCorners.cs b/src/ImageProcessor/Processors/RoundedCorners.cs new file mode 100644 index 000000000..9c817c6cc --- /dev/null +++ b/src/ImageProcessor/Processors/RoundedCorners.cs @@ -0,0 +1,350 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) James South. +// Licensed under the Apache License, Version 2.0. +// +// ----------------------------------------------------------------------- + +namespace ImageProcessor.Processors +{ + #region Using + using System.Collections.Generic; + using System.Drawing; + using System.Drawing.Drawing2D; + using System.Text.RegularExpressions; + using ImageProcessor.Imaging; + #endregion + + /// + /// Encapsulates methods to add rounded corners to an image. + /// + public class RoundedCorners : IGraphicsProcessor + { + /// + /// The regular expression to search strings for. + /// + private static readonly Regex QueryRegex = new Regex(@"roundedcorners=(\d+|[^&]*)", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the angle attribute. + /// + private static readonly Regex RadiusRegex = new Regex(@"radius-(\d+)", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the color attribute. + /// + private static readonly Regex ColorRegex = new Regex(@"bgcolor-([0-9a-fA-F]{3}){1,2}", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the top left attribute. + /// + private static readonly Regex TopLeftRegex = new Regex(@"tl-(true|false)", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the top right attribute. + /// + private static readonly Regex TopRightRegex = new Regex(@"tr-(true|false)", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the bottom left attribute. + /// + private static readonly Regex BottomLeftRegex = new Regex(@"bl-(true|false)", RegexOptions.Compiled); + + /// + /// The regular expression to search strings for the bottom right attribute. + /// + private static readonly Regex BottomRightRegex = new Regex(@"br-(true|false)", 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; + + RoundedCornerLayer roundedCornerLayer; + + string toParse = match.Value; + + if (toParse.Contains("bgcolor")) + { + roundedCornerLayer = new RoundedCornerLayer(this.ParseRadius(toParse), this.ParseColor(toParse), this.ParseCorner(TopLeftRegex, toParse), this.ParseCorner(TopRightRegex, toParse), this.ParseCorner(BottomLeftRegex, toParse), this.ParseCorner(BottomRightRegex, toParse)); + } + else + { + int radius; + int.TryParse(match.Value.Split('=')[1], out radius); + + roundedCornerLayer = new RoundedCornerLayer(radius, this.ParseCorner(TopLeftRegex, toParse), this.ParseCorner(TopRightRegex, toParse), this.ParseCorner(BottomLeftRegex, toParse), this.ParseCorner(BottomRightRegex, toParse)); + } + + this.DynamicParameter = roundedCornerLayer; + } + + 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 + { + RoundedCornerLayer roundedCornerLayer = this.DynamicParameter; + int radius = roundedCornerLayer.Radius; + Color backgroundColor = roundedCornerLayer.BackgroundColor; + bool topLeft = roundedCornerLayer.TopLeft; + bool topRight = roundedCornerLayer.TopRight; + bool bottomLeft = roundedCornerLayer.BottomLeft; + bool bottomRight = roundedCornerLayer.BottomRight; + + // Create a rotated image. + newImage = this.RoundCornerImage(image, radius, backgroundColor, topLeft, topRight, bottomLeft, bottomRight); + newImage.Tag = image.Tag; + + image.Dispose(); + image = newImage; + } + catch + { + if (newImage != null) + { + newImage.Dispose(); + } + } + + return image; + } + #endregion + + #region Private Methods + /// + /// Adds rounded corners to the image + /// + /// The image to add corners too + /// The radius of the corners. + /// The background color to fill an image with. + /// If the top left corner will have a rounded corner? + /// If the top right corner will have a rounded corner? + /// If the bottom left corner will have a rounded corner? + /// If the bottom right corner will have a rounded corner? + /// The image with rounded corners. + private Bitmap RoundCornerImage(Image image, int cornerRadius, Color backgroundColor, bool topLeft = false, bool topRight = false, bool bottomLeft = false, bool bottomRight = false) + { + int width = image.Width; + int height = image.Height; + + // Create a new empty bitmap to hold rotated image + Bitmap newImage = new Bitmap(image.Width, image.Height); + newImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); + + // Make a graphics object from the empty bitmap + using (Graphics graphics = Graphics.FromImage(newImage)) + { + // Reduce the jagged edge. + graphics.SmoothingMode = SmoothingMode.HighQuality; + + // Contrary to everything I have read bicubic is producing the best results. + graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; + graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; + graphics.CompositingQuality = CompositingQuality.HighSpeed; + + // Fill the background. + graphics.Clear(backgroundColor); + + // Add rounded corners + using (GraphicsPath path = new GraphicsPath()) + { + // Determined if the top left has a rounded corner + if (topLeft) + { + path.AddArc(0, 0, cornerRadius, cornerRadius, 180, 90); + } + else + { + path.AddLine(0, 0, 0, 0); + } + + // Determined if the top right has a rounded corner + if (topRight) + { + path.AddArc(0 + width - cornerRadius, 0, cornerRadius, cornerRadius, 270, 90); + } + else + { + path.AddLine(width, 0, width, 0); + } + + // Determined if the bottom left has a rounded corner + if (bottomRight) + { + path.AddArc(0 + width - cornerRadius, 0 + height - cornerRadius, cornerRadius, cornerRadius, 0, 90); + } + else + { + path.AddLine(width, height, width, height); + } + + // Determined if the bottom right has a rounded corner + if (bottomLeft) + { + path.AddArc(0, 0 + height - cornerRadius, cornerRadius, cornerRadius, 90, 90); + } + else + { + path.AddLine(0, height, 0, height); + } + + using (Brush brush = new TextureBrush(image)) + { + graphics.FillPath(brush, path); + } + } + } + + return newImage; + } + + /// + /// Returns the correct containing the radius for the given string. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct containing the radius for the given string. + /// + private int ParseRadius(string input) + { + foreach (Match match in RadiusRegex.Matches(input)) + { + // Split on radius- + int radius; + int.TryParse(match.Value.Split('-')[1], out radius); + return radius; + } + + // No rotate - matches the RotateLayer default. + return 0; + } + + /// + /// 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 ColorRegex.Matches(input)) + { + // split on color-hex + return ColorTranslator.FromHtml("#" + match.Value.Split('-')[1]); + } + + return Color.Transparent; + } + + /// + /// Returns a either true or false. + /// + /// + /// The corner. + /// + /// + /// The input string containing the value to parse. + /// + /// + /// The correct true or false. + /// + private bool ParseCorner(Regex corner, string input) + { + foreach (Match match in corner.Matches(input)) + { + // Split on corner- + bool cornerRound; + bool.TryParse(match.Value.Split('-')[1], out cornerRound); + return cornerRound; + } + + // No rotate - matches the RotateLayer default. + return true; + } + #endregion + } +} diff --git a/src/ImageProcessor/Properties/AssemblyInfo.cs b/src/ImageProcessor/Properties/AssemblyInfo.cs index c921411c0..49264fada 100644 --- a/src/ImageProcessor/Properties/AssemblyInfo.cs +++ b/src/ImageProcessor/Properties/AssemblyInfo.cs @@ -32,6 +32,6 @@ using System.Security; // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.5.0.0")] -[assembly: AssemblyFileVersion("1.5.0.0")] +[assembly: AssemblyVersion("1.6.0.0")] +[assembly: AssemblyFileVersion("1.6.0.0")] diff --git a/src/Nuget/ImageProcessor.1.6.0.0.nupkg b/src/Nuget/ImageProcessor.1.6.0.0.nupkg new file mode 100644 index 0000000000000000000000000000000000000000..ad93e29863de1c5d1a633401fd8aba00c08f6cf6 GIT binary patch literal 53918 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 z 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 QMu`1