| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469 |
- using PicView.ImageHandling;
- using System.Collections.Concurrent;
- using System.Diagnostics;
- using System.IO;
- using System.Threading.Tasks;
- using System.Windows.Media.Imaging;
- using static PicView.Library.Fields;
- namespace PicView.ChangeImage
- {
- /// <summary>
- /// Used for containing a list of BitmapSources
- /// </summary>
- internal static class Preloader
- {
- /// <summary>
- /// Start preload every third entry
- /// </summary>
- /// <returns></returns>
- internal static bool StartPreload()
- {
- if (FreshStartup || PreloadCount > 2 || PreloadCount < -2)
- {
- PreloadCount = 0;
- return true;
- }
- return false;
- }
- /// <summary>
- /// Preloader list of BitmapSources
- /// </summary>
- private static readonly ConcurrentDictionary<string, BitmapSource> Sources = new ConcurrentDictionary<string, BitmapSource>();
- /// <summary>
- /// When Preloader is adding an image
- /// </summary>
- internal static bool IsLoading;
- /// <summary>
- /// Used for manual loading fix
- /// </summary>
- internal static bool IsReset;
- //internal static int Count { get { return Sources.Count; } }
- /// <summary>
- /// Add file to prelader
- /// </summary>
- /// <param name="file">file path</param>
- internal static async Task<bool> Add(string file)
- {
- if (Contains(file) || Pics.Count == 0 || Pics.IndexOf(file) == -1)
- {
- return IsLoading = false;
- }
- IsLoading = true;
- var pic = await ImageDecoder.RenderToBitmapSource(file).ConfigureAwait(true);
- if (pic == null)
- {
- return IsLoading = false;
- }
- if (!pic.IsFrozen)
- {
- pic.Freeze();
- }
- IsLoading = false;
- #if DEBUG
- Trace.WriteLine("Add string file = " + file + " to Preloader, index " + Pics.IndexOf(file));
- #endif
- return Sources.TryAdd(file, pic);
- }
- /// <summary>
- /// Add file to preloader from index
- /// </summary>
- /// <param name="i">Index of Pics</param>
- internal static async Task<bool> Add(int i)
- {
- if (i >= Pics.Count || i < 0)
- {
- return false;
- }
- IsLoading = true;
- if (File.Exists(Pics[i]))
- {
- if (!Contains(Pics[i]))
- {
- return await Add(Pics[i]).ConfigureAwait(true);
- }
- else
- {
- #if DEBUG
- Trace.WriteLine("Skipped at index " + i);
- #endif
- return false;
- }
- }
- else
- {
- Pics.Remove(Pics[i]);
- #if DEBUG
- Trace.WriteLine("Preloader removed = " + Pics[i] + " from Pics, index " + i);
- #endif
- return IsLoading = false;
- }
- }
- internal static void Add(BitmapSource bmp, string key)
- {
- if (string.IsNullOrWhiteSpace(key))
- {
- #if DEBUG
- Trace.WriteLine("Preloader.Add key is null");
- #endif
- return;
- }
- if (Contains(key))
- {
- #if DEBUG
- Trace.WriteLine("Preloader.Add already contains " + key);
- #endif
- return;
- }
- if (bmp == null)
- {
- #if DEBUG
- Trace.WriteLine("Preloader.Add bmp null " + key);
- #endif
- return;
- }
- if (!bmp.IsFrozen)
- {
- bmp.Freeze();
- }
- #if DEBUG
- if (Sources.TryAdd(key, bmp))
- {
- Trace.WriteLine("Manually added = " + key + " to Preloader, index " + Pics.IndexOf(key));
- }
- else
- {
- Trace.WriteLine("Preloader failed to add = " + key + " , index " + Pics.IndexOf(key));
- }
- #else
- Sources.TryAdd(key, bmp);
- #endif
- }
- /// <summary>
- /// Removes the key, after checking if it exists
- /// </summary>
- /// <param name="key"></param>
- internal static void Remove(string key)
- {
- if (key == null)
- {
- #if DEBUG
- Trace.WriteLine("Preloader.Remove key null, " + key);
- #endif
- return;
- }
- if (!Contains(key))
- {
- #if DEBUG
- Trace.WriteLine("Preloader.Remove does not contain " + key);
- #endif
- return;
- }
- _ = Sources[key];
- #if DEBUG
- if (Sources.TryRemove(key, out _))
- {
- Trace.WriteLine("Removed = " + key + " from Preloader, index " + Pics.IndexOf(key));
- }
- else
- {
- Trace.WriteLine("Failed to Remove = " + key + " from Preloader, index " + Pics.IndexOf(key));
- }
- #else
- Sources.TryRemove(key, out _);
- #endif
- }
- /// <summary>
- /// Removes the key, after checking if it exists
- /// </summary>
- /// <param name="key"></param>
- internal static void Remove(int i)
- {
- if (i >= Pics.Count || i < 0)
- {
- return;
- }
- if (File.Exists(Pics[i]))
- {
- if (Contains(Pics[i]))
- {
- Remove(Pics[i]);
- }
- }
- }
- /// <summary>
- /// Removes all keys
- /// </summary>
- internal static void Clear()
- {
- if (Sources.Count <= 0)
- {
- return;
- }
- Sources.Clear();
- PreloadCount = 4; // Reset to make sure
- #if DEBUG
- Trace.WriteLine("Cleared Preloader");
- #endif
- }
- /// <summary>
- /// Removes specific keys
- /// </summary>
- /// <param name="array"></param>
- internal static void Clear(string[] array)
- {
- for (int i = 0; i < array.Length; i++)
- {
- Remove(array[i]);
- #if DEBUG
- Trace.WriteLine("Removed = " + array[i] + " from Preloader");
- #endif
- }
- }
- /// <summary>
- /// Returns the specified BitmapSource.
- /// Returns null if key not found.
- /// </summary>
- /// <param name="key"></param>
- /// <returns></returns>
- internal static BitmapSource Load(string key)
- {
- if (string.IsNullOrWhiteSpace(key) || !Contains(key))
- {
- return null;
- }
- return Sources[key];
- }
- /// <summary>
- /// Checks if the specified key exists
- /// </summary>
- /// <param name="key"></param>
- /// <returns></returns>
- internal static bool Contains(string key)
- {
- if (string.IsNullOrWhiteSpace(key) || Sources.Count <= 0)
- {
- return false;
- }
- return Sources.ContainsKey(key);
- }
- internal static async void PreloaderFix(string file)
- {
- if (!Contains(file))
- {
- PreloadCount = 4;
- IsReset = true;
- await Add(file).ConfigureAwait(false);
- }
- }
- /// <summary>
- /// Starts decoding images into memory,
- /// based on current index and if reverse or not
- /// </summary>
- /// <param name="index"></param>
- /// <param name="reverse"></param>
- internal static Task PreLoad(int index)
- {
- #if DEBUG
- Trace.WriteLine("Preolader started, "
- + string.Concat(Properties.Settings.Default.Looping ? "looping " : string.Empty)
- + string.Concat(Reverse ? "backwards" : "forwards"));
- #endif
- return Task.Run(async () =>
- {
- var toLoad = 8;
- var extraToLoad = toLoad / 2;
- var cleanUp = toLoad + extraToLoad;
- // Not looping
- if (!Properties.Settings.Default.Looping)
- {
- // Forwards
- if (!Reverse)
- {
- // Add first elements
- for (int i = index + 1; i < (index + 1) + toLoad; i++)
- {
- if (i > Pics.Count)
- {
- break;
- }
- await Add(i).ConfigureAwait(false);
- }
- // Add second elements behind
- for (int i = index - 1; i > (index - 1) - extraToLoad; i--)
- {
- if (i < 0)
- {
- break;
- }
- await Add(i).ConfigureAwait(false);
- }
- //Clean up behind
- if (Pics.Count > cleanUp * 2 && !FreshStartup)
- {
- for (int i = (index - 1) - cleanUp; i < ((index - 1) - extraToLoad); i++)
- {
- if (i < 0)
- {
- continue;
- }
- if (i > Pics.Count)
- {
- break;
- }
- Remove(i);
- }
- }
- }
- // Backwards
- else
- {
- // Add first elements behind
- for (int i = index - 1; i > (index - 1) - toLoad; i--)
- {
- if (i < 0)
- {
- break;
- }
- await Add(i).ConfigureAwait(false);
- }
- // Add second elements
- for (int i = index + 1; i <= (index + 1) + toLoad; i++)
- {
- if (i > Pics.Count)
- {
- break;
- }
- await Add(i).ConfigureAwait(false);
- }
- //Clean up infront
- if (Pics.Count > cleanUp * 2 && !FreshStartup)
- {
- for (int i = (index + 1) + cleanUp; i > ((index + 1) + cleanUp) - extraToLoad; i--)
- {
- if (i < 0)
- {
- continue;
- }
- if (i > Pics.Count)
- {
- break;
- }
- Remove(i);
- }
- }
- }
- }
- // Looping!
- else
- {
- // Forwards
- if (!Reverse)
- {
- // Add first elements
- for (int i = index + 1; i < (index + 1) + toLoad; i++)
- {
- await Add(i % Pics.Count).ConfigureAwait(false);
- }
- // Add second elements behind
- for (int i = index - 1; i > (index - 1) - extraToLoad; i--)
- {
- await Add(i % Pics.Count).ConfigureAwait(false);
- }
- //Clean up behind
- if (Pics.Count > cleanUp * 2 && !FreshStartup)
- {
- for (int i = (index - 1) - cleanUp; i < ((index - 1) - extraToLoad); i++)
- {
- Remove(i % Pics.Count);
- }
- }
- }
- // Backwards
- else
- {
- // Add first elements behind
- int y = 0;
- for (int i = index - 1; i > (index - 1) - toLoad; i--)
- {
- y++;
- if (i < 0)
- {
- for (int x = Pics.Count - 1; x >= Pics.Count - y; x--)
- {
- await Add(x).ConfigureAwait(false);
- }
- break;
- }
- await Add(i).ConfigureAwait(false);
- }
- // Add second elements
- for (int i = index + 1; i <= (index + 1) + toLoad; i++)
- {
- await Add(i % Pics.Count).ConfigureAwait(false);
- }
- //Clean up infront
- if (Pics.Count > cleanUp + toLoad && !FreshStartup)
- {
- for (int i = (index + 1) + cleanUp; i > ((index + 1) + cleanUp) - extraToLoad; i--)
- {
- Remove(i % Pics.Count);
- }
- }
- }
- }
- IsLoading = false; // Fixes loading erros
- });
- }
- }
- }
|