Browse Source

Fix Glow

Former-commit-id: dbea7d85b184eecdbac2eb1d3330469885ef9cdd
Former-commit-id: 0e6fb4eb1dd1ce575a04100eef819cb80a72834a
Former-commit-id: 728c0fe6fae89ac1d551af02a030a6bdf78d18a3
af/merge-core
James Jackson-South 10 years ago
parent
commit
f35a8c30b9
  1. 20
      src/ImageProcessorCore/Filters/Glow.cs
  2. 2
      src/ImageProcessorCore/Filters/Processors/ColorMatrix/LomographProcessor.cs
  3. 12
      src/ImageProcessorCore/Filters/Processors/ColorMatrix/PolaroidProcessor.cs
  4. 32
      src/ImageProcessorCore/Filters/Processors/GlowProcessor.cs
  5. 2
      tests/ImageProcessorCore.Tests/Processors/Filters/GlowTest.cs

20
src/ImageProcessorCore/Filters/Glow.cs

@ -24,7 +24,7 @@ namespace ImageProcessorCore
where T : IPackedVector<TP>
where TP : struct
{
return Glow(source, default(T), source.Bounds.Width * .5F, source.Bounds.Height * .5F, source.Bounds, progressHandler);
return Glow(source, default(T), source.Bounds.Width * .5F, source.Bounds, progressHandler);
}
/// <summary>
@ -40,7 +40,7 @@ namespace ImageProcessorCore
where T : IPackedVector<TP>
where TP : struct
{
return Glow(source, color, source.Bounds.Width * .5F, source.Bounds.Height * .5F, source.Bounds, progressHandler);
return Glow(source, color, source.Bounds.Width * .5F, source.Bounds, progressHandler);
}
/// <summary>
@ -49,15 +49,14 @@ namespace ImageProcessorCore
/// <typeparam name="T">The pixel format.</typeparam>
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="radiusX">The the x-radius.</param>
/// <param name="radiusY">The the y-radius.</param>
/// <param name="radius">The the radius.</param>
/// <param name="progressHandler">A delegate which is called as progress is made processing the image.</param>
/// <returns>The <see cref="Image{T,TP}"/>.</returns>
public static Image<T, TP> Glow<T, TP>(this Image<T, TP> source, float radiusX, float radiusY, ProgressEventHandler progressHandler = null)
public static Image<T, TP> Glow<T, TP>(this Image<T, TP> source, float radius, ProgressEventHandler progressHandler = null)
where T : IPackedVector<TP>
where TP : struct
{
return Glow(source, default(T), radiusX, radiusY, source.Bounds, progressHandler);
return Glow(source, default(T), radius, source.Bounds, progressHandler);
}
/// <summary>
@ -75,7 +74,7 @@ namespace ImageProcessorCore
where T : IPackedVector<TP>
where TP : struct
{
return Glow(source, default(T), 0, 0, rectangle, progressHandler);
return Glow(source, default(T), 0, rectangle, progressHandler);
}
/// <summary>
@ -85,18 +84,17 @@ namespace ImageProcessorCore
/// <typeparam name="TP">The packed format. <example>long, float.</example></typeparam>
/// <param name="source">The image this method extends.</param>
/// <param name="color">The color to set as the glow.</param>
/// <param name="radiusX">The the x-radius.</param>
/// <param name="radiusY">The the y-radius.</param>
/// <param name="radius">The the radius.</param>
/// <param name="rectangle">
/// The <see cref="Rectangle"/> structure that specifies the portion of the image object to alter.
/// </param>
/// <param name="progressHandler">A delegate which is called as progress is made processing the image.</param>
/// <returns>The <see cref="Image{T,TP}"/>.</returns>
public static Image<T, TP> Glow<T, TP>(this Image<T, TP> source, T color, float radiusX, float radiusY, Rectangle rectangle, ProgressEventHandler progressHandler = null)
public static Image<T, TP> Glow<T, TP>(this Image<T, TP> source, T color, float radius, Rectangle rectangle, ProgressEventHandler progressHandler = null)
where T : IPackedVector<TP>
where TP : struct
{
GlowProcessor<T, TP> processor = new GlowProcessor<T, TP> { RadiusX = radiusX, RadiusY = radiusY };
GlowProcessor<T, TP> processor = new GlowProcessor<T, TP> { Radius = radius, };
if (!color.Equals(default(T)))
{

2
src/ImageProcessorCore/Filters/Processors/ColorMatrix/LomographProcessor.cs

@ -31,7 +31,7 @@ namespace ImageProcessorCore.Processors
protected override void AfterApply(ImageBase<T, TP> target, ImageBase<T, TP> source, Rectangle targetRectangle, Rectangle sourceRectangle)
{
T packed = default(T);
packed.PackFromBytes(0, 10, 0, 255);
packed.PackFromBytes(0, 10, 0, 255); // Very dark (mostly black) lime green.
new VignetteProcessor<T, TP> { VignetteColor = packed }.Apply(target, target, targetRectangle);
}
}

12
src/ImageProcessorCore/Filters/Processors/ColorMatrix/PolaroidProcessor.cs

@ -37,18 +37,12 @@ namespace ImageProcessorCore.Processors
protected override void AfterApply(ImageBase<T, TP> target, ImageBase<T, TP> source, Rectangle targetRectangle, Rectangle sourceRectangle)
{
T packedV = default(T);
packedV.PackFromBytes(102, 34, 0, 255);
packedV.PackFromBytes(102, 34, 0, 255); // Very dark orange [Brown tone]
new VignetteProcessor<T, TP> { VignetteColor = packedV }.Apply(target, target, targetRectangle);
T packedG = default(T);
packedG.PackFromBytes(255, 153, 102, 178);
new GlowProcessor<T, TP>
{
GlowColor = packedG,
RadiusX = target.Width / 4f,
RadiusY = target.Width / 4f
}
.Apply(target, target, targetRectangle);
packedG.PackFromBytes(255, 153, 102, 178); // Light orange
new GlowProcessor<T, TP> { GlowColor = packedG, Radius = target.Width / 4F }.Apply(target, target, targetRectangle);
}
}
}

32
src/ImageProcessorCore/Filters/Processors/GlowProcessor.cs

@ -24,7 +24,7 @@ namespace ImageProcessorCore.Processors
public GlowProcessor()
{
T color = default(T);
color.PackFromVector4(Color.White.ToVector4());
color.PackFromVector4(Color.Black.ToVector4());
this.GlowColor = color;
}
@ -34,14 +34,9 @@ namespace ImageProcessorCore.Processors
public T GlowColor { get; set; }
/// <summary>
/// Gets or sets the the x-radius.
/// Gets or sets the the radius.
/// </summary>
public float RadiusX { get; set; }
/// <summary>
/// Gets or sets the the y-radius.
/// </summary>
public float RadiusY { get; set; }
public float Radius { get; set; }
/// <inheritdoc/>
protected override void Apply(ImageBase<T, TP> target, ImageBase<T, TP> source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
@ -50,9 +45,8 @@ namespace ImageProcessorCore.Processors
int endX = sourceRectangle.Right;
T glowColor = this.GlowColor;
Vector2 centre = Rectangle.Center(sourceRectangle).ToVector2();
float rX = this.RadiusX > 0 ? Math.Min(this.RadiusX, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F;
float rY = this.RadiusY > 0 ? Math.Min(this.RadiusY, sourceRectangle.Height * .5F) : sourceRectangle.Height * .5F;
float maxDistance = (float)Math.Sqrt((rX * rX) + (rY * rY));
float maxDistance = this.Radius > 0 ? Math.Min(this.Radius, sourceRectangle.Width * .5F) : sourceRectangle.Width * .5F;
Ellipse ellipse = new Ellipse(new Point(centre), maxDistance, maxDistance);
// Align start/end positions.
int minX = Math.Max(0, startX);
@ -84,13 +78,15 @@ namespace ImageProcessorCore.Processors
for (int x = minX; x < maxX; x++)
{
int offsetX = x - startX;
// TODO: Premultiply?
float distance = Vector2.Distance(centre, new Vector2(offsetX, offsetY));
Vector4 sourceColor = sourcePixels[offsetX, offsetY].ToVector4();
T packed = default(T);
packed.PackFromVector4(Vector4.Lerp(glowColor.ToVector4(), sourceColor, .5F * (distance / maxDistance)));
targetPixels[offsetX, offsetY] = packed;
if (ellipse.Contains(offsetX, offsetY))
{
// TODO: Premultiply?
float distance = Vector2.Distance(centre, new Vector2(offsetX, offsetY));
Vector4 sourceColor = sourcePixels[offsetX, offsetY].ToVector4();
T packed = default(T);
packed.PackFromVector4(Vector4.Lerp(glowColor.ToVector4(), sourceColor, distance / maxDistance));
targetPixels[offsetX, offsetY] = packed;
}
}
this.OnRowProcessed();

2
tests/ImageProcessorCore.Tests/Processors/Filters/GlowTest.cs

@ -76,7 +76,7 @@ namespace ImageProcessorCore.Tests
Image image = new Image(stream);
using (FileStream output = File.OpenWrite($"{path}/{filename}"))
{
image.Glow(image.Width / 4, image.Height / 4)
image.Glow(image.Width / 4)
.Save(output);
}
}

Loading…
Cancel
Save