Browse Source

Mask now accepts position instructions

Former-commit-id: 6cdb65e44c00bed1e3222c8ccdb47c191326a397
Former-commit-id: 39e063291f11b4a85369734826bd6a11d357d53e
af/merge-core
James South 12 years ago
parent
commit
e03125dce3
  1. 15
      src/ImageProcessor.Playground/Program.cs
  2. 3
      src/ImageProcessor.Playground/images/input/mask2.png
  3. 3
      src/ImageProcessor.Playground/images/input/mask3.png
  4. 11
      src/ImageProcessor/ImageFactory.cs
  5. 6
      src/ImageProcessor/Imaging/Filters/Photo/ComicMatrixFilter.cs
  6. 2
      src/ImageProcessor/Imaging/Helpers/Effects.cs
  7. 8
      src/ImageProcessor/Imaging/Helpers/ImageMaths.cs
  8. 77
      src/ImageProcessor/Processors/Mask.cs

15
src/ImageProcessor.Playground/Program.cs

@ -49,8 +49,8 @@ namespace ImageProcessor.PlayGround
di.Create(); di.Create();
} }
Image mask = Image.FromFile(Path.Combine(resolvedPath, "mask.png")); Image mask = Image.FromFile(Path.Combine(resolvedPath, "mask2.png"));
IEnumerable<FileInfo> files = GetFilesByExtensions(di, ".png"); IEnumerable<FileInfo> files = GetFilesByExtensions(di, ".jpg");
//IEnumerable<FileInfo> files = GetFilesByExtensions(di, ".gif", ".webp", ".bmp", ".jpg", ".png", ".tif"); //IEnumerable<FileInfo> files = GetFilesByExtensions(di, ".gif", ".webp", ".bmp", ".jpg", ".png", ".tif");
foreach (FileInfo fileInfo in files) foreach (FileInfo fileInfo in files)
@ -66,7 +66,7 @@ namespace ImageProcessor.PlayGround
{ {
using (ImageFactory imageFactory = new ImageFactory(true)) using (ImageFactory imageFactory = new ImageFactory(true))
{ {
Size size = new Size(400, 0); Size size = new Size(800, 0);
ResizeLayer layer = new ResizeLayer(size, ResizeMode.Max, AnchorPosition.Center, false); ResizeLayer layer = new ResizeLayer(size, ResizeMode.Max, AnchorPosition.Center, false);
//ContentAwareResizeLayer layer = new ContentAwareResizeLayer(size) //ContentAwareResizeLayer layer = new ContentAwareResizeLayer(size)
@ -78,16 +78,17 @@ namespace ImageProcessor.PlayGround
//.BackgroundColor(Color.White) //.BackgroundColor(Color.White)
//.Resize(new Size((int)(size.Width * 1.1), 0)) //.Resize(new Size((int)(size.Width * 1.1), 0))
//.ContentAwareResize(layer) //.ContentAwareResize(layer)
//.Constrain(size) .Constrain(size)
//.Mask(mask) .Mask(mask)
//.Format(new PngFormat())
//.BackgroundColor(Color.HotPink) //.BackgroundColor(Color.HotPink)
//.ReplaceColor(Color.FromArgb(255, 1, 107, 165), Color.FromArgb(255, 1, 165, 13), 80) //.ReplaceColor(Color.FromArgb(255, 1, 107, 165), Color.FromArgb(255, 1, 165, 13), 80)
//.Resize(layer) //.Resize(layer)
//.DetectEdges(new SobelEdgeFilter(), false) //.DetectEdges(new SobelEdgeFilter(), false)
//.DetectEdges(new LaplacianOfGaussianEdgeFilter()) //.DetectEdges(new LaplacianOfGaussianEdgeFilter())
.EntropyCrop() //.EntropyCrop()
//.Filter(MatrixFilters.Invert) //.Filter(MatrixFilters.Invert)
//.Filter(MatrixFilters.Comic) .Filter(MatrixFilters.Comic)
//.Filter(MatrixFilters.HiSatch) //.Filter(MatrixFilters.HiSatch)
//.Pixelate(8) //.Pixelate(8)
//.GaussianSharpen(10) //.GaussianSharpen(10)

3
src/ImageProcessor.Playground/images/input/mask2.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d6491cd9ea308fcc3eef561fdc756d6e7f71296a224aebebb6c1d9e33d7b1ea3
size 3620

3
src/ImageProcessor.Playground/images/input/mask3.png

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bed5d8a12117d5675d4e5d7f540b70391b69a19b5103b60ebae55efbf4b411cb
size 2869

11
src/ImageProcessor/ImageFactory.cs

@ -671,20 +671,23 @@ namespace ImageProcessor
} }
/// <summary> /// <summary>
/// Applies the given image mask to the current image. If the mask is not the same size as the image /// Applies the given image mask to the current image.
/// it will be centered against the image.
/// </summary> /// </summary>
/// <param name="imageMask"> /// <param name="imageMask">
/// The image containing the mask to apply. /// The image containing the mask to apply.
/// </param> /// </param>
/// <param name="point">
/// The <see cref="Point"/> to place the mask if it not the same dimensions as the original image.
/// If no position is set, the mask will be centered within the image.
/// </param>
/// <returns> /// <returns>
/// The current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class. /// The current instance of the <see cref="T:ImageProcessor.ImageFactory"/> class.
/// </returns> /// </returns>
public ImageFactory Mask(Image imageMask) public ImageFactory Mask(Image imageMask, Point? point = null)
{ {
if (this.ShouldProcess) if (this.ShouldProcess)
{ {
Mask mask = new Mask { DynamicParameter = imageMask }; Mask mask = new Mask { DynamicParameter = new Tuple<Image, Point?>(imageMask, point) };
this.CurrentImageFormat.ApplyProcessor(mask.ProcessImage, this); this.CurrentImageFormat.ApplyProcessor(mask.ProcessImage, this);
} }

6
src/ImageProcessor/Imaging/Filters/Photo/ComicMatrixFilter.cs

@ -92,12 +92,12 @@ namespace ImageProcessor.Imaging.Filters.Photo
// Create the pattern mask. // Create the pattern mask.
using (Graphics graphics = Graphics.FromImage(patternBitmap)) using (Graphics graphics = Graphics.FromImage(patternBitmap))
{ {
graphics.Clear(Color.Black); graphics.Clear(Color.Transparent);
graphics.SmoothingMode = SmoothingMode.HighQuality; graphics.SmoothingMode = SmoothingMode.HighQuality;
for (int y = 0; y < image.Height; y += 8) for (int y = 0; y < height; y += 8)
{ {
for (int x = 0; x < image.Width; x += 4) for (int x = 0; x < width; x += 4)
{ {
graphics.FillEllipse(Brushes.White, x, y, 3, 3); graphics.FillEllipse(Brushes.White, x, y, 3, 3);
graphics.FillEllipse(Brushes.White, x + 2, y + 4, 3, 3); graphics.FillEllipse(Brushes.White, x + 2, y + 4, 3, 3);

2
src/ImageProcessor/Imaging/Helpers/Effects.cs

@ -155,7 +155,7 @@ namespace ImageProcessor.Imaging.Helpers
if (sourceColor.A != 0) if (sourceColor.A != 0)
{ {
sourceBitmap.SetPixel(x, y, Color.FromArgb(maskColor.B, sourceColor.R, sourceColor.G, sourceColor.B)); sourceBitmap.SetPixel(x, y, Color.FromArgb(maskColor.A, sourceColor.R, sourceColor.G, sourceColor.B));
} }
// ReSharper restore AccessToDisposedClosure // ReSharper restore AccessToDisposedClosure

8
src/ImageProcessor/Imaging/Helpers/ImageMaths.cs

@ -145,10 +145,10 @@ namespace ImageProcessor.Imaging.Helpers
using (FastBitmap fastBitmap = new FastBitmap(bitmap)) using (FastBitmap fastBitmap = new FastBitmap(bitmap))
{ {
topLeft.Y = getMinY(fastBitmap) + 1; topLeft.Y = getMinY(fastBitmap);
topLeft.X = getMinX(fastBitmap) + 1; topLeft.X = getMinX(fastBitmap);
bottomRight.Y = getMaxY(fastBitmap); bottomRight.Y = getMaxY(fastBitmap) + 1;
bottomRight.X = getMaxX(fastBitmap); bottomRight.X = getMaxX(fastBitmap) + 1;
} }
return ImageMaths.GetBoundingRectangle(topLeft, bottomRight); return ImageMaths.GetBoundingRectangle(topLeft, bottomRight);

77
src/ImageProcessor/Processors/Mask.cs

@ -15,6 +15,7 @@ namespace ImageProcessor.Processors
using System.Drawing; using System.Drawing;
using ImageProcessor.Common.Exceptions; using ImageProcessor.Common.Exceptions;
using ImageProcessor.Imaging.Colors;
using ImageProcessor.Imaging.Helpers; using ImageProcessor.Imaging.Helpers;
/// <summary> /// <summary>
@ -63,30 +64,67 @@ namespace ImageProcessor.Processors
{ {
Bitmap newImage = null; Bitmap newImage = null;
Bitmap mask = null; Bitmap mask = null;
Bitmap maskResized = null; Bitmap maskCropped = null;
Bitmap maskPositioned = null;
Image image = factory.Image; Image image = factory.Image;
try try
{ {
int width = image.Width; int width = image.Width;
int height = image.Height; int height = image.Height;
mask = new Bitmap(this.DynamicParameter); Tuple<Image, Point?> parameters = this.DynamicParameter;
Rectangle parent = new Rectangle(0, 0, width, height); mask = new Bitmap(parameters.Item1);
Rectangle child = new Rectangle(0, 0, mask.Width, mask.Height); Point? position = parameters.Item2.HasValue ? parameters.Item2 : null;
RectangleF centered = ImageMaths.CenteredRectangle(parent, child);
if (mask.Size != image.Size)
// Resize the mask to the size of the input image so that we can apply it.
maskResized = new Bitmap(width, height);
using (Graphics graphics = Graphics.FromImage(maskResized))
{ {
graphics.Clear(Color.Transparent); Rectangle parent = new Rectangle(0, 0, width, height);
graphics.DrawImage(mask, new PointF(centered.X, centered.Y)); Rectangle child = ImageMaths.GetFilteredBoundingRectangle(mask, 0, RgbaComponent.A);
} maskCropped = new Bitmap(child.Width, child.Height);
// First crop any bounding transparency.
using (Graphics graphics = Graphics.FromImage(maskCropped))
{
graphics.Clear(Color.Transparent);
graphics.DrawImage(
mask,
new Rectangle(0, 0, child.Width, child.Height),
child.X,
child.Y,
child.Width,
child.Height,
GraphicsUnit.Pixel);
}
newImage = Effects.ApplyMask(image, maskResized); // Now position the mask in an image of the same dimensions as the original.
maskPositioned = new Bitmap(width, height);
using (Graphics graphics = Graphics.FromImage(maskPositioned))
{
graphics.Clear(Color.Transparent);
if (position != null)
{
// Apply the mask at the given position.
graphics.DrawImage(maskCropped, position.Value);
}
else
{
// Center it instead
RectangleF centered = ImageMaths.CenteredRectangle(parent, child);
graphics.DrawImage(maskCropped, new PointF(centered.X, centered.Y));
}
}
newImage = Effects.ApplyMask(image, maskPositioned);
maskCropped.Dispose();
maskPositioned.Dispose();
}
else
{
newImage = Effects.ApplyMask(image, mask);
mask.Dispose();
}
mask.Dispose();
maskResized.Dispose();
image.Dispose(); image.Dispose();
image = newImage; image = newImage;
} }
@ -97,9 +135,14 @@ namespace ImageProcessor.Processors
mask.Dispose(); mask.Dispose();
} }
if (maskResized != null) if (maskCropped != null)
{
maskCropped.Dispose();
}
if (maskPositioned != null)
{ {
maskResized.Dispose(); maskPositioned.Dispose();
} }
if (newImage != null) if (newImage != null)

Loading…
Cancel
Save