Browse Source

Use premultiplication for convolution #428

af/merge-core
James Jackson-South 8 years ago
parent
commit
7fd7f18a76
  1. 26
      src/ImageSharp/Common/Extensions/Vector4Extensions.cs
  2. 4
      src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs
  3. 4
      src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs
  4. 4
      src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs

26
src/ImageSharp/Common/Extensions/Vector4Extensions.cs

@ -12,6 +12,32 @@ namespace SixLabors.ImageSharp
/// </summary>
internal static class Vector4Extensions
{
/// <summary>
/// Premultiplies the "x", "y", "z" components of a vector by its "w" component leaving the "w" component intact.
/// </summary>
/// <param name="source">The <see cref="Vector4"/> to premultiply</param>
/// <returns>The <see cref="Vector4"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 Premultiply(this Vector4 source)
{
float w = source.W;
Vector4 premultiplied = source * w;
return new Vector4(premultiplied.X, premultiplied.Y, premultiplied.Z, w);
}
/// <summary>
/// Reverses the result of premultiplying a vector via <see cref="Premultiply(Vector4)"/>.
/// </summary>
/// <param name="source">The <see cref="Vector4"/> to premultiply</param>
/// <returns>The <see cref="Vector4"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 UnPremultiply(this Vector4 source)
{
float w = source.W;
Vector4 unpremultiplied = source / w;
return new Vector4(unpremultiplied.X, unpremultiplied.Y, unpremultiplied.Z, w);
}
/// <summary>
/// Compresses a linear color signal to its sRGB equivalent.
/// <see href="http://www.4p8.com/eric.brasseur/gamma.html#formulas"/>

4
src/ImageSharp/Processing/Processors/Convolution/Convolution2DProcessor.cs

@ -93,7 +93,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
int offsetX = x + fxr;
offsetX = offsetX.Clamp(0, maxX);
var currentColor = sourceOffsetRow[offsetX].ToVector4();
Vector4 currentColor = sourceOffsetRow[offsetX].ToVector4().Premultiply();
if (fy < kernelXHeight)
{
@ -118,7 +118,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
float blue = MathF.Sqrt((bX * bX) + (bY * bY));
ref TPixel pixel = ref targetRow[x];
pixel.PackFromVector4(new Vector4(red, green, blue, sourceRow[x].ToVector4().W));
pixel.PackFromVector4(new Vector4(red, green, blue, sourceRow[x].ToVector4().W).UnPremultiply());
}
});

4
src/ImageSharp/Processing/Processors/Convolution/Convolution2PassProcessor.cs

@ -113,13 +113,13 @@ namespace SixLabors.ImageSharp.Processing.Processors
offsetX = offsetX.Clamp(0, maxX);
var currentColor = row[offsetX].ToVector4();
Vector4 currentColor = row[offsetX].ToVector4().Premultiply();
destination += kernel[fy, fx] * currentColor;
}
}
ref TPixel pixel = ref targetRow[x];
pixel.PackFromVector4(destination);
pixel.PackFromVector4(destination.UnPremultiply());
}
});
}

4
src/ImageSharp/Processing/Processors/Convolution/ConvolutionProcessor.cs

@ -80,7 +80,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
offsetX = offsetX.Clamp(0, maxX);
var currentColor = sourceOffsetRow[offsetX].ToVector4();
Vector4 currentColor = sourceOffsetRow[offsetX].ToVector4().Premultiply();
currentColor *= this.KernelXY[fy, fx];
red += currentColor.X;
@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
}
ref TPixel pixel = ref targetRow[x];
pixel.PackFromVector4(new Vector4(red, green, blue, sourceRow[x].ToVector4().W));
pixel.PackFromVector4(new Vector4(red, green, blue, sourceRow[x].ToVector4().W).UnPremultiply());
}
});

Loading…
Cancel
Save