mirror of https://github.com/SixLabors/ImageSharp
19 changed files with 2054 additions and 424 deletions
@ -0,0 +1,64 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="BlackWhiteMatrixFilter.cs" company="James South">
|
|||
// TODO: Update copyright text.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Imaging.Filters |
|||
{ |
|||
#region Using
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Drawing; |
|||
using System.Drawing.Imaging; |
|||
#endregion
|
|||
|
|||
/// <summary>
|
|||
/// Encapsulates methods with which to add a black and white filter to an image.
|
|||
/// </summary>
|
|||
class BlackWhiteMatrixFilter : IMatrixFilter |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the <see cref="T:System.Drawing.Imaging.ColoMatrix"/> for this filter instance.
|
|||
/// </summary>
|
|||
public ColorMatrix Matrix |
|||
{ |
|||
get { return ColorMatrixes.BlackWhite; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Processes the image.
|
|||
/// </summary>
|
|||
/// <param name="factory">
|
|||
/// The 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 Image ProcessImage(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); |
|||
} |
|||
} |
|||
|
|||
// Reassign the image.
|
|||
image.Dispose(); |
|||
image = newImage; |
|||
|
|||
return image; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,193 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="ColorMatrixes.cs" company="James South">
|
|||
// TODO: Update copyright text.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Imaging.Filters |
|||
{ |
|||
#region Using
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Drawing.Imaging; |
|||
#endregion
|
|||
|
|||
/// <summary>
|
|||
/// A list of available color matrices to apply to an image.
|
|||
/// </summary>
|
|||
internal static class ColorMatrixes |
|||
{ |
|||
/// <summary>
|
|||
/// Gets Sepia.
|
|||
/// </summary>
|
|||
internal static ColorMatrix Sepia |
|||
{ |
|||
get |
|||
{ |
|||
return new ColorMatrix( |
|||
new float[][] |
|||
{ |
|||
new float[] { .393f, .349f, .272f, 0, 0 }, |
|||
new float[] { .769f, .686f, .534f, 0, 0 }, |
|||
new float[] { .189f, .168f, .131f, 0, 0 }, |
|||
new float[] { 0, 0, 0, 1, 0 }, |
|||
new float[] { 0, 0, 0, 0, 1 } |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets BlackWhite.
|
|||
/// </summary>
|
|||
internal static ColorMatrix BlackWhite |
|||
{ |
|||
get |
|||
{ |
|||
return new ColorMatrix( |
|||
new float[][] |
|||
{ |
|||
new float[] { 1.5f, 1.5f, 1.5f, 0, 0 }, |
|||
new float[] { 1.5f, 1.5f, 1.5f, 0, 0 }, |
|||
new float[] { 1.5f, 1.5f, 1.5f, 0, 0 }, |
|||
new float[] { 0, 0, 0, 1, 0 }, |
|||
new float[] { -1, -1, -1, 0, 1 } |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets Polaroid.
|
|||
/// </summary>
|
|||
internal static ColorMatrix Polaroid |
|||
{ |
|||
get |
|||
{ |
|||
return new ColorMatrix( |
|||
new float[][] |
|||
{ |
|||
new float[] { 1.638f, -0.062f, -0.262f, 0, 0 }, |
|||
new float[] { -0.122f, 1.378f, -0.122f, 0, 0 }, |
|||
new float[] { 1.016f, -0.016f, 1.383f, 0, 0 }, |
|||
new float[] { 0, 0, 0, 1, 0 }, |
|||
new float[] { 0.06f, -0.05f, -0.05f, 0, 1 } |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets Lomograph.
|
|||
/// </summary>
|
|||
internal static ColorMatrix Lomograph |
|||
{ |
|||
get |
|||
{ |
|||
return new ColorMatrix( |
|||
new float[][] |
|||
{ |
|||
new float[] { 1.50f, 0, 0, 0, 0 }, |
|||
new float[] { 0, 1.45f, 0, 0, 0 }, |
|||
new float[] { 0, 0, 1.09f, 0, 0 }, |
|||
new float[] { 0, 0, 0, 1, 0 }, |
|||
new float[] { -0.10f, 0.05f, -0.08f, 0, 1 } |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets GreyScale.
|
|||
/// </summary>
|
|||
internal static ColorMatrix GreyScale |
|||
{ |
|||
get |
|||
{ |
|||
return new ColorMatrix( |
|||
new float[][] |
|||
{ |
|||
new float[] { .33f, .33f, .33f, 0, 0 }, |
|||
new float[] { .59f, .59f, .59f, 0, 0 }, |
|||
new float[] { .11f, .11f, .11f, 0, 0 }, |
|||
new float[] { 0, 0, 0, 1, 0 }, |
|||
new float[] { 0, 0, 0, 0, 1 } |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets Gotham.
|
|||
/// </summary>
|
|||
internal static ColorMatrix Gotham |
|||
{ |
|||
get |
|||
{ |
|||
return new ColorMatrix( |
|||
new float[][] |
|||
{ |
|||
new float[] { .9f, .9f, .9f, 0, 0 }, |
|||
new float[] { .9f, .9f, .9f, 0, 0 }, |
|||
new float[] { .9f, .9f, .9f, 0, 0 }, |
|||
new float[] { 0, 0, 0, 1, 0 }, |
|||
new float[] { -.5f, -.5f, -.45f, 0, 1 } |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets Invert.
|
|||
/// </summary>
|
|||
internal static ColorMatrix Invert |
|||
{ |
|||
get |
|||
{ |
|||
return new ColorMatrix( |
|||
new float[][] |
|||
{ |
|||
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 float[] { 1, 1, 1, 0, 1 } |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets HiSatch.
|
|||
/// </summary>
|
|||
internal static ColorMatrix HiSatch |
|||
{ |
|||
get |
|||
{ |
|||
return new ColorMatrix( |
|||
new float[][] |
|||
{ |
|||
new float[] { 3, -1, -1, 0, 0 }, |
|||
new float[] { -1, 3, -1, 0, 0 }, |
|||
new float[] { -1, -1, 3, 0, 0 }, |
|||
new float[] { 0, 0, 0, 1, 0 }, |
|||
new float[] { 0, 0, 0, 0, 1 } |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets LoSatch.
|
|||
/// </summary>
|
|||
internal static ColorMatrix LoSatch |
|||
{ |
|||
get |
|||
{ |
|||
return new ColorMatrix( |
|||
new float[][] |
|||
{ |
|||
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 float[] { .25f, .25f, .25f, 0, 1 } |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,222 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="ComicMatrixFilter.cs" company="James South">
|
|||
// TODO: Update copyright text.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Imaging.Filters |
|||
{ |
|||
#region Using
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Drawing; |
|||
using System.Drawing.Imaging; |
|||
using System.Drawing.Drawing2D; |
|||
#endregion
|
|||
|
|||
/// <summary>
|
|||
/// Encapsulates methods with which to add a comic filter to an image.
|
|||
/// </summary>
|
|||
class ComicMatrixFilter : IMatrixFilter |
|||
{ |
|||
/// <summary>
|
|||
/// Enumurates Argb colour channels.
|
|||
/// </summary>
|
|||
private enum ChannelArgb |
|||
{ |
|||
/// <summary>
|
|||
/// The blue channel
|
|||
/// </summary>
|
|||
Blue = 0, |
|||
|
|||
/// <summary>
|
|||
/// The green channel
|
|||
/// </summary>
|
|||
Green = 1, |
|||
|
|||
/// <summary>
|
|||
/// The red channel
|
|||
/// </summary>
|
|||
Red = 2, |
|||
|
|||
/// <summary>
|
|||
/// The alpha channel
|
|||
/// </summary>
|
|||
Alpha = 3 |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the <see cref="T:System.Drawing.Imaging.ColoMatrix"/> for this filter instance.
|
|||
/// </summary>
|
|||
public ColorMatrix Matrix |
|||
{ |
|||
get { return ColorMatrixes.LoSatch; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Processes the image.
|
|||
/// </summary>
|
|||
/// <param name="factory">
|
|||
/// The 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 Image ProcessImage(ImageFactory factory, Image image, Image newImage) |
|||
{ |
|||
// Bitmaps for comic pattern
|
|||
Bitmap hisatchBitmap = null; |
|||
Bitmap patternBitmap = null; |
|||
|
|||
try |
|||
{ |
|||
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); |
|||
|
|||
// Set the attributes to LoSatch and draw the image.
|
|||
graphics.DrawImage(image, rectangle, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes); |
|||
|
|||
// Create a bitmap for overlaying.
|
|||
hisatchBitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppPArgb); |
|||
|
|||
// Set the color matrix
|
|||
attributes.SetColorMatrix(ColorMatrixes.HiSatch); |
|||
|
|||
// Draw the image with the hisatch colormatrix.
|
|||
using (var g = Graphics.FromImage(hisatchBitmap)) |
|||
{ |
|||
g.DrawImage(image, rectangle, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes); |
|||
} |
|||
|
|||
// We need to create a new image now with the hi saturation colormatrix and a pattern mask to paint it
|
|||
// onto the other image with.
|
|||
patternBitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppPArgb); |
|||
|
|||
// Create the pattern mask.
|
|||
using (var g = Graphics.FromImage(patternBitmap)) |
|||
{ |
|||
g.Clear(Color.Black); |
|||
g.SmoothingMode = SmoothingMode.HighQuality; |
|||
for (var y = 0; y < image.Height; y += 10) |
|||
{ |
|||
for (var x = 0; x < image.Width; x += 6) |
|||
{ |
|||
g.FillEllipse(Brushes.White, x, y, 4, 4); |
|||
g.FillEllipse(Brushes.White, x + 3, y + 5, 4, 4); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Transfer the alpha channel from the mask to the hi sturation image.
|
|||
TransferOneArgbChannelFromOneBitmapToAnother(patternBitmap, hisatchBitmap, ChannelArgb.Blue, ChannelArgb.Alpha); |
|||
|
|||
// Overlay the image.
|
|||
graphics.DrawImage(hisatchBitmap, 0, 0); |
|||
|
|||
// Dispose of the other images
|
|||
hisatchBitmap.Dispose(); |
|||
patternBitmap.Dispose(); |
|||
} |
|||
} |
|||
|
|||
// Reassign the image.
|
|||
image.Dispose(); |
|||
image = newImage; |
|||
} |
|||
catch |
|||
{ |
|||
if (newImage != null) |
|||
{ |
|||
newImage.Dispose(); |
|||
} |
|||
|
|||
if (hisatchBitmap != null) |
|||
{ |
|||
hisatchBitmap.Dispose(); |
|||
} |
|||
|
|||
if (patternBitmap != null) |
|||
{ |
|||
patternBitmap.Dispose(); |
|||
} |
|||
} |
|||
return image; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Transfers a single ARGB channel from one image to another.
|
|||
/// </summary>
|
|||
/// <param name="source">
|
|||
/// The source.
|
|||
/// </param>
|
|||
/// <param name="destination">
|
|||
/// The destination.
|
|||
/// </param>
|
|||
/// <param name="sourceChannel">
|
|||
/// The source channel.
|
|||
/// </param>
|
|||
/// <param name="destinationChannel">
|
|||
/// The destination channel.
|
|||
/// </param>
|
|||
private static void TransferOneArgbChannelFromOneBitmapToAnother(Bitmap source, Bitmap destination, ChannelArgb sourceChannel, ChannelArgb destinationChannel) |
|||
{ |
|||
if (source.Size != destination.Size) |
|||
{ |
|||
throw new ArgumentException(); |
|||
} |
|||
|
|||
Rectangle rectangle = new Rectangle(Point.Empty, source.Size); |
|||
|
|||
// Lockbits the source.
|
|||
BitmapData bitmapDataSource = source.LockBits(rectangle, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); |
|||
|
|||
// Declare an array to hold the bytes of the bitmap.
|
|||
int bytes = bitmapDataSource.Stride * bitmapDataSource.Height; |
|||
|
|||
// Allocate a buffer for the source image
|
|||
byte[] sourceRgbValues = new byte[bytes]; |
|||
|
|||
// Copy the RGB values into the array.
|
|||
System.Runtime.InteropServices.Marshal.Copy(bitmapDataSource.Scan0, sourceRgbValues, 0, bytes); |
|||
|
|||
// Unlockbits the source.
|
|||
source.UnlockBits(bitmapDataSource); |
|||
|
|||
// Lockbits the destination.
|
|||
BitmapData bitmapDataDestination = destination.LockBits(rectangle, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); |
|||
|
|||
// Allocate a buffer for image
|
|||
byte[] destinationRgbValues = new byte[bytes]; |
|||
|
|||
// Copy the RGB values into the array.
|
|||
System.Runtime.InteropServices.Marshal.Copy(bitmapDataDestination.Scan0, destinationRgbValues, 0, bytes); |
|||
|
|||
int s = (int)sourceChannel; |
|||
int d = (int)destinationChannel; |
|||
|
|||
for (int i = rectangle.Height * rectangle.Width; i > 0; i--) |
|||
{ |
|||
destinationRgbValues[d] = sourceRgbValues[s]; |
|||
d += 4; |
|||
s += 4; |
|||
} |
|||
|
|||
// Copy the RGB values back to the bitmap
|
|||
System.Runtime.InteropServices.Marshal.Copy(destinationRgbValues, 0, bitmapDataDestination.Scan0, bytes); |
|||
|
|||
// Unlock bits the destination.
|
|||
destination.UnlockBits(bitmapDataDestination); |
|||
} |
|||
|
|||
} |
|||
} |
|||
@ -0,0 +1,85 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="GothamMatrixFilter.cs" company="James South">
|
|||
// TODO: Update copyright text.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Imaging.Filters |
|||
{ |
|||
#region Using
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Drawing; |
|||
using System.Drawing.Imaging; |
|||
using System.Drawing.Drawing2D; |
|||
#endregion
|
|||
|
|||
/// <summary>
|
|||
/// Encapsulates methods with which to add a gotham filter to an image.
|
|||
/// </summary>
|
|||
class GothamMatrixFilter : IMatrixFilter |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the <see cref="T:System.Drawing.Imaging.ColoMatrix"/> for this filter instance.
|
|||
/// </summary>
|
|||
public ColorMatrix Matrix |
|||
{ |
|||
get { return ColorMatrixes.Gotham; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Processes the image.
|
|||
/// </summary>
|
|||
/// <param name="factory">
|
|||
/// The 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 Image ProcessImage(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); |
|||
|
|||
// Overlay the image with some semi-transparent colors to finish the effect.
|
|||
using (GraphicsPath path = new GraphicsPath()) |
|||
{ |
|||
path.AddRectangle(rectangle); |
|||
|
|||
// Paint a burgundy rectangle with a transparency of ~30% over the image.
|
|||
// Paint a blue rectangle with a transparency of 20% over the image.
|
|||
using (SolidBrush brush = new SolidBrush(Color.FromArgb(77, 43, 4, 18))) |
|||
{ |
|||
Region oldClip = graphics.Clip; |
|||
graphics.Clip = new Region(rectangle); |
|||
graphics.FillRectangle(brush, rectangle); |
|||
|
|||
// Fill the blue.
|
|||
brush.Color = Color.FromArgb(51, 12, 22, 88); |
|||
graphics.FillRectangle(brush, rectangle); |
|||
graphics.Clip = oldClip; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Reassign the image.
|
|||
image.Dispose(); |
|||
image = newImage; |
|||
|
|||
return image; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,64 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="GreyScaleMatrixFilter.cs" company="James South">
|
|||
// TODO: Update copyright text.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Imaging.Filters |
|||
{ |
|||
#region Using
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Drawing; |
|||
using System.Drawing.Imaging; |
|||
#endregion
|
|||
|
|||
/// <summary>
|
|||
/// Encapsulates methods with which to add a greyscale filter to an image.
|
|||
/// </summary>
|
|||
class GreyScaleMatrixFilter : IMatrixFilter |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the <see cref="T:System.Drawing.Imaging.ColoMatrix"/> for this filter instance.
|
|||
/// </summary>
|
|||
public ColorMatrix Matrix |
|||
{ |
|||
get { return ColorMatrixes.GreyScale; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Processes the image.
|
|||
/// </summary>
|
|||
/// <param name="factory">
|
|||
/// The 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 Image ProcessImage(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); |
|||
} |
|||
} |
|||
|
|||
// Reassign the image.
|
|||
image.Dispose(); |
|||
image = newImage; |
|||
|
|||
return image; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,64 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="HiSatchMatrixFilter.cs" company="James South">
|
|||
// TODO: Update copyright text.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Imaging.Filters |
|||
{ |
|||
#region Using
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Drawing; |
|||
using System.Drawing.Imaging; |
|||
#endregion
|
|||
|
|||
/// <summary>
|
|||
/// Encapsulates methods with which to add a high saturated filter to an image.
|
|||
/// </summary>
|
|||
class HiSatchMatrixFilter : IMatrixFilter |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the <see cref="T:System.Drawing.Imaging.ColoMatrix"/> for this filter instance.
|
|||
/// </summary>
|
|||
public ColorMatrix Matrix |
|||
{ |
|||
get { return ColorMatrixes.HiSatch; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Processes the image.
|
|||
/// </summary>
|
|||
/// <param name="factory">
|
|||
/// The 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 Image ProcessImage(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); |
|||
} |
|||
} |
|||
|
|||
// Reassign the image.
|
|||
image.Dispose(); |
|||
image = newImage; |
|||
|
|||
return image; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,40 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="IMatrixFilter.cs" company="James South">
|
|||
// TODO: Update copyright text.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Imaging.Filters |
|||
{ |
|||
#region Using
|
|||
using System.Drawing; |
|||
using System.Drawing.Imaging; |
|||
#endregion
|
|||
|
|||
/// <summary>
|
|||
/// Defines properties and methods for ColorMatrix based filters.
|
|||
/// </summary>
|
|||
interface IMatrixFilter |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the <see cref="T:System.Drawing.ColoMatrix"/> for this filter instance.
|
|||
/// </summary>
|
|||
ColorMatrix Matrix { get; } |
|||
|
|||
#region Methods
|
|||
/// <summary>
|
|||
/// Processes the image.
|
|||
/// </summary>
|
|||
/// <param name="factory">
|
|||
/// The 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>
|
|||
Image ProcessImage(ImageFactory factory, Image image, Image newImage); |
|||
#endregion
|
|||
} |
|||
} |
|||
@ -0,0 +1,64 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="InvertMatrixFilter.cs" company="James South">
|
|||
// TODO: Update copyright text.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Imaging.Filters |
|||
{ |
|||
#region Using
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Drawing; |
|||
using System.Drawing.Imaging; |
|||
#endregion
|
|||
|
|||
/// <summary>
|
|||
/// Encapsulates methods with which to add an inverted filter to an image.
|
|||
/// </summary>
|
|||
class InvertMatrixFilter : IMatrixFilter |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the <see cref="T:System.Drawing.Imaging.ColoMatrix"/> for this filter instance.
|
|||
/// </summary>
|
|||
public ColorMatrix Matrix |
|||
{ |
|||
get { return ColorMatrixes.Invert; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Processes the image.
|
|||
/// </summary>
|
|||
/// <param name="factory">
|
|||
/// The 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 Image ProcessImage(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); |
|||
} |
|||
} |
|||
|
|||
// Reassign the image.
|
|||
image.Dispose(); |
|||
image = newImage; |
|||
|
|||
return image; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,64 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="LoSatchMatrixFilter.cs" company="James South">
|
|||
// TODO: Update copyright text.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Imaging.Filters |
|||
{ |
|||
#region Using
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Drawing; |
|||
using System.Drawing.Imaging; |
|||
#endregion
|
|||
|
|||
/// <summary>
|
|||
/// Encapsulates methods with which to add a low saturated filter to an image.
|
|||
/// </summary>
|
|||
class LoSatchMatrixFilter : IMatrixFilter |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the <see cref="T:System.Drawing.Imaging.ColoMatrix"/> for this filter instance.
|
|||
/// </summary>
|
|||
public ColorMatrix Matrix |
|||
{ |
|||
get { return ColorMatrixes.LoSatch; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Processes the image.
|
|||
/// </summary>
|
|||
/// <param name="factory">
|
|||
/// The 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 Image ProcessImage(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); |
|||
} |
|||
} |
|||
|
|||
// Reassign the image.
|
|||
image.Dispose(); |
|||
image = newImage; |
|||
|
|||
return image; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,70 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="LomographMatrixFilter.cs" company="James South">
|
|||
// TODO: Update copyright text.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Imaging.Filters |
|||
{ |
|||
#region Using
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Drawing; |
|||
using System.Drawing.Imaging; |
|||
using ImageProcessor.Processors; |
|||
#endregion
|
|||
|
|||
/// <summary>
|
|||
/// Encapsulates methods with which to add a lomograph filter to an image.
|
|||
/// </summary>
|
|||
class LomographMatrixFilter : IMatrixFilter |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the <see cref="T:System.Drawing.Imaging.ColoMatrix"/> for this filter instance.
|
|||
/// </summary>
|
|||
public ColorMatrix Matrix |
|||
{ |
|||
get { return ColorMatrixes.Lomograph; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Processes the image.
|
|||
/// </summary>
|
|||
/// <param name="factory">
|
|||
/// The 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 Image ProcessImage(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 vignette to finish the effect.
|
|||
factory.Image = newImage; |
|||
Vignette vignette = new Vignette(); |
|||
newImage = (Bitmap)vignette.ProcessImage(factory); |
|||
|
|||
// Reassign the image.
|
|||
image.Dispose(); |
|||
image = newImage; |
|||
|
|||
return image; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,99 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="PolaroidMatrixFilter.cs" company="James South">
|
|||
// TODO: Update copyright text.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Imaging.Filters |
|||
{ |
|||
#region Using
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Drawing; |
|||
using System.Drawing.Imaging; |
|||
using ImageProcessor.Processors; |
|||
using System.Drawing.Drawing2D; |
|||
#endregion
|
|||
|
|||
/// <summary>
|
|||
/// Encapsulates methods with which to add a polaroid filter to an image.
|
|||
/// </summary>
|
|||
class PolaroidMatrixFilter : IMatrixFilter |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the <see cref="T:System.Drawing.Imaging.ColoMatrix"/> for this filter instance.
|
|||
/// </summary>
|
|||
public ColorMatrix Matrix |
|||
{ |
|||
get { return ColorMatrixes.Polaroid; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Processes the image.
|
|||
/// </summary>
|
|||
/// <param name="factory">
|
|||
/// The 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 Image ProcessImage(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[] { Color.FromArgb(0, 0, 0, 0) }; |
|||
|
|||
Blend blend = new Blend |
|||
{ |
|||
Positions = new float[] { 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0F }, |
|||
Factors = new float[] { 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 = (Bitmap)vignette.ProcessImage(factory); |
|||
|
|||
// Reassign the image.
|
|||
image.Dispose(); |
|||
image = newImage; |
|||
|
|||
return image; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,64 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="SepiaMatrixFilter.cs" company="James South">
|
|||
// TODO: Update copyright text.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Imaging.Filters |
|||
{ |
|||
#region Using
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Linq; |
|||
using System.Text; |
|||
using System.Drawing; |
|||
using System.Drawing.Imaging; |
|||
#endregion
|
|||
|
|||
/// <summary>
|
|||
/// Encapsulates methods with which to add a sepia filter to an image.
|
|||
/// </summary>
|
|||
class SepiaMatrixFilter : IMatrixFilter |
|||
{ |
|||
/// <summary>
|
|||
/// Gets the <see cref="T:System.Drawing.Imaging.ColoMatrix"/> for this filter instance.
|
|||
/// </summary>
|
|||
public ColorMatrix Matrix |
|||
{ |
|||
get { return ColorMatrixes.Sepia; } |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Processes the image.
|
|||
/// </summary>
|
|||
/// <param name="factory">
|
|||
/// The 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 Image ProcessImage(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); |
|||
} |
|||
} |
|||
|
|||
// Reassign the image.
|
|||
image.Dispose(); |
|||
image = newImage; |
|||
|
|||
return image; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,610 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="Filter.cs" company="James South">
|
|||
// TODO: Update copyright text.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Processors |
|||
{ |
|||
#region Using
|
|||
|
|||
using System; |
|||
using System.Collections.Generic; |
|||
using System.Drawing; |
|||
using System.Drawing.Drawing2D; |
|||
using System.Drawing.Imaging; |
|||
using System.IO; |
|||
using System.Text.RegularExpressions; |
|||
using System.Web; |
|||
using System.Web.Hosting; |
|||
|
|||
#endregion
|
|||
|
|||
/// <summary>
|
|||
/// Encapsulates methods with which to add filters to an image.
|
|||
/// </summary>
|
|||
public class Filter : IGraphicsProcessor |
|||
{ |
|||
/// <summary>
|
|||
/// The regular expression to search strings for.
|
|||
/// </summary>
|
|||
private static readonly Regex QueryRegex = new Regex(@"filter=(lomograph|polaroid|blackwhite|sepia|greyscale|gotham|invert|hisatch|losatch|comic)", RegexOptions.Compiled); |
|||
|
|||
/// <summary>
|
|||
/// Enumurates Argb colour channels.
|
|||
/// </summary>
|
|||
private enum ChannelArgb |
|||
{ |
|||
/// <summary>
|
|||
/// The blue channel
|
|||
/// </summary>
|
|||
Blue = 0, |
|||
|
|||
/// <summary>
|
|||
/// The green channel
|
|||
/// </summary>
|
|||
Green = 1, |
|||
|
|||
/// <summary>
|
|||
/// The red channel
|
|||
/// </summary>
|
|||
Red = 2, |
|||
|
|||
/// <summary>
|
|||
/// The alpha channel
|
|||
/// </summary>
|
|||
Alpha = 3 |
|||
} |
|||
|
|||
#region IGraphicsProcessor Members
|
|||
/// <summary>
|
|||
/// Gets the name.
|
|||
/// </summary>
|
|||
public string Name |
|||
{ |
|||
get |
|||
{ |
|||
return "Filter"; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the description.
|
|||
/// </summary>
|
|||
public string Description |
|||
{ |
|||
get |
|||
{ |
|||
return "Encapsulates methods with which to add filters to an image. e.g polaroid, lomograph"; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the regular expression to search strings for.
|
|||
/// </summary>
|
|||
public Regex RegexPattern |
|||
{ |
|||
get |
|||
{ |
|||
return QueryRegex; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets DynamicParameter.
|
|||
/// </summary>
|
|||
public dynamic DynamicParameter |
|||
{ |
|||
get; |
|||
set; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the order in which this processor is to be used in a chain.
|
|||
/// </summary>
|
|||
public int SortOrder |
|||
{ |
|||
get; |
|||
private set; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets any additional settings required by the processor.
|
|||
/// </summary>
|
|||
public Dictionary<string, string> Settings |
|||
{ |
|||
get; |
|||
set; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// The position in the original string where the first character of the captured substring was found.
|
|||
/// </summary>
|
|||
/// <param name="queryString">
|
|||
/// The query string to search.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// The zero-based starting position in the original string where the captured substring was found.
|
|||
/// </returns>
|
|||
public int MatchRegexIndex(string queryString) |
|||
{ |
|||
int index = 0; |
|||
|
|||
// Set the sort order to max to allow filtering.
|
|||
this.SortOrder = int.MaxValue; |
|||
|
|||
foreach (Match match in this.RegexPattern.Matches(queryString)) |
|||
{ |
|||
if (match.Success) |
|||
{ |
|||
if (index == 0) |
|||
{ |
|||
// Set the index on the first instance only.
|
|||
this.SortOrder = match.Index; |
|||
this.DynamicParameter = match.Value.Split('=')[1]; |
|||
} |
|||
|
|||
index += 1; |
|||
} |
|||
} |
|||
|
|||
return this.SortOrder; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Processes the image.
|
|||
/// </summary>
|
|||
/// <param name="factory">
|
|||
/// The the current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class containing
|
|||
/// the image to process.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// The processed image from the current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class.
|
|||
/// </returns>
|
|||
public Image ProcessImage(ImageFactory factory) |
|||
{ |
|||
Bitmap newImage = null; |
|||
Image image = factory.Image; |
|||
|
|||
// Bitmaps for comic pattern
|
|||
Bitmap hisatchBitmap = null; |
|||
Bitmap patternBitmap = null; |
|||
|
|||
try |
|||
{ |
|||
// Dont use an object initializer here.
|
|||
newImage = new Bitmap(image.Width, image.Height, PixelFormat.Format32bppPArgb); |
|||
newImage.Tag = image.Tag; |
|||
|
|||
ColorMatrix colorMatrix = null; |
|||
|
|||
switch ((string)this.DynamicParameter) |
|||
{ |
|||
case "polaroid": |
|||
colorMatrix = ColorMatrixes.Polaroid; |
|||
break; |
|||
case "lomograph": |
|||
colorMatrix = ColorMatrixes.Lomograph; |
|||
break; |
|||
case "sepia": |
|||
colorMatrix = ColorMatrixes.Sepia; |
|||
break; |
|||
case "blackwhite": |
|||
colorMatrix = ColorMatrixes.BlackWhite; |
|||
break; |
|||
case "greyscale": |
|||
colorMatrix = ColorMatrixes.GreyScale; |
|||
break; |
|||
case "gotham": |
|||
colorMatrix = ColorMatrixes.Gotham; |
|||
break; |
|||
case "invert": |
|||
colorMatrix = ColorMatrixes.Invert; |
|||
break; |
|||
case "hisatch": |
|||
colorMatrix = ColorMatrixes.HiSatch; |
|||
break; |
|||
case "losatch": |
|||
colorMatrix = ColorMatrixes.LoSatch; |
|||
break; |
|||
case "comic": |
|||
colorMatrix = ColorMatrixes.LoSatch; |
|||
break; |
|||
} |
|||
|
|||
using (Graphics graphics = Graphics.FromImage(newImage)) |
|||
{ |
|||
using (ImageAttributes attributes = new ImageAttributes()) |
|||
{ |
|||
if (colorMatrix != null) |
|||
{ |
|||
attributes.SetColorMatrix(colorMatrix); |
|||
} |
|||
|
|||
Rectangle rectangle = new Rectangle(0, 0, image.Width, image.Height); |
|||
|
|||
if (this.DynamicParameter == "comic") |
|||
{ |
|||
// Set the attributes to LoSatch and draw the image.
|
|||
graphics.DrawImage(image, rectangle, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes); |
|||
|
|||
// Create a bitmap for overlaying.
|
|||
hisatchBitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppPArgb); |
|||
|
|||
// Set the color matrix
|
|||
attributes.SetColorMatrix(ColorMatrixes.HiSatch); |
|||
|
|||
// Draw the image with the hisatch colormatrix.
|
|||
using (var g = Graphics.FromImage(hisatchBitmap)) |
|||
{ |
|||
g.DrawImage(image, rectangle, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes); |
|||
} |
|||
|
|||
// We need to create a new image now with the hi saturation colormatrix and a pattern mask to paint it
|
|||
// onto the other image with.
|
|||
patternBitmap = new Bitmap(rectangle.Width, rectangle.Height, PixelFormat.Format32bppPArgb); |
|||
|
|||
// Create the pattern mask.
|
|||
using (var g = Graphics.FromImage(patternBitmap)) |
|||
{ |
|||
g.Clear(Color.Black); |
|||
g.SmoothingMode = SmoothingMode.HighQuality; |
|||
for (var y = 0; y < image.Height; y += 10) |
|||
{ |
|||
for (var x = 0; x < image.Width; x += 6) |
|||
{ |
|||
g.FillEllipse(Brushes.White, x, y, 4, 4); |
|||
g.FillEllipse(Brushes.White, x + 3, y + 5, 4, 4); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Transfer the alpha channel from the mask to the hi sturation image.
|
|||
TransferOneArgbChannelFromOneBitmapToAnother(patternBitmap, hisatchBitmap, ChannelArgb.Blue, ChannelArgb.Alpha); |
|||
|
|||
// Overlay the image.
|
|||
graphics.DrawImage(hisatchBitmap, 0, 0); |
|||
|
|||
// Dispose of the other images
|
|||
hisatchBitmap.Dispose(); |
|||
patternBitmap.Dispose(); |
|||
} |
|||
else |
|||
{ |
|||
graphics.DrawImage(image, rectangle, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes); |
|||
|
|||
// Polaroid requires an extra tweak.
|
|||
if (this.DynamicParameter == "polaroid") |
|||
{ |
|||
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[] { Color.FromArgb(0, 0, 0, 0) }; |
|||
|
|||
Blend blend = new Blend |
|||
{ |
|||
Positions = new float[] { 0.0f, 0.2f, 0.4f, 0.6f, 0.8f, 1.0F }, |
|||
Factors = new float[] { 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; |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Gotham requires an extra tweak.
|
|||
if (this.DynamicParameter == "gotham") |
|||
{ |
|||
using (GraphicsPath path = new GraphicsPath()) |
|||
{ |
|||
path.AddRectangle(rectangle); |
|||
|
|||
// Paint a burgundy rectangle with a transparency of ~30% over the image.
|
|||
// Paint a blue rectangle with a transparency of 20% over the image.
|
|||
using (SolidBrush brush = new SolidBrush(Color.FromArgb(77, 43, 4, 18))) |
|||
{ |
|||
Region oldClip = graphics.Clip; |
|||
graphics.Clip = new Region(rectangle); |
|||
graphics.FillRectangle(brush, rectangle); |
|||
|
|||
// Fill the blue.
|
|||
brush.Color = Color.FromArgb(51, 12, 22, 88); |
|||
graphics.FillRectangle(brush, rectangle); |
|||
graphics.Clip = oldClip; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
// Add a vignette to finish the effect.
|
|||
// TODO: This feels a bit mucky so I might chop it out.
|
|||
if (this.DynamicParameter == "polaroid" || this.DynamicParameter == "lomograph") |
|||
{ |
|||
factory.Image = newImage; |
|||
Vignette vignette = new Vignette(); |
|||
newImage = (Bitmap)vignette.ProcessImage(factory); |
|||
} |
|||
|
|||
// Reassign the image.
|
|||
image.Dispose(); |
|||
image = newImage; |
|||
} |
|||
catch |
|||
{ |
|||
if (newImage != null) |
|||
{ |
|||
newImage.Dispose(); |
|||
} |
|||
|
|||
if (hisatchBitmap != null) |
|||
{ |
|||
hisatchBitmap.Dispose(); |
|||
} |
|||
|
|||
if (patternBitmap != null) |
|||
{ |
|||
patternBitmap.Dispose(); |
|||
} |
|||
} |
|||
|
|||
return image; |
|||
} |
|||
#endregion
|
|||
|
|||
/// <summary>
|
|||
/// Transfers a single ARGB channel from one image to another.
|
|||
/// </summary>
|
|||
/// <param name="source">
|
|||
/// The source.
|
|||
/// </param>
|
|||
/// <param name="destination">
|
|||
/// The destination.
|
|||
/// </param>
|
|||
/// <param name="sourceChannel">
|
|||
/// The source channel.
|
|||
/// </param>
|
|||
/// <param name="destinationChannel">
|
|||
/// The destination channel.
|
|||
/// </param>
|
|||
private static void TransferOneArgbChannelFromOneBitmapToAnother(Bitmap source, Bitmap destination, ChannelArgb sourceChannel, ChannelArgb destinationChannel) |
|||
{ |
|||
if (source.Size != destination.Size) |
|||
{ |
|||
throw new ArgumentException(); |
|||
} |
|||
|
|||
Rectangle rectangle = new Rectangle(Point.Empty, source.Size); |
|||
|
|||
// Lockbits the source.
|
|||
BitmapData bitmapDataSource = source.LockBits(rectangle, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); |
|||
|
|||
// Declare an array to hold the bytes of the bitmap.
|
|||
int bytes = bitmapDataSource.Stride * bitmapDataSource.Height; |
|||
|
|||
// Allocate a buffer for the source image
|
|||
byte[] sourceRgbValues = new byte[bytes]; |
|||
|
|||
// Copy the RGB values into the array.
|
|||
System.Runtime.InteropServices.Marshal.Copy(bitmapDataSource.Scan0, sourceRgbValues, 0, bytes); |
|||
|
|||
// Unlockbits the source.
|
|||
source.UnlockBits(bitmapDataSource); |
|||
|
|||
// Lockbits the destination.
|
|||
BitmapData bitmapDataDestination = destination.LockBits(rectangle, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb); |
|||
|
|||
// Allocate a buffer for image
|
|||
byte[] destinationRgbValues = new byte[bytes]; |
|||
|
|||
// Copy the RGB values into the array.
|
|||
System.Runtime.InteropServices.Marshal.Copy(bitmapDataDestination.Scan0, destinationRgbValues, 0, bytes); |
|||
|
|||
int s = (int)sourceChannel; |
|||
int d = (int)destinationChannel; |
|||
|
|||
for (int i = rectangle.Height * rectangle.Width; i > 0; i--) |
|||
{ |
|||
destinationRgbValues[d] = sourceRgbValues[s]; |
|||
d += 4; |
|||
s += 4; |
|||
} |
|||
|
|||
// Copy the RGB values back to the bitmap
|
|||
System.Runtime.InteropServices.Marshal.Copy(destinationRgbValues, 0, bitmapDataDestination.Scan0, bytes); |
|||
|
|||
// Unlock bits the destination.
|
|||
destination.UnlockBits(bitmapDataDestination); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// A list of available color matrices to apply to an image.
|
|||
/// </summary>
|
|||
private static class ColorMatrixes |
|||
{ |
|||
/// <summary>
|
|||
/// Gets Sepia.
|
|||
/// </summary>
|
|||
internal static ColorMatrix Sepia |
|||
{ |
|||
get |
|||
{ |
|||
return new ColorMatrix( |
|||
new float[][] |
|||
{ |
|||
new float[] { .393f, .349f, .272f, 0, 0 }, |
|||
new float[] { .769f, .686f, .534f, 0, 0 }, |
|||
new float[] { .189f, .168f, .131f, 0, 0 }, |
|||
new float[] { 0, 0, 0, 1, 0 }, |
|||
new float[] { 0, 0, 0, 0, 1 } |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets BlackWhite.
|
|||
/// </summary>
|
|||
internal static ColorMatrix BlackWhite |
|||
{ |
|||
get |
|||
{ |
|||
return new ColorMatrix( |
|||
new float[][] |
|||
{ |
|||
new float[] { 1.5f, 1.5f, 1.5f, 0, 0 }, |
|||
new float[] { 1.5f, 1.5f, 1.5f, 0, 0 }, |
|||
new float[] { 1.5f, 1.5f, 1.5f, 0, 0 }, |
|||
new float[] { 0, 0, 0, 1, 0 }, |
|||
new float[] { -1, -1, -1, 0, 1 } |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets Polaroid.
|
|||
/// </summary>
|
|||
internal static ColorMatrix Polaroid |
|||
{ |
|||
get |
|||
{ |
|||
return new ColorMatrix( |
|||
new float[][] |
|||
{ |
|||
new float[] { 1.638f, -0.062f, -0.262f, 0, 0 }, |
|||
new float[] { -0.122f, 1.378f, -0.122f, 0, 0 }, |
|||
new float[] { 1.016f, -0.016f, 1.383f, 0, 0 }, |
|||
new float[] { 0, 0, 0, 1, 0 }, |
|||
new float[] { 0.06f, -0.05f, -0.05f, 0, 1 } |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets Lomograph.
|
|||
/// </summary>
|
|||
internal static ColorMatrix Lomograph |
|||
{ |
|||
get |
|||
{ |
|||
return new ColorMatrix( |
|||
new float[][] |
|||
{ |
|||
new float[] { 1.50f, 0, 0, 0, 0 }, |
|||
new float[] { 0, 1.45f, 0, 0, 0 }, |
|||
new float[] { 0, 0, 1.09f, 0, 0 }, |
|||
new float[] { 0, 0, 0, 1, 0 }, |
|||
new float[] { -0.10f, 0.05f, -0.08f, 0, 1 } |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets GreyScale.
|
|||
/// </summary>
|
|||
internal static ColorMatrix GreyScale |
|||
{ |
|||
get |
|||
{ |
|||
return new ColorMatrix( |
|||
new float[][] |
|||
{ |
|||
new float[] { .33f, .33f, .33f, 0, 0 }, |
|||
new float[] { .59f, .59f, .59f, 0, 0 }, |
|||
new float[] { .11f, .11f, .11f, 0, 0 }, |
|||
new float[] { 0, 0, 0, 1, 0 }, |
|||
new float[] { 0, 0, 0, 0, 1 } |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets Gotham.
|
|||
/// </summary>
|
|||
internal static ColorMatrix Gotham |
|||
{ |
|||
get |
|||
{ |
|||
return new ColorMatrix( |
|||
new float[][] |
|||
{ |
|||
new float[] { .9f, .9f, .9f, 0, 0 }, |
|||
new float[] { .9f, .9f, .9f, 0, 0 }, |
|||
new float[] { .9f, .9f, .9f, 0, 0 }, |
|||
new float[] { 0, 0, 0, 1, 0 }, |
|||
new float[] { -.5f, -.5f, -.45f, 0, 1 } |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets Invert.
|
|||
/// </summary>
|
|||
internal static ColorMatrix Invert |
|||
{ |
|||
get |
|||
{ |
|||
return new ColorMatrix( |
|||
new float[][] |
|||
{ |
|||
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 float[] { 1, 1, 1, 0, 1 } |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets HiSatch.
|
|||
/// </summary>
|
|||
internal static ColorMatrix HiSatch |
|||
{ |
|||
get |
|||
{ |
|||
return new ColorMatrix( |
|||
new float[][] |
|||
{ |
|||
new float[] { 3, -1, -1, 0, 0 }, |
|||
new float[] { -1, 3, -1, 0, 0 }, |
|||
new float[] { -1, -1, 3, 0, 0 }, |
|||
new float[] { 0, 0, 0, 1, 0 }, |
|||
new float[] { 0, 0, 0, 0, 1 } |
|||
}); |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets LoSatch.
|
|||
/// </summary>
|
|||
internal static ColorMatrix LoSatch |
|||
{ |
|||
get |
|||
{ |
|||
return new ColorMatrix( |
|||
new float[][] |
|||
{ |
|||
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 float[] { .25f, .25f, .25f, 0, 1 } |
|||
}); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,282 @@ |
|||
// -----------------------------------------------------------------------
|
|||
// <copyright file="Rotate.cs" company="James South">
|
|||
// TODO: Update copyright text.
|
|||
// </copyright>
|
|||
// -----------------------------------------------------------------------
|
|||
|
|||
namespace ImageProcessor.Processors |
|||
{ |
|||
#region Using
|
|||
using System.Collections.Generic; |
|||
using System.Drawing; |
|||
using System.Drawing.Imaging; |
|||
using System.Text.RegularExpressions; |
|||
using ImageProcessor.Helpers.Extensions; |
|||
using System; |
|||
using System.Drawing.Drawing2D; |
|||
#endregion
|
|||
|
|||
/// <summary>
|
|||
/// Encapsulates methods to rotate an image.
|
|||
/// </summary>
|
|||
public class Rotate : IGraphicsProcessor |
|||
{ |
|||
/// <summary>
|
|||
/// The regular expression to search strings for.
|
|||
/// </summary>
|
|||
//private static readonly Regex QueryRegex = new Regex(@"rotate=-*([1-9][0-7][0-9]|\d{1,2}(?!\d)|180)|rotate=[^&]*", RegexOptions.Compiled);
|
|||
private static readonly Regex QueryRegex = new Regex(@"rotate=-*([1-2][0-9][0-9]|3[0-5][0-9]|\d{1}(?!\d)|\d{1,2}(?!\d)|360)|rotate=[^&]*", RegexOptions.Compiled); |
|||
|
|||
/// <summary>
|
|||
/// The regular expression to search strings for the angle attribute.
|
|||
/// </summary>
|
|||
private static readonly Regex AngleRegex = new Regex(@"rotate=\[-*([1-9][0-7][0-9]|\d{1,2}(?!\d)|180)\]", RegexOptions.Compiled); |
|||
|
|||
/// <summary>
|
|||
/// The regular expression to search strings for the color attribute.
|
|||
/// </summary>
|
|||
private static readonly Regex ColorRegex = new Regex(@"bgcolor-([0-9a-fA-F]{3}){1,2}", RegexOptions.Compiled); |
|||
|
|||
/// <summary>
|
|||
/// The format of the image to rotate.
|
|||
/// </summary>
|
|||
private ImageFormat imageFormat; |
|||
|
|||
#region IGraphicsProcessor Members
|
|||
/// <summary>
|
|||
/// Gets the name.
|
|||
/// </summary>
|
|||
public string Name |
|||
{ |
|||
get |
|||
{ |
|||
return "Rotate"; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the description.
|
|||
/// </summary>
|
|||
public string Description |
|||
{ |
|||
get |
|||
{ |
|||
return "Rotates an image at the given angle."; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the regular expression to search strings for.
|
|||
/// </summary>
|
|||
public Regex RegexPattern |
|||
{ |
|||
get |
|||
{ |
|||
return QueryRegex; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets DynamicParameter.
|
|||
/// </summary>
|
|||
public dynamic DynamicParameter |
|||
{ |
|||
get; |
|||
set; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the order in which this processor is to be used in a chain.
|
|||
/// </summary>
|
|||
public int SortOrder |
|||
{ |
|||
get; |
|||
private set; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets or sets any additional settings required by the processor.
|
|||
/// </summary>
|
|||
public Dictionary<string, string> Settings |
|||
{ |
|||
get; |
|||
set; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// The position in the original string where the first character of the captured substring was found.
|
|||
/// </summary>
|
|||
/// <param name="queryString">
|
|||
/// The query string to search.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// The zero-based starting position in the original string where the captured substring was found.
|
|||
/// </returns>
|
|||
public int MatchRegexIndex(string queryString) |
|||
{ |
|||
int index = 0; |
|||
|
|||
// Set the sort order to max to allow filtering.
|
|||
this.SortOrder = int.MaxValue; |
|||
|
|||
foreach (Match match in this.RegexPattern.Matches(queryString)) |
|||
{ |
|||
if (match.Success) |
|||
{ |
|||
if (index == 0) |
|||
{ |
|||
// Set the index on the first instance only.
|
|||
this.SortOrder = match.Index; |
|||
int degrees; |
|||
|
|||
int.TryParse(match.Value.Split('=')[1], out degrees); |
|||
|
|||
this.DynamicParameter = degrees; |
|||
} |
|||
|
|||
index += 1; |
|||
} |
|||
} |
|||
|
|||
return this.SortOrder; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Processes the image.
|
|||
/// </summary>
|
|||
/// <param name="factory">
|
|||
/// The the current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class containing
|
|||
/// the image to process.
|
|||
/// </param>
|
|||
/// <returns>
|
|||
/// The processed image from the current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class.
|
|||
/// </returns>
|
|||
public Image ProcessImage(ImageFactory factory) |
|||
{ |
|||
Bitmap newImage = null; |
|||
Image image = factory.Image; |
|||
|
|||
try |
|||
{ |
|||
int angle = this.DynamicParameter; |
|||
|
|||
// Center of the image
|
|||
float rotateAtX = image.Width / 2; |
|||
float rotateAtY = image.Height / 2; |
|||
|
|||
this.imageFormat = factory.ImageFormat; |
|||
|
|||
// Create a rotated image.
|
|||
newImage = RotateImage(image, rotateAtX, rotateAtY, angle); |
|||
newImage.Tag = image.Tag; |
|||
|
|||
image.Dispose(); |
|||
image = newImage; |
|||
|
|||
} |
|||
catch |
|||
{ |
|||
if (newImage != null) |
|||
{ |
|||
newImage.Dispose(); |
|||
} |
|||
} |
|||
|
|||
return image; |
|||
} |
|||
#endregion
|
|||
|
|||
/// <summary>
|
|||
///
|
|||
/// </summary>
|
|||
/// <param name="image"></param>
|
|||
/// <param name="rotateAtX"></param>
|
|||
/// <param name="rotateAtY"></param>
|
|||
/// <param name="angle"></param>
|
|||
/// <returns></returns>
|
|||
/// <remarks> Based on http://www.codeproject.com/Articles/58815/C-Image-PictureBox-Rotations?msg=4155374#xx4155374xx</remarks>
|
|||
private Bitmap RotateImage(Image image, float rotateAtX, float rotateAtY, float angle) |
|||
{ |
|||
int width, height, X, Y; |
|||
|
|||
// Degrees to radians according to Google.
|
|||
const double degreeToRadian = 0.0174532925; |
|||
|
|||
double widthAsDouble = (double)image.Width; |
|||
double heightAsDouble = (double)image.Height; |
|||
|
|||
// Allow for angles over 180
|
|||
if (angle > 180) |
|||
{ |
|||
angle = angle - 360; |
|||
} |
|||
|
|||
double degrees = Math.Abs(angle); |
|||
|
|||
if (degrees <= 90) |
|||
{ |
|||
double radians = degreeToRadian * degrees; |
|||
double radiansSin = Math.Sin(radians); |
|||
double radiansCos = Math.Cos(radians); |
|||
width = (int)(heightAsDouble * radiansSin + widthAsDouble * radiansCos); |
|||
height = (int)(widthAsDouble * radiansSin + heightAsDouble * radiansCos); |
|||
X = (width - image.Width) / 2; |
|||
Y = (height - image.Height) / 2; |
|||
} |
|||
else |
|||
{ |
|||
degrees -= 90; |
|||
double radians = degreeToRadian * degrees; |
|||
double radiansSin = Math.Sin(radians); |
|||
double radiansCos = Math.Cos(radians); |
|||
|
|||
// Fix the 270 bug
|
|||
if (radiansCos == -1) |
|||
{ |
|||
radiansCos = -1 * -1; |
|||
} |
|||
|
|||
width = (int)(widthAsDouble * radiansSin + heightAsDouble * radiansCos); |
|||
height = (int)(heightAsDouble * radiansSin + widthAsDouble * radiansCos); |
|||
X = (width - image.Width) / 2; |
|||
Y = (height - image.Height) / 2; |
|||
} |
|||
|
|||
//create a new empty bitmap to hold rotated image
|
|||
Bitmap newImage = new Bitmap(width, height); |
|||
newImage.SetResolution(image.HorizontalResolution, image.VerticalResolution); |
|||
|
|||
//make a graphics object from the empty bitmap
|
|||
using (Graphics graphics = Graphics.FromImage(newImage)) |
|||
{ |
|||
// Reduce the jagged edge.
|
|||
graphics.SmoothingMode = SmoothingMode.HighQuality; |
|||
|
|||
// Contrary to everything I have read bicubic is producing the best results.
|
|||
graphics.InterpolationMode = InterpolationMode.HighQualityBicubic; |
|||
graphics.PixelOffsetMode = PixelOffsetMode.HighQuality; |
|||
graphics.CompositingQuality = CompositingQuality.HighSpeed; |
|||
|
|||
// Fill the background TODO: Set a color
|
|||
if (this.imageFormat == ImageFormat.Jpeg) |
|||
{ |
|||
graphics.Clear(Color.White); |
|||
} |
|||
|
|||
// Put the rotation point in the "center" of the image
|
|||
graphics.TranslateTransform(rotateAtX + X, rotateAtY + Y); |
|||
|
|||
// Rotate the image
|
|||
graphics.RotateTransform(angle); |
|||
|
|||
// Move the image back
|
|||
graphics.TranslateTransform(-rotateAtX - X, -rotateAtY - Y); |
|||
|
|||
// Draw passed in image onto graphics object
|
|||
graphics.DrawImage(image, new PointF(0 + X, 0 + Y)); |
|||
|
|||
} |
|||
return newImage; |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue