update project files
This commit is contained in:
parent
abf18bac52
commit
34c3783f42
|
@ -52,7 +52,12 @@
|
|||
<Compile Include="..\SharedVersion.cs">
|
||||
<Link>Properties\SharedVersion.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="PercentPlayedDrawer.cs" />
|
||||
<Compile Include="PlayedIndicatorDrawer.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="SkiaEncoder.cs" />
|
||||
<Compile Include="StripCollageBuilder.cs" />
|
||||
<Compile Include="UnplayedCountIndicator.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="SkiaSharp, Version=1.57.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
|
||||
|
@ -61,6 +66,7 @@
|
|||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="fonts\robotoregular.ttf" />
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\Portable\$(TargetFrameworkVersion)\Microsoft.Portable.CSharp.targets" />
|
||||
|
|
31
Emby.Drawing.Skia/PercentPlayedDrawer.cs
Normal file
31
Emby.Drawing.Skia/PercentPlayedDrawer.cs
Normal file
|
@ -0,0 +1,31 @@
|
|||
using SkiaSharp;
|
||||
using MediaBrowser.Model.Drawing;
|
||||
using System;
|
||||
|
||||
namespace Emby.Drawing.Skia
|
||||
{
|
||||
public class PercentPlayedDrawer
|
||||
{
|
||||
private const int IndicatorHeight = 8;
|
||||
|
||||
public void Process(SKCanvas canvas, ImageSize imageSize, double percent)
|
||||
{
|
||||
using (var paint = new SKPaint())
|
||||
{
|
||||
var endX = imageSize.Width - 1;
|
||||
var endY = imageSize.Height - 1;
|
||||
|
||||
paint.Color = SKColor.Parse("#99000000");
|
||||
paint.Style = SKPaintStyle.Fill;
|
||||
canvas.DrawRect(SKRect.Create(0, (float)endY - IndicatorHeight, (float)endX, (float)endY), paint);
|
||||
|
||||
double foregroundWidth = endX;
|
||||
foregroundWidth *= percent;
|
||||
foregroundWidth /= 100;
|
||||
|
||||
paint.Color = SKColor.Parse("#FF52B54B");
|
||||
canvas.DrawRect(SKRect.Create(0, (float)endY - IndicatorHeight, Convert.ToInt32(Math.Round(foregroundWidth)), (float)endY), paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
120
Emby.Drawing.Skia/PlayedIndicatorDrawer.cs
Normal file
120
Emby.Drawing.Skia/PlayedIndicatorDrawer.cs
Normal file
|
@ -0,0 +1,120 @@
|
|||
using SkiaSharp;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Model.Drawing;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Model.IO;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Emby.Drawing.Skia
|
||||
{
|
||||
public class PlayedIndicatorDrawer
|
||||
{
|
||||
private const int FontSize = 42;
|
||||
private const int OffsetFromTopRightCorner = 38;
|
||||
|
||||
private readonly IApplicationPaths _appPaths;
|
||||
private readonly IHttpClient _iHttpClient;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
|
||||
public PlayedIndicatorDrawer(IApplicationPaths appPaths, IHttpClient iHttpClient, IFileSystem fileSystem)
|
||||
{
|
||||
_appPaths = appPaths;
|
||||
_iHttpClient = iHttpClient;
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
|
||||
public async Task DrawPlayedIndicator(SKCanvas canvas, ImageSize imageSize)
|
||||
{
|
||||
var x = imageSize.Width - OffsetFromTopRightCorner;
|
||||
|
||||
using (var paint = new SKPaint())
|
||||
{
|
||||
paint.Color = SKColor.Parse("#CC52B54B");
|
||||
paint.Style = SKPaintStyle.Fill;
|
||||
canvas.DrawCircle((float)x, OffsetFromTopRightCorner, 20, paint);
|
||||
}
|
||||
|
||||
using (var paint = new SKPaint())
|
||||
{
|
||||
paint.Color = new SKColor(255, 255, 255, 255);
|
||||
paint.Style = SKPaintStyle.Fill;
|
||||
paint.Typeface = SKTypeface.FromFile(await DownloadFont("webdings.ttf", "https://github.com/MediaBrowser/Emby.Resources/raw/master/fonts/webdings.ttf",
|
||||
_appPaths, _iHttpClient, _fileSystem).ConfigureAwait(false));
|
||||
paint.TextSize = FontSize;
|
||||
paint.IsAntialias = true;
|
||||
|
||||
canvas.DrawText("a", (float)x-20, OffsetFromTopRightCorner + 12, paint);
|
||||
}
|
||||
}
|
||||
|
||||
internal static string ExtractFont(string name, IApplicationPaths paths, IFileSystem fileSystem)
|
||||
{
|
||||
var filePath = Path.Combine(paths.ProgramDataPath, "fonts", name);
|
||||
|
||||
if (fileSystem.FileExists(filePath))
|
||||
{
|
||||
return filePath;
|
||||
}
|
||||
|
||||
var namespacePath = typeof(PlayedIndicatorDrawer).Namespace + ".fonts." + name;
|
||||
var tempPath = Path.Combine(paths.TempDirectory, Guid.NewGuid().ToString("N") + ".ttf");
|
||||
fileSystem.CreateDirectory(fileSystem.GetDirectoryName(tempPath));
|
||||
|
||||
using (var stream = typeof(PlayedIndicatorDrawer).GetTypeInfo().Assembly.GetManifestResourceStream(namespacePath))
|
||||
{
|
||||
using (var fileStream = fileSystem.GetFileStream(tempPath, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
|
||||
{
|
||||
stream.CopyTo(fileStream);
|
||||
}
|
||||
}
|
||||
|
||||
fileSystem.CreateDirectory(fileSystem.GetDirectoryName(filePath));
|
||||
|
||||
try
|
||||
{
|
||||
fileSystem.CopyFile(tempPath, filePath, false);
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
|
||||
internal static async Task<string> DownloadFont(string name, string url, IApplicationPaths paths, IHttpClient httpClient, IFileSystem fileSystem)
|
||||
{
|
||||
var filePath = Path.Combine(paths.ProgramDataPath, "fonts", name);
|
||||
|
||||
if (fileSystem.FileExists(filePath))
|
||||
{
|
||||
return filePath;
|
||||
}
|
||||
|
||||
var tempPath = await httpClient.GetTempFile(new HttpRequestOptions
|
||||
{
|
||||
Url = url,
|
||||
Progress = new Progress<double>()
|
||||
|
||||
}).ConfigureAwait(false);
|
||||
|
||||
fileSystem.CreateDirectory(fileSystem.GetDirectoryName(filePath));
|
||||
|
||||
try
|
||||
{
|
||||
fileSystem.CopyFile(tempPath, filePath, false);
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return tempPath;
|
||||
}
|
||||
}
|
||||
}
|
261
Emby.Drawing.Skia/SkiaEncoder.cs
Normal file
261
Emby.Drawing.Skia/SkiaEncoder.cs
Normal file
|
@ -0,0 +1,261 @@
|
|||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller.Drawing;
|
||||
using MediaBrowser.Model.Drawing;
|
||||
using MediaBrowser.Model.IO;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using SkiaSharp;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Emby.Drawing.Skia
|
||||
{
|
||||
public class SkiaEncoder : IImageEncoder
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly IApplicationPaths _appPaths;
|
||||
private readonly Func<IHttpClient> _httpClientFactory;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
|
||||
public SkiaEncoder(ILogger logger, IApplicationPaths appPaths, Func<IHttpClient> httpClientFactory, IFileSystem fileSystem)
|
||||
{
|
||||
_logger = logger;
|
||||
_appPaths = appPaths;
|
||||
_httpClientFactory = httpClientFactory;
|
||||
_fileSystem = fileSystem;
|
||||
|
||||
LogVersion();
|
||||
}
|
||||
|
||||
public string[] SupportedInputFormats
|
||||
{
|
||||
get
|
||||
{
|
||||
// Some common file name extensions for RAW picture files include: .cr2, .crw, .dng, .nef, .orf, .rw2, .pef, .arw, .sr2, .srf, and .tif.
|
||||
return new[]
|
||||
{
|
||||
"jpeg",
|
||||
"jpg",
|
||||
"png",
|
||||
"dng",
|
||||
"webp",
|
||||
"gif",
|
||||
"bmp",
|
||||
"ico",
|
||||
"astc",
|
||||
"ktx",
|
||||
"pkm",
|
||||
"wbmp"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public ImageFormat[] SupportedOutputFormats
|
||||
{
|
||||
get
|
||||
{
|
||||
return new[] { ImageFormat.Webp, ImageFormat.Gif, ImageFormat.Jpg, ImageFormat.Png, ImageFormat.Bmp };
|
||||
}
|
||||
}
|
||||
|
||||
private void LogVersion()
|
||||
{
|
||||
_logger.Info("SkiaSharp version: " + GetVersion());
|
||||
}
|
||||
|
||||
public static string GetVersion()
|
||||
{
|
||||
return typeof(SKCanvas).GetTypeInfo().Assembly.GetName().Version.ToString();
|
||||
}
|
||||
|
||||
public static SKEncodedImageFormat GetImageFormat(ImageFormat selectedFormat)
|
||||
{
|
||||
switch (selectedFormat)
|
||||
{
|
||||
case ImageFormat.Bmp:
|
||||
return SKEncodedImageFormat.Bmp;
|
||||
case ImageFormat.Jpg:
|
||||
return SKEncodedImageFormat.Jpeg;
|
||||
case ImageFormat.Gif:
|
||||
return SKEncodedImageFormat.Gif;
|
||||
case ImageFormat.Webp:
|
||||
return SKEncodedImageFormat.Webp;
|
||||
case ImageFormat.Png:
|
||||
default:
|
||||
return SKEncodedImageFormat.Png;
|
||||
}
|
||||
}
|
||||
|
||||
public void CropWhiteSpace(string inputPath, string outputPath)
|
||||
{
|
||||
CheckDisposed();
|
||||
|
||||
using (var bitmap = SKBitmap.Decode(inputPath))
|
||||
{
|
||||
// @todo
|
||||
}
|
||||
}
|
||||
|
||||
public ImageSize GetImageSize(string path)
|
||||
{
|
||||
CheckDisposed();
|
||||
|
||||
using (var s = new SKFileStream(path))
|
||||
{
|
||||
using (var codec = SKCodec.Create(s))
|
||||
{
|
||||
var info = codec.Info;
|
||||
|
||||
return new ImageSize
|
||||
{
|
||||
Width = info.Width,
|
||||
Height = info.Height
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void EncodeImage(string inputPath, string outputPath, bool autoOrient, int width, int height, int quality, ImageProcessingOptions options, ImageFormat selectedOutputFormat)
|
||||
{
|
||||
using (var bitmap = SKBitmap.Decode(inputPath))
|
||||
{
|
||||
using (var resizedBitmap = new SKBitmap(width, height, bitmap.ColorType, bitmap.AlphaType))
|
||||
{
|
||||
// scale image
|
||||
bitmap.Resize(resizedBitmap, SKBitmapResizeMethod.Lanczos3);
|
||||
|
||||
// create bitmap to use for canvas drawing
|
||||
using (var saveBitmap = new SKBitmap(width, height, bitmap.ColorType, bitmap.AlphaType))
|
||||
{
|
||||
// create canvas used to draw into bitmap
|
||||
using (var canvas = new SKCanvas(saveBitmap))
|
||||
{
|
||||
// set background color if present
|
||||
if (!string.IsNullOrWhiteSpace(options.BackgroundColor))
|
||||
{
|
||||
canvas.Clear(SKColor.Parse(options.BackgroundColor));
|
||||
}
|
||||
|
||||
// Add blur if option is present
|
||||
if (options.Blur > 0)
|
||||
{
|
||||
using (var paint = new SKPaint())
|
||||
{
|
||||
// create image from resized bitmap to apply blur
|
||||
using (var filter = SKImageFilter.CreateBlur(5, 5))
|
||||
{
|
||||
paint.ImageFilter = filter;
|
||||
canvas.DrawBitmap(resizedBitmap, SKRect.Create(width, height), paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// draw resized bitmap onto canvas
|
||||
canvas.DrawBitmap(resizedBitmap, SKRect.Create(width, height));
|
||||
}
|
||||
|
||||
// If foreground layer present then draw
|
||||
if (!string.IsNullOrWhiteSpace(options.ForegroundLayer))
|
||||
{
|
||||
Double opacity;
|
||||
if (!Double.TryParse(options.ForegroundLayer, out opacity)) opacity = .4;
|
||||
|
||||
var foregroundColor = String.Format("#{0:X2}000000", (Byte)((1-opacity) * 0xFF));
|
||||
canvas.DrawColor(SKColor.Parse(foregroundColor), SKBlendMode.SrcOver);
|
||||
}
|
||||
|
||||
DrawIndicator(canvas, width, height, options);
|
||||
|
||||
using (var outputStream = new SKFileWStream(outputPath))
|
||||
{
|
||||
saveBitmap.Encode(outputStream, GetImageFormat(selectedOutputFormat), quality);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CreateImageCollage(ImageCollageOptions options)
|
||||
{
|
||||
double ratio = options.Width;
|
||||
ratio /= options.Height;
|
||||
|
||||
if (ratio >= 1.4)
|
||||
{
|
||||
new StripCollageBuilder(_appPaths, _fileSystem).BuildThumbCollage(options.InputPaths, options.OutputPath, options.Width, options.Height);
|
||||
}
|
||||
else if (ratio >= .9)
|
||||
{
|
||||
new StripCollageBuilder(_appPaths, _fileSystem).BuildSquareCollage(options.InputPaths, options.OutputPath, options.Width, options.Height);
|
||||
}
|
||||
else
|
||||
{
|
||||
new StripCollageBuilder(_appPaths, _fileSystem).BuildPosterCollage(options.InputPaths, options.OutputPath, options.Width, options.Height);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawIndicator(SKCanvas canvas, int imageWidth, int imageHeight, ImageProcessingOptions options)
|
||||
{
|
||||
if (!options.AddPlayedIndicator && !options.UnplayedCount.HasValue && options.PercentPlayed.Equals(0))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var currentImageSize = new ImageSize(imageWidth, imageHeight);
|
||||
|
||||
if (options.AddPlayedIndicator)
|
||||
{
|
||||
var task = new PlayedIndicatorDrawer(_appPaths, _httpClientFactory(), _fileSystem).DrawPlayedIndicator(canvas, currentImageSize);
|
||||
Task.WaitAll(task);
|
||||
}
|
||||
else if (options.UnplayedCount.HasValue)
|
||||
{
|
||||
new UnplayedCountIndicator(_appPaths, _httpClientFactory(), _fileSystem).DrawUnplayedCountIndicator(canvas, currentImageSize, options.UnplayedCount.Value);
|
||||
}
|
||||
|
||||
if (options.PercentPlayed > 0)
|
||||
{
|
||||
new PercentPlayedDrawer().Process(canvas, currentImageSize, options.PercentPlayed);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Error drawing indicator overlay", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return "Skia"; }
|
||||
}
|
||||
|
||||
private bool _disposed;
|
||||
public void Dispose()
|
||||
{
|
||||
_disposed = true;
|
||||
}
|
||||
|
||||
private void CheckDisposed()
|
||||
{
|
||||
if (_disposed)
|
||||
{
|
||||
throw new ObjectDisposedException(GetType().Name);
|
||||
}
|
||||
}
|
||||
|
||||
public bool SupportsImageCollageCreation
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
|
||||
public bool SupportsImageEncoding
|
||||
{
|
||||
get { return true; }
|
||||
}
|
||||
}
|
||||
}
|
245
Emby.Drawing.Skia/StripCollageBuilder.cs
Normal file
245
Emby.Drawing.Skia/StripCollageBuilder.cs
Normal file
|
@ -0,0 +1,245 @@
|
|||
using SkiaSharp;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections.Generic;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Model.IO;
|
||||
|
||||
namespace Emby.Drawing.Skia
|
||||
{
|
||||
public class StripCollageBuilder
|
||||
{
|
||||
private readonly IApplicationPaths _appPaths;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
|
||||
public StripCollageBuilder(IApplicationPaths appPaths, IFileSystem fileSystem)
|
||||
{
|
||||
_appPaths = appPaths;
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
|
||||
private SKEncodedImageFormat GetEncodedFormat(string outputPath)
|
||||
{
|
||||
var ext = Path.GetExtension(outputPath).ToLower();
|
||||
|
||||
if (ext == ".jpg" || ext == ".jpeg")
|
||||
return SKEncodedImageFormat.Jpeg;
|
||||
|
||||
if (ext == ".webp")
|
||||
return SKEncodedImageFormat.Webp;
|
||||
|
||||
if (ext == ".gif")
|
||||
return SKEncodedImageFormat.Gif;
|
||||
|
||||
if (ext == ".bmp")
|
||||
return SKEncodedImageFormat.Bmp;
|
||||
|
||||
// default to png
|
||||
return SKEncodedImageFormat.Png;
|
||||
}
|
||||
|
||||
public void BuildPosterCollage(string[] paths, string outputPath, int width, int height)
|
||||
{
|
||||
using (var bitmap = BuildPosterCollageBitmap(paths, width, height))
|
||||
{
|
||||
using (var outputStream = new SKFileWStream(outputPath))
|
||||
{
|
||||
bitmap.Encode(outputStream, GetEncodedFormat(outputPath), 90);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void BuildSquareCollage(string[] paths, string outputPath, int width, int height)
|
||||
{
|
||||
using (var bitmap = BuildSquareCollageBitmap(paths, width, height))
|
||||
{
|
||||
using (var outputStream = new SKFileWStream(outputPath))
|
||||
{
|
||||
bitmap.Encode(outputStream, GetEncodedFormat(outputPath), 90);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void BuildThumbCollage(string[] paths, string outputPath, int width, int height)
|
||||
{
|
||||
using (var bitmap = BuildThumbCollageBitmap(paths, width, height))
|
||||
{
|
||||
using (var outputStream = new SKFileWStream(outputPath))
|
||||
{
|
||||
bitmap.Encode(outputStream, GetEncodedFormat(outputPath), 90);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private SKBitmap BuildPosterCollageBitmap(string[] paths, int width, int height)
|
||||
{
|
||||
return null;
|
||||
/* var inputPaths = ImageHelpers.ProjectPaths(paths, 3);
|
||||
using (var wandImages = new MagickWand(inputPaths.ToArray()))
|
||||
{
|
||||
var wand = new MagickWand(width, height);
|
||||
wand.OpenImage("gradient:#111111-#111111");
|
||||
using (var draw = new DrawingWand())
|
||||
{
|
||||
var iSlice = Convert.ToInt32(width * 0.3);
|
||||
int iTrans = Convert.ToInt32(height * .25);
|
||||
int iHeight = Convert.ToInt32(height * .65);
|
||||
var horizontalImagePadding = Convert.ToInt32(width * 0.0366);
|
||||
|
||||
foreach (var element in wandImages.ImageList)
|
||||
{
|
||||
using (var blackPixelWand = new PixelWand(ColorName.Black))
|
||||
{
|
||||
int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
|
||||
element.Gravity = GravityType.CenterGravity;
|
||||
element.BackgroundColor = blackPixelWand;
|
||||
element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
|
||||
int ix = (int)Math.Abs((iWidth - iSlice) / 2);
|
||||
element.CropImage(iSlice, iHeight, ix, 0);
|
||||
|
||||
element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
|
||||
}
|
||||
}
|
||||
|
||||
wandImages.SetFirstIterator();
|
||||
using (var wandList = wandImages.AppendImages())
|
||||
{
|
||||
wandList.CurrentImage.TrimImage(1);
|
||||
using (var mwr = wandList.CloneMagickWand())
|
||||
{
|
||||
using (var blackPixelWand = new PixelWand(ColorName.Black))
|
||||
{
|
||||
using (var greyPixelWand = new PixelWand(ColorName.Grey70))
|
||||
{
|
||||
mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
|
||||
mwr.CurrentImage.FlipImage();
|
||||
|
||||
mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
|
||||
mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand);
|
||||
|
||||
using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
|
||||
{
|
||||
mwg.OpenImage("gradient:black-none");
|
||||
var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
|
||||
mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.CopyOpacityCompositeOp, 0, verticalSpacing);
|
||||
|
||||
wandList.AddImage(mwr);
|
||||
int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
|
||||
wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .05));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wand;
|
||||
}*/
|
||||
}
|
||||
|
||||
private SKBitmap BuildThumbCollageBitmap(string[] paths, int width, int height)
|
||||
{
|
||||
return null;
|
||||
/*var inputPaths = ImageHelpers.ProjectPaths(paths, 4);
|
||||
using (var wandImages = new MagickWand(inputPaths.ToArray()))
|
||||
{
|
||||
var wand = new MagickWand(width, height);
|
||||
wand.OpenImage("gradient:#111111-#111111");
|
||||
using (var draw = new DrawingWand())
|
||||
{
|
||||
var iSlice = Convert.ToInt32(width * 0.24125);
|
||||
int iTrans = Convert.ToInt32(height * .25);
|
||||
int iHeight = Convert.ToInt32(height * .70);
|
||||
var horizontalImagePadding = Convert.ToInt32(width * 0.0125);
|
||||
|
||||
foreach (var element in wandImages.ImageList)
|
||||
{
|
||||
using (var blackPixelWand = new PixelWand(ColorName.Black))
|
||||
{
|
||||
int iWidth = (int)Math.Abs(iHeight * element.Width / element.Height);
|
||||
element.Gravity = GravityType.CenterGravity;
|
||||
element.BackgroundColor = blackPixelWand;
|
||||
element.ResizeImage(iWidth, iHeight, FilterTypes.LanczosFilter);
|
||||
int ix = (int)Math.Abs((iWidth - iSlice) / 2);
|
||||
element.CropImage(iSlice, iHeight, ix, 0);
|
||||
|
||||
element.ExtentImage(iSlice, iHeight, 0 - horizontalImagePadding, 0);
|
||||
}
|
||||
}
|
||||
|
||||
wandImages.SetFirstIterator();
|
||||
using (var wandList = wandImages.AppendImages())
|
||||
{
|
||||
wandList.CurrentImage.TrimImage(1);
|
||||
using (var mwr = wandList.CloneMagickWand())
|
||||
{
|
||||
using (var blackPixelWand = new PixelWand(ColorName.Black))
|
||||
{
|
||||
using (var greyPixelWand = new PixelWand(ColorName.Grey70))
|
||||
{
|
||||
mwr.CurrentImage.ResizeImage(wandList.CurrentImage.Width, (wandList.CurrentImage.Height / 2), FilterTypes.LanczosFilter, 1);
|
||||
mwr.CurrentImage.FlipImage();
|
||||
|
||||
mwr.CurrentImage.AlphaChannel = AlphaChannelType.DeactivateAlphaChannel;
|
||||
mwr.CurrentImage.ColorizeImage(blackPixelWand, greyPixelWand);
|
||||
|
||||
using (var mwg = new MagickWand(wandList.CurrentImage.Width, iTrans))
|
||||
{
|
||||
mwg.OpenImage("gradient:black-none");
|
||||
var verticalSpacing = Convert.ToInt32(height * 0.01111111111111111111111111111111);
|
||||
mwr.CurrentImage.CompositeImage(mwg, CompositeOperator.CopyOpacityCompositeOp, 0, verticalSpacing);
|
||||
|
||||
wandList.AddImage(mwr);
|
||||
int ex = (int)(wand.CurrentImage.Width - mwg.CurrentImage.Width) / 2;
|
||||
wand.CurrentImage.CompositeImage(wandList.AppendImages(true), CompositeOperator.AtopCompositeOp, ex, Convert.ToInt32(height * .045));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return wand;
|
||||
}*/
|
||||
}
|
||||
|
||||
private SKBitmap BuildSquareCollageBitmap(string[] paths, int width, int height)
|
||||
{
|
||||
var bitmap = new SKBitmap(width, height);
|
||||
var imageIndex = 0;
|
||||
var cellWidth = width / 2;
|
||||
var cellHeight = height / 2;
|
||||
|
||||
using (var canvas = new SKCanvas(bitmap))
|
||||
{
|
||||
for (var x = 0; x < 2; x++)
|
||||
{
|
||||
for (var y = 0; y < 2; y++)
|
||||
{
|
||||
using (var currentBitmap = SKBitmap.Decode(paths[imageIndex]))
|
||||
{
|
||||
using (var resizedBitmap = new SKBitmap(cellWidth, cellHeight, currentBitmap.ColorType, currentBitmap.AlphaType))
|
||||
{
|
||||
// scale image
|
||||
currentBitmap.Resize(resizedBitmap, SKBitmapResizeMethod.Lanczos3);
|
||||
|
||||
// draw this image into the strip at the next position
|
||||
var xPos = x * cellWidth;
|
||||
var yPos = y * cellHeight;
|
||||
canvas.DrawBitmap(resizedBitmap, xPos, yPos);
|
||||
}
|
||||
}
|
||||
imageIndex++;
|
||||
|
||||
if (imageIndex >= paths.Length)
|
||||
imageIndex = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bitmap;
|
||||
}
|
||||
}
|
||||
}
|
68
Emby.Drawing.Skia/UnplayedCountIndicator.cs
Normal file
68
Emby.Drawing.Skia/UnplayedCountIndicator.cs
Normal file
|
@ -0,0 +1,68 @@
|
|||
using SkiaSharp;
|
||||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Model.Drawing;
|
||||
using System.Globalization;
|
||||
using System.Threading.Tasks;
|
||||
using MediaBrowser.Common.IO;
|
||||
using MediaBrowser.Controller.IO;
|
||||
using MediaBrowser.Model.IO;
|
||||
|
||||
namespace Emby.Drawing.Skia
|
||||
{
|
||||
public class UnplayedCountIndicator
|
||||
{
|
||||
private const int OffsetFromTopRightCorner = 38;
|
||||
|
||||
private readonly IApplicationPaths _appPaths;
|
||||
private readonly IHttpClient _iHttpClient;
|
||||
private readonly IFileSystem _fileSystem;
|
||||
|
||||
public UnplayedCountIndicator(IApplicationPaths appPaths, IHttpClient iHttpClient, IFileSystem fileSystem)
|
||||
{
|
||||
_appPaths = appPaths;
|
||||
_iHttpClient = iHttpClient;
|
||||
_fileSystem = fileSystem;
|
||||
}
|
||||
|
||||
public void DrawUnplayedCountIndicator(SKCanvas canvas, ImageSize imageSize, int count)
|
||||
{
|
||||
var x = imageSize.Width - OffsetFromTopRightCorner;
|
||||
var text = count.ToString(CultureInfo.InvariantCulture);
|
||||
|
||||
using (var paint = new SKPaint())
|
||||
{
|
||||
paint.Color = SKColor.Parse("#CC52B54B");
|
||||
paint.Style = SKPaintStyle.Fill;
|
||||
canvas.DrawCircle((float)x, OffsetFromTopRightCorner, 20, paint);
|
||||
}
|
||||
using (var paint = new SKPaint())
|
||||
{
|
||||
paint.Color = new SKColor(255, 255, 255, 255);
|
||||
paint.Style = SKPaintStyle.Fill;
|
||||
paint.Typeface = SKTypeface.FromFile(PlayedIndicatorDrawer.ExtractFont("robotoregular.ttf", _appPaths, _fileSystem));
|
||||
paint.TextSize = 24;
|
||||
paint.IsAntialias = true;
|
||||
|
||||
var y = OffsetFromTopRightCorner + 9;
|
||||
|
||||
if (text.Length == 1)
|
||||
{
|
||||
x -= 7;
|
||||
}
|
||||
if (text.Length == 2)
|
||||
{
|
||||
x -= 13;
|
||||
}
|
||||
else if (text.Length >= 3)
|
||||
{
|
||||
x -= 15;
|
||||
y -= 2;
|
||||
paint.TextSize = 18;
|
||||
}
|
||||
|
||||
canvas.DrawText(text, (float)x, y, paint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -191,9 +191,11 @@
|
|||
<ItemGroup>
|
||||
<Content Include="..\packages\SkiaSharp.1.57.1\runtimes\win7-x64\native\libSkiaSharp.dll">
|
||||
<Link>x64\libSkiaSharp.dll</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="..\packages\SkiaSharp.1.57.1\runtimes\win7-x86\native\libSkiaSharp.dll">
|
||||
<Link>x86\libSkiaSharp.dll</Link>
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="..\Tools\Installation\MediaBrowser.InstallUtil.dll">
|
||||
<Link>MediaBrowser.InstallUtil.dll</Link>
|
||||
|
|
Loading…
Reference in New Issue
Block a user