Jelajahi Sumber

Refactor image processing logic: handle `MagickCorruptImageErrorException` gracefully in `ImageAnalyzer`, simplify `IsAnimated` method, rename GIF/WEBP processing methods, restructure metadata extraction.

Ruben 4 bulan lalu
induk
melakukan
c5db69841e

+ 7 - 12
src/PicView.Avalonia/ImageHandling/GetImageModel.cs

@@ -11,8 +11,8 @@ public static class GetImageModel
     // Group extensions by how they should be handled
     private static readonly Dictionary<string, Func<FileInfo, ImageModel, Task>> ExtensionHandlers = new()
     {
-        { ".webp", ProcessAnimatedWebpAsync },
-        { ".gif", ProcessAnimatedGifAsync },
+        { ".webp", ProcessWebpAsync },
+        { ".gif", ProcessGifAsync },
         { ".png", ProcessStandardBitmapAsync },
         { ".jpg", ProcessStandardBitmapAsync },
         { ".jpeg", ProcessStandardBitmapAsync },
@@ -52,8 +52,9 @@ public static class GetImageModel
             // Initialize MagickImage if not provided
             magickImage ??= CreateAndPingMagickImage(fileInfo);
 
-            // Extract metadata early
-            ExtractImageMetadata(magickImage, imageModel);
+            // Extract metadata
+            imageModel.EXIFOrientation = EXIFHelper.GetImageOrientation(magickImage);
+            imageModel.Format = magickImage.Format;
 
             // Process the image based on extension
             var ext = fileInfo.Extension.ToLowerInvariant();
@@ -83,12 +84,6 @@ public static class GetImageModel
         return magickImage;
     }
 
-    private static void ExtractImageMetadata(MagickImage magickImage, ImageModel imageModel)
-    {
-        imageModel.EXIFOrientation = EXIFHelper.GetImageOrientation(magickImage);
-        imageModel.Format = magickImage.Format;
-    }
-
     private static void SetBitmapProperties(Bitmap? bitmap, ImageModel imageModel, ImageType imageType = ImageType.Bitmap)
     {
         imageModel.Image = bitmap;
@@ -118,14 +113,14 @@ public static class GetImageModel
         SetBitmapProperties(bitmap, imageModel);
     }
 
-    private static async Task ProcessAnimatedWebpAsync(FileInfo fileInfo, ImageModel imageModel)
+    private static async Task ProcessWebpAsync(FileInfo fileInfo, ImageModel imageModel)
     {
         var bitmap = await GetImage.GetStandardBitmapAsync(fileInfo).ConfigureAwait(false);
         var imageType = ImageAnalyzer.IsAnimated(fileInfo) ? ImageType.AnimatedWebp : ImageType.Bitmap;
         SetBitmapProperties(bitmap, imageModel, imageType);
     }
 
-    private static async Task ProcessAnimatedGifAsync(FileInfo fileInfo, ImageModel imageModel)
+    private static async Task ProcessGifAsync(FileInfo fileInfo, ImageModel imageModel)
     {
         var bitmap = await GetImage.GetStandardBitmapAsync(fileInfo).ConfigureAwait(false);
         var imageType = ImageAnalyzer.IsAnimated(fileInfo) ? ImageType.AnimatedGif : ImageType.Bitmap;

+ 16 - 15
src/PicView.Core/ImageDecoding/ImageAnalyzer.cs

@@ -1,5 +1,6 @@
 using System.Diagnostics;
 using ImageMagick;
+using PicView.Core.DebugTools;
 
 namespace PicView.Core.ImageDecoding;
 
@@ -24,12 +25,20 @@ public static class ImageAnalyzer
             magickImageCollection.Ping(file);
             return magickImageCollection.Count;
         }
-        catch (MagickException ex)
-        {
 #if DEBUG
-            Trace.WriteLine($"{nameof(GetImageFrames)} Exception \n{ex}");
-#endif
+        catch (MagickCorruptImageErrorException ex)
+        {
+            // This can happen with malformed or unsupported image files.
+            // We'll treat it as a non-animated image with 0 frames.
 
+            Trace.WriteLine($"Caught a corrupt image exception for file '{file}'. Treating as 0 frames. Details: {ex.Message}");
+            DebugHelper.LogDebug(nameof(ImageAnalyzer),nameof(GetImageFrames), ex);
+            return 0;
+        }
+#endif
+        catch (MagickException ex)
+        {
+            DebugHelper.LogDebug(nameof(ImageAnalyzer),nameof(GetImageFrames), ex);
             return 0;
         }
     }
@@ -39,17 +48,9 @@ public static class ImageAnalyzer
     /// </summary>
     /// <param name="fileInfo">File information for the image</param>
     /// <returns>True if the image is animated; otherwise, false</returns>
-    public static bool IsAnimated(FileInfo fileInfo)
-    {
-        if (fileInfo is not { Exists: true })
-        {
-            return false;
-        }
-        
-        var frames = GetImageFrames(fileInfo.FullName);
-        return frames > 1;
-    }
-        
+    public static bool IsAnimated(FileInfo fileInfo) => 
+        GetImageFrames(fileInfo.FullName) > 1;
+
     /// <summary>
     ///     Retrieves the compression quality of the specified image file.
     /// </summary>