Browse Source

SIMD optimisations

Former-commit-id: 30dca08470d0e771bbc18bb717d05443fcf404b5
Former-commit-id: 75095f939b10143f2bef62096f9ab40e4aeeec9b
Former-commit-id: 9b8f804b79ec99a32915123a41553009d1bd1af8
af/merge-core
James Jackson-South 10 years ago
parent
commit
d26210912a
  1. 18
      src/ImageProcessor/Colors/Color.cs
  2. 9
      src/ImageProcessor/Filters/Alpha.cs
  3. 5
      src/ImageProcessor/Filters/BackgroundColor.cs
  4. 1
      src/ImageProcessor/Filters/Binarization/Threshold.cs
  5. 25
      src/ImageProcessor/Filters/Contrast.cs
  6. 8
      src/ImageProcessor/Filters/Invert.cs
  7. 7
      src/ImageProcessor/Formats/Gif/Quantizer/OctreeQuantizer.cs
  8. 11
      src/ImageProcessor/Samplers/Resampler.cs

18
src/ImageProcessor/Colors/Color.cs

@ -211,17 +211,7 @@ namespace ImageProcessor
/// <summary>
/// Gets this color with the component values clamped from 0 to 1.
/// </summary>
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));
/// <summary>
/// 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));
}
/// <summary>
@ -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));
}
/// <summary>

9
src/ImageProcessor/Filters/Alpha.cs

@ -6,6 +6,7 @@
namespace ImageProcessor.Filters
{
using System;
using System.Numerics;
using System.Threading.Tasks;
/// <summary>
@ -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));
}
}
});

5
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;
}

1
src/ImageProcessor/Filters/Binarization/Threshold.cs

@ -6,6 +6,7 @@
namespace ImageProcessor.Filters
{
using System;
using System.Numerics;
using System.Threading.Tasks;
/// <summary>

25
src/ImageProcessor/Filters/Contrast.cs

@ -6,6 +6,7 @@
namespace ImageProcessor.Filters
{
using System;
using System.Numerics;
using System.Threading.Tasks;
/// <summary>
@ -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));
}
}
});

8
src/ImageProcessor/Filters/Invert.cs

@ -5,6 +5,7 @@
namespace ImageProcessor.Filters
{
using System.Numerics;
using System.Threading.Tasks;
/// <summary>
@ -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);
}
}
});

7
src/ImageProcessor/Formats/Gif/Quantizer/OctreeQuantizer.cs

@ -60,6 +60,11 @@ namespace ImageProcessor.Formats
this.maxColors = maxColors;
}
/// <summary>
/// Gets or sets the transparency threshold.
/// </summary>
public byte Threshold { get; set; } = 128;
/// <summary>
/// Process the pixel in the first pass of the algorithm
/// </summary>
@ -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);
}

11
src/ImageProcessor/Samplers/Resampler.cs

@ -9,6 +9,8 @@ namespace ImageProcessor.Samplers
using System.Collections.Generic;
using System.Threading.Tasks;
using ImageProcessor.Filters;
/// <summary>
/// Provides methods that allow the resampling of images using various algorithms.
/// </summary>
@ -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);
}
/// <inheritdoc/>
@ -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;
}
}

Loading…
Cancel
Save