mirror of https://github.com/SixLabors/ImageSharp
42 changed files with 465 additions and 401 deletions
@ -0,0 +1,69 @@ |
|||||
|
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
// <copyright file="PolaroidMatrixFilter.cs" company="James South">
|
||||
|
// Copyright (c) James South.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
// <summary>
|
||||
|
// Encapsulates methods with which to add a Polaroid filter to an image.
|
||||
|
// </summary>
|
||||
|
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
|
||||
|
namespace ImageProcessor.Imaging.Filters.Photo |
||||
|
{ |
||||
|
using System.Drawing; |
||||
|
using System.Drawing.Imaging; |
||||
|
|
||||
|
using ImageProcessor.Imaging.Helpers; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Encapsulates methods with which to add a Polaroid filter to an image.
|
||||
|
/// </summary>
|
||||
|
internal class PolaroidMatrixFilter : MatrixFilterBase |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Gets the <see cref="T:System.Drawing.Imaging.ColorMatrix"/> for this filter instance.
|
||||
|
/// </summary>
|
||||
|
public override ColorMatrix Matrix |
||||
|
{ |
||||
|
get { return ColorMatrixes.Polaroid; } |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Processes the image.
|
||||
|
/// </summary>
|
||||
|
/// <param name="image">The current image to process</param>
|
||||
|
/// <param name="newImage">The new Image to return</param>
|
||||
|
/// <returns>
|
||||
|
/// The processed image.
|
||||
|
/// </returns>
|
||||
|
public override Image TransformImage(Image image, Image newImage) |
||||
|
{ |
||||
|
using (Graphics graphics = Graphics.FromImage(newImage)) |
||||
|
{ |
||||
|
using (ImageAttributes attributes = new ImageAttributes()) |
||||
|
{ |
||||
|
attributes.SetColorMatrix(this.Matrix); |
||||
|
|
||||
|
Rectangle rectangle = new Rectangle(0, 0, image.Width, image.Height); |
||||
|
|
||||
|
graphics.DrawImage(image, rectangle, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// Fade the contrast
|
||||
|
newImage = Adjustments.Contrast((Bitmap)newImage, -30); |
||||
|
|
||||
|
// Add a glow to the image.
|
||||
|
newImage = Effects.Glow((Bitmap)newImage, Color.FromArgb(70, 255, 153, 102)); |
||||
|
|
||||
|
// Add a vignette to finish the effect.
|
||||
|
newImage = Effects.Vignette((Bitmap)newImage, Color.FromArgb(80, 0, 0)); |
||||
|
|
||||
|
// Reassign the image.
|
||||
|
image.Dispose(); |
||||
|
image = newImage; |
||||
|
|
||||
|
return image; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,99 +0,0 @@ |
|||||
// --------------------------------------------------------------------------------------------------------------------
|
|
||||
// <copyright file="PolaroidMatrixFilter.cs" company="James South">
|
|
||||
// Copyright (c) James South.
|
|
||||
// Licensed under the Apache License, Version 2.0.
|
|
||||
// </copyright>
|
|
||||
// <summary>
|
|
||||
// Encapsulates methods with which to add a Polaroid filter to an image.
|
|
||||
// </summary>
|
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
|
||||
|
|
||||
namespace ImageProcessor.Imaging.Filters |
|
||||
{ |
|
||||
#region Using
|
|
||||
using System.Drawing; |
|
||||
using System.Drawing.Drawing2D; |
|
||||
using System.Drawing.Imaging; |
|
||||
using ImageProcessor.Processors; |
|
||||
#endregion
|
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Encapsulates methods with which to add a Polaroid filter to an image.
|
|
||||
/// </summary>
|
|
||||
internal class PolaroidMatrixFilter : MatrixFilterBase |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// Gets the <see cref="T:System.Drawing.Imaging.ColorMatrix"/> for this filter instance.
|
|
||||
/// </summary>
|
|
||||
public override ColorMatrix Matrix |
|
||||
{ |
|
||||
get { return ColorMatrixes.Polaroid; } |
|
||||
} |
|
||||
|
|
||||
/// <summary>
|
|
||||
/// Processes the image.
|
|
||||
/// </summary>
|
|
||||
/// <param name="factory">
|
|
||||
/// The current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class containing
|
|
||||
/// the image to process.
|
|
||||
/// </param>
|
|
||||
/// <param name="image">The current image to process</param>
|
|
||||
/// <param name="newImage">The new Image to return</param>
|
|
||||
/// <returns>
|
|
||||
/// The processed image from the current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class.
|
|
||||
/// </returns>
|
|
||||
public override Image TransformImage(ImageFactory factory, Image image, Image newImage) |
|
||||
{ |
|
||||
using (Graphics graphics = Graphics.FromImage(newImage)) |
|
||||
{ |
|
||||
using (ImageAttributes attributes = new ImageAttributes()) |
|
||||
{ |
|
||||
attributes.SetColorMatrix(this.Matrix); |
|
||||
|
|
||||
Rectangle rectangle = new Rectangle(0, 0, image.Width, image.Height); |
|
||||
|
|
||||
graphics.DrawImage(image, rectangle, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes); |
|
||||
|
|
||||
// Add a glow to the image.
|
|
||||
using (GraphicsPath path = new GraphicsPath()) |
|
||||
{ |
|
||||
path.AddEllipse(rectangle); |
|
||||
using (PathGradientBrush brush = new PathGradientBrush(path)) |
|
||||
{ |
|
||||
// Fill a rectangle with an elliptical gradient brush that goes from orange to transparent.
|
|
||||
// This has the effect of painting the far corners transparent and fading in to orange on the
|
|
||||
// way in to the centre.
|
|
||||
brush.WrapMode = WrapMode.Tile; |
|
||||
brush.CenterColor = Color.FromArgb(70, 255, 153, 102); |
|
||||
brush.SurroundColors = new[] { Color.FromArgb(0, 0, 0, 0) }; |
|
||||
|
|
||||
Blend blend = new Blend |
|
||||
{ |
|
||||
Positions = new[] { 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0F }, |
|
||||
Factors = new[] { 0.0f, 0.5f, 1f, 1f, 1.0f, 1.0f } |
|
||||
}; |
|
||||
|
|
||||
brush.Blend = blend; |
|
||||
|
|
||||
Region oldClip = graphics.Clip; |
|
||||
graphics.Clip = new Region(rectangle); |
|
||||
graphics.FillRectangle(brush, rectangle); |
|
||||
graphics.Clip = oldClip; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Add a vignette to finish the effect.
|
|
||||
factory.Image = newImage; |
|
||||
Vignette vignette = new Vignette(); |
|
||||
newImage = vignette.ProcessImage(factory); |
|
||||
|
|
||||
// Reassign the image.
|
|
||||
image.Dispose(); |
|
||||
image = newImage; |
|
||||
|
|
||||
return image; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,126 @@ |
|||||
|
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
// <copyright file="Adjustments.cs" company="James South">
|
||||
|
// Copyright (c) James South.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
// <summary>
|
||||
|
// Provides reusable adjustment methods to apply to images.
|
||||
|
// </summary>
|
||||
|
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
|
||||
|
namespace ImageProcessor.Imaging.Helpers |
||||
|
{ |
||||
|
using System; |
||||
|
using System.Drawing; |
||||
|
using System.Drawing.Imaging; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Provides reusable adjustment methods to apply to images.
|
||||
|
/// </summary>
|
||||
|
public static class Adjustments |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Adjusts the brightness component of the given image.
|
||||
|
/// </summary>
|
||||
|
/// <param name="source">
|
||||
|
/// The <see cref="Bitmap"/> source to adjust.
|
||||
|
/// </param>
|
||||
|
/// <param name="threshold">
|
||||
|
/// The threshold value between -100 and 100 for adjusting the brightness.
|
||||
|
/// </param>
|
||||
|
/// <param name="rectangle">The rectangle to define the bounds of the area to adjust the brightness.
|
||||
|
/// If null then the effect is applied to the entire image.</param>
|
||||
|
/// <returns>
|
||||
|
/// The <see cref="Bitmap"/> with the brightness adjusted.
|
||||
|
/// </returns>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">
|
||||
|
/// Thrown if the threshold value falls outside the acceptable range.
|
||||
|
/// </exception>
|
||||
|
public static Bitmap Brightness(Bitmap source, int threshold, Rectangle? rectangle = null) |
||||
|
{ |
||||
|
if (threshold > 100 || threshold < -100) |
||||
|
{ |
||||
|
throw new ArgumentOutOfRangeException("threshold", "Threshold should be between -100 and 100."); |
||||
|
} |
||||
|
|
||||
|
float brightnessFactor = (float)threshold / 100; |
||||
|
Rectangle bounds = rectangle.HasValue ? rectangle.Value : new Rectangle(0, 0, source.Width, source.Height); |
||||
|
|
||||
|
ColorMatrix colorMatrix = |
||||
|
new ColorMatrix( |
||||
|
new[] |
||||
|
{ |
||||
|
new float[] { 1, 0, 0, 0, 0 }, |
||||
|
new float[] { 0, 1, 0, 0, 0 }, |
||||
|
new float[] { 0, 0, 1, 0, 0 }, |
||||
|
new float[] { 0, 0, 0, 1, 0 }, |
||||
|
new[] { brightnessFactor, brightnessFactor, brightnessFactor, 0, 1 } |
||||
|
}); |
||||
|
|
||||
|
using (Graphics graphics = Graphics.FromImage(source)) |
||||
|
{ |
||||
|
using (ImageAttributes imageAttributes = new ImageAttributes()) |
||||
|
{ |
||||
|
imageAttributes.SetColorMatrix(colorMatrix); |
||||
|
graphics.DrawImage(source, bounds, 0, 0, source.Width, source.Height, GraphicsUnit.Pixel, imageAttributes); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return source; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adjusts the contrast component of the given image.
|
||||
|
/// </summary>
|
||||
|
/// <param name="source">
|
||||
|
/// The <see cref="Bitmap"/> source to adjust.
|
||||
|
/// </param>
|
||||
|
/// <param name="threshold">
|
||||
|
/// The threshold value between -100 and 100 for adjusting the contrast.
|
||||
|
/// </param>
|
||||
|
/// <param name="rectangle">The rectangle to define the bounds of the area to adjust the contrast.
|
||||
|
/// If null then the effect is applied to the entire image.</param>
|
||||
|
/// <returns>
|
||||
|
/// The <see cref="Bitmap"/> with the contrast adjusted.
|
||||
|
/// </returns>
|
||||
|
/// <exception cref="ArgumentOutOfRangeException">
|
||||
|
/// Thrown if the threshold value falls outside the acceptable range.
|
||||
|
/// </exception>
|
||||
|
public static Bitmap Contrast(Bitmap source, int threshold, Rectangle? rectangle = null) |
||||
|
{ |
||||
|
if (threshold > 100 || threshold < -100) |
||||
|
{ |
||||
|
throw new ArgumentOutOfRangeException("threshold", "Threshold should be between -100 and 100."); |
||||
|
} |
||||
|
|
||||
|
Rectangle bounds = rectangle.HasValue ? rectangle.Value : new Rectangle(0, 0, source.Width, source.Height); |
||||
|
|
||||
|
float contrastFactor = (float)threshold / 100; |
||||
|
|
||||
|
// Stop at -1 to prevent inversion.
|
||||
|
contrastFactor++; |
||||
|
float factorTransform = 0.5f * (1.0f - contrastFactor); |
||||
|
|
||||
|
ColorMatrix colorMatrix = new ColorMatrix( |
||||
|
new[] |
||||
|
{ |
||||
|
new[] { contrastFactor, 0, 0, 0, 0 }, |
||||
|
new[] { 0, contrastFactor, 0, 0, 0 }, |
||||
|
new[] { 0, 0, contrastFactor, 0, 0 }, |
||||
|
new float[] { 0, 0, 0, 1, 0 }, |
||||
|
new[] { factorTransform, factorTransform, factorTransform, 0, 1 } |
||||
|
}); |
||||
|
|
||||
|
using (Graphics graphics = Graphics.FromImage(source)) |
||||
|
{ |
||||
|
using (ImageAttributes imageAttributes = new ImageAttributes()) |
||||
|
{ |
||||
|
imageAttributes.SetColorMatrix(colorMatrix); |
||||
|
graphics.DrawImage(source, bounds, 0, 0, source.Width, source.Height, GraphicsUnit.Pixel, imageAttributes); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return source; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,112 @@ |
|||||
|
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
// <copyright file="Effects.cs" company="James South">
|
||||
|
// Copyright (c) James South.
|
||||
|
// Licensed under the Apache License, Version 2.0.
|
||||
|
// </copyright>
|
||||
|
// <summary>
|
||||
|
// Provides reusable effect methods to apply to images.
|
||||
|
// </summary>
|
||||
|
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
|
||||
|
namespace ImageProcessor.Imaging.Helpers |
||||
|
{ |
||||
|
using System; |
||||
|
using System.Drawing; |
||||
|
using System.Drawing.Drawing2D; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Provides reusable effect methods to apply to images.
|
||||
|
/// </summary>
|
||||
|
public static class Effects |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Adds a vignette effect to the source image based on the given color.
|
||||
|
/// </summary>
|
||||
|
/// <param name="source">
|
||||
|
/// The <see cref="Bitmap"/> source.
|
||||
|
/// </param>
|
||||
|
/// <param name="baseColor">
|
||||
|
/// <see cref="Color"/> to base the vignette on.
|
||||
|
/// </param>
|
||||
|
/// <param name="rectangle">
|
||||
|
/// The rectangle to define the bounds of the area to vignette. If null then the effect is applied
|
||||
|
/// to the entire image.
|
||||
|
/// </param>
|
||||
|
/// <param name="invert">
|
||||
|
/// Whether to invert the vignette.
|
||||
|
/// </param>
|
||||
|
/// <returns>
|
||||
|
/// The <see cref="Bitmap"/> with the vignette applied.
|
||||
|
/// </returns>
|
||||
|
public static Bitmap Vignette(Bitmap source, Color baseColor, Rectangle? rectangle = null, bool invert = false) |
||||
|
{ |
||||
|
using (Graphics graphics = Graphics.FromImage(source)) |
||||
|
{ |
||||
|
Rectangle bounds = rectangle.HasValue ? rectangle.Value : new Rectangle(0, 0, source.Width, source.Height); |
||||
|
Rectangle ellipsebounds = bounds; |
||||
|
|
||||
|
// Increase the rectangle size by the difference between the rectangle dimensions and sqrt(2)/2 * the rectangle dimensions.
|
||||
|
// Why sqrt(2)/2? Because the point (sqrt(2)/2, sqrt(2)/2) is the 45 degree angle point on a unit circle. Scaling by the width
|
||||
|
// and height gives the distance needed to inflate the rectangle to make sure it's fully covered.
|
||||
|
ellipsebounds.Offset(-ellipsebounds.X, -ellipsebounds.Y); |
||||
|
int x = ellipsebounds.Width - (int)Math.Floor(.70712 * ellipsebounds.Width); |
||||
|
int y = ellipsebounds.Height - (int)Math.Floor(.70712 * ellipsebounds.Height); |
||||
|
ellipsebounds.Inflate(x, y); |
||||
|
|
||||
|
using (GraphicsPath path = new GraphicsPath()) |
||||
|
{ |
||||
|
path.AddEllipse(ellipsebounds); |
||||
|
using (PathGradientBrush brush = new PathGradientBrush(path)) |
||||
|
{ |
||||
|
// Fill a rectangle with an elliptical gradient brush that goes from transparent to opaque.
|
||||
|
// This has the effect of painting the far corners with the given color and shade less on the way in to the centre.
|
||||
|
Color centerColor; |
||||
|
Color edgeColor; |
||||
|
if (invert) |
||||
|
{ |
||||
|
centerColor = Color.FromArgb(50, baseColor.R, baseColor.G, baseColor.B); |
||||
|
edgeColor = Color.FromArgb(0, baseColor.R, baseColor.G, baseColor.B); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
centerColor = Color.FromArgb(0, baseColor.R, baseColor.G, baseColor.B); |
||||
|
edgeColor = Color.FromArgb(255, baseColor.R, baseColor.G, baseColor.B); |
||||
|
} |
||||
|
|
||||
|
brush.WrapMode = WrapMode.Tile; |
||||
|
brush.CenterColor = centerColor; |
||||
|
brush.SurroundColors = new[] { edgeColor }; |
||||
|
|
||||
|
Blend blend = new Blend |
||||
|
{ |
||||
|
Positions = new[] { 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0F }, |
||||
|
Factors = new[] { 0.0f, 0.5f, 1f, 1f, 1.0f, 1.0f } |
||||
|
}; |
||||
|
|
||||
|
brush.Blend = blend; |
||||
|
|
||||
|
Region oldClip = graphics.Clip; |
||||
|
graphics.Clip = new Region(bounds); |
||||
|
graphics.FillRectangle(brush, ellipsebounds); |
||||
|
graphics.Clip = oldClip; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return source; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Adds a diffused glow (inverted vignette) effect to the source image based on the given color.
|
||||
|
/// </summary>
|
||||
|
/// <param name="source">The <see cref="Bitmap"/> source.</param>
|
||||
|
/// <param name="baseColor"><see cref="Color"/> to base the vignette on.</param>
|
||||
|
/// <param name="rectangle">The rectangle to define the bounds of the area to vignette. If null then the effect is applied
|
||||
|
/// to the entire image.</param>
|
||||
|
/// <returns>The <see cref="Bitmap"/> with the vignette applied.</returns>
|
||||
|
public static Bitmap Glow(Bitmap source, Color baseColor, Rectangle? rectangle = null) |
||||
|
{ |
||||
|
return Vignette(source, baseColor, rectangle, true); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1 @@ |
|||||
|
d04aa90445e483d5614cf597cbd7caa6d55d9aaa |
||||
@ -1 +0,0 @@ |
|||||
e40fa501c49374e25d137627084dfa993931205f |
|
||||
Loading…
Reference in new issue