diff --git a/src/BingImageDownload/BingInteractionAndParsing.cs b/src/BingImageDownload/BingInteractionAndParsing.cs index 106a017..3711bab 100644 --- a/src/BingImageDownload/BingInteractionAndParsing.cs +++ b/src/BingImageDownload/BingInteractionAndParsing.cs @@ -1,11 +1,11 @@ using SixLabors.ImageSharp; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net; -using System.Threading; using System.Xml.Linq; namespace BingImageDownload @@ -15,108 +15,107 @@ internal class BingInteractionAndParsing private const string Url = "https://bing.com"; private readonly ConsoleWriter consoleWriter; - private readonly ImageHashing imageHashing; + private readonly ImageFingerprinting imageFingerprinting; private readonly ImagePropertyHandling imagePropertyHandling; private readonly Paths paths; private readonly Serializer serializer; private readonly List urlsRetrieved; - private readonly List countries; private readonly string urlsRetrievedBinFile; - public BingInteractionAndParsing(ConsoleWriter consoleWriter, ImageHashing imageHashing, ImagePropertyHandling imagePropertyHandling, Paths paths, Serializer serializer) + public BingInteractionAndParsing(ConsoleWriter consoleWriter, ImageFingerprinting imageFingerprinting, ImagePropertyHandling imagePropertyHandling, Paths paths, Serializer serializer) { this.consoleWriter = consoleWriter; - this.imageHashing = imageHashing; + this.imageFingerprinting = imageFingerprinting; this.imagePropertyHandling = imagePropertyHandling; this.paths = paths; this.serializer = serializer; urlsRetrievedBinFile = Path.Combine(paths.AppData, "urlsRetrieved.bin"); urlsRetrieved = serializer.Deserialize>(urlsRetrievedBinFile).ToList(); - countries = CultureInfo.GetCultures(CultureTypes.AllCultures).Where(x => x.Name.Contains("-")).ToList(); consoleWriter.WriteLine($"Have loaded {urlsRetrieved.Count} previous URLs"); - consoleWriter.WriteLine($"Have loaded {countries.Count} countries"); } - internal void GetBingImages(CancellationToken cancellationToken) + internal (int countryDownloadedImages, int countryDuplicateImages, int countrySeenUrls) GetBingImages(CultureInfo country) { - var downloadedImages = 0; - - foreach (var country in countries) + consoleWriter.WriteLine($"Searching for images for {country.Name} - {country.DisplayName}"); + var stopwatch = new Stopwatch(); + stopwatch.Start(); + + var countryDownloadedImages = 0; + var countryDuplicateImages = 0; + var countrySeenUrls = 0; + var moreImages = true; + var datePairs = new Dictionary<(string start, string end), XElement>(); + while (moreImages) { - if (cancellationToken.IsCancellationRequested) + var imageNodes = GetImages(datePairs.Count, country.Name); + + if (!imageNodes.Any()) { - return; + moreImages = false; } - - consoleWriter.WriteLine($"Searching for images for {country.Name} - {country.DisplayName}"); - var countryImages = 0; - var countryDuplicateImages = 0; - var moreImages = true; - var datePairs = new Dictionary<(string start, string end), XElement>(); - while (moreImages) + else { - var imageNodes = GetImages(datePairs.Count, country.Name); - - if (!imageNodes.Any()) + foreach (var imageNode in imageNodes) { - moreImages = false; - } - else - { - foreach (var imageNode in imageNodes) - { - var startDate = imageNode.Element("startdate")?.Value; - var endDate = imageNode.Element("enddate")?.Value; - - if (datePairs.Any(x => x.Key.start == startDate && x.Key.end == endDate)) - { - moreImages = false; - continue; - } + var startDate = imageNode.Element("startdate")?.Value; + var endDate = imageNode.Element("enddate")?.Value; - datePairs.Add((startDate, endDate), imageNode); + if (datePairs.Any(x => x.Key.start == startDate && x.Key.end == endDate)) + { + moreImages = false; + continue; } + + datePairs.Add((startDate, endDate), imageNode); } } + } - foreach (var ((startDate, endDate), imageNode) in datePairs.OrderBy(x => x.Key.start)) + foreach (var ((startDate, endDate), imageNode) in datePairs.OrderBy(x => x.Key.start)) + { + var imageUrl = $"{Url}{imageNode.Element("urlBase")?.Value}_1920x1080.jpg"; + consoleWriter.WriteLine(1, $"Image for: '{country.Name}' on {startDate}-{endDate} was: {imageUrl}"); + try { - var imageUrl = $"{Url}{imageNode.Element("urlBase")?.Value}_1920x1080.jpg"; - consoleWriter.WriteLine(1, $"Image for: '{country.Name}' on {startDate}-{endDate} was: {imageUrl}"); - try + var result = DownloadAndSaveImage(imageNode, imageUrl); + switch (result) { - if (DownloadAndSaveImage(imageNode, imageUrl)) - { - countryImages++; - } - else - { + case DownloadResult.SeenUrl: + countrySeenUrls++; + break; + + case DownloadResult.DuplicateImage: countryDuplicateImages++; - } - } - catch (Exception ex) - { - consoleWriter.WriteLine("There was an error getting image", ex); + break; + + case DownloadResult.NewImage: + countryDownloadedImages++; + break; } } - - downloadedImages += countryImages; - consoleWriter.WriteLine($"Found {countryImages} new images for {country.Name}"); - consoleWriter.WriteLine($"Found {countryDuplicateImages} duplicate images for {country.Name}"); - consoleWriter.WriteLine(""); + catch (Exception ex) + { + consoleWriter.WriteLine("There was an error getting image", ex); + } } - consoleWriter.WriteLine($"Found {downloadedImages} new images"); + consoleWriter.WriteLine($"Found {countryDownloadedImages} new images for {country.Name}"); + consoleWriter.WriteLine($"Found {countryDuplicateImages} duplicate images for {country.Name}"); + consoleWriter.WriteLine($"Found {countrySeenUrls} urls already downloaded for {country.Name}"); + consoleWriter.WriteLine($"Duration {stopwatch.Elapsed.TotalSeconds} seconds for {country.Name}"); + consoleWriter.WriteLine(""); + + return (countryDownloadedImages, countryDuplicateImages, countrySeenUrls); } - internal bool DownloadAndSaveImage(XElement imageNode, string imageUrl) + private DownloadResult DownloadAndSaveImage(XElement imageNode, string imageUrl) { if (urlsRetrieved.Contains(imageUrl)) { consoleWriter.WriteLine(2, "Already Downloaded Image URL"); - return false; + return DownloadResult.SeenUrl; } var tempFilename = Path.Combine(paths.DownloadPath, Guid.NewGuid() + ".jpg"); @@ -129,18 +128,18 @@ internal bool DownloadAndSaveImage(XElement imageNode, string imageUrl) catch (Exception e) { consoleWriter.WriteLine(2, $"Error downloading image from url: {imageUrl}", e); - return false; + return DownloadResult.Error; } consoleWriter.WriteLine(2, "Downloaded Image, Checking If Duplicate"); var newImage = false; - var haveIdenticalImage = imageHashing.HaveIdenticalImageInHashTable(tempFilename); + var haveIdenticalImage = imageFingerprinting.HaveIdenticalImageInFingerprints(tempFilename); if (!haveIdenticalImage) { var filePath = Path.Combine(paths.SavePath, GetFileName(imageUrl)); var counter = 0; - while (imageHashing.HaveFileNameInHashTable(filePath)) + while (imageFingerprinting.HaveFileNameInFingerprints(filePath)) { counter++; filePath = Path.Combine(paths.SavePath, GetFileName(imageUrl, counter)); @@ -153,7 +152,7 @@ internal bool DownloadAndSaveImage(XElement imageNode, string imageUrl) imagePropertyHandling.SetImageExifTags(imageNode, srcImg); srcImg.Save(filePath); } - imageHashing.AddHash(filePath); + imageFingerprinting.AddFingerprint(filePath); } else { @@ -161,12 +160,13 @@ internal bool DownloadAndSaveImage(XElement imageNode, string imageUrl) } urlsRetrieved.Add(imageUrl); + SaveUrlBin(); File.Delete(tempFilename); - return newImage; + return newImage ? DownloadResult.NewImage : DownloadResult.DuplicateImage; } - internal string GetFileName(string imageUrl, int counter = 0) + private string GetFileName(string imageUrl, int counter = 0) { var name = imageUrl.Substring(7 + Url.Length); if (name.Contains("_")) @@ -184,7 +184,7 @@ internal string GetFileName(string imageUrl, int counter = 0) return Path.GetInvalidFileNameChars().Aggregate(name, (current, invalidChar) => current.Replace(invalidChar, '-')); } - internal List GetImages(int currentIndex, string country) + private List GetImages(int currentIndex, string country) { var urlToLoad = $"{Url}/HPImageArchive.aspx?format=xml&idx={currentIndex}&n=5&mkt={country}"; @@ -220,5 +220,13 @@ private void SaveUrlBin() { serializer.Serialize(urlsRetrieved, urlsRetrievedBinFile); } + + private enum DownloadResult + { + Error, + SeenUrl, + DuplicateImage, + NewImage + } } } diff --git a/src/BingImageDownload/ConsoleWriter.cs b/src/BingImageDownload/ConsoleWriter.cs index 80701b8..a6cdeac 100644 --- a/src/BingImageDownload/ConsoleWriter.cs +++ b/src/BingImageDownload/ConsoleWriter.cs @@ -13,7 +13,15 @@ internal class ConsoleWriter internal ConsoleWriter(Paths paths) { Console.OutputEncoding = Encoding.UTF8; - logWriter = new StreamWriter(Path.Combine(paths.LogPath, $"Log-{DateTime.UtcNow:yyyy-MM-dd}.txt"), false, Encoding.UTF8); + var logPath = Path.Combine(paths.LogPath, $"Log {DateTime.UtcNow:yyyy-MM-dd}.txt"); + var counter = 0; + while (File.Exists(logPath)) + { + counter++; + logPath = Path.Combine(paths.LogPath, $"Log {DateTime.UtcNow:yyyy-MM-dd} ({counter}).txt"); + } + + logWriter = new StreamWriter(logPath, false, Encoding.UTF8); if (tempBuilder.Length > 0) { @@ -66,7 +74,11 @@ internal void WriteToFile(string textLine) if (tempBuilder.Length > 0) { - logWriter.Write(tempBuilder.ToString()); + lock (lockThis) + { + logWriter.Write(tempBuilder.ToString()); + } + tempBuilder.Clear(); } diff --git a/src/BingImageDownload/ImageFingerprinting.cs b/src/BingImageDownload/ImageFingerprinting.cs new file mode 100644 index 0000000..79f9961 --- /dev/null +++ b/src/BingImageDownload/ImageFingerprinting.cs @@ -0,0 +1,130 @@ +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace BingImageDownload +{ + internal class ImageFingerprinting + { + private readonly ConsoleWriter consoleWriter; + private readonly Serializer serializer; + private readonly Paths paths; + private readonly List imageFingerprints; + private readonly string fingerprintBinFile; + + internal ImageFingerprinting(ConsoleWriter consoleWriter, Paths paths, Serializer serializer) + { + this.consoleWriter = consoleWriter; + this.serializer = serializer; + this.paths = paths; + fingerprintBinFile = Path.Combine(paths.AppData, "imageFingerprints.bin"); + imageFingerprints = serializer.Deserialize>(fingerprintBinFile); + + consoleWriter.WriteLine($"Have loaded {imageFingerprints.Count} previous fingerprints"); + + RemoveInvalidFingerprintsEntries(); + + consoleWriter.WriteLine($"Have {imageFingerprints.Count} previous fingerprints after removing invalid"); + + FingerprintExistingImages(); + + consoleWriter.WriteLine($"Have {imageFingerprints.Count} previous fingerprints after adding missing"); + + RemoveInvalidFingerprintsEntries(); + + consoleWriter.WriteLine($"Have {imageFingerprints.Count} previous fingerprints after removing invalid (again)"); + + SaveFingerprintBin(); + } + + internal bool HaveIdenticalImageInFingerprints(string tempFilename) + { + var tempFileFingerprint = GetImageFingerprint(tempFilename); + return imageFingerprints.Any(fingerprint => fingerprint.Equal(tempFileFingerprint)); + } + + internal bool HaveFileNameInFingerprints(string filePath) + { + var fileName = Path.GetFileName(filePath); + return imageFingerprints.Any(x => x.FileName.Equals(fileName, StringComparison.InvariantCultureIgnoreCase)); + } + + internal void AddFingerprint(string filePath, bool saveFingerprints = true) + { + if (HaveFileNameInFingerprints(filePath)) return; + + imageFingerprints.Add(GetImageFingerprint(filePath)); + + if (saveFingerprints) + { + SaveFingerprintBin(); + } + } + + private void SaveFingerprintBin() + { + serializer.Serialize(imageFingerprints, fingerprintBinFile); + } + + private void RemoveInvalidFingerprintsEntries() + { + imageFingerprints.RemoveAll(x => x.IsInvalid(paths)); + } + + private void FingerprintExistingImages(int retryCount = 0) + { + consoleWriter.WriteLine(retryCount > 0 ? $"Fingerprinting missing images (attempt: {retryCount + 1})" : "Fingerprinting missing images"); + + try + { + foreach (var file in Directory.GetFiles(paths.SavePath, "*.jpg").Where(x => !HaveFileNameInFingerprints(x))) + { + consoleWriter.WriteLine($"Fingerprinting file: {file}"); + AddFingerprint(file, false); + } + + foreach (var file in Directory.GetFiles(paths.ArchivePath, "*.jpg").Where(x => !HaveFileNameInFingerprints(x))) + { + consoleWriter.WriteLine($"Fingerprinting file: {file}"); + AddFingerprint(file, false); + } + } + catch (Exception) when (retryCount < 3) + { + FingerprintExistingImages(retryCount + 1); + } + } + + private ImageFingerprint GetImageFingerprint(string filePath) + { + var histogramFile = Path.Combine(paths.HistogramPath, Guid.NewGuid() + ".jpg"); + File.Copy(filePath, histogramFile); + var rgb = new List(); + var fileName = Path.GetFileName(filePath); + + using (var image = Image.Load(histogramFile)) + { + //Scale down from 1920*1080 to 48*27 - this will pixelate but enough to tell differences. + //This means 1,296 total pixels rather than 2,073,600. + image.Mutate(x => x.Resize(48, 27).Grayscale()); + + for (var x = 0; x < image.Width; x++) + { + for (var y = 0; y < image.Height; y++) + { + var pixel = image[x, y]; + rgb.Add(new ImageFingerprint.RgbPixelData(x, y, pixel.R + pixel.G + pixel.B)); + } + } + } + + File.Delete(histogramFile); + + return new ImageFingerprint(fileName, rgb); + } + } +} diff --git a/src/BingImageDownload/ImageHashing.cs b/src/BingImageDownload/ImageHashing.cs deleted file mode 100644 index fdb68e8..0000000 --- a/src/BingImageDownload/ImageHashing.cs +++ /dev/null @@ -1,137 +0,0 @@ -using SixLabors.ImageSharp; -using SixLabors.ImageSharp.PixelFormats; -using SixLabors.ImageSharp.Processing; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace BingImageDownload -{ - internal class ImageHashing - { - private readonly ConsoleWriter consoleWriter; - private readonly Serializer serializer; - private readonly Paths paths; - private readonly List histogramHashTable; - private readonly string histogramBinFile; - - internal ImageHashing(ConsoleWriter consoleWriter, Paths paths, Serializer serializer) - { - this.consoleWriter = consoleWriter; - this.serializer = serializer; - this.paths = paths; - histogramBinFile = Path.Combine(paths.AppData, "imageHistogram.bin"); - histogramHashTable = serializer.Deserialize>(histogramBinFile); - - consoleWriter.WriteLine($"Have loaded {histogramHashTable.Count} previous hashes"); - - RemoveInvalidHashEntries(); - - consoleWriter.WriteLine($"Have {histogramHashTable.Count} previous hashes after removing invalid"); - - HashExistingImages(); - - consoleWriter.WriteLine($"Have {histogramHashTable.Count} previous hashes after adding missing"); - - RemoveInvalidHashEntries(); - - consoleWriter.WriteLine($"Have {histogramHashTable.Count} previous hashes after removing invalid (again)"); - - SaveHashTableBin(); - } - - internal bool HaveIdenticalImageInHashTable(string tempFilename) - { - var testHash = GetRgbHistogramHash(tempFilename); - return histogramHashTable.Any(hash => hash.Equal(testHash)); - } - - internal bool HaveFileNameInHashTable(string filePath) - { - var fileName = Path.GetFileName(filePath); - return histogramHashTable.Any(x => x.FileName.Equals(fileName, StringComparison.InvariantCultureIgnoreCase)); - } - - internal void AddHash(string filePath, bool saveHashTable = true) - { - if (HaveFileNameInHashTable(filePath)) return; - - histogramHashTable.Add(GetRgbHistogramHash(filePath)); - - if (saveHashTable) - { - SaveHashTableBin(); - } - } - - private void SaveHashTableBin() - { - serializer.Serialize(histogramHashTable, histogramBinFile); - } - - private void RemoveInvalidHashEntries() - { - histogramHashTable.RemoveAll(x => x.IsInvalid(paths)); - } - - private void HashExistingImages(int retryCount = 0) - { - consoleWriter.WriteLine($"Hashing images missing from hash (attempt: {retryCount + 1})"); - - try - { - foreach (var file in Directory.GetFiles(paths.SavePath, "*.jpg").Where(x => !HaveFileNameInHashTable(x))) - { - consoleWriter.WriteLine($"Hashing file: {file}"); - AddHash(file, false); - } - - foreach (var file in Directory.GetFiles(paths.ArchivePath, "*.jpg").Where(x => !HaveFileNameInHashTable(x))) - { - consoleWriter.WriteLine($"Hashing file: {file}"); - AddHash(file, false); - } - } - catch (Exception) - { - if (retryCount < 5) - { - HashExistingImages(retryCount + 1); - } - else - { - throw; - } - } - } - - private HistogramHash GetRgbHistogramHash(string filePath) - { - var histogramFile = Path.Combine(paths.HistogramPath, Guid.NewGuid() + ".jpg"); - File.Copy(filePath, histogramFile); - var Rgb = new List(); - var fileName = Path.GetFileName(filePath); - - using (var image = Image.Load(histogramFile)) - { - //Scale down from 1920*1080 to 48*27 - this will pixelate but enough to tell differences. - //This means 1296 total pixels rather than 2073600. - image.Mutate(x => x.Resize(48, 27).Grayscale()); - - for (var x = 0; x < image.Width; x++) - { - for (var y = 0; y < image.Height; y++) - { - var pixel = image[x, y]; - Rgb.Add(new RgbPixelData(x, y, pixel.R + pixel.G + pixel.B)); - } - } - } - - File.Delete(histogramFile); - - return new HistogramHash(fileName, Rgb); - } - } -} diff --git a/src/BingImageDownload/HistogramHash.cs b/src/BingImageDownload/ImageRecord.cs similarity index 61% rename from src/BingImageDownload/HistogramHash.cs rename to src/BingImageDownload/ImageRecord.cs index 0b3d9fa..7f34ad1 100644 --- a/src/BingImageDownload/HistogramHash.cs +++ b/src/BingImageDownload/ImageRecord.cs @@ -5,12 +5,12 @@ namespace BingImageDownload { - public class HistogramHash + public class ImageFingerprint { public string FileName { get; } public List Rgb { get; } - public HistogramHash(string fileName, List rgb) + public ImageFingerprint(string fileName, List rgb) { FileName = fileName; Rgb = rgb; @@ -20,11 +20,11 @@ internal bool IsInvalid(Paths paths) { if (string.IsNullOrWhiteSpace(FileName)) return true; if (!File.Exists(Path.Combine(paths.SavePath, FileName)) && !File.Exists(Path.Combine(paths.ArchivePath, FileName))) return true; - if (Rgb == null || !Rgb.Any()) return true; + if (Rgb == null || Rgb.Count != 1296 || Rgb.All(x => x.Rgb == 0)) return true; return false; } - internal bool Equal(HistogramHash other) + internal bool Equal(ImageFingerprint other) { var differencesOverTolerance = 0f; @@ -33,7 +33,7 @@ internal bool Equal(HistogramHash other) var otherVal = other.Rgb.FirstOrDefault(x => x.X.Equals(val.X) && x.Y.Equals(val.Y)); if (otherVal == null) return false; - var difference = Math.Abs(val.RGB - otherVal.RGB); + var difference = Math.Abs(val.Rgb - otherVal.Rgb); if (difference > 3) { differencesOverTolerance++; @@ -42,7 +42,21 @@ internal bool Equal(HistogramHash other) var differencePercent = differencesOverTolerance / Rgb.Count * 100; - return differencePercent < 1f; + return differencePercent < 5f; + } + + public class RgbPixelData + { + public int Rgb { get; } + public int X { get; } + public int Y { get; } + + public RgbPixelData(int x, int y, int rgb) + { + Rgb = rgb; + X = x; + Y = y; + } } } } diff --git a/src/BingImageDownload/RgbPixelData.cs b/src/BingImageDownload/RgbPixelData.cs deleted file mode 100644 index f719f0a..0000000 --- a/src/BingImageDownload/RgbPixelData.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace BingImageDownload -{ - public class RgbPixelData - { - public int RGB { get; } - public int X { get; } - public int Y { get; } - - public RgbPixelData(int x, int y, int rgb) - { - RGB = rgb; - X = x; - Y = y; - } - } -} diff --git a/src/BingImageDownload/Runner.cs b/src/BingImageDownload/Runner.cs index 5e49702..57eee49 100644 --- a/src/BingImageDownload/Runner.cs +++ b/src/BingImageDownload/Runner.cs @@ -1,4 +1,7 @@ using System; +using System.Diagnostics; +using System.Globalization; +using System.Linq; using System.Threading; namespace BingImageDownload @@ -13,14 +16,43 @@ public static int Start(RunnerArgs runnerArgs, in CancellationToken cancellation consoleWriter.WriteLine($"Saving to: {paths.SavePath}"); var serializer = new Serializer(consoleWriter); - var imageHashing = new ImageHashing(consoleWriter, paths, serializer); + var imageFingerprinting = new ImageFingerprinting(consoleWriter, paths, serializer); var imagePropertyHandling = new ImagePropertyHandling(); - var bingInteractionAndParsing = new BingInteractionAndParsing(consoleWriter, imageHashing, imagePropertyHandling, paths, serializer); + var bingInteractionAndParsing = new BingInteractionAndParsing(consoleWriter, imageFingerprinting, imagePropertyHandling, paths, serializer); var fileClearer = new FileClearer(consoleWriter, paths, runnerArgs.ArchiveMonths); try { - bingInteractionAndParsing.GetBingImages(cancellationToken); + var downloadedImages = 0; + var duplicateImages = 0; + var seenUrls = 0; + + var countries = CultureInfo.GetCultures(CultureTypes.AllCultures).Where(x => x.Name.Contains("-")).ToList(); + consoleWriter.WriteLine($"Have loaded {countries.Count} countries"); + + var stopwatch = new Stopwatch(); + stopwatch.Start(); + + foreach (var country in countries) + { + if (cancellationToken.IsCancellationRequested) + { + break; + } + + var (countryDownloadedImages, countryDuplicateImages, countrySeenUrls) = bingInteractionAndParsing.GetBingImages(country); + + downloadedImages += countryDownloadedImages; + duplicateImages += countryDuplicateImages; + seenUrls += countrySeenUrls; + } + + consoleWriter.WriteLine("Summary:"); + consoleWriter.WriteLine($"Found {downloadedImages} new images"); + consoleWriter.WriteLine($"Found {duplicateImages} duplicate images"); + consoleWriter.WriteLine($"Found {seenUrls} urls already downloaded"); + consoleWriter.WriteLine($"Duration {stopwatch.Elapsed.TotalMinutes} minutes"); + if (cancellationToken.IsCancellationRequested) { return -2; @@ -33,8 +65,8 @@ public static int Start(RunnerArgs runnerArgs, in CancellationToken cancellation } finally { - consoleWriter.WriteLine("Done, waiting 15 seconds before clearing up"); - Thread.Sleep(TimeSpan.FromSeconds(15)); + consoleWriter.WriteLine("Done, waiting 5 seconds before clearing up"); + Thread.Sleep(TimeSpan.FromSeconds(5)); consoleWriter.WriteLine("Clearing up"); fileClearer.ArchiveOldImages(); fileClearer.ClearLogFiles();