From e76f99ff28bb8bc19f71ec87761061ec839f9bb1 Mon Sep 17 00:00:00 2001 From: MBucari Date: Tue, 7 Mar 2023 22:03:42 -0700 Subject: [PATCH] Fix rmcrackan/Libation#523 --- .../Dialogs/ImageDisplayDialog.axaml.cs | 35 +++++++++---------- .../LibationAvalonia/ViewModels/GridEntry.cs | 24 ++++++++++--- .../Views/ProductsDisplay.axaml.cs | 4 +-- Source/LibationWinForms/GridView/GridEntry.cs | 18 ++++++++-- .../LibationWinForms/GridView/ImageDisplay.cs | 19 +++++++--- .../GridView/ProductsDisplay.cs | 6 ++-- 6 files changed, 71 insertions(+), 35 deletions(-) diff --git a/Source/LibationAvalonia/Dialogs/ImageDisplayDialog.axaml.cs b/Source/LibationAvalonia/Dialogs/ImageDisplayDialog.axaml.cs index c42cabce..837ef7ab 100644 --- a/Source/LibationAvalonia/Dialogs/ImageDisplayDialog.axaml.cs +++ b/Source/LibationAvalonia/Dialogs/ImageDisplayDialog.axaml.cs @@ -1,8 +1,5 @@ -using Avalonia; -using Avalonia.Controls; using Avalonia.Markup.Xaml; using Avalonia.Media.Imaging; -using Avalonia.Platform; using System; using System.ComponentModel; using System.IO; @@ -16,23 +13,8 @@ namespace LibationAvalonia.Dialogs public string PictureFileName { get; set; } public string BookSaveDirectory { get; set; } - private byte[] _coverBytes; - public byte[] CoverBytes - { - get => _coverBytes; - set - { - _coverBytes = value; - var ms = new MemoryStream(_coverBytes); - ms.Position = 0; - _bitmapHolder.CoverImage = new Bitmap(ms); - } - } - - private readonly BitmapHolder _bitmapHolder = new BitmapHolder(); - public ImageDisplayDialog() { InitializeComponent(); @@ -45,6 +27,21 @@ namespace LibationAvalonia.Dialogs AvaloniaXamlLoader.Load(this); } + public void SetCoverBytes(byte[] cover) + { + try + { + var ms = new MemoryStream(cover); + _bitmapHolder.CoverImage = new Bitmap(ms); + } + catch (Exception ex) + { + Serilog.Log.Logger.Error(ex, "Error loading cover art for {file}", PictureFileName); + using var ms = App.OpenAsset("img-coverart-prod-unavailable_500x500.jpg"); + _bitmapHolder.CoverImage = new Bitmap(ms); + } + } + public async void SaveImage_Clicked(object sender, Avalonia.Interactivity.RoutedEventArgs e) { var options = new FilePickerSaveOptions @@ -70,7 +67,7 @@ namespace LibationAvalonia.Dialogs try { - File.WriteAllBytes(uri.LocalPath, CoverBytes); + _bitmapHolder.CoverImage.Save(uri.LocalPath); } catch (Exception ex) { diff --git a/Source/LibationAvalonia/ViewModels/GridEntry.cs b/Source/LibationAvalonia/ViewModels/GridEntry.cs index 2d0dc3b8..2b989afd 100644 --- a/Source/LibationAvalonia/ViewModels/GridEntry.cs +++ b/Source/LibationAvalonia/ViewModels/GridEntry.cs @@ -1,5 +1,6 @@ using ApplicationServices; using Avalonia.Media; +using Avalonia.Media.Imaging; using DataLayer; using Dinah.Core; using FileLiberator; @@ -139,8 +140,7 @@ namespace LibationAvalonia.ViewModels PictureStorage.PictureCached += PictureStorage_PictureCached; // Mutable property. Set the field so PropertyChanged isn't fired. - using var ms = new System.IO.MemoryStream(picture); - _cover = new Avalonia.Media.Imaging.Bitmap(ms); + _cover = loadImage(picture); } private void PictureStorage_PictureCached(object sender, PictureCachedEventArgs e) @@ -156,12 +156,28 @@ namespace LibationAvalonia.ViewModels // logic validation if (e.Definition.PictureId == Book.PictureId) { - using var ms = new System.IO.MemoryStream(e.Picture); - Cover = new Avalonia.Media.Imaging.Bitmap(ms); + Cover = loadImage(e.Picture); PictureStorage.PictureCached -= PictureStorage_PictureCached; } } + private Bitmap loadImage(byte[] picture) + { + try + { + using var ms = new System.IO.MemoryStream(picture); + return new Bitmap(ms); + } + catch (Exception ex) + { + Serilog.Log.Logger.Error(ex, "Error loading cover art for {Book}", Book); + return DefaultImage; + } + } + + private static Bitmap _defaultImage; + private static Bitmap DefaultImage => _defaultImage ??= new Bitmap(App.OpenAsset("img-coverart-prod-unavailable_80x80.jpg")); + #endregion #region Static library display functions diff --git a/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs b/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs index 3c2c0493..14e30db3 100644 --- a/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs +++ b/Source/LibationAvalonia/Views/ProductsDisplay.axaml.cs @@ -327,7 +327,7 @@ namespace LibationAvalonia.Views void PictureCached(object sender, PictureCachedEventArgs e) { if (e.Definition.PictureId == picDef.PictureId) - imageDisplayDialog.CoverBytes = e.Picture; + imageDisplayDialog.SetCoverBytes(e.Picture); PictureStorage.PictureCached -= PictureCached; } @@ -342,7 +342,7 @@ namespace LibationAvalonia.Views imageDisplayDialog.BookSaveDirectory = AudibleFileStorage.Audio.GetDestinationDirectory(gEntry.LibraryBook); imageDisplayDialog.PictureFileName = System.IO.Path.GetFileName(AudibleFileStorage.Audio.GetBooksDirectoryFilename(gEntry.LibraryBook, ".jpg")); imageDisplayDialog.Title = windowTitle; - imageDisplayDialog.CoverBytes = initialImageBts; + imageDisplayDialog.SetCoverBytes(initialImageBts); if (!isDefault) PictureStorage.PictureCached -= PictureCached; diff --git a/Source/LibationWinForms/GridView/GridEntry.cs b/Source/LibationWinForms/GridView/GridEntry.cs index 95ae7128..a8594356 100644 --- a/Source/LibationWinForms/GridView/GridEntry.cs +++ b/Source/LibationWinForms/GridView/GridEntry.cs @@ -138,7 +138,7 @@ namespace LibationWinForms.GridView PictureStorage.PictureCached += PictureStorage_PictureCached; // Mutable property. Set the field so PropertyChanged isn't fired. - _cover = ImageReader.ToImage(picture); + _cover = loadImage(picture); } private void PictureStorage_PictureCached(object sender, PictureCachedEventArgs e) @@ -154,11 +154,25 @@ namespace LibationWinForms.GridView // logic validation if (e.Definition.PictureId == Book.PictureId) { - Cover = ImageReader.ToImage(e.Picture); + Cover = loadImage(e.Picture); PictureStorage.PictureCached -= PictureStorage_PictureCached; } } + + private Image loadImage(byte[] picture) + { + try + { + return ImageReader.ToImage(picture); + } + catch (Exception ex) + { + Serilog.Log.Logger.Error(ex, "Error loading cover art for {Book}", Book); + return Properties.Resources.default_cover_80x80; + } + } + #endregion #region Static library display functions diff --git a/Source/LibationWinForms/GridView/ImageDisplay.cs b/Source/LibationWinForms/GridView/ImageDisplay.cs index 6f74cd04..36419f3b 100644 --- a/Source/LibationWinForms/GridView/ImageDisplay.cs +++ b/Source/LibationWinForms/GridView/ImageDisplay.cs @@ -9,10 +9,6 @@ namespace LibationWinForms.GridView { public string PictureFileName { get; set; } public string BookSaveDirectory { get; set; } - public byte[] CoverPicture { get => _coverBytes; set => pictureBox1.Image = Dinah.Core.WindowsDesktop.Drawing.ImageReader.ToImage(_coverBytes = value); } - - private byte[] _coverBytes; - public ImageDisplay() { @@ -21,6 +17,19 @@ namespace LibationWinForms.GridView lastHeight = Height; } + public void SetCoverArt(byte[] cover) + { + try + { + pictureBox1.Image = Dinah.Core.WindowsDesktop.Drawing.ImageReader.ToImage(cover); + } + catch (Exception ex) + { + Serilog.Log.Logger.Error(ex, "Error loading cover art for {file}", PictureFileName); + pictureBox1.Image = Properties.Resources.default_cover_500x500; + } + } + #region Make the form's aspect ratio always match the picture's aspect ratio. private bool detectedResizeDirection = false; @@ -106,7 +115,7 @@ namespace LibationWinForms.GridView try { - File.WriteAllBytes(saveFileDialog.FileName, CoverPicture); + pictureBox1.Image.Save(saveFileDialog.FileName); } catch (Exception ex) { diff --git a/Source/LibationWinForms/GridView/ProductsDisplay.cs b/Source/LibationWinForms/GridView/ProductsDisplay.cs index 1db74b56..33f5a0a5 100644 --- a/Source/LibationWinForms/GridView/ProductsDisplay.cs +++ b/Source/LibationWinForms/GridView/ProductsDisplay.cs @@ -39,7 +39,7 @@ namespace LibationWinForms.GridView void PictureCached(object sender, PictureCachedEventArgs e) { if (e.Definition.PictureId == picDef.PictureId) - imageDisplay.CoverPicture = e.Picture; + imageDisplay.SetCoverArt(e.Picture); PictureStorage.PictureCached -= PictureCached; } @@ -51,7 +51,7 @@ namespace LibationWinForms.GridView if (imageDisplay is null || imageDisplay.IsDisposed || !imageDisplay.Visible) { - imageDisplay = new GridView.ImageDisplay(); + imageDisplay = new ImageDisplay(); imageDisplay.RestoreSizeAndLocation(Configuration.Instance); imageDisplay.FormClosed += (_, _) => imageDisplay.SaveSizeAndLocation(Configuration.Instance); } @@ -59,7 +59,7 @@ namespace LibationWinForms.GridView imageDisplay.BookSaveDirectory = AudibleFileStorage.Audio.GetDestinationDirectory(liveGridEntry.LibraryBook); imageDisplay.PictureFileName = System.IO.Path.GetFileName(AudibleFileStorage.Audio.GetBooksDirectoryFilename(liveGridEntry.LibraryBook, ".jpg")); imageDisplay.Text = windowTitle; - imageDisplay.CoverPicture = initialImageBts; + imageDisplay.SetCoverArt(initialImageBts); if (!isDefault) PictureStorage.PictureCached -= PictureCached;