Browse Source

Use premultiplication for convolution #428

pull/446/head
James Jackson-South 8 years ago
parent
commit
e985d6004b
  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> /// </summary>
internal static class Vector4Extensions 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> /// <summary>
/// Compresses a linear color signal to its sRGB equivalent. /// Compresses a linear color signal to its sRGB equivalent.
/// <see href="http://www.4p8.com/eric.brasseur/gamma.html#formulas"/> /// <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; int offsetX = x + fxr;
offsetX = offsetX.Clamp(0, maxX); offsetX = offsetX.Clamp(0, maxX);
var currentColor = sourceOffsetRow[offsetX].ToVector4(); Vector4 currentColor = sourceOffsetRow[offsetX].ToVector4().Premultiply();
if (fy < kernelXHeight) if (fy < kernelXHeight)
{ {
@ -118,7 +118,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
float blue = MathF.Sqrt((bX * bX) + (bY * bY)); float blue = MathF.Sqrt((bX * bX) + (bY * bY));
ref TPixel pixel = ref targetRow[x]; 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); offsetX = offsetX.Clamp(0, maxX);
var currentColor = row[offsetX].ToVector4(); Vector4 currentColor = row[offsetX].ToVector4().Premultiply();
destination += kernel[fy, fx] * currentColor; destination += kernel[fy, fx] * currentColor;
} }
} }
ref TPixel pixel = ref targetRow[x]; 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); offsetX = offsetX.Clamp(0, maxX);
var currentColor = sourceOffsetRow[offsetX].ToVector4(); Vector4 currentColor = sourceOffsetRow[offsetX].ToVector4().Premultiply();
currentColor *= this.KernelXY[fy, fx]; currentColor *= this.KernelXY[fy, fx];
red += currentColor.X; red += currentColor.X;
@ -90,7 +90,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
} }
ref TPixel pixel = ref targetRow[x]; 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