adjusted namespaces and made separate data dir

This commit is contained in:
Simon Gruber
2023-11-22 06:51:08 +01:00
parent ea51f37f81
commit beb194c106
299 changed files with 720 additions and 647 deletions
+2 -1
View File
@@ -6,7 +6,8 @@
}, },
"Test all img": { "Test all img": {
"commandName": "Project", "commandName": "Project",
"commandLineArgs": "\"img/*.png\"" "commandLineArgs": "\"img/*.png\"",
"workingDirectory": "D:\\git\\BA\\Examples\\testdata"
}, },
"Test single img": { "Test single img": {
"commandName": "Project", "commandName": "Project",
+37 -38
View File
@@ -3,49 +3,48 @@ using Lookup.Memory;
using Ocr.Tesseract.Models; using Ocr.Tesseract.Models;
using Process.Interface; using Process.Interface;
namespace Common namespace Common;
/// <summary>
/// Scanner class, scanning <see cref="MagickImage"/>s for <see cref="Word"/>s
/// via optical character recognition. Optimized for digital Screenshots.
/// </summary>
public class ScreenshotScanner
{ {
/// <summary> /// <summary>
/// Scanner class, scanning <see cref="MagickImage"/>s for <see cref="Word"/>s /// The screenshot processor
/// via optical character recognition. Optimized for digital Screenshots.
/// </summary> /// </summary>
public class ScreenshotScanner protected IProcessor<MagickImage, ScanResult> Processor { get; }
/// <summary>
/// Data storage
/// </summary>
public Lookup.Interface.ILookup<Word, MagickImage> Lookup { get; } =
new MemoryLookup<Word, MagickImage>();
/// <summary>
/// Constructor
/// </summary>
public ScreenshotScanner(IProcessor<MagickImage, ScanResult> processor)
{ {
/// <summary> Processor = processor;
/// The screenshot processor }
/// </summary>
protected IProcessor<MagickImage, ScanResult> Processor { get; }
/// <summary> /// <summary>
/// Data storage /// Process the provided <paramref name="images"/> and add the results to
/// </summary> /// the <see cref="Lookup"/>
public Lookup.Interface.ILookup<Word, MagickImage> Lookup { get; } = /// </summary>
new MemoryLookup<Word, MagickImage>(); /// <param name="images">The <see cref="MagickImage"/>s to process</param>
public void Process(IEnumerable<MagickImage> images)
/// <summary> {
/// Constructor foreach (var kv in Processor.Process(images))
/// </summary>
public ScreenshotScanner(IProcessor<MagickImage, ScanResult> processor)
{ {
Processor = processor; Lookup.Add(kv.Word, kv.Image);
}
/// <summary>
/// Process the provided <paramref name="images"/> and add the results to
/// the <see cref="Lookup"/>
/// </summary>
/// <param name="images">The <see cref="MagickImage"/>s to process</param>
public void Process(IEnumerable<MagickImage> images)
{
foreach (var kv in Processor.Process(images))
{
Lookup.Add(kv.Word, kv.Image);
}
}
public virtual void Clear()
{
Lookup.Clear();
} }
} }
}
public virtual void Clear()
{
Lookup.Clear();
}
}
+16 -17
View File
@@ -3,25 +3,24 @@ using GUI.Views;
using Serilog; using Serilog;
using System.Windows; using System.Windows;
namespace GUI namespace GUI;
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{ {
/// <summary> /// <inheritdoc />
/// Interaction logic for App.xaml protected override void OnStartup(StartupEventArgs e)
/// </summary>
public partial class App : Application
{ {
/// <inheritdoc /> base.OnStartup(e);
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var loggingCollection = new LoggingCollection(100); var loggingCollection = new LoggingCollection(100);
Log.Logger = new LoggerConfiguration() Log.Logger = new LoggerConfiguration()
.WriteTo.Sink(loggingCollection) .WriteTo.Sink(loggingCollection)
.CreateLogger(); .CreateLogger();
new LogView(loggingCollection).Show(); new LogView(loggingCollection).Show();
new ImageView().Show(); new ImageView().Show();
}
} }
} }
+35 -36
View File
@@ -2,44 +2,43 @@
using System.Windows; using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
namespace GUI.Controls namespace GUI.Controls;
/// <summary>
/// Interaction logic for ImageControl.xaml
/// </summary>
public partial class ImageControl : UserControl
{ {
/// <inheritdoc cref="Image"/>
public static readonly DependencyProperty ImageProperty = DependencyProperty.Register(
nameof(Image), typeof(MagickImage), typeof(ImageControl), new PropertyMetadata(default(MagickImage)));
/// <summary> /// <summary>
/// Interaction logic for ImageControl.xaml /// The <see cref="MagickImage"/> displayed in this <see cref="ImageControl"/>
/// </summary> /// </summary>
public partial class ImageControl : UserControl public MagickImage Image
{ {
/// <inheritdoc cref="Image"/> get => (MagickImage)GetValue(ImageProperty);
public static readonly DependencyProperty ImageProperty = DependencyProperty.Register( set => SetValue(ImageProperty, value);
nameof(Image), typeof(MagickImage), typeof(ImageControl), new PropertyMetadata(default(MagickImage)));
/// <summary>
/// The <see cref="MagickImage"/> displayed in this <see cref="ImageControl"/>
/// </summary>
public MagickImage Image
{
get => (MagickImage)GetValue(ImageProperty);
set => SetValue(ImageProperty, value);
}
/// <inheritdoc cref="ImageName"/>
public static readonly DependencyProperty ImageNameProperty = DependencyProperty.Register(
nameof(ImageName), typeof(object), typeof(ImageControl),
new PropertyMetadata(default(object)));
/// <summary>
/// The name of the loaded image
/// </summary>
public object ImageName
{
get => (object)GetValue(ImageNameProperty);
set => SetValue(ImageNameProperty, value);
}
/// <inheritdoc />
public ImageControl()
{
InitializeComponent();
}
} }
}
/// <inheritdoc cref="ImageName"/>
public static readonly DependencyProperty ImageNameProperty = DependencyProperty.Register(
nameof(ImageName), typeof(object), typeof(ImageControl),
new PropertyMetadata(default(object)));
/// <summary>
/// The name of the loaded image
/// </summary>
public object ImageName
{
get => (object)GetValue(ImageNameProperty);
set => SetValue(ImageNameProperty, value);
}
/// <inheritdoc />
public ImageControl()
{
InitializeComponent();
}
}
+37 -38
View File
@@ -6,49 +6,48 @@ using System.IO;
using System.Windows.Data; using System.Windows.Data;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
namespace GUI.Converters namespace GUI.Converters;
internal class ImageConverter : IValueConverter
{ {
internal class ImageConverter : IValueConverter #region Implementation of IValueConverter
/// <inheritdoc />
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{ {
#region Implementation of IValueConverter if (value is not MagickImage image)
/// <inheritdoc />
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{ {
if (value is not MagickImage image) return Binding.DoNothing;
{
return Binding.DoNothing;
}
try
{
using var stream = new MemoryStream();
// Save image to stream
image.Write(stream, MagickFormat.Png);
// Build Bitmap from stream
var imageSource = new BitmapImage();
imageSource.BeginInit();
imageSource.StreamSource = stream;
imageSource.CacheOption = BitmapCacheOption.OnLoad;
imageSource.EndInit();
return imageSource;
}
catch (Exception e)
{
Log.Error($"{e.Message}");
return Binding.DoNothing;
}
} }
/// <inheritdoc /> try
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{ {
throw new NotImplementedException(); using var stream = new MemoryStream();
}
#endregion // Save image to stream
image.Write(stream, MagickFormat.Png);
// Build Bitmap from stream
var imageSource = new BitmapImage();
imageSource.BeginInit();
imageSource.StreamSource = stream;
imageSource.CacheOption = BitmapCacheOption.OnLoad;
imageSource.EndInit();
return imageSource;
}
catch (Exception e)
{
Log.Error($"{e.Message}");
return Binding.DoNothing;
}
} }
}
/// <inheritdoc />
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion
}
+9 -10
View File
@@ -1,12 +1,11 @@
namespace GUI.ViewModels namespace GUI.ViewModels;
{
public class LogViewModel
{
public LoggingCollection LoggingCollection { get; }
public LogViewModel(LoggingCollection loggingCollection) public class LogViewModel
{ {
LoggingCollection = loggingCollection; public LoggingCollection LoggingCollection { get; }
}
public LogViewModel(LoggingCollection loggingCollection)
{
LoggingCollection = loggingCollection;
} }
} }
+37 -38
View File
@@ -5,44 +5,43 @@ using System.Windows;
using System.Windows.Controls; using System.Windows.Controls;
using System.Windows.Controls.Primitives; using System.Windows.Controls.Primitives;
namespace GUI.Views namespace GUI.Views;
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class ImageView : Window
{ {
/// <summary> private ImageViewModel ViewModel => (ImageViewModel)DataContext;
/// Interaction logic for MainWindow.xaml
/// </summary> public ImageView()
public partial class ImageView : Window
{ {
private ImageViewModel ViewModel => (ImageViewModel)DataContext; DataContext = new ImageViewModel();
InitializeComponent();
public ImageView()
{
DataContext = new ImageViewModel();
InitializeComponent();
}
public ImageView(MagickImage image)
{
DataContext = new ImageViewModel(image);
InitializeComponent();
}
private void SldThreshold1_OnDragCompleted(object sender, DragCompletedEventArgs args)
{
var vm = ViewModel;
vm.ProcessorConfig.ThresholdWidth = (int)Math.Round(((Slider)sender).Value);
}
private void SldThreshold2_OnDragCompleted(object sender, DragCompletedEventArgs args)
{
var vm = ViewModel;
vm.ProcessorConfig.ThresholdHeight = (int)Math.Round(((Slider)sender).Value);
}
private void SldBorder_OnDragCompleted(object sender, DragCompletedEventArgs e)
{
var vm = ViewModel;
vm.ProcessorConfig.Border = (int)Math.Round(((Slider)sender).Value);
}
} }
}
public ImageView(MagickImage image)
{
DataContext = new ImageViewModel(image);
InitializeComponent();
}
private void SldThreshold1_OnDragCompleted(object sender, DragCompletedEventArgs args)
{
var vm = ViewModel;
vm.ProcessorConfig.ThresholdWidth = (int)Math.Round(((Slider)sender).Value);
}
private void SldThreshold2_OnDragCompleted(object sender, DragCompletedEventArgs args)
{
var vm = ViewModel;
vm.ProcessorConfig.ThresholdHeight = (int)Math.Round(((Slider)sender).Value);
}
private void SldBorder_OnDragCompleted(object sender, DragCompletedEventArgs e)
{
var vm = ViewModel;
vm.ProcessorConfig.Border = (int)Math.Round(((Slider)sender).Value);
}
}
+10 -11
View File
@@ -1,17 +1,16 @@
using GUI.ViewModels; using GUI.ViewModels;
using System.Windows; using System.Windows;
namespace GUI.Views namespace GUI.Views;
/// <summary>
/// Interaction logic for LogView.xaml
/// </summary>
public partial class LogView : Window
{ {
/// <summary> public LogView(LoggingCollection loggingCollection)
/// Interaction logic for LogView.xaml
/// </summary>
public partial class LogView : Window
{ {
public LogView(LoggingCollection loggingCollection) InitializeComponent();
{ DataContext = new LogViewModel(loggingCollection);
InitializeComponent();
DataContext = new LogViewModel(loggingCollection);
}
} }
} }
+4 -10
View File
@@ -1,5 +1,4 @@
using ReportGenerator.Models; using ReportGenerator.Models;
using System.Text;
namespace ReportGenerator; namespace ReportGenerator;
@@ -15,19 +14,15 @@ internal static class Program
// Parse // Parse
Console.WriteLine("Evaluating"); Console.WriteLine("Generating report");
var scans = Scan(tagFileInfos, scanFileInfos); var scans = Scan(tagFileInfos, scanFileInfos);
var report = Table.ReportGenerator var report = ReportGenerator
.FromData(scans) .FromData(scans)
.WithTitle("OCR Report") .WithTitle("OCR Report")
.WithBestOf("Best of") .WithBestOf("Best of")
.WithFullStatistic("Statistic") .WithFullStatistic("Statistic");
.ToString();
// Generate output file report.ToFile("Report.md");
Console.WriteLine("Generating report");
File.WriteAllText("Report.md", report, Encoding.UTF8);
Console.WriteLine("Completed"); Console.WriteLine("Completed");
} }
@@ -48,7 +43,6 @@ internal static class Program
} }
} }
private static IEnumerable<TagFileInfo> GetTagFileInfos(string dir) private static IEnumerable<TagFileInfo> GetTagFileInfos(string dir)
{ {
if (!Directory.Exists(dir)) if (!Directory.Exists(dir))
@@ -3,7 +3,7 @@
"ReportGenerator": { "ReportGenerator": {
"commandName": "Project", "commandName": "Project",
"commandLineArgs": "\"img\" \"results\"", "commandLineArgs": "\"img\" \"results\"",
"workingDirectory": "D:\\git\\BA\\Examples\\CLI\\bin\\Debug\\net6.0" "workingDirectory": "D:\\git\\BA\\Examples\\testdata"
} }
} }
} }
+174
View File
@@ -0,0 +1,174 @@
using Common.Extensions;
using ReportGenerator.Models;
using System.Text;
namespace ReportGenerator;
public class ReportGenerator
{
private ICollection<ImageStats> Images { get; }
private readonly StringBuilder _sb = new();
private ReportGenerator(IEnumerable<ImageStats> stats) => Images = stats.ToArray();
public void ToFile(string path) =>
File.WriteAllText(path, ToString(), Encoding.UTF8);
/// <inheritdoc />
public override string ToString() =>
_sb.ToString();
#region Fluent definition
public ReportGenerator WithTitle(string text)
{
_sb.AppendHeading(1, text);
return this;
}
public ReportGenerator WithFullStatistic(string title)
{
_sb.AppendHeading(2, title);
foreach (var stat in Images)
{
_sb.AppendHeading(3, stat.ImageName);
_sb.AppendParagraph(HtmlImage(Path.Combine("img", stat.ImageName), 350, 350));
AppendRow(stat
.Reference
.Prepend("Image")
.Prepend("CER (avg)")
.Prepend("WER")
.Prepend("Elapsed")
.Prepend("Processor")
);
AppendRowSeparator(stat.Reference.Count + 5);
var processors = stat.Processors
.OrderBy(s => s.Distance)
.ThenBy(s => s.ProcessingTime);
foreach (var processor in processors)
{
var imgPath = Path.Combine("results", $"{processor.Name}.00.{stat.ImageName}.png");
AppendRow(processor.Words
.Select(s => s.ToString() ?? string.Empty)
.Prepend(HtmlImage(imgPath, 150, 150))
.Prepend(processor.Words.Average(s => s.Distance).ToString("F2"))
.Prepend($"{processor.Distance * 100:F1}%")
.Prepend($"{processor.ProcessingTime * 1000:F1}ms")
.Prepend(processor.Name)
);
}
_sb.AppendLine();
_sb.AppendParagraph(
$"*Comparison data generated based on {stat.Reference.Count} tagged words.*"
);
}
return this;
}
public ReportGenerator WithBestOf(string title, int context = 5)
{
_sb.AppendHeading(2, title);
var lookup = Images
.SelectMany(s => s.Processors)
.ToLookup(p => p.Name);
// Compare time across all images
var byTime = lookup
.Select(g => (Name: g.Key, Value: g.Average(p => p.ProcessingTime) * 1000))
.OrderBy(g => g.Value);
// Compare WER across all images
var byWer = lookup
.Select(g => (Name: g.Key, Value: g.Average(p => p.Distance) * 100))
.OrderBy(g => g.Value);
// Compare CER across all images
var byCer = lookup
.Select(g => (Name: g.Key, Value: g.Average(p => p.Words.Average(w => w.Distance))))
.OrderBy(g => g.Value);
// Print
AppendComparison(3, "Time", byTime, " ms");
AppendComparison(3, "WER", byWer, " %");
AppendComparison(3, "CER", byCer, " changes");
return this;
void AppendComparison(
int level,
string tableTitle,
IEnumerable<(string, double)> values,
string valueUnit = ""
)
{
var tValues = values.ToArray();
var tContext = Math.Min(tValues.Length / 2, context);
_sb.AppendHeading(level, tableTitle);
AppendRow(new[] { "Processor", "Average" });
AppendRowSeparator(2);
AppendRows(tValues.Take(tContext).Select(v => new[]
{
v.Item1,
v.Item2.ToString("F2") + valueUnit
}));
AppendRowSeparator(2, "...");
AppendRows(tValues.TakeLast(tContext).Select(v => new[]
{
v.Item1,
v.Item2.ToString("F2") + valueUnit
}));
}
}
#endregion
#region Helpers
private void AppendRow(IEnumerable<string> row)
{
const string separator = " | ";
_sb.AppendLine(separator + string.Join(" | ", row) + separator);
}
private void AppendRows(IEnumerable<IEnumerable<string>> rows)
{
foreach (var row in rows)
{
AppendRow(row);
}
}
private static string HtmlImage(string path, int maxWidth, int maxHeight)
{
if (!path.EndsWith(".png"))
{
path += ".png";
}
return $"<img src=\"{path}\" style=\"max-width:{maxWidth}px;max-height:{maxHeight}px;\" />";
}
private void AppendRowSeparator(int columns, string content = "---") =>
AppendRow(Enumerable.Range(0, columns).Select(_ => content));
#endregion
#region Factory Methods
public static ReportGenerator FromData(IEnumerable<ImageStats> stats) => new(stats);
#endregion
}
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
@@ -1,171 +0,0 @@
using Common.Extensions;
using ReportGenerator.Models;
using System.Text;
namespace ReportGenerator.Table
{
public class ReportGenerator
{
private ICollection<ImageStats> Images { get; }
private readonly StringBuilder _sb = new();
private ReportGenerator(IEnumerable<ImageStats> stats) => Images = stats.ToArray();
/// <inheritdoc />
public override string ToString() => _sb.ToString();
#region Fluent definition
public ReportGenerator WithTitle(string text)
{
_sb.AppendHeading(1, text);
return this;
}
public ReportGenerator WithFullStatistic(string title)
{
_sb.AppendHeading(2, title);
foreach (var stat in Images)
{
_sb.AppendHeading(3, stat.ImageName);
_sb.AppendParagraph(HtmlImage(Path.Combine("img", stat.ImageName), 350, 350));
AppendRow(stat
.Reference
.Prepend("Image")
.Prepend("CER (avg)")
.Prepend("WER")
.Prepend("Elapsed")
.Prepend("Processor")
);
AppendRowSeparator(stat.Reference.Count + 5);
var processors = stat.Processors
.OrderBy(s => s.Distance)
.ThenBy(s => s.ProcessingTime);
foreach (var processor in processors)
{
var imgPath = Path.Combine("results", $"{processor.Name}.00.{stat.ImageName}.png");
AppendRow(processor.Words
.Select(s => s.ToString() ?? string.Empty)
.Prepend(HtmlImage(imgPath, 150, 150))
.Prepend(processor.Words.Average(s => s.Distance).ToString("F2"))
.Prepend($"{processor.Distance * 100:F1}%")
.Prepend($"{processor.ProcessingTime * 1000:F1}ms")
.Prepend(processor.Name)
);
}
_sb.AppendLine();
_sb.AppendParagraph(
$"*Comparison data generated based on {stat.Reference.Count} tagged words.*"
);
}
return this;
}
public ReportGenerator WithBestOf(string title, int context = 5)
{
_sb.AppendHeading(2, title);
var lookup = Images
.SelectMany(s => s.Processors)
.ToLookup(p => p.Name);
// Compare time across all images
var byTime = lookup
.Select(g => (Name: g.Key, Value: g.Average(p => p.ProcessingTime) * 1000))
.OrderBy(g => g.Value);
// Compare WER across all images
var byWer = lookup
.Select(g => (Name: g.Key, Value: g.Average(p => p.Distance) * 100))
.OrderBy(g => g.Value);
// Compare CER across all images
var byCer = lookup
.Select(g => (Name: g.Key, Value: g.Average(p => p.Words.Average(w => w.Distance))))
.OrderBy(g => g.Value);
// Print
AppendComparison(3, "Time", byTime, " ms");
AppendComparison(3, "WER", byWer, " %");
AppendComparison(3, "CER", byCer, " changes");
return this;
void AppendComparison(
int level,
string tableTitle,
IEnumerable<(string, double)> values,
string valueUnit = ""
)
{
var tValues = values.ToArray();
var tContext = Math.Min(tValues.Length / 2, context);
_sb.AppendHeading(level, tableTitle);
AppendRow(new[] { "Processor", "Average" });
AppendRowSeparator(2);
AppendRows(tValues.Take(tContext).Select(v => new[]
{
v.Item1,
v.Item2.ToString("F2") + valueUnit
}));
AppendRowSeparator(2, "...");
AppendRows(tValues.TakeLast(tContext).Select(v => new[]
{
v.Item1,
v.Item2.ToString("F2") + valueUnit
}));
}
}
#endregion
#region Helpers
private void AppendRow(IEnumerable<string> row)
{
const string separator = " | ";
_sb.AppendLine(separator + string.Join(" | ", row) + separator);
}
private void AppendRows(IEnumerable<IEnumerable<string>> rows)
{
foreach (var row in rows)
{
AppendRow(row);
}
}
private static string HtmlImage(string path, int maxWidth, int maxHeight)
{
if (!path.EndsWith(".png"))
{
path += ".png";
}
return $"<img src=\"{path}\" style=\"max-width:{maxWidth}px;max-height:{maxHeight}px;\" />";
}
private void AppendRowSeparator(int columns, string content = "---") =>
AppendRow(Enumerable.Range(0, columns).Select(_ => content));
#endregion
#region Factory Methods
public static ReportGenerator FromData(IEnumerable<ImageStats> stats) => new(stats);
#endregion
}
}

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Before

Width:  |  Height:  |  Size: 116 KiB

After

Width:  |  Height:  |  Size: 116 KiB

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 105 KiB

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 101 KiB

Before

Width:  |  Height:  |  Size: 71 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 889 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Some files were not shown because too many files have changed in this diff Show More