diff --git a/ConsoleInterface/Program.cs b/ConsoleInterface/Program.cs
index 32e6b95..edb4920 100644
--- a/ConsoleInterface/Program.cs
+++ b/ConsoleInterface/Program.cs
@@ -31,7 +31,6 @@ namespace ConsoleInterface
private static void RunOptions(ProgramOptions options)
{
SetupLogging(options.LogLevel);
- CreateDestinationDirectory(options.DestinationDirectory);
var outputFormatter = SimpleOutputSink.Create(options.DestinationDirectory);
var executor = TaskExecutor.Create(new TaskExecutorOptions
{
@@ -44,15 +43,6 @@ namespace ConsoleInterface
executor.ParallelCleanImages(filesRetriever.GetFilenamesFromPath(options.SourceDirectory));
}
- ///
- /// Creates the directory if it doesn't exist.
- ///
- /// The destination directory.
- private static void CreateDestinationDirectory(string destinationDirectory)
- {
- FileSystemHelpers.CreateDestinationDirectory(destinationDirectory);
- }
-
public static void SetupLogging(string logLevel)
{
_loggerFactory = LoggerFactory.Create(b =>
diff --git a/ImageCore.Tests/TestKeepFilenameFormatter.cs b/ImageCore.Tests/TestKeepFilenameFormatter.cs
deleted file mode 100644
index c85cfd0..0000000
--- a/ImageCore.Tests/TestKeepFilenameFormatter.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System;
-using Image.Files;
-using Xunit;
-
-namespace ImageCore.Tests
-{
- public class TestSimpleOutputSink
- {
-
- [Theory]
- [InlineData("", "./", @".\.jpg")]
- [InlineData("", @".\", @".\.jpg")]
- [InlineData("", "asd", @".\asd.jpg")]
- [InlineData("dir", "asd", @"dir\asd.jpg")]
- public void TestGetOutputPath(string directory, string file, string expectedPath)
- {
- var outputPathFormatter = SimpleOutputSink.Create(directory);
- Assert.Equal(expectedPath, outputPathFormatter.GetOutputPath(file));
- }
-
- [Fact]
- public void TestGetOutputPathNull()
- {
- var outputPathFormatter = SimpleOutputSink.Create("directory");
- Assert.Throws(() => outputPathFormatter.GetOutputPath(""));
- }
- }
-}
\ No newline at end of file
diff --git a/ImageCore.Tests/TestLocalFileBrowser.cs b/ImageCore.Tests/TestLocalFileBrowser.cs
index f515bf4..5a764a9 100644
--- a/ImageCore.Tests/TestLocalFileBrowser.cs
+++ b/ImageCore.Tests/TestLocalFileBrowser.cs
@@ -32,7 +32,7 @@ namespace ImageCore.Tests
var filePathsList = filePaths.ToList();
var expectedFileNames = new List
{
- "IMG_0138.HEIC", "IMG_0140.HEIC",
+ "IMG_0138.HEIC", "IMG_0138.jpg", "IMG_0140.HEIC",
};
Assert.NotEmpty(filePathsList);
diff --git a/ImageCore.Tests/TestMetadataRemover.cs b/ImageCore.Tests/TestMetadataRemover.cs
index 6b15c6b..d09212d 100644
--- a/ImageCore.Tests/TestMetadataRemover.cs
+++ b/ImageCore.Tests/TestMetadataRemover.cs
@@ -8,7 +8,7 @@ namespace ImageCore.Tests
public class TestMetadataRemover
{
[Fact]
- public void TestCleanImage()
+ public void TestExifRemoverAndCompressorCleanImage()
{
// Setup
var magicImageMock = new Mock();
@@ -23,5 +23,22 @@ namespace ImageCore.Tests
magicImageMock.Verify( i => i.Write("path"));
compressorMock.Verify( i => i.Compress("path"));
}
+
+ [Fact]
+ public void TestExifRemoverAndCompressorGetImagePath()
+ {
+ // Setup
+ var magicImageMock = new Mock();
+ magicImageMock.Setup(i => i.FileName).Returns("P4th");
+
+ var compressorMock = new Mock();
+ var metadataRemover = new ExifRemoverAndCompressor(magicImageMock.Object, compressorMock.Object);
+
+ // Test
+ var result = metadataRemover.GetImagePath();
+
+ // Assert
+ Assert.Equal("P4th", result);
+ }
}
}
\ No newline at end of file
diff --git a/ImageCore.Tests/TestSimpleOutputSink.cs b/ImageCore.Tests/TestSimpleOutputSink.cs
new file mode 100644
index 0000000..90f6177
--- /dev/null
+++ b/ImageCore.Tests/TestSimpleOutputSink.cs
@@ -0,0 +1,68 @@
+using System;
+using System.IO;
+using Image.Core;
+using Image.Files;
+using Moq;
+using Xunit;
+
+namespace ImageCore.Tests
+{
+ public class TestSimpleOutputSink
+ {
+ private readonly string _testsProjectDirectory;
+
+ public TestSimpleOutputSink()
+ {
+ _testsProjectDirectory = Environment.GetEnvironmentVariable("IMAGE_CORE_TESTS");
+ }
+
+ [Theory]
+ [InlineData("", "./", @".\.jpg")]
+ [InlineData("", @".\", @".\.jpg")]
+ [InlineData("", "asd", @".\asd.jpg")]
+ [InlineData("dir", "asd", @"dir\asd.jpg")]
+ public void TestGetOutputPath(string directory, string file, string expectedPath)
+ {
+ var sink = SimpleOutputSink.Create(directory);
+ Assert.Equal(expectedPath, sink.GetOutputPath(file));
+ }
+
+ [Fact]
+ public void TestGetOutputPathNull()
+ {
+ var sink = SimpleOutputSink.Create("directory");
+ Assert.Throws(() => sink.GetOutputPath(""));
+ }
+
+ [Fact]
+ public void TestSave()
+ {
+ // Setup
+ var sink = SimpleOutputSink.Create("directory");
+ var metadataRemoverMock = new Mock();
+ metadataRemoverMock.Setup(i => i.GetImagePath()).Returns("alo.wtf");
+
+ // Test
+ sink.Save(metadataRemoverMock.Object);
+
+ // Assert
+ metadataRemoverMock.Verify(i => i.CleanImage("directory\\alo.jpg"));
+ }
+
+ [Fact]
+ public void TestSaveFileExists()
+ {
+ // Setup
+ var sink = SimpleOutputSink.Create(Path.Join(_testsProjectDirectory, "test_pictures"));
+ var metadataRemoverMock = new Mock();
+ var sourceFileName = Path.Join(_testsProjectDirectory, "test_pictures\\IMG_0138.HEIC");
+ metadataRemoverMock.Setup(i => i.GetImagePath()).Returns(sourceFileName);
+
+ // Test
+ sink.Save(metadataRemoverMock.Object);
+
+ // Assert
+ metadataRemoverMock.Verify(i => i.CleanImage(It.IsAny()), Times.Never);
+ }
+ }
+}
\ No newline at end of file
diff --git a/ImageCore.Tests/test_pictures/IMG_0138.jpg b/ImageCore.Tests/test_pictures/IMG_0138.jpg
new file mode 100644
index 0000000..de6943f
Binary files /dev/null and b/ImageCore.Tests/test_pictures/IMG_0138.jpg differ
diff --git a/ImageCore/Core/ExifRemoverAndCompressor.cs b/ImageCore/Core/ExifRemoverAndCompressor.cs
index c22a6d2..03f2d1a 100644
--- a/ImageCore/Core/ExifRemoverAndCompressor.cs
+++ b/ImageCore/Core/ExifRemoverAndCompressor.cs
@@ -31,5 +31,11 @@ namespace Image.Core
_magickImage.Write(newFilePath);
_compressor.Compress(newFilePath);
}
+
+ ///
+ public string GetImagePath()
+ {
+ return _magickImage.FileName;
+ }
}
}
\ No newline at end of file
diff --git a/ImageCore/Core/IMetadataRemover.cs b/ImageCore/Core/IMetadataRemover.cs
index ac27938..cd62aa3 100644
--- a/ImageCore/Core/IMetadataRemover.cs
+++ b/ImageCore/Core/IMetadataRemover.cs
@@ -6,9 +6,15 @@
public interface IMetadataRemover
{
///
- /// CleanImage cleans an image and saves it..
+ /// Cleans an image and saves it under a new path.
///
/// The file path to save the clean image.
void CleanImage(string newFilePath);
+
+ ///
+ /// GetImagePath gets the current image path on the filesystem.
+ ///
+ /// A string representing the absolute path.
+ string GetImagePath();
}
}
\ No newline at end of file
diff --git a/ImageCore/Files/IOutputSink.cs b/ImageCore/Files/IOutputSink.cs
index 4dcbc3b..532435d 100644
--- a/ImageCore/Files/IOutputSink.cs
+++ b/ImageCore/Files/IOutputSink.cs
@@ -1,4 +1,6 @@
-namespace Image.Files
+using Image.Core;
+
+namespace Image.Files
{
///
/// IOutputSink is an interface for generating saving the generated files..
@@ -6,10 +8,10 @@
public interface IOutputSink
{
///
- /// Generates an absolute output path given the initial absolute file path.
+ /// Saves the image.
///
- /// The initial file path.
- /// The formatted absolute output path.
- string GetOutputPath(string initialFilePath);
+ /// Metadata remover instance.
+ /// True if the image was saved successfully, false otherwise.
+ bool Save(IMetadataRemover metadataRemover);
}
}
\ No newline at end of file
diff --git a/ImageCore/Files/SimpleOutputSink.cs b/ImageCore/Files/SimpleOutputSink.cs
index 3da91e2..c769763 100644
--- a/ImageCore/Files/SimpleOutputSink.cs
+++ b/ImageCore/Files/SimpleOutputSink.cs
@@ -1,5 +1,6 @@
using System.IO;
using Ardalis.GuardClauses;
+using Image.Core;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
@@ -25,6 +26,10 @@ namespace Image.Files
{
outputDirectory = ".";
}
+ else
+ {
+ FileSystemHelpers.CreateDestinationDirectory(outputDirectory);
+ }
_outputDirectory = outputDirectory;
}
@@ -39,10 +44,23 @@ namespace Image.Files
Guard.Against.NullOrEmpty(initialFilePath, nameof(initialFilePath));
var fileName = Path.GetFileName(initialFilePath).Split('.')[0];
var path = Path.Combine(_outputDirectory, $"{fileName}.jpg");
-
return path;
}
+ public bool Save(IMetadataRemover metadataRemover)
+ {
+ var newFilePath = GetOutputPath(metadataRemover.GetImagePath());
+ var fileExists = FileSystemHelpers.CheckIfFileExists(newFilePath);
+ if (fileExists)
+ {
+ Logger.LogWarning($"File {newFilePath} exists, skipping");
+ return false;
+ }
+ // Save the image under the same name in the new directory.
+ metadataRemover.CleanImage(newFilePath);
+ return true;
+ }
+
///
/// Creates an instance of OriginalFilenameFileOutputPathFormatter.
///
diff --git a/ImageCore/Tasks/TaskExecutor.cs b/ImageCore/Tasks/TaskExecutor.cs
index c18a95f..aa399bb 100644
--- a/ImageCore/Tasks/TaskExecutor.cs
+++ b/ImageCore/Tasks/TaskExecutor.cs
@@ -41,27 +41,19 @@ namespace Image.Tasks
/// Cleans an image. Errors are silenced by default.
///
/// The file path of the image to be cleaned.
- /// The new file path of the cleaned image.
+ /// The output sink for the image..
/// True of the image was cleaned, false otherwise.
- public bool CleanImage(string filePath, string newFilePath)
+ public bool CleanImage(string filePath, IOutputSink outputSink)
{
try
{
- var fileExists = FileSystemHelpers.CheckIfFileExists(newFilePath);
- if (fileExists)
- {
- Logger.LogWarning($"File {newFilePath} exists, skipping");
- return false;
- }
+ Logger.LogDebug($"Cleaning {filePath}, compression {_options.EnableCompression}, outputFormatter {nameof(_options.OutputSink)}.");
+
ICompressor compressor = NullCompressor.Instance;
- var imageMagick = new MagickImage(filePath);
if (_options.EnableCompression) compressor = LosslessCompressor.Instance;
-
- Logger.LogDebug(
- $"Cleaning {filePath}, compression {_options.EnableCompression}, outputFormatter {nameof(_options.OutputSink)}.");
+ var imageMagick = new MagickImage(filePath);
IMetadataRemover metadataRemover = new ExifRemoverAndCompressor(imageMagick, compressor);
- metadataRemover.CleanImage(newFilePath);
- return true;
+ return outputSink.Save(metadataRemover);
}
catch (Exception e)
{
@@ -87,8 +79,7 @@ namespace Image.Tasks
var tasks = new List>();
foreach (var fileName in filenamesArray)
{
- var task = new Task(() =>
- CleanImage(fileName, _options.OutputSink.GetOutputPath(fileName)));
+ var task = new Task(() => CleanImage(fileName, _options.OutputSink));
tasks.Add(task);
task.Start();
}
diff --git a/ImageCore/Tasks/TaskExecutorOptions.cs b/ImageCore/Tasks/TaskExecutorOptions.cs
index 2e1cf2d..e4b34cb 100644
--- a/ImageCore/Tasks/TaskExecutorOptions.cs
+++ b/ImageCore/Tasks/TaskExecutorOptions.cs
@@ -17,7 +17,7 @@ namespace Image.Tasks
public IOutputSink OutputSink
{
get => _outputSink;
- set => _outputSink = value ?? throw new ArgumentException("Output formatter cannot be null!");
+ set => _outputSink = value ?? throw new ArgumentException("OutputSink cannot be null!");
}
///
diff --git a/ImgMetadataRemover.sln.DotSettings.user b/ImgMetadataRemover.sln.DotSettings.user
index 1c497a9..0d860a4 100644
--- a/ImgMetadataRemover.sln.DotSettings.user
+++ b/ImgMetadataRemover.sln.DotSettings.user
@@ -4,6 +4,7 @@
<Assembly Path="C:\Users\nutiu\.nuget\packages\magick.net.core\8.6.1\lib\netstandard21\Magick.NET.Core.dll" />
<Assembly Path="C:\Users\nutiu\.nuget\packages\microsoft.extensions.logging.abstractions\6.0.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll" />
</AssemblyExplorer>
+ C:\Users\nutiu\AppData\Local\JetBrains\Rider2021.3\resharper-host\temp\Rider\vAny\CoverageData\_ImgMetadataRemover.61395890\Snapshot\snapshot.utdcvr
<SessionState ContinuousTestingMode="0" IsActive="True" Name="TestGetFilenamesFromPath" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
<Project Location="C:\Users\nutiu\RiderProjects\ImgMetadataRemover\ImageCore.Tests" Presentation="<ImageCore.Tests>" />
</SessionState>
\ No newline at end of file