Procházet zdrojové kódy

Update for .NET 8, performance improvements, etc

Ruben před 2 roky
rodič
revize
af8b4f9a63

+ 11 - 1
src/PicView/ChangeImage/FastPic.cs

@@ -64,7 +64,17 @@ internal static class FastPic
             }
             }
         }
         }
 
 
-        await UpdateImage.UpdateImageValuesAsync(index, preLoadValue).ConfigureAwait(false);
+        _ = UpdateImage.UpdateImageValuesAsync(index, preLoadValue).ConfigureAwait(false);
+        if (UC.GetPicGallery is not null)
+        {
+            await UC.GetPicGallery.Dispatcher.InvokeAsync(() =>
+            {
+                // Select next item
+                GalleryNavigation.SetSelected(FolderIndex, true);
+                GalleryNavigation.SelectedGalleryItem = FolderIndex;
+                GalleryNavigation.ScrollToGalleryCenter();
+            });
+        }
 
 
         _updateSource = false;
         _updateSource = false;
         await PreLoader.PreLoadAsync(index, Pics.Count).ConfigureAwait(false);
         await PreLoader.PreLoadAsync(index, Pics.Count).ConfigureAwait(false);

+ 36 - 32
src/PicView/ChangeImage/FileHistory.cs

@@ -104,55 +104,59 @@ internal class FileHistory
             }
             }
 
 
             SetTitle.SetLoadingString();
             SetTitle.SetLoadingString();
+            UC.GetSpinWaiter.Visibility = Visibility.Visible;
         }, DispatcherPriority.Normal);
         }, DispatcherPriority.Normal);
 
 
-        if (Settings.Default.IncludeSubDirectories)
+        await Task.Run(async () => // Make sure UI responsive
         {
         {
-            if (_fileHistory.Last().IsArchive())
+            if (Settings.Default.IncludeSubDirectories)
             {
             {
-                await LoadPic.LoadPicFromArchiveAsync(_fileHistory.Last()).ConfigureAwait(false);
-                return;
-            }
-            var currentFolder = Path.GetDirectoryName(_fileHistory.Last());
-            var parentFolder = Path.GetDirectoryName(currentFolder);
-            var fileInfo = new FileInfo(parentFolder);
-            Navigation.Pics = await Task.FromResult(FileLists.FileList(fileInfo)).ConfigureAwait(false);
-            if (Navigation.Pics.Count > 0)
-            {
-                Navigation.FolderIndex = Navigation.Pics.IndexOf(_fileHistory.Last());
-                await LoadPic.LoadPicAtIndexAsync(Navigation.FolderIndex).ConfigureAwait(false);
-
-                // Fix if Bottom Gallery is enabled
-                if (Settings.Default.IsBottomGalleryShown)
+                if (_fileHistory.Last().IsArchive())
                 {
                 {
-                    if (UC.GetPicGallery is { Visibility: Visibility.Collapsed })
+                    await LoadPic.LoadPicFromArchiveAsync(_fileHistory.Last()).ConfigureAwait(false);
+                    return;
+                }
+                var currentFolder = Path.GetDirectoryName(_fileHistory.Last());
+                var parentFolder = Path.GetDirectoryName(currentFolder);
+                var fileInfo = new FileInfo(parentFolder);
+                Navigation.Pics = await Task.FromResult(FileLists.FileList(fileInfo)).ConfigureAwait(false);
+                if (Navigation.Pics.Count > 0)
+                {
+                    Navigation.FolderIndex = Navigation.Pics.IndexOf(_fileHistory.Last());
+                    await LoadPic.LoadPicAtIndexAsync(Navigation.FolderIndex).ConfigureAwait(false);
+
+                    // Fix if Bottom Gallery is enabled
+                    if (Settings.Default.IsBottomGalleryShown)
                     {
                     {
-                        var shouldLoadGallery = false;
-                        await UC.GetPicGallery.Dispatcher.InvokeAsync(() =>
+                        if (UC.GetPicGallery is { Visibility: Visibility.Collapsed })
                         {
                         {
-                            GalleryToggle.ShowBottomGallery();
-                            ScaleImage.TryFitImage();
-                            if (UC.GetPicGallery.Container.Children.Count <= 0)
+                            var shouldLoadGallery = false;
+                            await UC.GetPicGallery.Dispatcher.InvokeAsync(() =>
+                            {
+                                GalleryToggle.ShowBottomGallery();
+                                ScaleImage.TryFitImage();
+                                if (UC.GetPicGallery.Container.Children.Count <= 0)
+                                {
+                                    shouldLoadGallery = true;
+                                }
+                            });
+                            if (shouldLoadGallery)
                             {
                             {
-                                shouldLoadGallery = true;
+                                await GalleryLoad.LoadAsync().ConfigureAwait(false);
                             }
                             }
-                        });
-                        if (shouldLoadGallery)
-                        {
-                            await GalleryLoad.LoadAsync().ConfigureAwait(false);
                         }
                         }
                     }
                     }
                 }
                 }
+                else
+                {
+                    await LoadPic.LoadPicFromStringAsync(_fileHistory.Last()).ConfigureAwait(false);
+                }
             }
             }
             else
             else
             {
             {
                 await LoadPic.LoadPicFromStringAsync(_fileHistory.Last()).ConfigureAwait(false);
                 await LoadPic.LoadPicFromStringAsync(_fileHistory.Last()).ConfigureAwait(false);
             }
             }
-        }
-        else
-        {
-            await LoadPic.LoadPicFromStringAsync(_fileHistory.Last()).ConfigureAwait(false);
-        }
+        });
     }
     }
 
 
     internal void Add(string fileName)
     internal void Add(string fileName)

+ 89 - 49
src/PicView/ChangeImage/LoadPic.cs

@@ -8,12 +8,16 @@ using System.Diagnostics;
 using System.IO;
 using System.IO;
 using System.Windows;
 using System.Windows;
 using System.Windows.Threading;
 using System.Windows.Threading;
+using PicView.UILogic.Sizing;
 using static PicView.ChangeImage.ErrorHandling;
 using static PicView.ChangeImage.ErrorHandling;
 using static PicView.ChangeImage.Navigation;
 using static PicView.ChangeImage.Navigation;
 using static PicView.ChangeTitlebar.SetTitle;
 using static PicView.ChangeTitlebar.SetTitle;
 using static PicView.FileHandling.ArchiveExtraction;
 using static PicView.FileHandling.ArchiveExtraction;
 using static PicView.FileHandling.FileLists;
 using static PicView.FileHandling.FileLists;
 using static PicView.UILogic.UC;
 using static PicView.UILogic.UC;
+using PicView.Views.UserControls.Gallery;
+using System.Windows.Media.Imaging;
+using ImageMagick;
 
 
 namespace PicView.ChangeImage;
 namespace PicView.ChangeImage;
 
 
@@ -31,67 +35,70 @@ internal static class LoadPic
     {
     {
         await ConfigureWindows.GetMainWindow.Dispatcher.InvokeAsync(SetLoadingString);
         await ConfigureWindows.GetMainWindow.Dispatcher.InvokeAsync(SetLoadingString);
 
 
-        if (fileInfo is not null)
+        await Task.Run(async () =>
         {
         {
-            if (fileInfo.Exists)
+            if (fileInfo is not null)
             {
             {
-                if (fileInfo.IsSupported())
+                if (fileInfo.Exists)
                 {
                 {
-                    await LoadPiFromFileAsync(null, fileInfo).ConfigureAwait(false);
+                    if (fileInfo.IsSupported())
+                    {
+                        await LoadPiFromFileAsync(null, fileInfo).ConfigureAwait(false);
+                    }
+                    else if (fileInfo.IsArchive())
+                    {
+                        await LoadPicFromArchiveAsync(path).ConfigureAwait(false);
+                    }
                 }
                 }
-                else if (fileInfo.IsArchive())
+                else if (path is not null && !string.IsNullOrWhiteSpace(path.GetURL()) ||
+                         !string.IsNullOrWhiteSpace(fileInfo.LinkTarget.GetURL()))
                 {
                 {
-                    await LoadPicFromArchiveAsync(path).ConfigureAwait(false);
+                    await HttpFunctions.LoadPicFromUrlAsync(path).ConfigureAwait(false);
+                }
+                else if (fileInfo.Attributes.HasFlag(FileAttributes.Directory))
+                {
+                    await LoadPicFromFolderAsync(fileInfo, 0).ConfigureAwait(false);
+                }
+                else
+                {
+                    await ReloadAsync().ConfigureAwait(false);
                 }
                 }
             }
             }
-            else if (path is not null && !string.IsNullOrWhiteSpace(path.GetURL()) ||
-                     !string.IsNullOrWhiteSpace(fileInfo.LinkTarget.GetURL()))
-            {
-                await HttpFunctions.LoadPicFromUrlAsync(path).ConfigureAwait(false);
-            }
-            else if (fileInfo.Attributes.HasFlag(FileAttributes.Directory))
-            {
-                await LoadPicFromFolderAsync(fileInfo, 0).ConfigureAwait(false);
-            }
-            else
-            {
-                await ReloadAsync().ConfigureAwait(false);
-            }
-        }
-        else if (!string.IsNullOrWhiteSpace(path))
-        {
-            var check = CheckIfLoadableString(path);
-            switch (check)
+            else if (!string.IsNullOrWhiteSpace(path))
             {
             {
-                default:
-                    await LoadPiFromFileAsync(check).ConfigureAwait(false);
-                    return;
+                var check = CheckIfLoadableString(path);
+                switch (check)
+                {
+                    default:
+                        await LoadPiFromFileAsync(check).ConfigureAwait(false);
+                        return;
 
 
-                case "web":
-                    await HttpFunctions.LoadPicFromUrlAsync(path).ConfigureAwait(false);
-                    return;
+                    case "web":
+                        await HttpFunctions.LoadPicFromUrlAsync(path).ConfigureAwait(false);
+                        return;
 
 
-                case "base64":
-                    await UpdateImage.UpdateImageFromBase64PicAsync(path).ConfigureAwait(false);
-                    return;
+                    case "base64":
+                        await UpdateImage.UpdateImageFromBase64PicAsync(path).ConfigureAwait(false);
+                        return;
 
 
-                case "directory":
-                    await LoadPicFromFolderAsync(path).ConfigureAwait(false);
-                    return;
+                    case "directory":
+                        await LoadPicFromFolderAsync(path).ConfigureAwait(false);
+                        return;
 
 
-                case "zip":
-                    await LoadPicFromArchiveAsync(path).ConfigureAwait(false);
-                    return;
+                    case "zip":
+                        await LoadPicFromArchiveAsync(path).ConfigureAwait(false);
+                        return;
 
 
-                case "":
-                    ConfigureWindows.GetMainWindow.Dispatcher.Invoke(DispatcherPriority.Render, () => Unload(true));
-                    return;
+                    case "":
+                        ConfigureWindows.GetMainWindow.Dispatcher.Invoke(DispatcherPriority.Render, () => Unload(true));
+                        return;
+                }
             }
             }
-        }
-        else
-        {
-            await ReloadAsync().ConfigureAwait(false);
-        }
+            else
+            {
+                await ReloadAsync().ConfigureAwait(false);
+            }
+        });
     }
     }
 
 
     #endregion Load Pic from String
     #endregion Load Pic from String
@@ -385,7 +392,38 @@ internal static class LoadPic
         // display the loading preview and wait until the image is loaded.
         // display the loading preview and wait until the image is loaded.
         if (preLoadValue is null or { BitmapSource: null })
         if (preLoadValue is null or { BitmapSource: null })
         {
         {
-            var thumb = Thumbnails.GetThumb(FolderIndex, fileInfo);
+            using var image = new MagickImage();
+            image.Ping(fileInfo);
+            BitmapSource? thumb = null;
+            if (GetPicGallery != null)
+            {
+                var fromGallery = false;
+                await UC.GetPicGallery.Dispatcher.InvokeAsync(() =>
+                {
+                    if (GetPicGallery.Container.Children.Count > 0 && index < GetPicGallery.Container.Children.Count)
+                    {
+                        var y = GetPicGallery.Container.Children[index] as PicGalleryItem;
+                        thumb = (BitmapSource)y.ThumbImage.Source;
+                        fromGallery = true;
+                    }
+                });
+                if (!fromGallery)
+                {
+                    var exifThumbnail = image.GetExifProfile()?.CreateThumbnail();
+                    thumb = exifThumbnail?.ToBitmapSource();
+                }
+            }
+            else
+            {
+                var exifThumbnail = image.GetExifProfile()?.CreateThumbnail();
+                thumb = exifThumbnail?.ToBitmapSource();
+            }
+
+            if (index != FolderIndex)
+            {
+                await PreLoader.PreLoadAsync(index, Pics.Count).ConfigureAwait(false);
+                return; // Skip loading if user went to next value
+            }
 
 
             await ConfigureWindows.GetMainWindow.Dispatcher.InvokeAsync(() =>
             await ConfigureWindows.GetMainWindow.Dispatcher.InvokeAsync(() =>
             {
             {
@@ -393,10 +431,12 @@ internal static class LoadPic
                 GetSpinWaiter.Visibility = Visibility.Visible;
                 GetSpinWaiter.Visibility = Visibility.Visible;
 
 
                 ConfigureWindows.GetMainWindow.MainImage.Source = thumb;
                 ConfigureWindows.GetMainWindow.MainImage.Source = thumb;
+                if (image is { Height: > 0, Width: > 0 })
+                    ScaleImage.FitImage(image.Width, image.Height);
             }, DispatcherPriority.Send);
             }, DispatcherPriority.Send);
 
 
             // Update gallery selections
             // Update gallery selections
-            if (GetPicGallery is not null)
+            if (GetPicGallery is not null && index == FolderIndex)
             {
             {
                 await UC.GetPicGallery.Dispatcher.InvokeAsync(() =>
                 await UC.GetPicGallery.Dispatcher.InvokeAsync(() =>
                 {
                 {

+ 8 - 15
src/PicView/ChangeImage/Navigation.cs

@@ -123,24 +123,17 @@ internal static class Navigation
             });
             });
         }
         }
 
 
-        if (fastPic)
+        await Task.Run(async () =>
         {
         {
-            await FastPic.Run(next).ConfigureAwait(false);
-            if (UC.GetPicGallery is not null)
+            if (fastPic)
             {
             {
-                await UC.GetPicGallery.Dispatcher.InvokeAsync(() =>
-                {
-                    // Select next item
-                    GalleryNavigation.SetSelected(FolderIndex, true);
-                    GalleryNavigation.SelectedGalleryItem = FolderIndex;
-                    GalleryNavigation.ScrollToGalleryCenter();
-                });
+                await FastPic.Run(next).ConfigureAwait(false);
             }
             }
-        }
-        else
-        {
-            await LoadPic.LoadPicAtIndexAsync(next).ConfigureAwait(false);
-        }
+            else
+            {
+                await LoadPic.LoadPicAtIndexAsync(next).ConfigureAwait(false);
+            }
+        });
     }
     }
 
 
     /// <summary>
     /// <summary>

+ 15 - 8
src/PicView/ChangeImage/QuickLoad.cs

@@ -12,6 +12,7 @@ using System.Windows.Threading;
 using XamlAnimatedGif;
 using XamlAnimatedGif;
 using static PicView.ChangeImage.LoadPic;
 using static PicView.ChangeImage.LoadPic;
 using static PicView.ChangeImage.Navigation;
 using static PicView.ChangeImage.Navigation;
+using static PicView.ChangeImage.PreLoader;
 using static PicView.ChangeTitlebar.SetTitle;
 using static PicView.ChangeTitlebar.SetTitle;
 using static PicView.FileHandling.ArchiveExtraction;
 using static PicView.FileHandling.ArchiveExtraction;
 using static PicView.FileHandling.FileLists;
 using static PicView.FileHandling.FileLists;
@@ -43,18 +44,24 @@ internal static class QuickLoad
         var bitmapSource = await ImageDecoder.ReturnBitmapSourceAsync(fileInfo).ConfigureAwait(false);
         var bitmapSource = await ImageDecoder.ReturnBitmapSourceAsync(fileInfo).ConfigureAwait(false);
         await mainWindow.MainImage.Dispatcher.InvokeAsync(() =>
         await mainWindow.MainImage.Dispatcher.InvokeAsync(() =>
         {
         {
-            if (fileInfo.Extension.ToLowerInvariant() == ".gif")
-            {
-                AnimationBehavior.SetSourceUri(ConfigureWindows.GetMainWindow.MainImage, new Uri(fileInfo.FullName));
-            }
-            else
-            {
-                ConfigureWindows.GetMainWindow.MainImage.Source = bitmapSource;
-            }
+            ConfigureWindows.GetMainWindow.MainImage.Source = bitmapSource;
 
 
             FitImage(bitmapSource.Width, bitmapSource.Height);
             FitImage(bitmapSource.Width, bitmapSource.Height);
         }, DispatcherPriority.Send);
         }, DispatcherPriority.Send);
 
 
+        if (fileInfo.Extension.Equals(".gif", StringComparison.OrdinalIgnoreCase))
+        {
+            var frames = ImageFunctions.GetImageFrames(fileInfo.FullName);
+            if (frames > 0)
+            {
+                var uri = new Uri(fileInfo.FullName);
+                await ConfigureWindows.GetMainWindow.Dispatcher.InvokeAsync(() =>
+                {
+                    AnimationBehavior.SetSourceUri(ConfigureWindows.GetMainWindow.MainImage, uri);
+                }, DispatcherPriority.Normal);
+            }
+        }
+
         Pics = await Task.FromResult(FileList(fileInfo)).ConfigureAwait(false);
         Pics = await Task.FromResult(FileList(fileInfo)).ConfigureAwait(false);
         FolderIndex = Pics.IndexOf(fileInfo.FullName);
         FolderIndex = Pics.IndexOf(fileInfo.FullName);
 
 

+ 9 - 4
src/PicView/ChangeImage/UpdateImage.cs

@@ -1,4 +1,5 @@
-using PicView.FileHandling;
+using System.IO;
+using PicView.FileHandling;
 using PicView.ImageHandling;
 using PicView.ImageHandling;
 using PicView.PicGallery;
 using PicView.PicGallery;
 using PicView.Properties;
 using PicView.Properties;
@@ -78,11 +79,15 @@ internal static class UpdateImage
 
 
         if (preLoadValue.FileInfo.Extension.Equals(".gif", StringComparison.OrdinalIgnoreCase))
         if (preLoadValue.FileInfo.Extension.Equals(".gif", StringComparison.OrdinalIgnoreCase))
         {
         {
-            var frames = ImageFunctions.GetImageFrames(Pics[index]);
+            var frames = ImageFunctions.GetImageFrames(preLoadValue.FileInfo.FullName);
             if (frames > 0)
             if (frames > 0)
             {
             {
-                var uri = new Uri(Pics[index]);
-                AnimationBehavior.SetSourceUri(ConfigureWindows.GetMainWindow.MainImage, uri);
+                var uri = new Uri(preLoadValue.FileInfo.FullName);
+                await ConfigureWindows.GetMainWindow.Dispatcher.InvokeAsync(() =>
+                {
+                    if (index == FolderIndex)
+                        AnimationBehavior.SetSourceUri(ConfigureWindows.GetMainWindow.MainImage, uri);
+                }, DispatcherPriority.Normal);
             }
             }
         }
         }
 
 

+ 10 - 50
src/PicView/ImageHandling/Thumbnails.cs

@@ -1,8 +1,7 @@
 using ImageMagick;
 using ImageMagick;
 using PicView.ChangeImage;
 using PicView.ChangeImage;
+using PicView.UILogic;
 using PicView.Views.UserControls.Gallery;
 using PicView.Views.UserControls.Gallery;
-using SkiaSharp;
-using SkiaSharp.Views.WPF;
 using System.Diagnostics;
 using System.Diagnostics;
 using System.IO;
 using System.IO;
 using System.Windows.Media.Imaging;
 using System.Windows.Media.Imaging;
@@ -22,7 +21,7 @@ internal static class Thumbnails
         BitmapSource? pic;
         BitmapSource? pic;
         try
         try
         {
         {
-            if (GetPicGallery != null && GetPicGallery.Container.Children.Count > 0 && x < GetPicGallery.Container.Children.Count)
+            if (ConfigureWindows.GetMainWindow.CheckAccess() && GetPicGallery != null && GetPicGallery.Container.Children.Count > 0 && x < GetPicGallery.Container.Children.Count)
             {
             {
                 var y = GetPicGallery.Container.Children[x] as PicGalleryItem;
                 var y = GetPicGallery.Container.Children[x] as PicGalleryItem;
                 pic = (BitmapSource)y.ThumbImage.Source;
                 pic = (BitmapSource)y.ThumbImage.Source;
@@ -61,7 +60,7 @@ internal static class Thumbnails
         return pic;
         return pic;
     }
     }
 
 
-    internal static BitmapSource GetBitmapSourceThumb(string file, int size)
+    internal static BitmapSource GetBitmapSourceThumb(string file, int size, FileInfo? fileInfo = null)
     {
     {
         try
         try
         {
         {
@@ -74,55 +73,16 @@ internal static class Thumbnails
                 bitmapThumb.Freeze();
                 bitmapThumb.Freeze();
                 return bitmapThumb;
                 return bitmapThumb;
             }
             }
-        }
-        catch (Exception e)
-        {
-#if DEBUG
-            Trace.WriteLine(nameof(GetBitmapSourceThumb) + " " + e.Message);
-#endif
-        }
 
 
-        try
-        {
-            var fileInfo = new FileInfo(file);
-            var extension = fileInfo.Extension.ToLowerInvariant();
+            fileInfo ??= new FileInfo(file);
             var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, bufferSize: 4096,
             var fileStream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, bufferSize: 4096,
                 useAsync: fileInfo.Length > 1e+8);
                 useAsync: fileInfo.Length > 1e+8);
-            switch (extension)
-            {
-                case ".jpg":
-                case ".jpeg":
-                case ".jpe":
-                case ".png":
-                case ".bmp":
-                case ".gif":
-                case ".jfif":
-                case ".ico":
-                case ".webp":
-                case ".wbmp":
-
-                    var sKBitmap = SKBitmap.Decode(fileStream);
-                    if (sKBitmap is null)
-                    {
-                        return ImageFunctions.ShowLogo() ?? ImageFunctions.ImageErrorMessage();
-                    }
-
-                    var skPic = sKBitmap.Resize(new SKImageInfo(size, size, SKColorType.Rgba8888), SKFilterQuality.High)
-                        .ToWriteableBitmap();
-                    sKBitmap.Dispose();
-                    fileStream.Dispose();
-                    skPic.Freeze();
-                    return skPic;
-
-                default:
-                    var image = new MagickImage();
-                    image.Read(fileStream);
-                    image.Thumbnail(new MagickGeometry(size, size));
-                    var bmp = image.ToBitmapSource();
-                    bmp?.Freeze();
-                    image.Dispose();
-                    return bmp ?? ImageFunctions.ShowLogo() ?? ImageFunctions.ImageErrorMessage();
-            }
+            image.Read(fileStream);
+            image.Thumbnail(new MagickGeometry(size, size));
+            var bmp = image.ToBitmapSource();
+            bmp?.Freeze();
+            image.Dispose();
+            return bmp ?? ImageFunctions.ShowLogo();
         }
         }
         catch (Exception e)
         catch (Exception e)
         {
         {

+ 36 - 40
src/PicView/PicGallery/GalleryLoad.cs

@@ -43,8 +43,8 @@ internal static class GalleryLoad
 
 
         internal static GalleryThumbHolder GetThumbData(int index)
         internal static GalleryThumbHolder GetThumbData(int index)
         {
         {
-            var bitmapSource = Thumbnails.GetBitmapSourceThumb(Navigation.Pics[index], (int)GalleryNavigation.PicGalleryItemSize);
             var fileInfo = new FileInfo(Navigation.Pics[index]);
             var fileInfo = new FileInfo(Navigation.Pics[index]);
+            var bitmapSource = Thumbnails.GetBitmapSourceThumb(Navigation.Pics[index], (int)GalleryNavigation.PicGalleryItemSize, fileInfo);
             var fileLocation = fileInfo.FullName;
             var fileLocation = fileInfo.FullName;
             var fileName = Path.GetFileNameWithoutExtension(fileInfo.Name);
             var fileName = Path.GetFileNameWithoutExtension(fileInfo.Name);
             var fileSize = $"{(string)Application.Current.Resources["FileSize"]}: {fileInfo.Length.GetReadableFileSize()}";
             var fileSize = $"{(string)Application.Current.Resources["FileSize"]}: {fileInfo.Length.GetReadableFileSize()}";
@@ -61,28 +61,44 @@ internal static class GalleryLoad
         var source = new CancellationTokenSource();
         var source = new CancellationTokenSource();
         var iterations = Navigation.Pics.Count;
         var iterations = Navigation.Pics.Count;
 
 
-        for (int i = 0; i < iterations; i++)
+        async Task UpdateThumbAsync(int i, int updates)
         {
         {
-            try
+            var galleryThumbHolderItem = await Task.FromResult(GalleryThumbHolder.GetThumbData(i)).ConfigureAwait(false);
+            await UC.GetPicGallery.Dispatcher.InvokeAsync(() =>
             {
             {
-                if (iterations != Navigation.Pics.Count)
+                UpdatePic(i, galleryThumbHolderItem.BitmapSource, galleryThumbHolderItem.FileLocation,
+                    galleryThumbHolderItem.FileName, galleryThumbHolderItem.FileSize,
+                    galleryThumbHolderItem.FileDate);
+            }, DispatcherPriority.Background, source.Token);
+            if (updates == iterations)
+                IsLoading = false;
+        }
+
+        await Task.Run(async () =>
+        {
+            for (int i = 0; i < iterations; i++)
+            {
+                try
                 {
                 {
-                    await source.CancelAsync();
+                    if (iterations != Navigation.Pics.Count)
+                    {
+                        await source.CancelAsync();
+                        return;
+                    }
+
+                    var i1 = i;
+                    await UC.GetPicGallery.Dispatcher.InvokeAsync(() =>
+                    {
+                        Add(i1);
+                    }, DispatcherPriority.DataBind, source.Token);
                 }
                 }
-                await UC.GetPicGallery.Dispatcher.InvokeAsync(() =>
+                catch (Exception)
                 {
                 {
-                    Add(i);
-                }, DispatcherPriority.DataBind, source.Token);
-            }
-            catch (Exception)
-            {
-                GalleryFunctions.Clear();
-                return;
+                    GalleryFunctions.Clear();
+                    return;
+                }
             }
             }
-        }
 
 
-        await Task.Run(async () =>
-        {
             var priority = iterations > 3000 ? DispatcherPriority.Background : DispatcherPriority.Render;
             var priority = iterations > 3000 ? DispatcherPriority.Background : DispatcherPriority.Render;
             var startPosition = 0;
             var startPosition = 0;
             var updates = 0;
             var updates = 0;
@@ -102,27 +118,16 @@ internal static class GalleryLoad
                     Thread.CurrentThread.Priority = ThreadPriority.BelowNormal;
                     Thread.CurrentThread.Priority = ThreadPriority.BelowNormal;
                 }
                 }
 
 
-                await Parallel.ForAsync(startPosition, iterations, source.Token, async (x, loopState) =>
+                for (int i = startPosition; i < iterations; i++)
                 {
                 {
                     updates++;
                     updates++;
                     try
                     try
                     {
                     {
-                        var i = x;
-
                         if (!IsLoading || Navigation.Pics.Count < Navigation.FolderIndex || Navigation.Pics.Count < 1 || i > Navigation.Pics.Count)
                         if (!IsLoading || Navigation.Pics.Count < Navigation.FolderIndex || Navigation.Pics.Count < 1 || i > Navigation.Pics.Count)
                         {
                         {
-                            loopState.ThrowIfCancellationRequested();
                             throw new TaskCanceledException();
                             throw new TaskCanceledException();
                         }
                         }
-                        var galleryThumbHolderItem = GalleryThumbHolder.GetThumbData(i);
-                        await UC.GetPicGallery.Dispatcher.InvokeAsync(() =>
-                        {
-                            UpdatePic(i, galleryThumbHolderItem.BitmapSource, galleryThumbHolderItem.FileLocation,
-                                galleryThumbHolderItem.FileName, galleryThumbHolderItem.FileSize,
-                                galleryThumbHolderItem.FileDate);
-                        }, DispatcherPriority.Background, source.Token);
-                        if (updates == iterations)
-                            IsLoading = false;
+                        await UpdateThumbAsync(i, updates).ConfigureAwait(false);
                     }
                     }
                     catch (Exception e)
                     catch (Exception e)
                     {
                     {
@@ -131,7 +136,7 @@ internal static class GalleryLoad
 #endif
 #endif
                         IsLoading = false;
                         IsLoading = false;
                     }
                     }
-                });
+                }
             }, source.Token).ConfigureAwait(false);
             }, source.Token).ConfigureAwait(false);
 
 
             _ = Task.Run(async () =>
             _ = Task.Run(async () =>
@@ -151,16 +156,7 @@ internal static class GalleryLoad
                         {
                         {
                             throw new TaskCanceledException();
                             throw new TaskCanceledException();
                         }
                         }
-
-                        var galleryThumbHolderItem = GalleryThumbHolder.GetThumbData(i);
-                        await UC.GetPicGallery.Dispatcher.InvokeAsync(() =>
-                        {
-                            UpdatePic(i, galleryThumbHolderItem.BitmapSource, galleryThumbHolderItem.FileLocation,
-                                galleryThumbHolderItem.FileName, galleryThumbHolderItem.FileSize,
-                                galleryThumbHolderItem.FileDate);
-                        }, DispatcherPriority.Background, source.Token);
-                        if (updates == iterations)
-                            IsLoading = false;
+                        await UpdateThumbAsync(i, updates).ConfigureAwait(false);
                     }
                     }
                     catch (Exception e)
                     catch (Exception e)
                     {
                     {

+ 3 - 0
src/PicView/PicView.csproj

@@ -322,6 +322,9 @@
   <ItemGroup>
   <ItemGroup>
     <Resource Include="Themes\Resources\img\icon__Q6k_icon.ico" />
     <Resource Include="Themes\Resources\img\icon__Q6k_icon.ico" />
   </ItemGroup>
   </ItemGroup>
+	<ItemGroup>
+		<RuntimeHostConfigurationOption Include="Switch.System.Windows.Media.EnableHardwareAccelerationInRdp" Value="true" />
+	</ItemGroup>
 	
 	
   <PropertyGroup>
   <PropertyGroup>
     <FileVersion>1.9.6</FileVersion>
     <FileVersion>1.9.6</FileVersion>

+ 0 - 1
src/PicView/Shortcuts/MainKeyboardShortcuts.cs

@@ -11,7 +11,6 @@ using PicView.UILogic;
 using PicView.UILogic.Sizing;
 using PicView.UILogic.Sizing;
 using System.Windows;
 using System.Windows;
 using System.Windows.Input;
 using System.Windows.Input;
-using System.Windows.Media;
 using static PicView.ChangeImage.ErrorHandling;
 using static PicView.ChangeImage.ErrorHandling;
 using static PicView.ChangeImage.Navigation;
 using static PicView.ChangeImage.Navigation;
 using static PicView.FileHandling.CopyPaste;
 using static PicView.FileHandling.CopyPaste;

+ 0 - 73
src/XamlAnimatedGif/AnimationBehavior.cs

@@ -131,29 +131,6 @@ public static class AnimationBehavior
 
 
     #endregion AutoStart
     #endregion AutoStart
 
 
-    #region AnimateInDesignMode
-
-    public static bool GetAnimateInDesignMode(DependencyObject obj)
-    {
-        return (bool)obj.GetValue(AnimateInDesignModeProperty);
-    }
-
-    public static void SetAnimateInDesignMode(DependencyObject obj, bool value)
-    {
-        obj.SetValue(AnimateInDesignModeProperty, value);
-    }
-
-    public static readonly DependencyProperty AnimateInDesignModeProperty =
-        DependencyProperty.RegisterAttached(
-            "AnimateInDesignMode",
-            typeof(bool),
-            typeof(AnimationBehavior),
-            new PropertyMetadata(
-                false,
-                AnimateInDesignModeChanged));
-
-    #endregion AnimateInDesignMode
-
     #region Animator
     #region Animator
 
 
     [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
     [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
@@ -319,44 +296,6 @@ public static class AnimationBehavior
         GetAnimator(o)?.OnRepeatBehaviorChanged();
         GetAnimator(o)?.OnRepeatBehaviorChanged();
     }
     }
 
 
-    private static async void AnimateInDesignModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
-    {
-        if (d is not Image image)
-            return;
-
-        await InitAnimationAsync(image).ConfigureAwait(false);
-    }
-
-    private static bool CheckDesignMode(Image image, Uri sourceUri, Stream sourceStream)
-    {
-        if (IsInDesignMode(image) && !GetAnimateInDesignMode(image))
-        {
-            try
-            {
-                if (sourceStream != null)
-                {
-                    SetStaticImage(image, sourceStream);
-                }
-                else if (sourceUri != null)
-                {
-                    var bmp = new BitmapImage
-                    {
-                        UriSource = sourceUri
-                    };
-                    image.Source = bmp;
-                }
-            }
-            catch
-            {
-                image.Source = null;
-            }
-
-            return false;
-        }
-
-        return true;
-    }
-
     private static async Task InitAnimationAsync(Image image)
     private static async Task InitAnimationAsync(Image image)
     {
     {
         if (IsLoaded(image))
         if (IsLoaded(image))
@@ -443,9 +382,6 @@ public static class AnimationBehavior
     private static async Task InitAnimationAsync(Image image, Uri sourceUri, RepeatBehavior repeatBehavior,
     private static async Task InitAnimationAsync(Image image, Uri sourceUri, RepeatBehavior repeatBehavior,
         int seqNum, bool cacheFrameDataInMemory)
         int seqNum, bool cacheFrameDataInMemory)
     {
     {
-        if (!CheckDesignMode(image, sourceUri, null))
-            return;
-
         try
         try
         {
         {
             var animator = await ImageAnimator.CreateAsync(sourceUri, repeatBehavior, null, image,
             var animator = await ImageAnimator.CreateAsync(sourceUri, repeatBehavior, null, image,
@@ -475,9 +411,6 @@ public static class AnimationBehavior
     private static async void InitAnimationAsync(Image image, Stream stream, RepeatBehavior repeatBehavior,
     private static async void InitAnimationAsync(Image image, Stream stream, RepeatBehavior repeatBehavior,
         int seqNum, bool cacheFrameDataInMemory)
         int seqNum, bool cacheFrameDataInMemory)
     {
     {
-        if (!CheckDesignMode(image, null, stream))
-            return;
-
         try
         try
         {
         {
             var animator = await ImageAnimator.CreateAsync(stream, repeatBehavior, image, cacheFrameDataInMemory);
             var animator = await ImageAnimator.CreateAsync(stream, repeatBehavior, image, cacheFrameDataInMemory);
@@ -533,12 +466,6 @@ public static class AnimationBehavior
         SetAnimator(image, null);
         SetAnimator(image, null);
     }
     }
 
 
-    // ReSharper disable once UnusedParameter.Local (used in WPF)
-    private static bool IsInDesignMode(DependencyObject obj)
-    {
-        return DesignerProperties.GetIsInDesignMode(obj);
-    }
-
     private static async Task SetStaticImageAsync(Image image, Uri sourceUri)
     private static async Task SetStaticImageAsync(Image image, Uri sourceUri)
     {
     {
         try
         try

+ 4 - 0
src/XamlAnimatedGif/XamlAnimatedGif.csproj

@@ -18,10 +18,14 @@
     <PackageIcon>assets/xamlanimatedgif.png</PackageIcon>
     <PackageIcon>assets/xamlanimatedgif.png</PackageIcon>
     <SupportedOSPlatformVersion>10.0.22621.0</SupportedOSPlatformVersion>
     <SupportedOSPlatformVersion>10.0.22621.0</SupportedOSPlatformVersion>
     <ImplicitUsings>enable</ImplicitUsings>
     <ImplicitUsings>enable</ImplicitUsings>
+    <PlatformTarget>x64</PlatformTarget>
   </PropertyGroup>
   </PropertyGroup>
   <PropertyGroup Condition="'$(TargetFramework)' == 'net45'">
   <PropertyGroup Condition="'$(TargetFramework)' == 'net45'">
     <DefineConstants>$(DefineConstants);LACKS_STREAM_MEMORY_OVERLOADS</DefineConstants>
     <DefineConstants>$(DefineConstants);LACKS_STREAM_MEMORY_OVERLOADS</DefineConstants>
   </PropertyGroup>
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
+    <DebugType>none</DebugType>
+  </PropertyGroup>
   <ItemGroup Condition="'$(TargetFramework)' == 'net45'">
   <ItemGroup Condition="'$(TargetFramework)' == 'net45'">
     <Reference Include="PresentationCore" />
     <Reference Include="PresentationCore" />
     <Reference Include="PresentationFramework" />
     <Reference Include="PresentationFramework" />