diff --git a/src/ImageProcessor/ImageProcessor.csproj b/src/ImageProcessor/ImageProcessor.csproj
index 22ffe9fa39..65709a2e38 100644
--- a/src/ImageProcessor/ImageProcessor.csproj
+++ b/src/ImageProcessor/ImageProcessor.csproj
@@ -22,6 +22,7 @@
prompt
4
bin\Debug\ImageProcessor.XML
+ false
pdbonly
diff --git a/src/ImageProcessor/Processors/Filter.cs b/src/ImageProcessor/Processors/Filter.cs
index b3c0d2756c..88cf22d1a0 100644
--- a/src/ImageProcessor/Processors/Filter.cs
+++ b/src/ImageProcessor/Processors/Filter.cs
@@ -7,10 +7,17 @@
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
///
@@ -21,7 +28,18 @@ namespace ImageProcessor.Processors
///
/// The regular expression to search strings for.
///
- private static readonly Regex QueryRegex = new Regex(@"filter=(lomograph|polaroid|blackwhite|sepia|greyscale)", RegexOptions.Compiled);
+ private static readonly Regex QueryRegex = new Regex(@"filter=(lomograph|polaroid|blackwhite|sepia|greyscale|gotham|invert|hisatch|losatch|comic)", RegexOptions.Compiled);
+
+ ///
+ /// Enumurates Argb colour channels.
+ ///
+ private enum ChannelArgb
+ {
+ Blue = 0,
+ Green = 1,
+ Red = 2,
+ Alpha = 3
+ }
#region IGraphicsProcessor Members
///
@@ -141,7 +159,7 @@ namespace ImageProcessor.Processors
switch ((string)this.DynamicParameter)
{
case "polaroid":
- colorMatrix = ColorMatrixes.Poloroid;
+ colorMatrix = ColorMatrixes.Polaroid;
break;
case "lomograph":
colorMatrix = ColorMatrixes.Lomograph;
@@ -155,6 +173,21 @@ namespace ImageProcessor.Processors
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))
@@ -168,7 +201,110 @@ namespace ImageProcessor.Processors
Rectangle rectangle = new Rectangle(0, 0, image.Width, image.Height);
- graphics.DrawImage(image, rectangle, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, attributes);
+ 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.
+ Bitmap 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.
+ Bitmap 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;
+ }
+ }
+ }
+ }
}
}
@@ -188,6 +324,71 @@ namespace ImageProcessor.Processors
}
#endregion
+ ///
+ /// Transfers a single ARGB channel from one image to another.
+ ///
+ ///
+ /// The source.
+ ///
+ ///
+ /// The destination.
+ ///
+ ///
+ /// The source channel.
+ ///
+ ///
+ /// The destination channel.
+ ///
+ 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);
+ }
+
///
/// A list of available color matrices to apply to an image.
///
@@ -232,20 +433,20 @@ namespace ImageProcessor.Processors
}
///
- /// Gets Poloroid.
+ /// Gets Polaroid.
///
- internal static ColorMatrix Poloroid
+ internal static ColorMatrix Polaroid
{
get
{
return new ColorMatrix(
new float[][]
{
- new float[] { 1.438f, -0.062f, -0.062f, 0, 0 },
+ new float[] { 1.638f, -0.062f, -0.262f, 0, 0 },
new float[] { -0.122f, 1.378f, -0.122f, 0, 0 },
- new float[] { -0.016f, -0.016f, 1.483f, 0, 0 },
+ new float[] { 1.016f, -0.016f, 1.383f, 0, 0 },
new float[] { 0, 0, 0, 1, 0 },
- new float[] { -0.03f, 0.05f, -0.02f, 0, 1 }
+ new float[] { 0.06f, -0.05f, -0.05f, 0, 1 }
});
}
}
@@ -260,11 +461,11 @@ namespace ImageProcessor.Processors
return new ColorMatrix(
new float[][]
{
- new float[] { 1.25f, 0, 0, 0, 0 },
- new float[] { 0, 1.25f, 0, 0, 0 },
- new float[] { 0, 0, 0.94f, 0, 0 },
+ 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, 0, 0, 0, 1 }
+ new float[] { -0.10f, 0.05f, -0.08f, 0, 1 }
});
}
}
@@ -287,6 +488,82 @@ namespace ImageProcessor.Processors
});
}
}
+
+ ///
+ /// Gets Gotham.
+ ///
+ 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 }
+ });
+ }
+ }
+
+ ///
+ /// Gets Invert.
+ ///
+ 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 }
+ });
+ }
+ }
+
+ ///
+ /// Gets HiSatch.
+ ///
+ 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 }
+ });
+ }
+ }
+
+ ///
+ /// Gets LoSatch.
+ ///
+ 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 }
+ });
+ }
+ }
}
}
}
diff --git a/src/Test/Test/Test.csproj b/src/Test/Test/Test.csproj
index 3b61c60faf..ff800dd95b 100644
--- a/src/Test/Test/Test.csproj
+++ b/src/Test/Test/Test.csproj
@@ -122,7 +122,9 @@
-
+
+ Designer
+
Web.config
diff --git a/src/Test/Test/Web.config b/src/Test/Test/Web.config
index b400b2c812..0f037fa209 100644
--- a/src/Test/Test/Web.config
+++ b/src/Test/Test/Web.config
@@ -1,117 +1,117 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+