Initial commit
This commit is contained in:
commit
8a9217aede
19 changed files with 382 additions and 0 deletions
116
.gitignore
vendored
Normal file
116
.gitignore
vendored
Normal file
|
@ -0,0 +1,116 @@
|
||||||
|
bin/
|
||||||
|
obj/
|
||||||
|
/packages/
|
||||||
|
riderModule.iml
|
||||||
|
/_ReSharper.Caches/
|
||||||
|
|
||||||
|
|
||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/rider,windows
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=rider,windows
|
||||||
|
|
||||||
|
### Rider ###
|
||||||
|
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||||
|
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||||
|
|
||||||
|
# User-specific stuff
|
||||||
|
.idea/**/workspace.xml
|
||||||
|
.idea/**/tasks.xml
|
||||||
|
.idea/**/usage.statistics.xml
|
||||||
|
.idea/**/dictionaries
|
||||||
|
.idea/**/shelf
|
||||||
|
|
||||||
|
# AWS User-specific
|
||||||
|
.idea/**/aws.xml
|
||||||
|
|
||||||
|
# Generated files
|
||||||
|
.idea/**/contentModel.xml
|
||||||
|
|
||||||
|
# Sensitive or high-churn files
|
||||||
|
.idea/**/dataSources/
|
||||||
|
.idea/**/dataSources.ids
|
||||||
|
.idea/**/dataSources.local.xml
|
||||||
|
.idea/**/sqlDataSources.xml
|
||||||
|
.idea/**/dynamic.xml
|
||||||
|
.idea/**/uiDesigner.xml
|
||||||
|
.idea/**/dbnavigator.xml
|
||||||
|
|
||||||
|
# Gradle
|
||||||
|
.idea/**/gradle.xml
|
||||||
|
.idea/**/libraries
|
||||||
|
|
||||||
|
# Gradle and Maven with auto-import
|
||||||
|
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||||
|
# since they will be recreated, and may cause churn. Uncomment if using
|
||||||
|
# auto-import.
|
||||||
|
# .idea/artifacts
|
||||||
|
# .idea/compiler.xml
|
||||||
|
# .idea/jarRepositories.xml
|
||||||
|
# .idea/modules.xml
|
||||||
|
# .idea/*.iml
|
||||||
|
# .idea/modules
|
||||||
|
# *.iml
|
||||||
|
# *.ipr
|
||||||
|
|
||||||
|
# CMake
|
||||||
|
cmake-build-*/
|
||||||
|
|
||||||
|
# Mongo Explorer plugin
|
||||||
|
.idea/**/mongoSettings.xml
|
||||||
|
|
||||||
|
# File-based project format
|
||||||
|
*.iws
|
||||||
|
|
||||||
|
# IntelliJ
|
||||||
|
out/
|
||||||
|
|
||||||
|
# mpeltonen/sbt-idea plugin
|
||||||
|
.idea_modules/
|
||||||
|
|
||||||
|
# JIRA plugin
|
||||||
|
atlassian-ide-plugin.xml
|
||||||
|
|
||||||
|
# Cursive Clojure plugin
|
||||||
|
.idea/replstate.xml
|
||||||
|
|
||||||
|
# SonarLint plugin
|
||||||
|
.idea/sonarlint/
|
||||||
|
|
||||||
|
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||||
|
com_crashlytics_export_strings.xml
|
||||||
|
crashlytics.properties
|
||||||
|
crashlytics-build.properties
|
||||||
|
fabric.properties
|
||||||
|
|
||||||
|
# Editor-based Rest Client
|
||||||
|
.idea/httpRequests
|
||||||
|
|
||||||
|
# Android studio 3.1+ serialized cache file
|
||||||
|
.idea/caches/build_file_checksums.ser
|
||||||
|
|
||||||
|
### Windows ###
|
||||||
|
# Windows thumbnail cache files
|
||||||
|
Thumbs.db
|
||||||
|
Thumbs.db:encryptable
|
||||||
|
ehthumbs.db
|
||||||
|
ehthumbs_vista.db
|
||||||
|
|
||||||
|
# Dump file
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Folder config file
|
||||||
|
[Dd]esktop.ini
|
||||||
|
|
||||||
|
# Recycle Bin used on file shares
|
||||||
|
$RECYCLE.BIN/
|
||||||
|
|
||||||
|
# Windows Installer files
|
||||||
|
*.cab
|
||||||
|
*.msi
|
||||||
|
*.msix
|
||||||
|
*.msm
|
||||||
|
*.msp
|
||||||
|
|
||||||
|
# Windows shortcuts
|
||||||
|
*.lnk
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/rider,windows
|
13
.idea/.idea.ImgMetadataRemover/.idea/.gitignore
vendored
Normal file
13
.idea/.idea.ImgMetadataRemover/.idea/.gitignore
vendored
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Rider ignored files
|
||||||
|
/projectSettingsUpdater.xml
|
||||||
|
/contentModel.xml
|
||||||
|
/modules.xml
|
||||||
|
/.idea.ImgMetadataRemover.iml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
4
.idea/.idea.ImgMetadataRemover/.idea/encodings.xml
Normal file
4
.idea/.idea.ImgMetadataRemover/.idea/encodings.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
|
||||||
|
</project>
|
8
.idea/.idea.ImgMetadataRemover/.idea/indexLayout.xml
Normal file
8
.idea/.idea.ImgMetadataRemover/.idea/indexLayout.xml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="UserContentModel">
|
||||||
|
<attachedFolders />
|
||||||
|
<explicitIncludes />
|
||||||
|
<explicitExcludes />
|
||||||
|
</component>
|
||||||
|
</project>
|
6
.idea/.idea.ImgMetadataRemover/.idea/vcs.xml
Normal file
6
.idea/.idea.ImgMetadataRemover/.idea/vcs.xml
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
14
ConsoleInterface/ConsoleInterface.csproj
Normal file
14
ConsoleInterface/ConsoleInterface.csproj
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Image\Image.csproj"/>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging" Version="6.0.0"/>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
23
ConsoleInterface/Program.cs
Normal file
23
ConsoleInterface/Program.cs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
using Image;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace ConsoleInterface
|
||||||
|
{
|
||||||
|
internal static class Program
|
||||||
|
{
|
||||||
|
private static void Main(string[] args)
|
||||||
|
{
|
||||||
|
var loggerFactory = LoggerFactory.Create(b => b.AddConsole());
|
||||||
|
var outputFormatter = OriginalFilenameOutputFormatter.Create(@"C:\Users\nutiu\Downloads\Photos-001\clean");
|
||||||
|
var executor = TasksExecutor.Create();
|
||||||
|
executor.Logger = loggerFactory.CreateLogger("Executor");
|
||||||
|
executor.ParallelCleanImages(new[]
|
||||||
|
{
|
||||||
|
@"C:\Users\nutiu\Downloads\Photos-001\IMG_0138.HEIC",
|
||||||
|
@"C:\Users\nutiu\Downloads\Photos-001\IMG_0137.HEIC",
|
||||||
|
@"C:\Users\nutiu\Downloads\Photos-001\IMG_0140.HEIC",
|
||||||
|
@"C:\Users\nutiu\Downloads\Photos-001\12382975864_09e6e069e7_o.jpg"
|
||||||
|
}, outputFormatter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
Image/Cleaner.cs
Normal file
38
Image/Cleaner.cs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
using ImageMagick;
|
||||||
|
|
||||||
|
namespace Image
|
||||||
|
{
|
||||||
|
public class Cleaner : ICleaner
|
||||||
|
{
|
||||||
|
private readonly ICompressor _compressor;
|
||||||
|
private readonly IMagickImage _magickImage;
|
||||||
|
|
||||||
|
public Cleaner(IMagickImage magickImage, ICompressor compressor)
|
||||||
|
{
|
||||||
|
_magickImage = magickImage;
|
||||||
|
_compressor = compressor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Cleaner(string fileName) : this(new MagickImage(fileName), new LosslessCompressor())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CleanImage(string newFileName)
|
||||||
|
{
|
||||||
|
_magickImage.RemoveProfile("exif");
|
||||||
|
_magickImage.Write(newFileName);
|
||||||
|
_compressor.Compress(newFileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveExifData(string newFilename)
|
||||||
|
{
|
||||||
|
_magickImage.RemoveProfile("exif");
|
||||||
|
_magickImage.Write(newFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OptimizeImage(string fileName)
|
||||||
|
{
|
||||||
|
_compressor.Compress(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
Image/ICleaner.cs
Normal file
9
Image/ICleaner.cs
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
namespace Image
|
||||||
|
{
|
||||||
|
public interface ICleaner
|
||||||
|
{
|
||||||
|
void CleanImage(string newFileName);
|
||||||
|
void OptimizeImage(string fileName);
|
||||||
|
public void RemoveExifData(string newFilename);
|
||||||
|
}
|
||||||
|
}
|
7
Image/ICompressor.cs
Normal file
7
Image/ICompressor.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Image
|
||||||
|
{
|
||||||
|
public interface ICompressor
|
||||||
|
{
|
||||||
|
public void Compress(string fileName);
|
||||||
|
}
|
||||||
|
}
|
7
Image/IOutputFormatter.cs
Normal file
7
Image/IOutputFormatter.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace Image
|
||||||
|
{
|
||||||
|
public interface IOutputFormatter
|
||||||
|
{
|
||||||
|
string FormatOutputPath(string filePath);
|
||||||
|
}
|
||||||
|
}
|
14
Image/Image.csproj
Normal file
14
Image/Image.csproj
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
<RootNamespace>Image</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Magick.NET-Q16-AnyCPU" Version="8.6.1"/>
|
||||||
|
<PackageReference Include="Magick.NET.Core" Version="8.6.1"/>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="6.0.0"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
19
Image/LosslessCompressor.cs
Normal file
19
Image/LosslessCompressor.cs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
using ImageMagick;
|
||||||
|
|
||||||
|
namespace Image
|
||||||
|
{
|
||||||
|
public class LosslessCompressor : ICompressor
|
||||||
|
{
|
||||||
|
private readonly ImageOptimizer _imageOptimizer;
|
||||||
|
|
||||||
|
public LosslessCompressor()
|
||||||
|
{
|
||||||
|
_imageOptimizer = new ImageOptimizer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Compress(string fileName)
|
||||||
|
{
|
||||||
|
_imageOptimizer.LosslessCompress(fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
Image/OriginalFilenameOutputFormatter.cs
Normal file
27
Image/OriginalFilenameOutputFormatter.cs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Image
|
||||||
|
{
|
||||||
|
public class OriginalFilenameOutputFormatter : IOutputFormatter
|
||||||
|
{
|
||||||
|
private readonly string _rootDirectory;
|
||||||
|
|
||||||
|
public OriginalFilenameOutputFormatter(string rootDirectory)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(rootDirectory)) Directory.CreateDirectory(rootDirectory);
|
||||||
|
_rootDirectory = rootDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string FormatOutputPath(string filePath)
|
||||||
|
{
|
||||||
|
var fileName = Path.GetFileName(filePath);
|
||||||
|
var path = Path.Join(_rootDirectory, $"{fileName}.jpg");
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static OriginalFilenameOutputFormatter Create(string rootDirectory)
|
||||||
|
{
|
||||||
|
return new OriginalFilenameOutputFormatter(rootDirectory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
Image/TasksExecutor.cs
Normal file
43
Image/TasksExecutor.cs
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Logging.Abstractions;
|
||||||
|
|
||||||
|
namespace Image
|
||||||
|
{
|
||||||
|
public class TasksExecutor
|
||||||
|
{
|
||||||
|
public ILogger Logger = NullLogger.Instance;
|
||||||
|
|
||||||
|
public static TasksExecutor Create()
|
||||||
|
{
|
||||||
|
return new TasksExecutor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CleanImage(string fileName, string newFilename)
|
||||||
|
{
|
||||||
|
ICleaner cleaner = new Cleaner(fileName);
|
||||||
|
cleaner.CleanImage(newFilename);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ParallelCleanImages(IEnumerable<string> fileNames, IOutputFormatter outputFormatter)
|
||||||
|
{
|
||||||
|
Logger.LogInformation("Starting parallel image cleaning.");
|
||||||
|
var tasks = new List<Task>();
|
||||||
|
foreach (var fileName in fileNames)
|
||||||
|
{
|
||||||
|
var task = new Task(() => { CleanImage(fileName, outputFormatter.FormatOutputPath(fileName)); });
|
||||||
|
tasks.Add(task);
|
||||||
|
task.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = Task.WhenAll(tasks);
|
||||||
|
result.Wait();
|
||||||
|
|
||||||
|
var successTasks = tasks.Count(t => t.IsCompletedSuccessfully);
|
||||||
|
var errorTasks = tasks.Count() - successTasks;
|
||||||
|
Logger.LogInformation($"All tasks completed. Success: {successTasks}, Errors: {errorTasks}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
22
ImgMetadataRemover.sln
Normal file
22
ImgMetadataRemover.sln
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Image", "Image\Image.csproj", "{10AD7910-C8AA-43ED-9231-EBE267AC270F}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleInterface", "ConsoleInterface\ConsoleInterface.csproj", "{F04E0337-23D3-4209-9BDE-B798090A7A63}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{10AD7910-C8AA-43ED-9231-EBE267AC270F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{10AD7910-C8AA-43ED-9231-EBE267AC270F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{10AD7910-C8AA-43ED-9231-EBE267AC270F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{10AD7910-C8AA-43ED-9231-EBE267AC270F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{F04E0337-23D3-4209-9BDE-B798090A7A63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{F04E0337-23D3-4209-9BDE-B798090A7A63}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{F04E0337-23D3-4209-9BDE-B798090A7A63}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{F04E0337-23D3-4209-9BDE-B798090A7A63}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
5
ImgMetadataRemover.sln.DotSettings.user
Normal file
5
ImgMetadataRemover.sln.DotSettings.user
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
|
<s:String x:Key="/Default/Environment/AssemblyExplorer/XmlDocument/@EntryValue"><AssemblyExplorer>
|
||||||
|
<Assembly Path="C:\Program Files\dotnet\packs\Microsoft.NETCore.App.Ref\3.1.0\ref\netcoreapp3.1\System.Net.Mail.dll" />
|
||||||
|
<Assembly Path="C:\Users\nutiu\.nuget\packages\magick.net.core\8.6.1\lib\netstandard21\Magick.NET.Core.dll" />
|
||||||
|
</AssemblyExplorer></s:String></wpf:ResourceDictionary>
|
BIN
README.md
Normal file
BIN
README.md
Normal file
Binary file not shown.
7
global.json
Normal file
7
global.json
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"sdk": {
|
||||||
|
"version": "3.1",
|
||||||
|
"rollForward": "latestMajor",
|
||||||
|
"allowPrerelease": false
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue