Browse Source

Add blending functionlity.

Former-commit-id: 35f80976d4212395f217df999689b6be437746d4
Former-commit-id: 450afda3ccbfa96b2fd788569aee363711819971
Former-commit-id: 448dcb8c150762d54d053f1598b5d0a231acced6
pull/17/head
James Jackson-South 10 years ago
parent
commit
a080d98e8d
  1. 77
      src/ImageProcessor/Filters/Blend.cs
  2. 12
      src/ImageProcessor/Filters/ImageFilterExtensions.cs
  3. 3
      src/ImageProcessor/ImageProcessor.csproj
  4. 15
      src/ImageProcessor/Numerics/Rectangle.cs
  5. 5
      tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs

77
src/ImageProcessor/Filters/Blend.cs

@ -0,0 +1,77 @@
// <copyright file="Blend.cs" company="James South">
// Copyright (c) James South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageProcessor.Filters
{
using System.Threading.Tasks;
/// <summary>
/// Combines two images together by blending the pixels.
/// </summary>
public class Blend : ParallelImageProcessor
{
/// <summary>
/// The image to blend.
/// </summary>
private readonly ImageBase toBlend;
/// <summary>
/// Initializes a new instance of the <see cref="Blend"/> class.
/// </summary>
/// <param name="image">The image to blend.</param>
/// <param name="alpha">The opacity of the image to blend. Between 0 and 100.</param>
public Blend(ImageBase image, int alpha = 100)
{
Guard.MustBeBetweenOrEqualTo(alpha, 0, 100, nameof(alpha));
this.toBlend = image;
this.Value = alpha;
}
/// <summary>
/// Gets the alpha percentage value.
/// </summary>
public int Value { get; }
/// <inheritdoc/>
protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
{
int sourceY = sourceRectangle.Y;
int sourceBottom = sourceRectangle.Bottom;
int startX = sourceRectangle.X;
int endX = sourceRectangle.Right;
Rectangle bounds = this.toBlend.Bounds;
float alpha = this.Value / 100f;
Parallel.For(
startY,
endY,
y =>
{
if (y >= sourceY && y < sourceBottom)
{
for (int x = startX; x < endX; x++)
{
Color color = source[x, y];
if (bounds.Contains(x, y))
{
Color blendedColor = this.toBlend[x, y];
// Combining colors is dependent on the alpha of the blended color
float alphaFactor = alpha > 0 ? alpha : blendedColor.A;
float invertedAlphaFactor = 1 - alphaFactor;
color.R = (color.R * invertedAlphaFactor) + (blendedColor.R * alphaFactor);
color.G = (color.G * invertedAlphaFactor) + (blendedColor.G * alphaFactor);
color.B = (color.B * invertedAlphaFactor) + (blendedColor.B * alphaFactor);
}
target[x, y] = color;
}
}
});
}
}
}

12
src/ImageProcessor/Filters/ImageFilterExtensions.cs

@ -35,6 +35,18 @@ namespace ImageProcessor.Filters
return source.Process(rectangle, new Alpha(percent));
}
/// <summary>
/// Combines the given image together with the current one by blending their pixels.
/// </summary>
/// <param name="source">The image this method extends.</param>
/// <param name="image">The image to blend with the currently processing image.</param>
/// <param name="percent">The opacity of the image image to blend. Must be between 0 and 100.</param>
/// <returns>The <see cref="Image"/>.</returns>
public static Image Blend(this Image source, ImageBase image, int percent = 100)
{
return source.Process(source.Bounds, new Blend(image, percent));
}
/// <summary>
/// Alters the contrast component of the image.
/// </summary>

3
src/ImageProcessor/ImageProcessor.csproj

@ -48,9 +48,10 @@
<Compile Include="Common\Extensions\EnumerableExtensions.cs" />
<Compile Include="Common\Helpers\ImageMaths.cs" />
<Compile Include="Common\Helpers\PixelOperations.cs" />
<Compile Include="Filters\Blend.cs" />
<Compile Include="Filters\ColorMatrix\ColorMatrixFilter.cs" />
<Compile Include="Filters\ColorMatrix\Kodachrome.cs" />
<Compile Include="Filters\Saturation.cs" />
<Compile Include="Filters\ColorMatrix\Saturation.cs" />
<Compile Include="Filters\ColorMatrix\GreyscaleMode.cs" />
<Compile Include="Filters\Brightness.cs" />
<Compile Include="Filters\Invert.cs" />

15
src/ImageProcessor/Numerics/Rectangle.cs

@ -140,6 +140,21 @@ namespace ImageProcessor
return !left.Equals(right);
}
/// <summary>
/// Determines if the specfied point is contained within the rectangular region defined by
/// this <see cref="Rectangle"/>.
/// </summary>
/// <param name="x">The x-coordinate of the given point.</param>
/// <param name="y">The y-coordinate of the given point.</param>
/// <returns>The <see cref="bool"/></returns>
public bool Contains(int x, int y)
{
return this.X <= x
&& x < this.X + this.Width
&& this.Y <= y
&& y < this.Y + this.Height;
}
/// <summary>
/// Indicates whether this instance and a specified object are equal.
/// </summary>

5
tests/ImageProcessor.Tests/Processors/Filters/FilterTests.cs

@ -16,8 +16,9 @@ namespace ImageProcessor.Tests
//{ "Brightness--50", new Brightness(-50) },
//{ "Contrast-50", new Contrast(50) },
//{ "Contrast--50", new Contrast(-50) },
{ "Saturation-50", new Saturation(50) },
{ "Saturation--50", new Saturation(-50) },
{ "Blend", new Blend(new Image(File.OpenRead("../../TestImages/Formats/Bmp/Car.bmp")),50)},
//{ "Saturation-50", new Saturation(50) },
//{ "Saturation--50", new Saturation(-50) },
//{ "Alpha--50", new Alpha(50) },
//{ "Invert", new Invert() },
//{ "Sepia", new Sepia() },

Loading…
Cancel
Save