diff --git a/ConsoleInterface/Program.cs b/ConsoleInterface/Program.cs
index de28a1c..ee408d6 100644
--- a/ConsoleInterface/Program.cs
+++ b/ConsoleInterface/Program.cs
@@ -10,40 +10,60 @@ namespace ConsoleInterface
{
internal static class Program
{
+ ///
+ /// The console interface for the project and the main entrypoint.
+ ///
+ /// Command line provided args.
private static void Main(string[] args)
{
Parser.Default.ParseArguments(args).WithParsed(RunOptions);
}
+ ///
+ /// RunOptions will be called after the command-line arguments were successfully parsed.
+ ///
private static void RunOptions(Options options)
{
var loggerFactory = LoggerFactory.Create(b => b.AddConsole());
TaskExecutor.Logger = loggerFactory.CreateLogger(nameof(TaskExecutor));
- FilesRetriever.Logger = loggerFactory.CreateLogger(nameof(FilesRetriever));
- OriginalFilenameOutputFormatter.Logger =
- loggerFactory.CreateLogger(nameof(OriginalFilenameOutputFormatter));
+ LocalSystemFilesRetriever.Logger = loggerFactory.CreateLogger(nameof(LocalSystemFilesRetriever));
+ OriginalFilenameFileOutputPathFormatter.Logger =
+ loggerFactory.CreateLogger(nameof(OriginalFilenameFileOutputPathFormatter));
- var outputFormatter = OriginalFilenameOutputFormatter.Create(options.DestinationDirectory);
+ var outputFormatter = OriginalFilenameFileOutputPathFormatter.Create(options.DestinationDirectory);
var executor = TaskExecutor.Create(new TaskExecutorOptions
{
EnableCompression = options.CompressFiles is true,
- OutputFormatter = outputFormatter
+ FileOutputPathFormatter = outputFormatter
});
- var filesRetriever = FilesRetriever.Create();
+ var filesRetriever = LocalSystemFilesRetriever.Create();
executor.ParallelCleanImages(filesRetriever.GetFilenamesFromPath(options.SourceDirectory));
}
+ ///
+ /// Options is a class defining command line options supported by this program.
+ ///
public class Options
{
+ ///
+ /// CompressFiles indicates whether files should be compressed after being cleaned.
+ ///
[Option('c', "compress", Required = false, HelpText = "Compress images after cleaning.", Default = true)]
public bool? CompressFiles { get; set; }
- [Option('d', "dest", Required = false, HelpText = "The destination directory.", Default = "./cleaned")]
+ ///
+ /// DestinationDirectory represents the destination directory for the cleaned images.
+ ///
+ [Option('d', "dest", Required = false, HelpText = "The destination directory for the cleaned images.",
+ Default = "./cleaned")]
public string DestinationDirectory { get; set; }
- [Value(0, MetaName = "source", HelpText = "The source directory.", Default = ".")]
+ ///
+ /// SourceDirectory represents the source directory of images.
+ ///
+ [Value(0, MetaName = "source", HelpText = "The source directory of images.", Default = ".")]
public string SourceDirectory { get; set; }
}
}
diff --git a/ImageCore/FilesRetriever.cs b/ImageCore/FilesRetriever.cs
deleted file mode 100644
index c54f0bd..0000000
--- a/ImageCore/FilesRetriever.cs
+++ /dev/null
@@ -1,27 +0,0 @@
-using System.Collections.Generic;
-using System.IO;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Logging.Abstractions;
-
-namespace Image
-{
- public class FilesRetriever
- {
- public static ILogger Logger = NullLogger.Instance;
-
- private FilesRetriever()
- {
- }
-
- public static FilesRetriever Create()
- {
- return new FilesRetriever();
- }
-
- public IEnumerable GetFilenamesFromPath(string path)
- {
- Logger.LogInformation($"Getting files from {path}.");
- return Directory.GetFiles(path, "*.*");
- }
- }
-}
\ No newline at end of file
diff --git a/ImageCore/ICompressor.cs b/ImageCore/ICompressor.cs
index 3cbfec1..8750779 100644
--- a/ImageCore/ICompressor.cs
+++ b/ImageCore/ICompressor.cs
@@ -1,7 +1,14 @@
namespace Image
{
+ ///
+ /// ICompressor is an interface for implementing image compressors.
+ ///
public interface ICompressor
{
+ ///
+ /// The method compresses an image in place.
+ ///
+ /// The file name of the image to be compressed.
public void Compress(string fileName);
}
}
\ No newline at end of file
diff --git a/ImageCore/IFileOutputPathFormatter.cs b/ImageCore/IFileOutputPathFormatter.cs
new file mode 100644
index 0000000..8c1eae7
--- /dev/null
+++ b/ImageCore/IFileOutputPathFormatter.cs
@@ -0,0 +1,15 @@
+namespace Image
+{
+ ///
+ /// IOutputFormatter is an interface for generating the output path and destination file name.
+ ///
+ public interface IFileOutputPathFormatter
+ {
+ ///
+ /// Generates an absolute output path given the initial absolute file path.
+ ///
+ /// The initial file path.
+ /// The formatted absolute output path.
+ string GetOutputPath(string initialFilePath);
+ }
+}
\ No newline at end of file
diff --git a/ImageCore/IFilesRetriever.cs b/ImageCore/IFilesRetriever.cs
new file mode 100644
index 0000000..d04a732
--- /dev/null
+++ b/ImageCore/IFilesRetriever.cs
@@ -0,0 +1,17 @@
+using System.Collections.Generic;
+
+namespace Image
+{
+ ///
+ /// An to interface enabling implementation of filename retrievers.
+ ///
+ public interface IFilesRetriever
+ {
+ ///
+ /// Returns all filenames from given path.
+ ///
+ /// The path.
+ /// An enumerable containing all file names.
+ IEnumerable GetFilenamesFromPath(string directoryPath);
+ }
+}
\ No newline at end of file
diff --git a/ImageCore/IMetadataRemover.cs b/ImageCore/IMetadataRemover.cs
index 22b83d7..8d3fa27 100644
--- a/ImageCore/IMetadataRemover.cs
+++ b/ImageCore/IMetadataRemover.cs
@@ -1,7 +1,14 @@
namespace Image
{
+ ///
+ /// Interface for implementing metadata removers.
+ ///
public interface IMetadataRemover
{
- void CleanImage(string newFileName);
+ ///
+ /// CleanImage cleans an image and saves it..
+ ///
+ /// The file path to save the clean image.
+ void CleanImage(string newFilePath);
}
}
\ No newline at end of file
diff --git a/ImageCore/IOutputFormatter.cs b/ImageCore/IOutputFormatter.cs
deleted file mode 100644
index bcb263c..0000000
--- a/ImageCore/IOutputFormatter.cs
+++ /dev/null
@@ -1,7 +0,0 @@
-namespace Image
-{
- public interface IOutputFormatter
- {
- string FormatOutputPath(string filePath);
- }
-}
\ No newline at end of file
diff --git a/ImageCore/ImageCore.csproj b/ImageCore/ImageCore.csproj
index 99bc5d3..0b78338 100644
--- a/ImageCore/ImageCore.csproj
+++ b/ImageCore/ImageCore.csproj
@@ -6,9 +6,9 @@
-
-
-
+
+
+
diff --git a/ImageCore/LocalSystemFilesRetriever.cs b/ImageCore/LocalSystemFilesRetriever.cs
new file mode 100644
index 0000000..55d47ac
--- /dev/null
+++ b/ImageCore/LocalSystemFilesRetriever.cs
@@ -0,0 +1,35 @@
+using System.Collections.Generic;
+using System.IO;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+
+namespace Image
+{
+ ///
+ /// LocalSystemFilesRetriever reads files from the provided directory on the local system.
+ ///
+ public class LocalSystemFilesRetriever : IFilesRetriever
+ {
+ public static ILogger Logger = NullLogger.Instance;
+
+ private LocalSystemFilesRetriever()
+ {
+ }
+
+ ///
+ /// Give a directory path it returns all the filenames.
+ ///
+ /// An absolute path pointing to a directory.
+ /// A list of file names found in the directory.
+ public IEnumerable GetFilenamesFromPath(string directoryPath)
+ {
+ Logger.LogInformation($"Getting files from {directoryPath}.");
+ return Directory.GetFiles(directoryPath, "*.*");
+ }
+
+ public static LocalSystemFilesRetriever Create()
+ {
+ return new LocalSystemFilesRetriever();
+ }
+ }
+}
\ No newline at end of file
diff --git a/ImageCore/LosslessCompressor.cs b/ImageCore/LosslessCompressor.cs
index 098429b..52e17e9 100644
--- a/ImageCore/LosslessCompressor.cs
+++ b/ImageCore/LosslessCompressor.cs
@@ -2,6 +2,9 @@
namespace Image
{
+ ///
+ /// LosslessCompressor compresses an image using lossless compression provided by ImageMagick.
+ ///
public class LosslessCompressor : ICompressor
{
public static readonly LosslessCompressor Instance = new LosslessCompressor();
@@ -11,7 +14,10 @@ namespace Image
{
_imageOptimizer = new ImageOptimizer();
}
-
+
+ ///
+ ///
+ ///
public void Compress(string fileName)
{
_imageOptimizer.LosslessCompress(fileName);
diff --git a/ImageCore/MetadataRemover.cs b/ImageCore/MetadataRemover.cs
index 4fe6733..0f1716f 100644
--- a/ImageCore/MetadataRemover.cs
+++ b/ImageCore/MetadataRemover.cs
@@ -2,22 +2,34 @@
namespace Image
{
+ ///
+ /// MetadataRemover removes metadata from an image. The exif profile.
+ ///
public class MetadataRemover : IMetadataRemover
{
private readonly ICompressor _compressor;
private readonly IMagickImage _magickImage;
+ ///
+ /// Constructs an instance of MetadataRemover.
+ ///
+ /// MagicImage instance.
+ /// Compressor instance.
public MetadataRemover(IMagickImage magickImage, ICompressor compressor)
{
_magickImage = magickImage;
_compressor = compressor;
}
- public void CleanImage(string newFileName)
+ ///
+ /// Cleans the images and compresses it.
+ ///
+ /// The file path to save the clean image.
+ public void CleanImage(string newFilePath)
{
_magickImage.RemoveProfile("exif");
- _magickImage.Write(newFileName);
- _compressor.Compress(newFileName);
+ _magickImage.Write(newFilePath);
+ _compressor.Compress(newFilePath);
}
}
}
\ No newline at end of file
diff --git a/ImageCore/NullCompressor.cs b/ImageCore/NullCompressor.cs
index cdd7dd5..9435cd2 100644
--- a/ImageCore/NullCompressor.cs
+++ b/ImageCore/NullCompressor.cs
@@ -1,9 +1,15 @@
namespace Image
{
+ ///
+ /// Does nothing. Using this Compressor will have no effect.
+ ///
public class NullCompressor : ICompressor
{
public static readonly NullCompressor Instance = new NullCompressor();
-
+
+ ///
+ ///
+ ///
public void Compress(string fileName)
{
}
diff --git a/ImageCore/OriginalFilenameFileOutputPathFormatter.cs b/ImageCore/OriginalFilenameFileOutputPathFormatter.cs
new file mode 100644
index 0000000..9921d5a
--- /dev/null
+++ b/ImageCore/OriginalFilenameFileOutputPathFormatter.cs
@@ -0,0 +1,52 @@
+using System.IO;
+using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging.Abstractions;
+
+namespace Image
+{
+ ///
+ /// OriginalFilenameFileOutputPathFormatter keeps the original file name of the image when formatting the new output
+ /// path.
+ ///
+ public class OriginalFilenameFileOutputPathFormatter : IFileOutputPathFormatter
+ {
+ public static ILogger Logger = NullLogger.Instance;
+ private readonly string _outputDirectory;
+
+ ///
+ /// Creates an instance of OriginalFilenameFileOutputPathFormatter.
+ ///
+ /// The output directory.
+ public OriginalFilenameFileOutputPathFormatter(string outputDirectory)
+ {
+ if (!Directory.Exists(outputDirectory))
+ {
+ Logger.LogWarning("Output directory does not exists. Creating.");
+ Directory.CreateDirectory(outputDirectory);
+ }
+
+ _outputDirectory = outputDirectory;
+ }
+
+ ///
+ /// Returns a path containing the file name in the output directory.
+ ///
+ /// The initial path of the image.
+ /// An absolute path of the form output_directory/initialFileName.jpg
+ public string GetOutputPath(string initialFilePath)
+ {
+ var fileName = Path.GetFileName(initialFilePath)?.Split(".")[0];
+ var path = Path.Join(_outputDirectory, $"{fileName}.jpg");
+ return path;
+ }
+
+ ///
+ /// Creates an instance of OriginalFilenameFileOutputPathFormatter.
+ ///
+ /// The output directory.
+ public static OriginalFilenameFileOutputPathFormatter Create(string outputDirectory)
+ {
+ return new OriginalFilenameFileOutputPathFormatter(outputDirectory);
+ }
+ }
+}
\ No newline at end of file
diff --git a/ImageCore/OriginalFilenameOutputFormatter.cs b/ImageCore/OriginalFilenameOutputFormatter.cs
deleted file mode 100644
index 0e01e1a..0000000
--- a/ImageCore/OriginalFilenameOutputFormatter.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using System.IO;
-using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Logging.Abstractions;
-
-namespace Image
-{
- public class OriginalFilenameOutputFormatter : IOutputFormatter
- {
- public static ILogger Logger = NullLogger.Instance;
- private readonly string _rootDirectory;
-
- public OriginalFilenameOutputFormatter(string rootDirectory)
- {
- if (!Directory.Exists(rootDirectory))
- {
- Logger.LogWarning("Output directory does not exists. Creating.");
- Directory.CreateDirectory(rootDirectory);
- }
-
- _rootDirectory = rootDirectory;
- }
-
- public string FormatOutputPath(string filePath)
- {
- var fileName = Path.GetFileName(filePath)?.Split(".")[0];
- var path = Path.Join(_rootDirectory, $"{fileName}.jpg");
- return path;
- }
-
- public static OriginalFilenameOutputFormatter Create(string rootDirectory)
- {
- return new OriginalFilenameOutputFormatter(rootDirectory);
- }
- }
-}
\ No newline at end of file
diff --git a/ImageCore/TaskExecutor.cs b/ImageCore/TaskExecutor.cs
index 2711ea2..e64e521 100644
--- a/ImageCore/TaskExecutor.cs
+++ b/ImageCore/TaskExecutor.cs
@@ -8,34 +8,49 @@ using Microsoft.Extensions.Logging.Abstractions;
namespace Image
{
+ ///
+ /// TaskExecutor is a helper class for executing tasks in parallel.
+ ///
public class TaskExecutor
{
public static ILogger Logger = NullLogger.Instance;
private readonly TaskExecutorOptions _options;
+ ///
+ /// Creates a new instance of TaskExecutor.
+ ///
+ /// The TaskExecutor options.
+ /// Raised when the options are null.
private TaskExecutor(TaskExecutorOptions options)
{
_options = options ?? throw new ArgumentException("Options cannot be null!");
}
+ ///
+ /// Creates a new instance of TaskExecutor by calling the private constructor.
+ ///
+ /// The TaskExecutor options.
public static TaskExecutor Create(TaskExecutorOptions options)
{
return new TaskExecutor(options);
}
+ ///
+ /// Cleans an image. Errors are silenced by default.
+ ///
+ /// The file name of the image to be cleaned.
+ /// The new file name of the cleaned image.
+ /// True of the image was cleaned, false otherwise.
public bool CleanImage(string fileName, string newFilename)
{
try
{
ICompressor compressor = NullCompressor.Instance;
var imageMagick = new MagickImage(fileName);
- if (_options.EnableCompression)
- {
- compressor = LosslessCompressor.Instance;
- }
+ if (_options.EnableCompression) compressor = LosslessCompressor.Instance;
Logger.LogDebug(
- $"Cleaning {fileName}, compression {_options.EnableCompression}, outputFormatter {nameof(_options.OutputFormatter)}.");
+ $"Cleaning {fileName}, compression {_options.EnableCompression}, outputFormatter {nameof(_options.FileOutputPathFormatter)}.");
IMetadataRemover metadataRemover = new MetadataRemover(imageMagick, compressor);
metadataRemover.CleanImage(newFilename);
return true;
@@ -47,6 +62,10 @@ namespace Image
}
}
+ ///
+ /// Cleans images in parallel using the built in Task Parallel Library.
+ ///
+ /// An enumerable of file names.
public void ParallelCleanImages(IEnumerable fileNames)
{
Logger.LogInformation("Starting parallel image cleaning.");
@@ -61,7 +80,7 @@ namespace Image
foreach (var fileName in filenamesArray)
{
var task = new Task(() =>
- CleanImage(fileName, _options.OutputFormatter.FormatOutputPath(fileName)));
+ CleanImage(fileName, _options.FileOutputPathFormatter.GetOutputPath(fileName)));
tasks.Add(task);
task.Start();
}
diff --git a/ImageCore/TaskExecutorOptions.cs b/ImageCore/TaskExecutorOptions.cs
index 162e5b2..5c514f5 100644
--- a/ImageCore/TaskExecutorOptions.cs
+++ b/ImageCore/TaskExecutorOptions.cs
@@ -2,16 +2,26 @@
namespace Image
{
+ ///
+ /// TaskExecutorOptions is a class containing various parameters for the class.
+ ///
public class TaskExecutorOptions
{
- private IOutputFormatter _outputFormatter;
+ private IFileOutputPathFormatter _fileOutputPathFormatter;
- public IOutputFormatter OutputFormatter
+ ///
+ /// The file output path formatter. It cannot be null.
+ /// A implementation of .
+ ///
+ public IFileOutputPathFormatter FileOutputPathFormatter
{
- get => _outputFormatter;
- set => _outputFormatter = value ?? throw new ArgumentException("Output formatter cannot be null!");
+ get => _fileOutputPathFormatter;
+ set => _fileOutputPathFormatter = value ?? throw new ArgumentException("Output formatter cannot be null!");
}
+ ///
+ /// A boolean indicating if compression should be performed after cleaning the images.
+ ///
public bool EnableCompression { get; set; } = true;
}
}
\ No newline at end of file