Browse Source

Corrected implementation of PorterDuffFunctions.

pull/493/head
Dirk Lemstra 8 years ago
parent
commit
64345bb677
  1. 126
      src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs
  2. 17
      src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt

126
src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.cs

@ -15,19 +15,19 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static Vector4 Src(Vector4 backdrop, Vector4 source, float opacity) public static Vector4 Src(Vector4 backdrop, Vector4 source, float opacity)
{ {
opacity = opacity.Clamp(0, 1); opacity = opacity.Clamp(0, 1);
source.W *= opacity; source.W *= opacity;
Vector4 xform = source;
// calculate weights // calculate weights
float xw = Vector4.Zero.W * source.W; float xw = backdrop.W * source.W;
float bw = Vector4.Zero.W - xw; float bw = backdrop.W - xw;
float sw = source.W - xw; float sw = source.W - xw;
// calculate final alpha // calculate final alpha
float a = xw + bw + sw; float fw = (sw * 1) + (bw * 0) + (xw * 1);
// calculate final value // calculate final value
xform = ((xform * xw) + (Vector4.Zero * bw) + (source * sw)) / MathF.Max(a, Constants.Epsilon); Vector4 xform = ((source * xw) + (Vector4.Zero * bw) + (source * sw)) / MathF.Max(fw, Constants.Epsilon);
xform.W = fw;
return Vector4.Lerp(backdrop, xform, opacity); return Vector4.Lerp(backdrop, xform, opacity);
} }
@ -36,18 +36,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static Vector4 Atop(Vector4 backdrop, Vector4 source, float opacity) public static Vector4 Atop(Vector4 backdrop, Vector4 source, float opacity)
{ {
opacity = opacity.Clamp(0, 1); opacity = opacity.Clamp(0, 1);
Vector4 xform = source;
// calculate weights // calculate weights
float xw = backdrop.W * Vector4.Zero.W; float xw = backdrop.W * source.W;
float bw = backdrop.W - xw; float bw = backdrop.W - xw;
float sw = Vector4.Zero.W - xw; float sw = source.W - xw;
// calculate final alpha // calculate final alpha
float a = xw + bw + sw; float fw = (sw * 0) + (bw * 1) + (xw * 1);
// calculate final value // calculate final value
xform = ((xform * xw) + (backdrop * bw) + (Vector4.Zero * sw)) / MathF.Max(a, Constants.Epsilon); Vector4 xform = ((source * xw) + (backdrop * bw) + (Vector4.Zero * sw)) / MathF.Max(fw, Constants.Epsilon);
xform.W = fw;
return Vector4.Lerp(backdrop, xform, opacity); return Vector4.Lerp(backdrop, xform, opacity);
} }
@ -56,8 +56,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static Vector4 Over(Vector4 backdrop, Vector4 source, float opacity) public static Vector4 Over(Vector4 backdrop, Vector4 source, float opacity)
{ {
opacity = opacity.Clamp(0, 1); opacity = opacity.Clamp(0, 1);
source.W *= opacity; source.W *= opacity;
Vector4 xform = source;
// calculate weights // calculate weights
float xw = backdrop.W * source.W; float xw = backdrop.W * source.W;
@ -65,10 +64,11 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
float sw = source.W - xw; float sw = source.W - xw;
// calculate final alpha // calculate final alpha
float a = xw + bw + sw; float fw = (sw * 1) + (bw * 1) + (xw * 1);
// calculate final value // calculate final value
xform = ((xform * xw) + (backdrop * bw) + (source * sw)) / MathF.Max(a, Constants.Epsilon); Vector4 xform = ((source * xw) + (backdrop * bw) + (source * sw)) / MathF.Max(fw, Constants.Epsilon);
xform.W = fw;
return Vector4.Lerp(backdrop, xform, opacity); return Vector4.Lerp(backdrop, xform, opacity);
} }
@ -77,18 +77,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static Vector4 In(Vector4 backdrop, Vector4 source, float opacity) public static Vector4 In(Vector4 backdrop, Vector4 source, float opacity)
{ {
opacity = opacity.Clamp(0, 1); opacity = opacity.Clamp(0, 1);
Vector4 xform = source;
// calculate weights // calculate weights
float xw = Vector4.Zero.W * Vector4.Zero.W; float xw = backdrop.W * source.W;
float bw = Vector4.Zero.W - xw; float bw = backdrop.W - xw;
float sw = Vector4.Zero.W - xw; float sw = source.W - xw;
// calculate final alpha // calculate final alpha
float a = xw + bw + sw; float fw = (sw * 0) + (bw * 0) + (xw * 1);
// calculate final value // calculate final value
xform = ((xform * xw) + (Vector4.Zero * bw) + (Vector4.Zero * sw)) / MathF.Max(a, Constants.Epsilon); Vector4 xform = ((source * xw) + (Vector4.Zero * bw) + (Vector4.Zero * sw)) / MathF.Max(fw, Constants.Epsilon);
xform.W = fw;
return Vector4.Lerp(backdrop, xform, opacity); return Vector4.Lerp(backdrop, xform, opacity);
} }
@ -97,19 +97,19 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static Vector4 Out(Vector4 backdrop, Vector4 source, float opacity) public static Vector4 Out(Vector4 backdrop, Vector4 source, float opacity)
{ {
opacity = opacity.Clamp(0, 1); opacity = opacity.Clamp(0, 1);
source.W *= opacity; source.W *= opacity;
Vector4 xform = Vector4.Zero;
// calculate weights // calculate weights
float xw = Vector4.Zero.W * source.W; float xw = backdrop.W * source.W;
float bw = Vector4.Zero.W - xw; float bw = backdrop.W - xw;
float sw = source.W - xw; float sw = source.W - xw;
// calculate final alpha // calculate final alpha
float a = xw + bw + sw; float fw = (sw * 1) + (bw * 0) + (xw * 0);
// calculate final value // calculate final value
xform = ((xform * xw) + (Vector4.Zero * bw) + (source * sw)) / MathF.Max(a, Constants.Epsilon); Vector4 xform = ((Vector4.Zero * xw) + (Vector4.Zero * bw) + (source * sw)) / MathF.Max(fw, Constants.Epsilon);
xform.W = fw;
return Vector4.Lerp(backdrop, xform, opacity); return Vector4.Lerp(backdrop, xform, opacity);
} }
@ -118,18 +118,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static Vector4 Dest(Vector4 backdrop, Vector4 source, float opacity) public static Vector4 Dest(Vector4 backdrop, Vector4 source, float opacity)
{ {
opacity = opacity.Clamp(0, 1); opacity = opacity.Clamp(0, 1);
Vector4 xform = backdrop;
// calculate weights // calculate weights
float xw = backdrop.W * Vector4.Zero.W; float xw = backdrop.W * source.W;
float bw = backdrop.W - xw; float bw = backdrop.W - xw;
float sw = Vector4.Zero.W - xw; float sw = source.W - xw;
// calculate final alpha // calculate final alpha
float a = xw + bw + sw; float fw = (sw * 0) + (bw * 1) + (xw * 1);
// calculate final value // calculate final value
xform = ((xform * xw) + (backdrop * bw) + (Vector4.Zero * sw)) / MathF.Max(a, Constants.Epsilon); Vector4 xform = ((backdrop * xw) + (backdrop * bw) + (Vector4.Zero * sw)) / MathF.Max(fw, Constants.Epsilon);
xform.W = fw;
return Vector4.Lerp(backdrop, xform, opacity); return Vector4.Lerp(backdrop, xform, opacity);
} }
@ -138,19 +138,19 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static Vector4 DestAtop(Vector4 backdrop, Vector4 source, float opacity) public static Vector4 DestAtop(Vector4 backdrop, Vector4 source, float opacity)
{ {
opacity = opacity.Clamp(0, 1); opacity = opacity.Clamp(0, 1);
source.W *= opacity; source.W *= opacity;
Vector4 xform = backdrop;
// calculate weights // calculate weights
float xw = Vector4.Zero.W * source.W; float xw = backdrop.W * source.W;
float bw = Vector4.Zero.W - xw; float bw = backdrop.W - xw;
float sw = source.W - xw; float sw = source.W - xw;
// calculate final alpha // calculate final alpha
float a = xw + bw + sw; float fw = (sw * 1) + (bw * 0) + (xw * 1);
// calculate final value // calculate final value
xform = ((xform * xw) + (Vector4.Zero * bw) + (source * sw)) / MathF.Max(a, Constants.Epsilon); Vector4 xform = ((backdrop * xw) + (Vector4.Zero * bw) + (source * sw)) / MathF.Max(fw, Constants.Epsilon);
xform.W = fw;
return Vector4.Lerp(backdrop, xform, opacity); return Vector4.Lerp(backdrop, xform, opacity);
} }
@ -159,8 +159,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static Vector4 DestOver(Vector4 backdrop, Vector4 source, float opacity) public static Vector4 DestOver(Vector4 backdrop, Vector4 source, float opacity)
{ {
opacity = opacity.Clamp(0, 1); opacity = opacity.Clamp(0, 1);
source.W *= opacity; source.W *= opacity;
Vector4 xform = backdrop;
// calculate weights // calculate weights
float xw = backdrop.W * source.W; float xw = backdrop.W * source.W;
@ -168,10 +167,11 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
float sw = source.W - xw; float sw = source.W - xw;
// calculate final alpha // calculate final alpha
float a = xw + bw + sw; float fw = (sw * 1) + (bw * 1) + (xw * 1);
// calculate final value // calculate final value
xform = ((xform * xw) + (backdrop * bw) + (source * sw)) / MathF.Max(a, Constants.Epsilon); Vector4 xform = ((backdrop * xw) + (backdrop * bw) + (source * sw)) / MathF.Max(fw, Constants.Epsilon);
xform.W = fw;
return Vector4.Lerp(backdrop, xform, opacity); return Vector4.Lerp(backdrop, xform, opacity);
} }
@ -180,18 +180,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static Vector4 DestIn(Vector4 backdrop, Vector4 source, float opacity) public static Vector4 DestIn(Vector4 backdrop, Vector4 source, float opacity)
{ {
opacity = opacity.Clamp(0, 1); opacity = opacity.Clamp(0, 1);
Vector4 xform = backdrop;
// calculate weights // calculate weights
float xw = Vector4.Zero.W * Vector4.Zero.W; float xw = backdrop.W * source.W;
float bw = Vector4.Zero.W - xw; float bw = backdrop.W - xw;
float sw = Vector4.Zero.W - xw; float sw = source.W - xw;
// calculate final alpha // calculate final alpha
float a = xw + bw + sw; float fw = (sw * 0) + (bw * 0) + (xw * 1);
// calculate final value // calculate final value
xform = ((xform * xw) + (Vector4.Zero * bw) + (Vector4.Zero * sw)) / MathF.Max(a, Constants.Epsilon); Vector4 xform = ((backdrop * xw) + (Vector4.Zero * bw) + (Vector4.Zero * sw)) / MathF.Max(fw, Constants.Epsilon);
xform.W = fw;
return Vector4.Lerp(backdrop, xform, opacity); return Vector4.Lerp(backdrop, xform, opacity);
} }
@ -200,18 +200,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static Vector4 DestOut(Vector4 backdrop, Vector4 source, float opacity) public static Vector4 DestOut(Vector4 backdrop, Vector4 source, float opacity)
{ {
opacity = opacity.Clamp(0, 1); opacity = opacity.Clamp(0, 1);
Vector4 xform = Vector4.Zero;
// calculate weights // calculate weights
float xw = backdrop.W * Vector4.Zero.W; float xw = backdrop.W * source.W;
float bw = backdrop.W - xw; float bw = backdrop.W - xw;
float sw = Vector4.Zero.W - xw; float sw = source.W - xw;
// calculate final alpha // calculate final alpha
float a = xw + bw + sw; float fw = (sw * 0) + (bw * 1) + (xw * 0);
// calculate final value // calculate final value
xform = ((xform * xw) + (backdrop * bw) + (Vector4.Zero * sw)) / MathF.Max(a, Constants.Epsilon); Vector4 xform = ((Vector4.Zero * xw) + (backdrop * bw) + (Vector4.Zero * sw)) / MathF.Max(fw, Constants.Epsilon);
xform.W = fw;
return Vector4.Lerp(backdrop, xform, opacity); return Vector4.Lerp(backdrop, xform, opacity);
} }
@ -220,18 +220,18 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static Vector4 Clear(Vector4 backdrop, Vector4 source, float opacity) public static Vector4 Clear(Vector4 backdrop, Vector4 source, float opacity)
{ {
opacity = opacity.Clamp(0, 1); opacity = opacity.Clamp(0, 1);
Vector4 xform = Vector4.Zero;
// calculate weights // calculate weights
float xw = Vector4.Zero.W * Vector4.Zero.W; float xw = backdrop.W * source.W;
float bw = Vector4.Zero.W - xw; float bw = backdrop.W - xw;
float sw = Vector4.Zero.W - xw; float sw = source.W - xw;
// calculate final alpha // calculate final alpha
float a = xw + bw + sw; float fw = (sw * 0) + (bw * 0) + (xw * 0);
// calculate final value // calculate final value
xform = ((xform * xw) + (Vector4.Zero * bw) + (Vector4.Zero * sw)) / MathF.Max(a, Constants.Epsilon); Vector4 xform = ((Vector4.Zero * xw) + (Vector4.Zero * bw) + (Vector4.Zero * sw)) / MathF.Max(fw, Constants.Epsilon);
xform.W = fw;
return Vector4.Lerp(backdrop, xform, opacity); return Vector4.Lerp(backdrop, xform, opacity);
} }
@ -240,8 +240,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
public static Vector4 Xor(Vector4 backdrop, Vector4 source, float opacity) public static Vector4 Xor(Vector4 backdrop, Vector4 source, float opacity)
{ {
opacity = opacity.Clamp(0, 1); opacity = opacity.Clamp(0, 1);
source.W *= opacity; source.W *= opacity;
Vector4 xform = Vector4.Zero;
// calculate weights // calculate weights
float xw = backdrop.W * source.W; float xw = backdrop.W * source.W;
@ -249,10 +248,11 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
float sw = source.W - xw; float sw = source.W - xw;
// calculate final alpha // calculate final alpha
float a = xw + bw + sw; float fw = (sw * 1) + (bw * 1) + (xw * 0);
// calculate final value // calculate final value
xform = ((xform * xw) + (backdrop * bw) + (source * sw)) / MathF.Max(a, Constants.Epsilon); Vector4 xform = ((Vector4.Zero * xw) + (backdrop * bw) + (source * sw)) / MathF.Max(fw, Constants.Epsilon);
xform.W = fw;
return Vector4.Lerp(backdrop, xform, opacity); return Vector4.Lerp(backdrop, xform, opacity);
} }

17
src/ImageSharp/PixelFormats/PixelBlenders/PorterDuffFunctions.Generated.tt

@ -40,26 +40,29 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
void GenerateVectorCompositor(string name, string sourceVar, string destVar, string blendVar) void GenerateVectorCompositor(string name, string sourceVar, string destVar, string blendVar)
{ {
int a_s = sourceVar == "Vector4.Zero" ? 0 : 1;
int a_b = destVar == "Vector4.Zero" ? 0 : 1;
int a_x = blendVar == "Vector4.Zero" ? 0 : 1;
#> #>
[MethodImpl(MethodImplOptions.AggressiveInlining)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Vector4 <#=name#>(Vector4 backdrop, Vector4 source, float opacity) public static Vector4 <#=name#>(Vector4 backdrop, Vector4 source, float opacity)
{ {
opacity = opacity.Clamp(0, 1); opacity = opacity.Clamp(0, 1);
<# if(sourceVar != "Vector4.Zero" ) { #> <# if(sourceVar != "Vector4.Zero" ) { #>
source.W *= opacity; source.W *= opacity;
<# } #> <# } #>
Vector4 xform = <#=blendVar#>;
// calculate weights // calculate weights
float xw = <#=destVar#>.W * <#=sourceVar#>.W; float xw = backdrop.W * source.W;
float bw = <#=destVar#>.W - xw; float bw = backdrop.W - xw;
float sw = <#=sourceVar#>.W - xw; float sw = source.W - xw;
// calculate final alpha // calculate final alpha
float a = xw + bw + sw; float fw = (sw * <#=a_s#>) + (bw * <#=a_b#>) + (xw * <#=a_x#>);
// calculate final value // calculate final value
xform = ((xform * xw) + (<#=destVar#> * bw) + (<#=sourceVar#> * sw)) / MathF.Max(a, Constants.Epsilon); Vector4 xform = ((<#=blendVar#> * xw) + (<#=destVar#> * bw) + (<#=sourceVar#> * sw)) / MathF.Max(fw, Constants.Epsilon);
xform.W = fw;
return Vector4.Lerp(backdrop, xform, opacity); return Vector4.Lerp(backdrop, xform, opacity);
} }

Loading…
Cancel
Save