diff options
| author | JPVenson <ger-delta-07@hotmail.de> | 2024-10-17 15:35:03 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-10-17 07:35:03 -0600 |
| commit | 8b4fa42e49e305df544dd12fedb7a55a5bdaf74b (patch) | |
| tree | e3c4582e16f75e252d008a05207fc14ed4863d64 /src/Jellyfin.Drawing.Skia/SkiaEncoder.cs | |
| parent | 4251cbc27799f50eb58fda6fb30f735bbc781a0d (diff) | |
Ensure Skia images are always disposed (#12786)
Diffstat (limited to 'src/Jellyfin.Drawing.Skia/SkiaEncoder.cs')
| -rw-r--r-- | src/Jellyfin.Drawing.Skia/SkiaEncoder.cs | 157 |
1 files changed, 98 insertions, 59 deletions
diff --git a/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs index ede93aaa5..c5aadc890 100644 --- a/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs +++ b/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs @@ -269,14 +269,24 @@ public class SkiaEncoder : IImageEncoder } // create the bitmap - var bitmap = new SKBitmap(codec.Info.Width, codec.Info.Height, !requiresTransparencyHack); + SKBitmap? bitmap = null; + try + { + bitmap = new SKBitmap(codec.Info.Width, codec.Info.Height, !requiresTransparencyHack); - // decode - _ = codec.GetPixels(bitmap.Info, bitmap.GetPixels()); + // decode + _ = codec.GetPixels(bitmap.Info, bitmap.GetPixels()); - origin = codec.EncodedOrigin; + origin = codec.EncodedOrigin; - return bitmap; + return bitmap!; + } + catch (Exception e) + { + _logger.LogError(e, "Detected intermediary error decoding image {0}", path); + bitmap?.Dispose(); + throw; + } } var resultBitmap = SKBitmap.Decode(NormalizePath(path)); @@ -286,17 +296,26 @@ public class SkiaEncoder : IImageEncoder return Decode(path, true, orientation, out origin); } - // If we have to resize these they often end up distorted - if (resultBitmap.ColorType == SKColorType.Gray8) + try { - using (resultBitmap) + // If we have to resize these they often end up distorted + if (resultBitmap.ColorType == SKColorType.Gray8) { - return Decode(path, true, orientation, out origin); + using (resultBitmap) + { + return Decode(path, true, orientation, out origin); + } } - } - origin = SKEncodedOrigin.TopLeft; - return resultBitmap; + origin = SKEncodedOrigin.TopLeft; + return resultBitmap; + } + catch (Exception e) + { + _logger.LogError(e, "Detected intermediary error decoding image {0}", path); + resultBitmap?.Dispose(); + throw; + } } private SKBitmap? GetBitmap(string path, bool autoOrient, ImageOrientation? orientation) @@ -335,58 +354,78 @@ public class SkiaEncoder : IImageEncoder var width = (int)Math.Round(svg.Drawable.Bounds.Width); var height = (int)Math.Round(svg.Drawable.Bounds.Height); - var bitmap = new SKBitmap(width, height); - using var canvas = new SKCanvas(bitmap); - canvas.DrawPicture(svg.Picture); - canvas.Flush(); - canvas.Save(); + SKBitmap? bitmap = null; + try + { + bitmap = new SKBitmap(width, height); + using var canvas = new SKCanvas(bitmap); + canvas.DrawPicture(svg.Picture); + canvas.Flush(); + canvas.Save(); - return bitmap; + return bitmap!; + } + catch (Exception e) + { + _logger.LogError(e, "Detected intermediary error extracting image {0}", path); + bitmap?.Dispose(); + throw; + } } private SKBitmap OrientImage(SKBitmap bitmap, SKEncodedOrigin origin) { var needsFlip = origin is SKEncodedOrigin.LeftBottom or SKEncodedOrigin.LeftTop or SKEncodedOrigin.RightBottom or SKEncodedOrigin.RightTop; - var rotated = needsFlip - ? new SKBitmap(bitmap.Height, bitmap.Width) - : new SKBitmap(bitmap.Width, bitmap.Height); - using var surface = new SKCanvas(rotated); - var midX = (float)rotated.Width / 2; - var midY = (float)rotated.Height / 2; - - switch (origin) - { - case SKEncodedOrigin.TopRight: - surface.Scale(-1, 1, midX, midY); - break; - case SKEncodedOrigin.BottomRight: - surface.RotateDegrees(180, midX, midY); - break; - case SKEncodedOrigin.BottomLeft: - surface.Scale(1, -1, midX, midY); - break; - case SKEncodedOrigin.LeftTop: - surface.Translate(0, -rotated.Height); - surface.Scale(1, -1, midX, midY); - surface.RotateDegrees(-90); - break; - case SKEncodedOrigin.RightTop: - surface.Translate(rotated.Width, 0); - surface.RotateDegrees(90); - break; - case SKEncodedOrigin.RightBottom: - surface.Translate(rotated.Width, 0); - surface.Scale(1, -1, midX, midY); - surface.RotateDegrees(90); - break; - case SKEncodedOrigin.LeftBottom: - surface.Translate(0, rotated.Height); - surface.RotateDegrees(-90); - break; - } - - surface.DrawBitmap(bitmap, 0, 0); - return rotated; + SKBitmap? rotated = null; + try + { + rotated = needsFlip + ? new SKBitmap(bitmap.Height, bitmap.Width) + : new SKBitmap(bitmap.Width, bitmap.Height); + using var surface = new SKCanvas(rotated); + var midX = (float)rotated.Width / 2; + var midY = (float)rotated.Height / 2; + + switch (origin) + { + case SKEncodedOrigin.TopRight: + surface.Scale(-1, 1, midX, midY); + break; + case SKEncodedOrigin.BottomRight: + surface.RotateDegrees(180, midX, midY); + break; + case SKEncodedOrigin.BottomLeft: + surface.Scale(1, -1, midX, midY); + break; + case SKEncodedOrigin.LeftTop: + surface.Translate(0, -rotated.Height); + surface.Scale(1, -1, midX, midY); + surface.RotateDegrees(-90); + break; + case SKEncodedOrigin.RightTop: + surface.Translate(rotated.Width, 0); + surface.RotateDegrees(90); + break; + case SKEncodedOrigin.RightBottom: + surface.Translate(rotated.Width, 0); + surface.Scale(1, -1, midX, midY); + surface.RotateDegrees(90); + break; + case SKEncodedOrigin.LeftBottom: + surface.Translate(0, rotated.Height); + surface.RotateDegrees(-90); + break; + } + + surface.DrawBitmap(bitmap, 0, 0); + return rotated; + } + catch (Exception e) + { + _logger.LogError(e, "Detected intermediary error rotating image"); + rotated?.Dispose(); + throw; + } } /// <summary> @@ -562,7 +601,7 @@ public class SkiaEncoder : IImageEncoder // Only generate the splash screen if we have at least one poster and at least one backdrop/thumbnail. if (posters.Count > 0 && backdrops.Count > 0) { - var splashBuilder = new SplashscreenBuilder(this); + var splashBuilder = new SplashscreenBuilder(this, _logger); var outputPath = Path.Combine(_appPaths.DataPath, "splashscreen.png"); splashBuilder.GenerateSplash(posters, backdrops, outputPath); } |
