aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorCody Robibero <cody@robibe.ro>2024-02-28 09:56:02 -0700
committerCody Robibero <cody@robibe.ro>2024-02-28 09:56:02 -0700
commitc5e723bccd723c4c08b7239c5205085be00bd10d (patch)
treed653c6b579ceb8e1a9087f9d6a9347228d23f9d1 /src
parent4f0f364ac941dc4a856512c9bf0e6b93fdf7b3ab (diff)
Add support for converting from svg to other image types
Diffstat (limited to 'src')
-rw-r--r--src/Jellyfin.Drawing.Skia/SkiaEncoder.cs43
1 files changed, 39 insertions, 4 deletions
diff --git a/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs b/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs
index 4ae5a9a48..9454e63aa 100644
--- a/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs
+++ b/src/Jellyfin.Drawing.Skia/SkiaEncoder.cs
@@ -19,8 +19,8 @@ namespace Jellyfin.Drawing.Skia;
/// </summary>
public class SkiaEncoder : IImageEncoder
{
+ private const string SvgFormat = "svg";
private static readonly HashSet<string> _transparentImageTypes = new(StringComparer.OrdinalIgnoreCase) { ".png", ".gif", ".webp" };
-
private readonly ILogger<SkiaEncoder> _logger;
private readonly IApplicationPaths _appPaths;
private static readonly SKImageFilter _imageFilter;
@@ -89,12 +89,13 @@ public class SkiaEncoder : IImageEncoder
// working on windows at least
"cr2",
"nef",
- "arw"
+ "arw",
+ SvgFormat
};
/// <inheritdoc/>
public IReadOnlyCollection<ImageFormat> SupportedOutputFormats
- => new HashSet<ImageFormat> { ImageFormat.Webp, ImageFormat.Jpg, ImageFormat.Png };
+ => new HashSet<ImageFormat> { ImageFormat.Webp, ImageFormat.Jpg, ImageFormat.Png, ImageFormat.Svg };
/// <summary>
/// Check if the native lib is available.
@@ -312,6 +313,31 @@ public class SkiaEncoder : IImageEncoder
return Decode(path, false, orientation, out _);
}
+ private SKBitmap? GetBitmapFromSvg(string path)
+ {
+ if (!File.Exists(path))
+ {
+ throw new FileNotFoundException("File not found", path);
+ }
+
+ using var svg = SKSvg.CreateFromFile(path);
+ if (svg.Drawable is null)
+ {
+ return null;
+ }
+
+ 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();
+
+ return bitmap;
+ }
+
private SKBitmap OrientImage(SKBitmap bitmap, SKEncodedOrigin origin)
{
var needsFlip = origin is SKEncodedOrigin.LeftBottom or SKEncodedOrigin.LeftTop or SKEncodedOrigin.RightBottom or SKEncodedOrigin.RightTop;
@@ -402,6 +428,12 @@ public class SkiaEncoder : IImageEncoder
return inputPath;
}
+ if (outputFormat == ImageFormat.Svg
+ && !inputFormat.Equals(SvgFormat, StringComparison.OrdinalIgnoreCase))
+ {
+ throw new InvalidOperationException($"Requested svg output from {inputFormat} input");
+ }
+
var skiaOutputFormat = GetImageFormat(outputFormat);
var hasBackgroundColor = !string.IsNullOrWhiteSpace(options.BackgroundColor);
@@ -409,7 +441,10 @@ public class SkiaEncoder : IImageEncoder
var blur = options.Blur ?? 0;
var hasIndicator = options.UnplayedCount.HasValue || !options.PercentPlayed.Equals(0);
- using var bitmap = GetBitmap(inputPath, autoOrient, orientation);
+ using var bitmap = inputFormat.Equals(SvgFormat, StringComparison.OrdinalIgnoreCase)
+ ? GetBitmapFromSvg(inputPath)
+ : GetBitmap(inputPath, autoOrient, orientation);
+
if (bitmap is null)
{
throw new InvalidDataException($"Skia unable to read image {inputPath}");