diff --git a/src/ImageProcessor.Playground/Program.cs b/src/ImageProcessor.Playground/Program.cs
index 937909347..361cf8aab 100644
--- a/src/ImageProcessor.Playground/Program.cs
+++ b/src/ImageProcessor.Playground/Program.cs
@@ -108,7 +108,7 @@ namespace ImageProcessor.PlayGround
//.DetectEdges(new Laplacian3X3EdgeFilter(), true)
//.DetectEdges(new LaplacianOfGaussianEdgeFilter())
//.EntropyCrop()
- .Halftone()
+ .Halftone(true)
//.Filter(MatrixFilters.Invert)
//.Contrast(50)
//.Filter(MatrixFilters.Comic)
diff --git a/src/ImageProcessor/ImageFactory.cs b/src/ImageProcessor/ImageFactory.cs
index 0d07129e3..2950ad195 100644
--- a/src/ImageProcessor/ImageFactory.cs
+++ b/src/ImageProcessor/ImageFactory.cs
@@ -681,11 +681,20 @@ namespace ImageProcessor
return this;
}
- public ImageFactory Halftone()
+ ///
+ /// Converts the current image to a CMYK halftone representation of that image.
+ ///
+ ///
+ /// Whether to trace over the current image and add borders to add a comic book effect.
+ ///
+ ///
+ /// The current instance of the class.
+ ///
+ public ImageFactory Halftone(bool comicMode = false)
{
if (this.ShouldProcess)
{
- Halftone halftone = new Halftone();
+ Halftone halftone = new Halftone { DynamicParameter = comicMode };
this.CurrentImageFormat.ApplyProcessor(halftone.ProcessImage, this);
}
diff --git a/src/ImageProcessor/Imaging/Filters/Artistic/HalftoneFilter.cs b/src/ImageProcessor/Imaging/Filters/Artistic/HalftoneFilter.cs
index 43669cec1..a6b8cc7a1 100644
--- a/src/ImageProcessor/Imaging/Filters/Artistic/HalftoneFilter.cs
+++ b/src/ImageProcessor/Imaging/Filters/Artistic/HalftoneFilter.cs
@@ -37,6 +37,7 @@ namespace ImageProcessor.Imaging.Filters.Artistic
///
/// The angle of the yellow component in degrees.
///
+ // ReSharper disable once RedundantDefaultMemberInitializer
private float yellowAngle = 0f;
///
@@ -184,7 +185,7 @@ namespace ImageProcessor.Imaging.Filters.Artistic
float max = this.distance;
// Bump up the keyline max so that black looks black.
- float keylineMax = max + ((float)Math.Sqrt(2) * 1.5f);
+ float keylineMax = max + ((float)Math.Sqrt(2) * 1.44f);
// Color sampled process colours from Wikipedia pages.
// Keyline brush is declared separately.
@@ -239,9 +240,11 @@ namespace ImageProcessor.Imaging.Filters.Artistic
Color color;
CmykColor cmykColor;
float brushWidth;
+ int offsetX = x - (d >> 1);
+ int offsetY = y - (d >> 1);
// Cyan
- Point rotatedPoint = ImageMaths.RotatePoint(new Point(x, y), this.cyanAngle, center);
+ Point rotatedPoint = ImageMaths.RotatePoint(new Point(offsetX, offsetY), this.cyanAngle, center);
int angledX = rotatedPoint.X;
int angledY = rotatedPoint.Y;
if (rectangle.Contains(new Point(angledX, angledY)))
@@ -253,7 +256,7 @@ namespace ImageProcessor.Imaging.Filters.Artistic
}
// Magenta
- rotatedPoint = ImageMaths.RotatePoint(new Point(x, y), this.magentaAngle, center);
+ rotatedPoint = ImageMaths.RotatePoint(new Point(offsetX, offsetY), this.magentaAngle, center);
angledX = rotatedPoint.X;
angledY = rotatedPoint.Y;
if (rectangle.Contains(new Point(angledX, angledY)))
@@ -265,7 +268,7 @@ namespace ImageProcessor.Imaging.Filters.Artistic
}
// Yellow
- rotatedPoint = ImageMaths.RotatePoint(new Point(x, y), this.yellowAngle, center);
+ rotatedPoint = ImageMaths.RotatePoint(new Point(offsetX, offsetY), this.yellowAngle, center);
angledX = rotatedPoint.X;
angledY = rotatedPoint.Y;
if (rectangle.Contains(new Point(angledX, angledY)))
@@ -277,7 +280,7 @@ namespace ImageProcessor.Imaging.Filters.Artistic
}
// Keyline
- rotatedPoint = ImageMaths.RotatePoint(new Point(x, y), this.keylineAngle, center);
+ rotatedPoint = ImageMaths.RotatePoint(new Point(offsetX, offsetY), this.keylineAngle, center);
angledX = rotatedPoint.X;
angledY = rotatedPoint.Y;
if (rectangle.Contains(new Point(angledX, angledY)))
@@ -321,7 +324,10 @@ namespace ImageProcessor.Imaging.Filters.Artistic
Color keylinePixel = keylineBitmap.GetPixel(x, y);
CmykColor blended = cyanPixel.AddAsCmykColor(magentaPixel, yellowPixel, keylinePixel);
- destinationBitmap.SetPixel(x, y, blended);
+ if (rectangle.Contains(new Point(x, y)))
+ {
+ destinationBitmap.SetPixel(x, y, blended);
+ }
// ReSharper restore AccessToDisposedClosure
}
});
diff --git a/src/ImageProcessor/Processors/Halftone.cs b/src/ImageProcessor/Processors/Halftone.cs
index 1dea5b68c..995f47cbc 100644
--- a/src/ImageProcessor/Processors/Halftone.cs
+++ b/src/ImageProcessor/Processors/Halftone.cs
@@ -13,7 +13,6 @@ namespace ImageProcessor.Processors
using System;
using System.Collections.Generic;
using System.Drawing;
- using System.Drawing.Imaging;
using System.Threading.Tasks;
using ImageProcessor.Common.Exceptions;
@@ -70,43 +69,48 @@ namespace ImageProcessor.Processors
int width = image.Width;
int height = image.Height;
Bitmap newImage = null;
- //Bitmap edgeBitmap = null;
+ Bitmap edgeBitmap = null;
try
{
HalftoneFilter filter = new HalftoneFilter(5);
newImage = new Bitmap(image);
newImage.SetResolution(image.HorizontalResolution, image.VerticalResolution);
newImage = filter.ApplyFilter(newImage);
+ bool comicMode = this.DynamicParameter;
- // Draw the edges.
- //edgeBitmap = new Bitmap(width, height);
- //edgeBitmap.SetResolution(image.HorizontalResolution, image.VerticalResolution);
- //edgeBitmap = Trace(image, edgeBitmap, 120);
-
- using (Graphics graphics = Graphics.FromImage(newImage))
+ if (comicMode)
{
- // Overlay the image.
- //graphics.DrawImage(edgeBitmap, 0, 0);
- Rectangle rectangle = new Rectangle(0, 0, width, height);
-
- // Draw an edge around the image.
- //using (Pen blackPen = new Pen(Color.Black))
- //{
- // blackPen.Width = 4;
- // graphics.DrawRectangle(blackPen, rectangle);
- //}
+ // Draw the edges.
+ edgeBitmap = new Bitmap(width, height);
+ edgeBitmap.SetResolution(image.HorizontalResolution, image.VerticalResolution);
+ edgeBitmap = Trace(image, edgeBitmap, 120);
+
+ using (Graphics graphics = Graphics.FromImage(newImage))
+ {
+ // Overlay the image.
+ graphics.DrawImage(edgeBitmap, 0, 0);
+ Rectangle rectangle = new Rectangle(0, 0, width, height);
+
+ // Draw an edge around the image.
+ using (Pen blackPen = new Pen(Color.Black))
+ {
+ blackPen.Width = 4;
+ graphics.DrawRectangle(blackPen, rectangle);
+ }
+ }
+
+ edgeBitmap.Dispose();
}
- //edgeBitmap.Dispose();
image.Dispose();
image = newImage;
}
catch (Exception ex)
{
- //if (edgeBitmap != null)
- //{
- // edgeBitmap.Dispose();
- //}
+ if (edgeBitmap != null)
+ {
+ edgeBitmap.Dispose();
+ }
if (newImage != null)
{