Improve Magick image disposal and layer handling #1586
Some checks failed
build / build (push) Has been cancelled
build / publish (push) Has been cancelled

Refactored ImageMagickProvider to properly manage ownership and disposal of MagickImage instances, especially when flattening multi-layer XCF files. Updated logic to avoid unnecessary loading of all layers for non-XCF formats, improving performance and resource management. Minor formatting changes in CursorProvider and WebPProvider for consistency.
This commit is contained in:
ema
2026-01-29 00:02:23 +08:00
parent b43f014ae0
commit f1ea16b8d6
3 changed files with 26 additions and 10 deletions

View File

@@ -97,7 +97,7 @@ internal class CursorProvider : ImageMagickProvider
{ {
OutputColor = DngOutputColor.SRGB, OutputColor = DngOutputColor.SRGB,
UseCameraWhiteBalance = true, UseCameraWhiteBalance = true,
DisableAutoBrightness = false DisableAutoBrightness = false,
} }
}; };

View File

@@ -87,24 +87,35 @@ internal class ImageMagickProvider : AnimationProvider
{ {
OutputColor = DngOutputColor.SRGB, OutputColor = DngOutputColor.SRGB,
UseCameraWhiteBalance = true, UseCameraWhiteBalance = true,
DisableAutoBrightness = false DisableAutoBrightness = false,
} }
}; };
IMagickImage<byte> mi = null;
var isImageOwned = false; // Track whether this provider owns the Magick image instance and must dispose it.
try try
{ {
using var layers = new MagickImageCollection(Path.LocalPath, settings); // Only flatten multi-layer gimp xcf files. Other formats (e.g. PSD) should avoid
IMagickImage<byte> mi; // loading all layers via MagickImageCollection for performance.
// Only flatten multi-layer gimp xcf files. if (Path.LocalPath.ToLower().EndsWith(".xcf"))
if (Path.LocalPath.ToLower().EndsWith(".xcf") && layers.Count > 1) {
using var layers = new MagickImageCollection(Path.LocalPath, settings);
if (layers.Count > 1)
{ {
// Flatten crops layers to canvas
mi = layers.Flatten(MagickColor.FromRgba(0, 0, 0, 0)); mi = layers.Flatten(MagickColor.FromRgba(0, 0, 0, 0));
isImageOwned = true; // Flatten creates a new image instance we must dispose.
} }
else else
{ {
mi = layers[0]; mi = layers[0];
} }
}
else
{
mi = new MagickImage(Path.LocalPath, settings);
isImageOwned = true; // New MagickImage created here must be disposed by this provider.
}
if (SettingHelper.Get("UseColorProfile", false, "QuickLook.Plugin.ImageViewer")) if (SettingHelper.Get("UseColorProfile", false, "QuickLook.Plugin.ImageViewer"))
{ {
if (mi.ColorSpace == ColorSpace.RGB || mi.ColorSpace == ColorSpace.sRGB || mi.ColorSpace == ColorSpace.scRGB) if (mi.ColorSpace == ColorSpace.RGB || mi.ColorSpace == ColorSpace.sRGB || mi.ColorSpace == ColorSpace.scRGB)
@@ -133,6 +144,11 @@ internal class ImageMagickProvider : AnimationProvider
ProcessHelper.WriteLog(e.ToString()); ProcessHelper.WriteLog(e.ToString());
return null!; return null!;
} }
finally
{
if (isImageOwned)
mi?.Dispose();
}
} }
public override void Dispose() public override void Dispose()

View File

@@ -52,7 +52,7 @@ internal class WebPProvider : ImageMagickProvider
{ {
OutputColor = DngOutputColor.SRGB, OutputColor = DngOutputColor.SRGB,
UseCameraWhiteBalance = true, UseCameraWhiteBalance = true,
DisableAutoBrightness = false DisableAutoBrightness = false,
} }
}; };