diff --git a/src/ImageProcessorCore/Filters/Pixelate.cs b/src/ImageProcessorCore/Filters/Pixelate.cs
new file mode 100644
index 000000000..8bfb7cd2d
--- /dev/null
+++ b/src/ImageProcessorCore/Filters/Pixelate.cs
@@ -0,0 +1,64 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageProcessorCore
+{
+ using Processors;
+ using System;
+
+ ///
+ /// Extension methods for the type.
+ ///
+ /// The pixel format.
+ /// The packed format. long, float.
+ public static partial class ImageExtensions
+ {
+ ///
+ /// Pixelates and image with the given pixel size.
+ ///
+ /// The image this method extends.
+ /// The size of the pixels.
+ /// A delegate which is called as progress is made processing the image.
+ /// The .
+ public static Image Pixelate(this Image source, int size = 4, ProgressEventHandler progressHandler = null)
+ where T : IPackedVector
+ where TP : struct
+ {
+ return Pixelate(source, size, source.Bounds, progressHandler);
+ }
+
+ ///
+ /// Pixelates and image with the given pixel size.
+ ///
+ /// The image this method extends.
+ /// The size of the pixels.
+ ///
+ /// The structure that specifies the portion of the image object to alter.
+ ///
+ /// A delegate which is called as progress is made processing the image.
+ /// The .
+ public static Image Pixelate(this Image source, int size, Rectangle rectangle, ProgressEventHandler progressHandler = null)
+ where T : IPackedVector
+ where TP : struct
+ {
+ if (size <= 0 || size > source.Height || size > source.Width)
+ {
+ throw new ArgumentOutOfRangeException(nameof(size));
+ }
+
+ PixelateProcessor processor = new PixelateProcessor(size);
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
+ }
+ }
+}
diff --git a/src/ImageProcessorCore/Filters/Processors/PixelateProcessor.cs b/src/ImageProcessorCore/Filters/Processors/PixelateProcessor.cs
new file mode 100644
index 000000000..816ce2f42
--- /dev/null
+++ b/src/ImageProcessorCore/Filters/Processors/PixelateProcessor.cs
@@ -0,0 +1,97 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageProcessorCore.Processors
+{
+ using System.Collections.Generic;
+ using System.Threading.Tasks;
+
+ ///
+ /// An to invert the colors of an .
+ ///
+ /// The pixel format.
+ /// The packed format. long, float.
+ public class PixelateProcessor : ImageProcessor
+ where T : IPackedVector
+ where TP : struct
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The size of the pixels. Must be greater than 0.
+ ///
+ /// is less than 0 or equal to 0.
+ ///
+ public PixelateProcessor(int size)
+ {
+ Guard.MustBeGreaterThan(size, 0, nameof(size));
+ this.Value = size;
+ }
+
+ ///
+ /// Gets or the pixel size.
+ ///
+ public int Value { get; }
+
+ ///
+ protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
+ {
+ int sourceY = sourceRectangle.Y;
+ int sourceBottom = sourceRectangle.Bottom;
+ int startX = sourceRectangle.X;
+ int endX = sourceRectangle.Right;
+ int size = this.Value;
+ int offset = this.Value / 2;
+
+ // Get the range on the y-plane to choose from.
+ IEnumerable range = EnumerableExtensions.SteppedRange(startY, i => i < endY, size);
+
+ using (IPixelAccessor sourcePixels = source.Lock())
+ using (IPixelAccessor targetPixels = target.Lock())
+ {
+ Parallel.ForEach(
+ range,
+ y =>
+ {
+ if (y >= sourceY && y < sourceBottom)
+ {
+ for (int x = startX; x < endX; x += size)
+ {
+ int offsetX = offset;
+ int offsetY = offset;
+
+ // Make sure that the offset is within the boundary of the
+ // image.
+ while (y + offsetY >= sourceBottom)
+ {
+ offsetY--;
+ }
+
+ while (x + offsetX >= endX)
+ {
+ offsetX--;
+ }
+
+ // Get the pixel color in the centre of the soon to be pixelated area.
+ // ReSharper disable AccessToDisposedClosure
+ T pixel = sourcePixels[x + offsetX, y + offsetY];
+
+ // For each pixel in the pixelate size, set it to the centre color.
+ for (int l = y; l < y + size && l < sourceBottom; l++)
+ {
+ for (int k = x; k < x + size && k < endX; k++)
+ {
+ targetPixels[k, l] = pixel;
+ }
+ }
+ }
+
+ this.OnRowProcessed();
+ }
+ });
+ }
+ }
+ }
+}
diff --git a/tests/ImageProcessorCore.Tests/Processors/Filters/PixelateTest.cs b/tests/ImageProcessorCore.Tests/Processors/Filters/PixelateTest.cs
new file mode 100644
index 000000000..b2ef2fb38
--- /dev/null
+++ b/tests/ImageProcessorCore.Tests/Processors/Filters/PixelateTest.cs
@@ -0,0 +1,47 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageProcessorCore.Tests
+{
+ using System.IO;
+
+ using Xunit;
+
+ public class PixelateTest : FileTestBase
+ {
+ public static readonly TheoryData PixelateValues
+ = new TheoryData
+ {
+ 4 ,
+ 8 ,
+ };
+
+ [Theory]
+ [MemberData("PixelateValues")]
+ public void ImageShouldApplyPixelateFilter(int value)
+ {
+ const string path = "TestOutput/Pixelate";
+ if (!Directory.Exists(path))
+ {
+ Directory.CreateDirectory(path);
+ }
+
+ foreach (string file in Files)
+ {
+ using (FileStream stream = File.OpenRead(file))
+ {
+ string filename = Path.GetFileNameWithoutExtension(file) + "-" + value + Path.GetExtension(file);
+
+ Image image = new Image(stream);
+ using (FileStream output = File.OpenWrite($"{path}/{filename}"))
+ {
+ image.Pixelate(value)
+ .Save(output);
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file