diff --git a/src/ImageProcessor/Colors/Color.cs b/src/ImageProcessor/Colors/Color.cs index 482d2f9ac..abd3e8620 100644 --- a/src/ImageProcessor/Colors/Color.cs +++ b/src/ImageProcessor/Colors/Color.cs @@ -211,17 +211,7 @@ namespace ImageProcessor /// /// Gets this color with the component values clamped from 0 to 1. /// - public Color Limited - { - get - { - float r = this.R.Clamp(0, 1); - float g = this.G.Clamp(0, 1); - float b = this.B.Clamp(0, 1); - float a = this.A.Clamp(0, 1); - return new Color(r, g, b, a); - } - } + public Color Limited => new Color(Vector4.Clamp(this.backingVector, Vector4.Zero, Vector4.One)); /// /// Computes the product of multiplying a color by a given factor. @@ -402,7 +392,7 @@ namespace ImageProcessor public static Color FromNonPremultiplied(Color color) { float a = color.A; - return new Color(color.R * a, color.G * a, color.B * a, a); + return new Color(color.backingVector * new Vector4(a, a, a, 1)); } /// @@ -416,10 +406,10 @@ namespace ImageProcessor float a = color.A; if (Math.Abs(a) < Epsilon) { - return new Color(color.R, color.G, color.B, a); + return new Color(color.backingVector); } - return new Color(color.R / a, color.G / a, color.B / a, a); + return new Color(color.backingVector / new Vector4(a, a, a, 1)); } /// diff --git a/src/ImageProcessor/Filters/Alpha.cs b/src/ImageProcessor/Filters/Alpha.cs index e3f051b9a..9607fcbb0 100644 --- a/src/ImageProcessor/Filters/Alpha.cs +++ b/src/ImageProcessor/Filters/Alpha.cs @@ -6,6 +6,7 @@ namespace ImageProcessor.Filters { using System; + using System.Numerics; using System.Threading.Tasks; /// @@ -39,6 +40,7 @@ namespace ImageProcessor.Filters int sourceBottom = sourceRectangle.Bottom; int startX = sourceRectangle.X; int endX = sourceRectangle.Right; + Vector4 alphaVector = new Vector4(1, 1, 1, alpha); Parallel.For( startY, @@ -49,10 +51,9 @@ namespace ImageProcessor.Filters { for (int x = startX; x < endX; x++) { - Color color = Color.ToNonPremultiplied(source[x, y]); - color.A = color.A * alpha; - color = Color.FromNonPremultiplied(color); - target[x, y] = color; + Vector4 color = Color.ToNonPremultiplied(source[x, y]).ToVector4(); + color *= alphaVector; + target[x, y] = Color.FromNonPremultiplied(new Color(color)); } } }); diff --git a/src/ImageProcessor/Filters/BackgroundColor.cs b/src/ImageProcessor/Filters/BackgroundColor.cs index cfb9a66d6..f089cc2a6 100644 --- a/src/ImageProcessor/Filters/BackgroundColor.cs +++ b/src/ImageProcessor/Filters/BackgroundColor.cs @@ -51,13 +51,14 @@ namespace ImageProcessor.Filters for (int x = startX; x < endX; x++) { Color color = source[x, y]; + float a = color.A; - if (color.A < 1 && color.A > 0) + if (a < 1 && a > 0) { color = Color.Lerp(color, backgroundColor, .5f); } - if (Math.Abs(color.A) < Epsilon) + if (Math.Abs(a) < Epsilon) { color = backgroundColor; } diff --git a/src/ImageProcessor/Filters/Binarization/Threshold.cs b/src/ImageProcessor/Filters/Binarization/Threshold.cs index 7e394f775..a48ca5aa0 100644 --- a/src/ImageProcessor/Filters/Binarization/Threshold.cs +++ b/src/ImageProcessor/Filters/Binarization/Threshold.cs @@ -6,6 +6,7 @@ namespace ImageProcessor.Filters { using System; + using System.Numerics; using System.Threading.Tasks; /// diff --git a/src/ImageProcessor/Filters/Contrast.cs b/src/ImageProcessor/Filters/Contrast.cs index 4a45e2c48..da55507ff 100644 --- a/src/ImageProcessor/Filters/Contrast.cs +++ b/src/ImageProcessor/Filters/Contrast.cs @@ -6,6 +6,7 @@ namespace ImageProcessor.Filters { using System; + using System.Numerics; using System.Threading.Tasks; /// @@ -39,7 +40,8 @@ namespace ImageProcessor.Filters int sourceBottom = sourceRectangle.Bottom; int startX = sourceRectangle.X; int endX = sourceRectangle.Right; - + Vector4 contrastVector = new Vector4(contrast, contrast, contrast, 1); + Vector4 shiftVector = new Vector4(.5f, .5f, .5f, 1); Parallel.For( startY, endY, @@ -49,22 +51,11 @@ namespace ImageProcessor.Filters { for (int x = startX; x < endX; x++) { - Color color = Color.Expand(source[x, y]); - - // Seems to be faster than Vector3. - color.R -= 0.5f; - color.R *= contrast; - color.R += 0.5f; - - color.G -= 0.5f; - color.G *= contrast; - color.G += 0.5f; - - color.B -= 0.5f; - color.B *= contrast; - color.B += 0.5f; - - target[x, y] = Color.Compress(color); + Vector4 color = Color.Expand(source[x, y]).ToVector4(); + color -= shiftVector; + color *= contrastVector; + color += shiftVector; + target[x, y] = Color.Compress(new Color(color)); } } }); diff --git a/src/ImageProcessor/Filters/Invert.cs b/src/ImageProcessor/Filters/Invert.cs index 3363c12a9..ab6c827b3 100644 --- a/src/ImageProcessor/Filters/Invert.cs +++ b/src/ImageProcessor/Filters/Invert.cs @@ -5,6 +5,7 @@ namespace ImageProcessor.Filters { + using System.Numerics; using System.Threading.Tasks; /// @@ -19,6 +20,7 @@ namespace ImageProcessor.Filters int sourceBottom = sourceRectangle.Bottom; int startX = sourceRectangle.X; int endX = sourceRectangle.Right; + Vector3 inverseVector = Vector3.One; Parallel.For( startY, @@ -30,10 +32,8 @@ namespace ImageProcessor.Filters for (int x = startX; x < endX; x++) { Color color = source[x, y]; - color.R = 1 - color.R; - color.G = 1 - color.G; - color.B = 1 - color.B; - target[x, y] = color; + Vector3 vector = inverseVector - color.ToVector3(); + target[x, y] = new Color(vector, color.A); } } }); diff --git a/src/ImageProcessor/Formats/Gif/Quantizer/OctreeQuantizer.cs b/src/ImageProcessor/Formats/Gif/Quantizer/OctreeQuantizer.cs index 79eaf26c2..86f229da8 100644 --- a/src/ImageProcessor/Formats/Gif/Quantizer/OctreeQuantizer.cs +++ b/src/ImageProcessor/Formats/Gif/Quantizer/OctreeQuantizer.cs @@ -60,6 +60,11 @@ namespace ImageProcessor.Formats this.maxColors = maxColors; } + /// + /// Gets or sets the transparency threshold. + /// + public byte Threshold { get; set; } = 128; + /// /// Process the pixel in the first pass of the algorithm /// @@ -91,7 +96,7 @@ namespace ImageProcessor.Formats byte paletteIndex = (byte)this.maxColors; // Get the palette index if it's transparency meets criterea. - if (pixel.A > 0) + if (pixel.A > this.Threshold) { paletteIndex = (byte)this.octree.GetPaletteIndex(pixel); } diff --git a/src/ImageProcessor/Samplers/Resampler.cs b/src/ImageProcessor/Samplers/Resampler.cs index b490a8203..5b67e76cf 100644 --- a/src/ImageProcessor/Samplers/Resampler.cs +++ b/src/ImageProcessor/Samplers/Resampler.cs @@ -9,6 +9,8 @@ namespace ImageProcessor.Samplers using System.Collections.Generic; using System.Threading.Tasks; + using ImageProcessor.Filters; + /// /// Provides methods that allow the resampling of images using various algorithms. /// @@ -81,6 +83,8 @@ namespace ImageProcessor.Samplers this.horizontalWeights = this.PrecomputeWeights(targetRectangle.Width, sourceRectangle.Width); this.verticalWeights = this.PrecomputeWeights(targetRectangle.Height, sourceRectangle.Height); } + + new BackgroundColor(Color.Transparent).Apply(source, source, sourceRectangle); } /// @@ -189,10 +193,6 @@ namespace ImageProcessor.Samplers } destination = Color.Compress(destination); - - // Round alpha values in an attempt to prevent bleed. - destination.A = (float)Math.Round(destination.A, 2); - target[x, y] = destination; } } @@ -304,9 +304,6 @@ namespace ImageProcessor.Samplers } destination = Color.Compress(destination); - - // Round alpha values in an attempt to prevent bleed. - destination.A = (float)Math.Round(destination.A, 2); target[x, y] = destination; } }