From 6525ca10ef990e38a584d3f64b863c0d0e6a89d0 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Thu, 28 Jul 2016 18:08:51 +1000 Subject: [PATCH] Invert Former-commit-id: 543588719050a2a824a61b3578bad8b1453937d4 Former-commit-id: 0e0ca33a0e82a2696f63609b1332c85949f42fda Former-commit-id: 2750fc6e82392ec3c9368d9b2f062e8823ffb363 --- src/ImageProcessorCore/Filters/Invert.cs | 54 +++++++++++++++++++ .../Filters/Processors/BrightnessProcessor.cs | 2 +- .../ColorMatrix/ColorMatrixFilter.cs | 2 +- .../Filters/Processors/InvertProcessor.cs | 54 +++++++++++++++++++ .../Processors/Filters/InvertTest.cs | 38 +++++++++++++ 5 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 src/ImageProcessorCore/Filters/Invert.cs create mode 100644 src/ImageProcessorCore/Filters/Processors/InvertProcessor.cs create mode 100644 tests/ImageProcessorCore.Tests/Processors/Filters/InvertTest.cs diff --git a/src/ImageProcessorCore/Filters/Invert.cs b/src/ImageProcessorCore/Filters/Invert.cs new file mode 100644 index 0000000000..d7888be591 --- /dev/null +++ b/src/ImageProcessorCore/Filters/Invert.cs @@ -0,0 +1,54 @@ +// +// 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 + { + /// + /// Inverts the colors of the image. + /// + /// The image this method extends. + /// A delegate which is called as progress is made processing the image. + /// The . + public static Image Invert(this Image source, ProgressEventHandler progressHandler = null) + where T : IPackedVector + where TP : struct + { + return Invert(source, source.Bounds, progressHandler); + } + + /// + /// Inverts the colors of the image. + /// + /// The image this method extends. + /// + /// 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 Invert(this Image source, Rectangle rectangle, ProgressEventHandler progressHandler = null) + where T : IPackedVector + where TP : struct + { + InvertProcessor processor = new InvertProcessor(); + 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 index d253c4ebf0..3b3be22a51 100644 --- a/src/ImageProcessorCore/Filters/Processors/BrightnessProcessor.cs +++ b/src/ImageProcessorCore/Filters/Processors/BrightnessProcessor.cs @@ -60,7 +60,7 @@ namespace ImageProcessorCore.Processors 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); + vector = new Vector4(transformed, vector.W); T packed = default(T); packed.PackVector(vector.Compress()); diff --git a/src/ImageProcessorCore/Filters/Processors/ColorMatrix/ColorMatrixFilter.cs b/src/ImageProcessorCore/Filters/Processors/ColorMatrix/ColorMatrixFilter.cs index 3aeb33327f..47145c23ec 100644 --- a/src/ImageProcessorCore/Filters/Processors/ColorMatrix/ColorMatrixFilter.cs +++ b/src/ImageProcessorCore/Filters/Processors/ColorMatrix/ColorMatrixFilter.cs @@ -68,7 +68,7 @@ namespace ImageProcessorCore.Processors } Vector3 transformed = Vector3.Transform(new Vector3(vector.X, vector.Y, vector.Z), matrix); - vector = new Vector4(transformed.X, transformed.Y, transformed.Z, vector.W); + vector = new Vector4(transformed, vector.W); T packed = default(T); packed.PackVector(compand ? vector.Compress() : vector); return packed; diff --git a/src/ImageProcessorCore/Filters/Processors/InvertProcessor.cs b/src/ImageProcessorCore/Filters/Processors/InvertProcessor.cs new file mode 100644 index 0000000000..08cdb8f242 --- /dev/null +++ b/src/ImageProcessorCore/Filters/Processors/InvertProcessor.cs @@ -0,0 +1,54 @@ +// +// 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 invert the colors of an . + /// + public class InvertProcessor : ImageProcessor + where T : IPackedVector + where TP : struct + { + /// + 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; + Vector3 inverseVector = Vector3.One; + + 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++) + { + Vector4 color = sourcePixels[x, y].ToVector4(); + Vector3 vector = inverseVector - new Vector3(color.X, color.Y, color.Z); + + T packed = default(T); + packed.PackVector(new Vector4(vector, color.W)); + targetPixels[x, y] = packed; + } + + this.OnRowProcessed(); + } + }); + } + } + } +} + diff --git a/tests/ImageProcessorCore.Tests/Processors/Filters/InvertTest.cs b/tests/ImageProcessorCore.Tests/Processors/Filters/InvertTest.cs new file mode 100644 index 0000000000..14b589b3f6 --- /dev/null +++ b/tests/ImageProcessorCore.Tests/Processors/Filters/InvertTest.cs @@ -0,0 +1,38 @@ +// +// 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 InvertTest : FileTestBase + { + [Fact] + public void ImageShouldApplyInvertFilter() + { + const string path = "TestOutput/Invert"; + if (!Directory.Exists(path)) + { + Directory.CreateDirectory(path); + } + + foreach (string file in Files) + { + using (FileStream stream = File.OpenRead(file)) + { + string filename = Path.GetFileName(file); + Image image = new Image(stream); + using (FileStream output = File.OpenWrite($"{path}/{filename}")) + { + image.Invert() + .Save(output); + } + } + } + } + } +} \ No newline at end of file