diff --git a/src/ImageProcessorCore/Filters/Brightness.cs b/src/ImageProcessorCore/Filters/Brightness.cs
new file mode 100644
index 000000000..fb29ff0d9
--- /dev/null
+++ b/src/ImageProcessorCore/Filters/Brightness.cs
@@ -0,0 +1,60 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageProcessorCore
+{
+ using Processors;
+
+ ///
+ /// Extension methods for the type.
+ ///
+ public static partial class ImageExtensions
+ {
+ ///
+ /// Alters the brightness component of the image.
+ ///
+ /// The pixel format.
+ /// The packed format. long, float.
+ /// The image this method extends.
+ /// The new brightness of the image. Must be between -100 and 100.
+ /// A delegate which is called as progress is made processing the image.
+ /// The .
+ public static Image Brightness(this Image source, int amount, ProgressEventHandler progressHandler = null)
+ where T : IPackedVector
+ where TP : struct
+ {
+ return Brightness(source, amount, source.Bounds, progressHandler);
+ }
+
+ ///
+ /// Alters the brightness component of the image.
+ ///
+ /// The pixel format.
+ /// The packed format. long, float.
+ /// The image this method extends.
+ /// The new brightness of the image. Must be between -100 and 100.
+ ///
+ /// 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 Brightness(this Image source, int amount, Rectangle rectangle, ProgressEventHandler progressHandler = null)
+ where T : IPackedVector
+ where TP : struct
+ {
+ BrightnessProcessor processor = new BrightnessProcessor(amount);
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
+ }
+ }
+}
diff --git a/src/ImageProcessorCore/Filters/Hue.cs b/src/ImageProcessorCore/Filters/Hue.cs
new file mode 100644
index 000000000..a4de7c610
--- /dev/null
+++ b/src/ImageProcessorCore/Filters/Hue.cs
@@ -0,0 +1,60 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageProcessorCore
+{
+ using Processors;
+
+ ///
+ /// Extension methods for the type.
+ ///
+ public static partial class ImageExtensions
+ {
+ ///
+ /// Alters the hue component of the image.
+ ///
+ /// The pixel format.
+ /// The packed format. long, float.
+ /// The image this method extends.
+ /// The angle in degrees to adjust the image.
+ /// A delegate which is called as progress is made processing the image.
+ /// The .
+ public static Image Hue(this Image source, float degrees, ProgressEventHandler progressHandler = null)
+ where T : IPackedVector
+ where TP : struct
+ {
+ return Hue(source, degrees, source.Bounds, progressHandler);
+ }
+
+ ///
+ /// Alters the hue component of the image.
+ ///
+ /// The pixel format.
+ /// The packed format. long, float.
+ /// The image this method extends.
+ /// The angle in degrees to adjust the image.
+ ///
+ /// 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 Hue(this Image source, float degrees, Rectangle rectangle, ProgressEventHandler progressHandler = null)
+ where T : IPackedVector
+ where TP : struct
+ {
+ HueProcessor processor = new HueProcessor(degrees);
+ processor.OnProgress += progressHandler;
+
+ try
+ {
+ return source.Process(rectangle, processor);
+ }
+ finally
+ {
+ processor.OnProgress -= progressHandler;
+ }
+ }
+ }
+}
diff --git a/src/ImageProcessorCore/Filters/Processors/BrightnessProcessor.cs b/src/ImageProcessorCore/Filters/Processors/BrightnessProcessor.cs
new file mode 100644
index 000000000..d253c4ebf
--- /dev/null
+++ b/src/ImageProcessorCore/Filters/Processors/BrightnessProcessor.cs
@@ -0,0 +1,77 @@
+//
+// Copyright (c) James Jackson-South and contributors.
+// Licensed under the Apache License, Version 2.0.
+//
+
+namespace ImageProcessorCore.Processors
+{
+ using System.Numerics;
+ using System.Threading.Tasks;
+
+ ///
+ /// An to change the brightness of an .
+ ///
+ /// The pixel format.
+ /// The packed format. long, float.
+ public class BrightnessProcessor : ImageProcessor
+ where T : IPackedVector
+ where TP : struct
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The new brightness of the image. Must be between -100 and 100.
+ ///
+ /// is less than -100 or is greater than 100.
+ ///
+ public BrightnessProcessor(int brightness)
+ {
+ Guard.MustBeBetweenOrEqualTo(brightness, -100, 100, nameof(brightness));
+ this.Value = brightness;
+ }
+
+ ///
+ /// Gets the brightness value.
+ ///
+ public int Value { get; }
+
+ ///
+ protected override void Apply(ImageBase target, ImageBase source, Rectangle targetRectangle, Rectangle sourceRectangle, int startY, int endY)
+ {
+ float brightness = this.Value / 100f;
+ int sourceY = sourceRectangle.Y;
+ int sourceBottom = sourceRectangle.Bottom;
+ int startX = sourceRectangle.X;
+ int endX = sourceRectangle.Right;
+
+ using (IPixelAccessor sourcePixels = source.Lock())
+ using (IPixelAccessor targetPixels = target.Lock())
+ {
+ Parallel.For(
+ startY,
+ endY,
+ y =>
+ {
+ if (y >= sourceY && y < sourceBottom)
+ {
+ for (int x = startX; x < endX; x++)
+ {
+ // TODO: Check this with other formats.
+ Vector4 vector = sourcePixels[x, y].ToVector4().Expand();
+ Vector3 transformed = new Vector3(vector.X, vector.Y, vector.Z);
+ transformed += new Vector3(brightness);
+ vector = new Vector4(transformed.X, transformed.Y, transformed.Z, vector.W);
+
+ T packed = default(T);
+ packed.PackVector(vector.Compress());
+
+ targetPixels[x, y] = packed;
+ }
+
+ this.OnRowProcessed();
+ }
+ });
+ }
+ }
+ }
+}
diff --git a/src/ImageProcessorCore/Filters/Saturation.cs b/src/ImageProcessorCore/Filters/Saturation.cs
index 3c39d4e5c..cdd2a1bc0 100644
--- a/src/ImageProcessorCore/Filters/Saturation.cs
+++ b/src/ImageProcessorCore/Filters/Saturation.cs
@@ -1,7 +1,7 @@
//
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
-// -------------------------------------------------------------------------------------------------------------------
+//
namespace ImageProcessorCore
{
diff --git a/tests/ImageProcessorCore.Tests/Processors/Filters/BrightnessTest.cs b/tests/ImageProcessorCore.Tests/Processors/Filters/BrightnessTest.cs
new file mode 100644
index 000000000..9c0d840df
--- /dev/null
+++ b/tests/ImageProcessorCore.Tests/Processors/Filters/BrightnessTest.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 BrightnessTest : FileTestBase
+ {
+ public static readonly TheoryData BrightnessValues
+ = new TheoryData
+ {
+ 50 ,
+ -50 ,
+ };
+
+ [Theory]
+ [MemberData("BrightnessValues")]
+ public void ImageShouldApplyBrightnessFilter(int value)
+ {
+ const string path = "TestOutput/Brightness";
+ 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.Brightness(value)
+ .Save(output);
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageProcessorCore.Tests/Processors/Filters/HueTest.cs b/tests/ImageProcessorCore.Tests/Processors/Filters/HueTest.cs
new file mode 100644
index 000000000..7ece88159
--- /dev/null
+++ b/tests/ImageProcessorCore.Tests/Processors/Filters/HueTest.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 HueTest : FileTestBase
+ {
+ public static readonly TheoryData HueValues
+ = new TheoryData
+ {
+ 180 ,
+ -180 ,
+ };
+
+ [Theory]
+ [MemberData("HueValues")]
+ public void ImageShouldApplyHueFilter(int value)
+ {
+ const string path = "TestOutput/Hue";
+ 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.Hue(value)
+ .Save(output);
+ }
+ }
+ }
+ }
+ }
+}
\ No newline at end of file