Skip to content

Commit

Permalink
Added quite some code to actually optimize images
Browse files Browse the repository at this point in the history
  • Loading branch information
devedse committed Apr 6, 2017
1 parent 0f0f785 commit 462d127
Show file tree
Hide file tree
Showing 11 changed files with 271 additions and 6 deletions.
8 changes: 8 additions & 0 deletions DeveImageOptimizer/Constants.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace DeveImageOptimizer
{
public static class Constants
{
public static string[] ValidExtensions { get; } = new string[] { ".PNG", ".JPG", ".JPEG", ".GIF" };
public const string TempDirectoryName = "Temp";
}
}
8 changes: 8 additions & 0 deletions DeveImageOptimizer/DeveImageOptimizer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\MvvmLightLibs.5.3.0.0\lib\net45\System.Windows.Interactivity.dll</HintPath>
<Private>True</Private>
Expand All @@ -76,6 +77,13 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Constants.cs" />
<Compile Include="FileProcessing\FileOptimizerProcessor.cs" />
<Compile Include="FileProcessing\FileProcessor.cs" />
<Compile Include="Helpers\AsyncFileHelper.cs" />
<Compile Include="Helpers\FolderHelperMethods.cs" />
<Compile Include="Helpers\ImageComparer.cs" />
<Compile Include="Helpers\ProcessRunner.cs" />
<Compile Include="State\IChangable.cs" />
<Compile Include="State\ProcessingState\ProcessingStateData.cs" />
<Compile Include="State\StateManager.cs" />
Expand Down
38 changes: 38 additions & 0 deletions DeveImageOptimizer/FileProcessing/FileOptimizerProcessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using DeveImageOptimizer.Helpers;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DeveImageOptimizer.FileProcessing
{
public class FileOptimizerProcessor
{
private string _pathToFileOptimizer;
private string _tempDirectory;

public FileOptimizerProcessor(string pathToFileOptimizer, string tempDirectory)
{
_pathToFileOptimizer = pathToFileOptimizer;
_tempDirectory = tempDirectory;

Directory.CreateDirectory(tempDirectory);
}

public async Task<bool> OptimizeFile(string fileToOptimize)
{
var fileName = Path.GetFileName(fileToOptimize);
var tempFilePath = Path.Combine(_tempDirectory, fileName);

await AsyncFileHelper.CopyFileAsync(fileToOptimize, tempFilePath, true);

var processStartInfo = new ProcessStartInfo(_pathToFileOptimizer, tempFilePath);
await ProcessRunner.RunProcessAsync(processStartInfo);

return await ImageComparer.AreImagesEqualAsync(fileToOptimize, tempFilePath);
}
}
}
62 changes: 62 additions & 0 deletions DeveImageOptimizer/FileProcessing/FileProcessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using DeveImageOptimizer.ProcessingState;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DeveImageOptimizer.FileProcessing
{
public class FileProcessor
{
private FileOptimizerProcessor _fileOptimizer;
private ProcessingStateData _processingStateData;

public FileProcessor(FileOptimizerProcessor fileOptimizer, ProcessingStateData processingStateData)
{
_fileOptimizer = fileOptimizer;
_processingStateData = processingStateData;
}

public async Task ProcessDirectory(string directory)
{
await ProcessDirectoryInternal(directory);
}

private async Task ProcessDirectoryInternal(string directory)
{
var files = Directory.GetFiles(directory);

foreach (var file in files)
{
await ProcessFile(file);
}

var directories = Directory.GetDirectories(directory);

foreach (var subDirectory in directories)
{
await ProcessDirectoryInternal(subDirectory);
}
}

private async Task ProcessFile(string file)
{
var extension = Path.GetExtension(file).ToUpperInvariant();
if (Constants.ValidExtensions.Contains(extension))
{
var worked = await _fileOptimizer.OptimizeFile(file);

if (worked)
{
_processingStateData.ProcessedFiles.Add(file);
}
else
{
_processingStateData.FailedFiles.Add(file);
}
}
}
}
}
19 changes: 19 additions & 0 deletions DeveImageOptimizer/Helpers/AsyncFileHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System.IO;
using System.Threading.Tasks;

namespace DeveImageOptimizer.Helpers
{
public static class AsyncFileHelper
{
public static async Task CopyFileAsync(string sourceFile, string destinationFile, bool overwrite = false)
{
using (var sourceStream = new FileStream(sourceFile, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.Asynchronous | FileOptions.SequentialScan))
{
using (var destinationStream = new FileStream(destinationFile, overwrite ? FileMode.Create : FileMode.CreateNew, FileAccess.Write, FileShare.None, 4096, FileOptions.Asynchronous | FileOptions.SequentialScan))
{
await sourceStream.CopyToAsync(destinationStream);
}
}
}
}
}
19 changes: 19 additions & 0 deletions DeveImageOptimizer/Helpers/FolderHelperMethods.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using System.IO;
using System.Reflection;

namespace DeveImageOptimizer.Helpers
{
public static class FolderHelperMethods
{
public static Lazy<string> AssemblyDirectory = new Lazy<string>(() => CreateAssemblyDirectory());

private static string CreateAssemblyDirectory()
{
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);
}
}
}
43 changes: 43 additions & 0 deletions DeveImageOptimizer/Helpers/ImageComparer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System.Drawing;
using System.Threading.Tasks;

namespace DeveImageOptimizer.Helpers
{
public static class ImageComparer
{
public static async Task<bool> AreImagesEqualAsync(string image1Path, string image2Path)
{
//on bitmap asynchronously
return await Task.Run(() =>
{
return AreImagesEqual(image1Path, image2Path);
});
}

public static bool AreImagesEqual(string image1Path, string image2Path)
{
using (var image1 = new Bitmap(image1Path))
{
using (var image2 = new Bitmap(image2Path))
{
if (image1.Size != image2.Size)
return false;

for (int y = 0; y < image1.Height; y++)
{
for (int x = 0; x < image1.Width; x++)
{
var pixel1 = image1.GetPixel(x, y);
var pixel2 = image2.GetPixel(x, y);

if (pixel1 != pixel2)
return false;
}
}
}
}

return true;
}
}
}
34 changes: 34 additions & 0 deletions DeveImageOptimizer/Helpers/ProcessRunner.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DeveImageOptimizer.Helpers
{
public static class ProcessRunner
{
public static Task RunProcessAsync(ProcessStartInfo processStartInfo)
{
// there is no non-generic TaskCompletionSource
var tcs = new TaskCompletionSource<bool>();

var process = new Process
{
StartInfo = processStartInfo,
EnableRaisingEvents = true
};

process.Exited += (sender, args) =>
{
tcs.SetResult(true);
process.Dispose();
};

process.Start();

return tcs.Task;
}
}
}
24 changes: 20 additions & 4 deletions DeveImageOptimizer/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,33 @@
<Grid>
<TabControl x:Name="tabControl">
<TabItem Header="Main" DataContext="{Binding Main, Source={StaticResource Locator}}">
<StackPanel Background="AliceBlue">
<Label Content="Path:"></Label>
<Grid HorizontalAlignment="Stretch">
<Grid Background="AliceBlue">
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>

<Label Grid.Row="0" Content="Path:"></Label>
<Grid Grid.Row="1" HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Text="{Binding ProcessingStateData.ProcessingDirectory, UpdateSourceTrigger=PropertyChanged}"></TextBox>
<Button Grid.Column="1" Content="Browse"></Button>
</Grid>
</StackPanel>
<Button Grid.Row="2" Content="Go" Command="{Binding GoCommand}"/>
<Grid Grid.Row="3">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ListBox Grid.Column="0" DataContext="{Binding ProcessingStateData.ProcessedFiles}"></ListBox>
<ListBox Grid.Column="1" DataContext="{Binding ProcessingStateData.FailedFiles}"></ListBox>
</Grid>
</Grid>
</TabItem>
<TabItem Header="Configuration" DataContext="{Binding Settings, Source={StaticResource Locator}}">
<Grid Background="AliceBlue">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using DeveImageOptimizer.State;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace DeveImageOptimizer.ProcessingState
Expand All @@ -9,8 +10,8 @@ namespace DeveImageOptimizer.ProcessingState
public class ProcessingStateData : INotifyPropertyChanged
{
public string ProcessingDirectory { get; set; } = string.Empty;
public List<string> ProcessedFiles { get; set; } = new List<string>();
public List<string> FailedFiles { get; set; } = new List<string>();
public ObservableCollection<string> ProcessedFiles { get; set; } = new ObservableCollection<string>();
public ObservableCollection<string> FailedFiles { get; set; } = new ObservableCollection<string>();

public event PropertyChangedEventHandler PropertyChanged;
}
Expand Down
17 changes: 17 additions & 0 deletions DeveImageOptimizer/ViewModel/MainViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
using DeveImageOptimizer.FileProcessing;
using DeveImageOptimizer.Helpers;
using DeveImageOptimizer.ProcessingState;
using DeveImageOptimizer.State;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Input;

namespace DeveImageOptimizer.ViewModel
{
Expand All @@ -25,11 +31,22 @@ public MainViewModel()
ProcessingStateData = StaticState.ProcessingStateManager.State;

ProcessingStateData.PropertyChanged += ProcessingStateData_PropertyChanged;

GoCommand = new RelayCommand(async () => await GoCommandImp(), () => true);
}

private void ProcessingStateData_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
StaticState.ProcessingStateManager.Save();
}

public ICommand GoCommand { get; private set; }
private async Task GoCommandImp()
{
var fileOptimizer = new FileOptimizerProcessor(StaticState.UserSettingsManager.State.FileOptimizerPath, Path.Combine(FolderHelperMethods.AssemblyDirectory.Value, Constants.TempDirectoryName));
var fileProcessor = new FileProcessor(fileOptimizer, ProcessingStateData);
await fileProcessor.ProcessDirectory(ProcessingStateData.ProcessingDirectory);

}
}
}

0 comments on commit 462d127

Please sign in to comment.