From 96a057df23b53ea0d02b2ae1028021de9b438af0 Mon Sep 17 00:00:00 2001 From: SpoinkyNL Date: Tue, 3 Dec 2019 00:09:32 +0100 Subject: [PATCH] Implemented most of the rendering pipeline in SkiaSharp --- src/Artemis.Core/Artemis.Core.csproj | 10 +-- .../Events/FrameRenderedEventArgs.cs | 9 +- .../Events/FrameRenderingEventArgs.cs | 8 +- .../Extensions/RgbRectangleExtensions.cs | 15 ++-- .../Models/Profile/Abstract/ProfileElement.cs | 4 +- src/Artemis.Core/Models/Profile/Folder.cs | 6 +- src/Artemis.Core/Models/Profile/Layer.cs | 36 ++++---- src/Artemis.Core/Models/Profile/Profile.cs | 6 +- .../Models/Surface/ArtemisDevice.cs | 19 ++--- src/Artemis.Core/Models/Surface/ArtemisLed.cs | 28 +++---- src/Artemis.Core/Plugins/Abstract/Module.cs | 1 - .../Plugins/Abstract/ProfileModule.cs | 6 +- .../Plugins/LayerElement/LayerElement.cs | 10 +-- src/Artemis.Core/RGB.NET/GraphicsDecorator.cs | 9 +- src/Artemis.Core/Services/CoreService.cs | 28 ++++--- src/Artemis.Core/Services/DeviceService.cs | 9 +- src/Artemis.Core/Services/RgbService.cs | 28 ++++--- src/Artemis.Core/app.config | 2 +- src/Artemis.Core/packages.config | 6 +- .../app.config | 2 +- .../app.config | 2 +- ...Artemis.Plugins.LayerElements.Brush.csproj | 16 ++-- .../BrushLayerElement.cs | 15 ++-- .../BrushLayerElementSettings.cs | 11 ++- .../app.config | 2 +- .../packages.config | 8 +- .../Artemis.Plugins.Modules.General.csproj | 16 ++-- .../ColorHelpers.cs | 25 ------ .../GeneralModule.cs | 84 +++++++------------ .../app.config | 2 +- .../packages.config | 8 +- src/Artemis.UI/App.config | 2 +- src/Artemis.UI/Artemis.UI.csproj | 19 +++-- .../Screens/Settings/Debug/DebugViewModel.cs | 48 +++++------ src/Artemis.UI/packages.config | 8 +- 35 files changed, 234 insertions(+), 274 deletions(-) diff --git a/src/Artemis.Core/Artemis.Core.csproj b/src/Artemis.Core/Artemis.Core.csproj index 0012730ab..4a90f4988 100644 --- a/src/Artemis.Core/Artemis.Core.csproj +++ b/src/Artemis.Core/Artemis.Core.csproj @@ -113,8 +113,8 @@ ..\packages\SkiaSharp.1.68.1\lib\net45\SkiaSharp.dll - - ..\packages\Stylet.1.2.0\lib\net45\Stylet.dll + + ..\packages\Stylet.1.3.0\lib\net45\Stylet.dll @@ -132,15 +132,15 @@ ..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll - - ..\packages\System.Numerics.Vectors.4.6.0-preview5.19224.8\lib\net46\System.Numerics.Vectors.dll + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll ..\packages\System.Reflection.Metadata.1.7.0-preview8.19405.3\lib\netstandard2.0\System.Reflection.Metadata.dll - ..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0-preview8.19405.3\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + ..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll diff --git a/src/Artemis.Core/Events/FrameRenderedEventArgs.cs b/src/Artemis.Core/Events/FrameRenderedEventArgs.cs index 144482c9c..d88bb89b7 100644 --- a/src/Artemis.Core/Events/FrameRenderedEventArgs.cs +++ b/src/Artemis.Core/Events/FrameRenderedEventArgs.cs @@ -1,18 +1,19 @@ using System; using System.Drawing; +using Artemis.Core.RGB.NET; using RGB.NET.Core; namespace Artemis.Core.Events { public class FrameRenderedEventArgs : EventArgs { - public FrameRenderedEventArgs(Bitmap bitmap, RGBSurface rgbSurface) + public FrameRenderedEventArgs(GraphicsDecorator graphicsDecorator, RGBSurface rgbSurface) { - Bitmap = bitmap; + GraphicsDecorator = graphicsDecorator; RgbSurface = rgbSurface; } - - public Bitmap Bitmap { get; } + + public GraphicsDecorator GraphicsDecorator { get; } public RGBSurface RgbSurface { get; } } } \ No newline at end of file diff --git a/src/Artemis.Core/Events/FrameRenderingEventArgs.cs b/src/Artemis.Core/Events/FrameRenderingEventArgs.cs index fb6f49184..05d05eff0 100644 --- a/src/Artemis.Core/Events/FrameRenderingEventArgs.cs +++ b/src/Artemis.Core/Events/FrameRenderingEventArgs.cs @@ -1,23 +1,23 @@ using System; using System.Collections.Generic; using Artemis.Core.Plugins.Abstract; -using Artemis.Core.RGB.NET; using RGB.NET.Core; +using SkiaSharp; namespace Artemis.Core.Events { public class FrameRenderingEventArgs : EventArgs { - public FrameRenderingEventArgs(List modules, GraphicsDecorator graphicsDecorator, double deltaTime, RGBSurface rgbSurface) + public FrameRenderingEventArgs(List modules, SKCanvas canvas, double deltaTime, RGBSurface rgbSurface) { Modules = modules; - GraphicsDecorator = graphicsDecorator; + Canvas = canvas; DeltaTime = deltaTime; RgbSurface = rgbSurface; } public List Modules { get; } - public GraphicsDecorator GraphicsDecorator { get; } + public SKCanvas Canvas { get; } public double DeltaTime { get; } public RGBSurface RgbSurface { get; } } diff --git a/src/Artemis.Core/Extensions/RgbRectangleExtensions.cs b/src/Artemis.Core/Extensions/RgbRectangleExtensions.cs index bbc3c21e1..3910dc9a0 100644 --- a/src/Artemis.Core/Extensions/RgbRectangleExtensions.cs +++ b/src/Artemis.Core/Extensions/RgbRectangleExtensions.cs @@ -1,16 +1,17 @@ -using System.Drawing; +using RGB.NET.Core; +using SkiaSharp; namespace Artemis.Core.Extensions { public static class RgbRectangleExtensions { - public static Rectangle ToDrawingRectangle(this global::RGB.NET.Core.Rectangle rectangle, double scale) + public static SKRect ToSKRect(this Rectangle rectangle, double scale) { - return new Rectangle( - (int) (rectangle.Location.X * scale), - (int) (rectangle.Location.Y * scale), - (int) (rectangle.Size.Width * scale), - (int) (rectangle.Size.Height * scale) + return SKRect.Create( + (rectangle.Location.X * scale).RoundToInt(), + (rectangle.Location.Y * scale).RoundToInt(), + (rectangle.Size.Width * scale).RoundToInt(), + (rectangle.Size.Height * scale).RoundToInt() ); } } diff --git a/src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs b/src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs index 8fec27918..ca259edd1 100644 --- a/src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs +++ b/src/Artemis.Core/Models/Profile/Abstract/ProfileElement.cs @@ -1,9 +1,9 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Drawing; using System.Linq; using Artemis.Core.Models.Surface; +using SkiaSharp; using Stylet; namespace Artemis.Core.Models.Profile.Abstract @@ -45,7 +45,7 @@ namespace Artemis.Core.Models.Profile.Abstract /// /// Renders the element /// - public abstract void Render(double deltaTime, ArtemisSurface surface, Graphics graphics); + public abstract void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas); /// /// Applies the profile element's properties to the underlying storage entity diff --git a/src/Artemis.Core/Models/Profile/Folder.cs b/src/Artemis.Core/Models/Profile/Folder.cs index 41fde07ae..5d72238ee 100644 --- a/src/Artemis.Core/Models/Profile/Folder.cs +++ b/src/Artemis.Core/Models/Profile/Folder.cs @@ -1,9 +1,9 @@ using System; -using System.Drawing; using System.Linq; using Artemis.Core.Models.Profile.Abstract; using Artemis.Core.Models.Surface; using Artemis.Storage.Entities.Profile; +using SkiaSharp; namespace Artemis.Core.Models.Profile { @@ -56,11 +56,11 @@ namespace Artemis.Core.Models.Profile profileElement.Update(deltaTime); } - public override void Render(double deltaTime, ArtemisSurface surface, Graphics graphics) + public override void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas) { // Folders don't render but their children do foreach (var profileElement in Children) - profileElement.Render(deltaTime, surface, graphics); + profileElement.Render(deltaTime, surface, canvas); } public Folder AddFolder(string name) diff --git a/src/Artemis.Core/Models/Profile/Layer.cs b/src/Artemis.Core/Models/Profile/Layer.cs index aee7eab8b..cc8affc16 100644 --- a/src/Artemis.Core/Models/Profile/Layer.cs +++ b/src/Artemis.Core/Models/Profile/Layer.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; -using System.Drawing; -using System.Drawing.Drawing2D; using System.Linq; using Artemis.Core.Extensions; using Artemis.Core.Models.Profile.Abstract; @@ -10,6 +8,7 @@ using Artemis.Core.Models.Surface; using Artemis.Core.Plugins.LayerElement; using Artemis.Storage.Entities.Profile; using Newtonsoft.Json; +using SkiaSharp; namespace Artemis.Core.Models.Profile { @@ -50,8 +49,8 @@ namespace Artemis.Core.Models.Profile public ReadOnlyCollection Leds => _leds.AsReadOnly(); public ReadOnlyCollection LayerElements => _layerElements.AsReadOnly(); - public Rectangle RenderRectangle { get; set; } - public GraphicsPath RenderPath { get; set; } + public SKRect RenderRectangle { get; set; } + public SKPath RenderPath { get; set; } public override void Update(double deltaTime) { @@ -59,20 +58,21 @@ namespace Artemis.Core.Models.Profile layerElement.Update(deltaTime); } - public override void Render(double deltaTime, ArtemisSurface surface, Graphics graphics) + public override void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas) { - graphics.SetClip(RenderPath); + canvas.Save(); + canvas.ClipPath(RenderPath); foreach (var layerElement in LayerElements) - layerElement.RenderPreProcess(surface, graphics); + layerElement.RenderPreProcess(surface, canvas); foreach (var layerElement in LayerElements) - layerElement.Render(surface, graphics); + layerElement.Render(surface, canvas); foreach (var layerElement in LayerElements) - layerElement.RenderPostProcess(surface, graphics); + layerElement.RenderPostProcess(surface, canvas); - graphics.ResetClip(); + canvas.Restore(); } internal override void ApplyToEntity() @@ -167,15 +167,17 @@ namespace Artemis.Core.Models.Profile } // Determine to top-left and bottom-right - var minX = Leds.Min(l => l.AbsoluteRenderRectangle.X); - var minY = Leds.Min(l => l.AbsoluteRenderRectangle.Y); - var maxX = Leds.Max(l => l.AbsoluteRenderRectangle.X + l.AbsoluteRenderRectangle.Width); - var maxY = Leds.Max(l => l.AbsoluteRenderRectangle.Y + l.AbsoluteRenderRectangle.Height); + var minX = Leds.Min(l => l.AbsoluteRenderRectangle.Left); + var minY = Leds.Min(l => l.AbsoluteRenderRectangle.Top); + var maxX = Leds.Max(l => l.AbsoluteRenderRectangle.Bottom); + var maxY = Leds.Max(l => l.AbsoluteRenderRectangle.Right); - RenderRectangle = new Rectangle(minX, minY, maxX - minX, maxY - minY); + RenderRectangle = SKRect.Create(minX, minY, maxX - minX, maxY - minY); + + var path = new SKPath {FillType = SKPathFillType.Winding}; + foreach (var artemisLed in Leds) + path.AddRect(artemisLed.AbsoluteRenderRectangle); - var path = new GraphicsPath(); - path.AddRectangles(Leds.Select(l => l.AbsoluteRenderRectangle).ToArray()); RenderPath = path; } diff --git a/src/Artemis.Core/Models/Profile/Profile.cs b/src/Artemis.Core/Models/Profile/Profile.cs index 2f6f17395..beea80582 100644 --- a/src/Artemis.Core/Models/Profile/Profile.cs +++ b/src/Artemis.Core/Models/Profile/Profile.cs @@ -1,11 +1,11 @@ using System; -using System.Drawing; using System.Linq; using Artemis.Core.Exceptions; using Artemis.Core.Models.Profile.Abstract; using Artemis.Core.Models.Surface; using Artemis.Core.Plugins.Models; using Artemis.Storage.Entities.Profile; +using SkiaSharp; namespace Artemis.Core.Models.Profile { @@ -56,7 +56,7 @@ namespace Artemis.Core.Models.Profile } } - public override void Render(double deltaTime, ArtemisSurface surface, Graphics graphics) + public override void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas) { lock (this) { @@ -64,7 +64,7 @@ namespace Artemis.Core.Models.Profile throw new ArtemisCoreException($"Cannot render inactive profile: {this}"); foreach (var profileElement in Children) - profileElement.Render(deltaTime, surface, graphics); + profileElement.Render(deltaTime, surface, canvas); } } diff --git a/src/Artemis.Core/Models/Surface/ArtemisDevice.cs b/src/Artemis.Core/Models/Surface/ArtemisDevice.cs index 402e13102..12fdc8269 100644 --- a/src/Artemis.Core/Models/Surface/ArtemisDevice.cs +++ b/src/Artemis.Core/Models/Surface/ArtemisDevice.cs @@ -1,6 +1,5 @@ using System; using System.Collections.ObjectModel; -using System.Drawing.Drawing2D; using System.Linq; using Artemis.Core.Extensions; using Artemis.Core.Plugins.Abstract; @@ -8,7 +7,6 @@ using Artemis.Storage.Entities.Surface; using RGB.NET.Core; using SkiaSharp; using Stylet; -using Rectangle = System.Drawing.Rectangle; namespace Artemis.Core.Models.Surface { @@ -99,14 +97,8 @@ namespace Artemis.Core.Models.Surface RenderRectangle = SKRect.Create( (RgbDevice.Location.X * Surface.Scale).RoundToInt(), (RgbDevice.Location.Y * Surface.Scale).RoundToInt(), - (RgbDevice.Location.X * Surface.Scale).RoundToInt(), - (RgbDevice.Location.X * Surface.Scale).RoundToInt() - ); - RenderRectangle = new Rectangle( - (int) Math.Round(RgbDevice.Location.X * Surface.Scale, MidpointRounding.AwayFromZero), - (int) Math.Round(RgbDevice.Location.Y * Surface.Scale, MidpointRounding.AwayFromZero), - (int) Math.Round(RgbDevice.DeviceRectangle.Size.Width * Surface.Scale, MidpointRounding.AwayFromZero), - (int) Math.Round(RgbDevice.DeviceRectangle.Size.Height * Surface.Scale, MidpointRounding.AwayFromZero) + (RgbDevice.DeviceRectangle.Size.Width * Surface.Scale).RoundToInt(), + (RgbDevice.DeviceRectangle.Size.Height * Surface.Scale).RoundToInt() ); if (!Leds.Any()) @@ -115,9 +107,10 @@ namespace Artemis.Core.Models.Surface foreach (var led in Leds) led.CalculateRenderRectangle(); - var path = new GraphicsPath(); - path.AddRectangles(Leds.Select(l => l.AbsoluteRenderRectangle).ToArray()); - path.FillMode = FillMode.Winding; + var path = new SKPath {FillType = SKPathFillType.Winding}; + foreach (var artemisLed in Leds) + path.AddRect(artemisLed.AbsoluteRenderRectangle); + RenderPath = path; } diff --git a/src/Artemis.Core/Models/Surface/ArtemisLed.cs b/src/Artemis.Core/Models/Surface/ArtemisLed.cs index fdc6f1162..5b5cb0910 100644 --- a/src/Artemis.Core/Models/Surface/ArtemisLed.cs +++ b/src/Artemis.Core/Models/Surface/ArtemisLed.cs @@ -1,7 +1,7 @@ -using System; +using Artemis.Core.Extensions; using RGB.NET.Core; +using SkiaSharp; using Stylet; -using Rectangle = System.Drawing.Rectangle; namespace Artemis.Core.Models.Surface { @@ -17,22 +17,22 @@ namespace Artemis.Core.Models.Surface public Led RgbLed { get; } public ArtemisDevice Device { get; } - public Rectangle RenderRectangle { get; private set; } - public Rectangle AbsoluteRenderRectangle { get; private set; } + public SKRect RenderRectangle { get; private set; } + public SKRect AbsoluteRenderRectangle { get; private set; } public void CalculateRenderRectangle() { - RenderRectangle = new Rectangle( - (int) Math.Round(RgbLed.LedRectangle.Location.X * Device.Surface.Scale, MidpointRounding.AwayFromZero), - (int) Math.Round(RgbLed.LedRectangle.Location.Y * Device.Surface.Scale, MidpointRounding.AwayFromZero), - (int) Math.Round(RgbLed.LedRectangle.Size.Width * Device.Surface.Scale, MidpointRounding.AwayFromZero), - (int) Math.Round(RgbLed.LedRectangle.Size.Height * Device.Surface.Scale, MidpointRounding.AwayFromZero) + RenderRectangle = SKRect.Create( + (RgbLed.LedRectangle.Location.X * Device.Surface.Scale).RoundToInt(), + (RgbLed.LedRectangle.Location.Y * Device.Surface.Scale).RoundToInt(), + (RgbLed.LedRectangle.Size.Width * Device.Surface.Scale).RoundToInt(), + (RgbLed.LedRectangle.Size.Height * Device.Surface.Scale).RoundToInt() ); - AbsoluteRenderRectangle = new Rectangle( - (int) Math.Round(RgbLed.AbsoluteLedRectangle.Location.X * Device.Surface.Scale, MidpointRounding.AwayFromZero), - (int) Math.Round(RgbLed.AbsoluteLedRectangle.Location.Y * Device.Surface.Scale, MidpointRounding.AwayFromZero), - (int) Math.Round(RgbLed.AbsoluteLedRectangle.Size.Width * Device.Surface.Scale, MidpointRounding.AwayFromZero), - (int) Math.Round(RgbLed.AbsoluteLedRectangle.Size.Height * Device.Surface.Scale, MidpointRounding.AwayFromZero) + AbsoluteRenderRectangle = SKRect.Create( + (RgbLed.AbsoluteLedRectangle.Location.X * Device.Surface.Scale).RoundToInt(), + (RgbLed.AbsoluteLedRectangle.Location.Y * Device.Surface.Scale).RoundToInt(), + (RgbLed.AbsoluteLedRectangle.Size.Width * Device.Surface.Scale).RoundToInt(), + (RgbLed.AbsoluteLedRectangle.Size.Height * Device.Surface.Scale).RoundToInt() ); } } diff --git a/src/Artemis.Core/Plugins/Abstract/Module.cs b/src/Artemis.Core/Plugins/Abstract/Module.cs index fdc28e2f1..244e83ce6 100644 --- a/src/Artemis.Core/Plugins/Abstract/Module.cs +++ b/src/Artemis.Core/Plugins/Abstract/Module.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using System.Drawing; using Artemis.Core.Models.Surface; using Artemis.Core.Plugins.Models; using SkiaSharp; diff --git a/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs b/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs index 69d4f52ed..10954ed4f 100644 --- a/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs +++ b/src/Artemis.Core/Plugins/Abstract/ProfileModule.cs @@ -1,9 +1,9 @@ using System; -using System.Drawing; using Artemis.Core.Exceptions; using Artemis.Core.Models.Profile; using Artemis.Core.Models.Surface; using Artemis.Core.Plugins.Models; +using SkiaSharp; namespace Artemis.Core.Plugins.Abstract { @@ -26,12 +26,12 @@ namespace Artemis.Core.Plugins.Abstract } /// - public override void Render(double deltaTime, ArtemisSurface surface, Graphics graphics) + public override void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas) { lock (this) { // Render the profile - ActiveProfile?.Render(deltaTime, surface, graphics); + ActiveProfile?.Render(deltaTime, surface, canvas); } } diff --git a/src/Artemis.Core/Plugins/LayerElement/LayerElement.cs b/src/Artemis.Core/Plugins/LayerElement/LayerElement.cs index b4df0ab4e..a529a8b7d 100644 --- a/src/Artemis.Core/Plugins/LayerElement/LayerElement.cs +++ b/src/Artemis.Core/Plugins/LayerElement/LayerElement.cs @@ -1,6 +1,6 @@ -using System.Drawing; -using Artemis.Core.Models.Profile; +using Artemis.Core.Models.Profile; using Artemis.Core.Models.Surface; +using SkiaSharp; namespace Artemis.Core.Plugins.LayerElement { @@ -32,16 +32,16 @@ namespace Artemis.Core.Plugins.LayerElement /// /// Called before rendering, in the order configured on the layer /// - public abstract void RenderPreProcess(ArtemisSurface surface, Graphics graphics); + public abstract void RenderPreProcess(ArtemisSurface surface, SKCanvas canvas); /// /// Called during rendering, in the order configured on the layer /// - public abstract void Render(ArtemisSurface surface, Graphics graphics); + public abstract void Render(ArtemisSurface surface, SKCanvas canvas); /// /// Called after rendering, in the order configured on the layer /// - public abstract void RenderPostProcess(ArtemisSurface surface, Graphics graphics); + public abstract void RenderPostProcess(ArtemisSurface surface, SKCanvas canvas); } } \ No newline at end of file diff --git a/src/Artemis.Core/RGB.NET/GraphicsDecorator.cs b/src/Artemis.Core/RGB.NET/GraphicsDecorator.cs index e37334a02..f93cecb82 100644 --- a/src/Artemis.Core/RGB.NET/GraphicsDecorator.cs +++ b/src/Artemis.Core/RGB.NET/GraphicsDecorator.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using Artemis.Core.Extensions; using RGB.NET.Core; using SkiaSharp; @@ -19,12 +20,10 @@ namespace Artemis.Core.RGB.NET var width = Math.Min(leds.Max(l => l.AbsoluteLedRectangle.Location.X + l.AbsoluteLedRectangle.Size.Width) * scale, 4096); var height = Math.Min(leds.Max(l => l.AbsoluteLedRectangle.Location.Y + l.AbsoluteLedRectangle.Size.Height) * scale, 4096); - Bitmap = new SKBitmap(new SKImageInfo(RoundToInt(width), RoundToInt(height))); - Canvas = new SKCanvas(Bitmap); + Bitmap = new SKBitmap(new SKImageInfo(width.RoundToInt(), height.RoundToInt())); } - + public SKBitmap Bitmap { get; private set; } - public SKCanvas Canvas { get; private set; } public Color ManipulateColor(Rectangle rectangle, BrushRenderTarget renderTarget, Color color) { @@ -46,9 +45,7 @@ namespace Artemis.Core.RGB.NET public void Dispose() { Bitmap?.Dispose(); - Canvas?.Dispose(); Bitmap = null; - Canvas = null; } private int RoundToInt(double number) diff --git a/src/Artemis.Core/Services/CoreService.cs b/src/Artemis.Core/Services/CoreService.cs index 023788a86..f784b2c65 100644 --- a/src/Artemis.Core/Services/CoreService.cs +++ b/src/Artemis.Core/Services/CoreService.cs @@ -8,6 +8,7 @@ using Artemis.Core.Services.Interfaces; using Artemis.Core.Services.Storage.Interfaces; using RGB.NET.Core; using Serilog; +using SkiaSharp; namespace Artemis.Core.Services { @@ -78,19 +79,24 @@ namespace Artemis.Core.Services } // If there is no ready graphics decorator, skip the frame - if (_rgbService.GraphicsDecorator?.Canvas == null) - return; - - // Render all active modules - _rgbService.GraphicsDecorator.Canvas.Clear(); - lock (_modules) + lock (_rgbService.GraphicsDecorator) { - foreach (var module in _modules) - module.Render(args.DeltaTime, _surfaceService.ActiveSurface, _rgbService.GraphicsDecorator.Canvas); + if (_rgbService.GraphicsDecorator?.Bitmap == null) + return; + + // Render all active modules + using (var canvas = new SKCanvas(_rgbService.GraphicsDecorator.Bitmap)) + { + canvas.Clear(new SKColor(0, 0, 0)); + lock (_modules) + { + foreach (var module in _modules) + module.Render(args.DeltaTime, _surfaceService.ActiveSurface, canvas); + } + + OnFrameRendering(new FrameRenderingEventArgs(_modules, canvas, args.DeltaTime, _rgbService.Surface)); + } } - - - OnFrameRendering(new FrameRenderingEventArgs(_modules, _rgbService.GraphicsDecorator, args.DeltaTime, _rgbService.Surface)); } catch (Exception e) { diff --git a/src/Artemis.Core/Services/DeviceService.cs b/src/Artemis.Core/Services/DeviceService.cs index c511a1593..fab36dec0 100644 --- a/src/Artemis.Core/Services/DeviceService.cs +++ b/src/Artemis.Core/Services/DeviceService.cs @@ -1,8 +1,8 @@ -using System.Drawing; -using System.Threading.Tasks; +using System.Threading.Tasks; using Artemis.Core.Events; using Artemis.Core.Models.Surface; using Artemis.Core.Services.Interfaces; +using SkiaSharp; namespace Artemis.Core.Services { @@ -25,10 +25,7 @@ namespace Artemis.Core.Services // Draw a white overlay over the device void DrawOverlay(object sender, FrameRenderingEventArgs args) { - using (var g = Graphics.FromImage(args.Bitmap)) - { - g.FillPath(new SolidBrush(Color.White), device.RenderPath); - } + args.Canvas.DrawPath(device.RenderPath, new SKPaint {Color = new SKColor(255, 255, 255)}); } _coreService.FrameRendering += DrawOverlay; diff --git a/src/Artemis.Core/Services/RgbService.cs b/src/Artemis.Core/Services/RgbService.cs index 34ef7ff62..5f6719938 100644 --- a/src/Artemis.Core/Services/RgbService.cs +++ b/src/Artemis.Core/Services/RgbService.cs @@ -30,6 +30,7 @@ namespace Artemis.Core.Services _targetFrameRateSetting = settingsService.GetSetting("Core.TargetFrameRate", 25); Surface = RGBSurface.Instance; + GraphicsDecorator = new GraphicsDecorator(new ListLedGroup(), 1); // Let's throw these for now Surface.Exception += SurfaceOnException; @@ -100,21 +101,22 @@ namespace Artemis.Core.Services public void UpdateGraphicsDecorator() { - // TODO: Create new one first, then clean up the old one for a smoother transition - - // Clean up the old background if present - if (_background != null) + lock (GraphicsDecorator) { - _background.Brush?.RemoveAllDecorators(); - _background.Detach(); + // Clean up the old background if present + if (_background != null) + { + _background.Brush?.RemoveAllDecorators(); + _background.Detach(); + } + + // Apply the application wide brush and decorator + _background = new ListLedGroup(Surface.Leds) {Brush = new SolidColorBrush(new Color(255, 255, 255, 255))}; + GraphicsDecorator = new GraphicsDecorator(_background, _renderScaleSetting.Value); + _background.Brush.RemoveAllDecorators(); + + _background.Brush.AddDecorator(GraphicsDecorator); } - - // Apply the application wide brush and decorator - _background = new ListLedGroup(Surface.Leds) {Brush = new SolidColorBrush(new Color(255, 255, 255, 255))}; - GraphicsDecorator = new GraphicsDecorator(_background, _renderScaleSetting.Value); - _background.Brush.RemoveAllDecorators(); - - _background.Brush.AddDecorator(GraphicsDecorator); } private void OnDeviceLoaded(DeviceEventArgs e) diff --git a/src/Artemis.Core/app.config b/src/Artemis.Core/app.config index 32dcf9823..29342a3c3 100644 --- a/src/Artemis.Core/app.config +++ b/src/Artemis.Core/app.config @@ -97,7 +97,7 @@ - + diff --git a/src/Artemis.Core/packages.config b/src/Artemis.Core/packages.config index 182a96878..b00ab366b 100644 --- a/src/Artemis.Core/packages.config +++ b/src/Artemis.Core/packages.config @@ -15,13 +15,13 @@ - + - + - + \ No newline at end of file diff --git a/src/Artemis.Plugins.Devices.Corsair/app.config b/src/Artemis.Plugins.Devices.Corsair/app.config index 9b3e8ff8d..7567ab9a5 100644 --- a/src/Artemis.Plugins.Devices.Corsair/app.config +++ b/src/Artemis.Plugins.Devices.Corsair/app.config @@ -13,7 +13,7 @@ - + diff --git a/src/Artemis.Plugins.Devices.Logitech/app.config b/src/Artemis.Plugins.Devices.Logitech/app.config index c8bc187aa..be637eaeb 100644 --- a/src/Artemis.Plugins.Devices.Logitech/app.config +++ b/src/Artemis.Plugins.Devices.Logitech/app.config @@ -21,7 +21,7 @@ - + diff --git a/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerElements.Brush.csproj b/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerElements.Brush.csproj index 1f7f03acc..daf7ce136 100644 --- a/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerElements.Brush.csproj +++ b/src/Artemis.Plugins.LayerTypes.Brush/Artemis.Plugins.LayerElements.Brush.csproj @@ -53,23 +53,23 @@ ..\packages\SkiaSharp.1.68.1\lib\net45\SkiaSharp.dll - - ..\packages\Stylet.1.2.0\lib\net45\Stylet.dll + + ..\packages\Stylet.1.3.0\lib\net45\Stylet.dll - - ..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll + + ..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll ..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll - - ..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll - - ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll diff --git a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElement.cs b/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElement.cs index 37153dd13..d0569be56 100644 --- a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElement.cs +++ b/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElement.cs @@ -1,7 +1,7 @@ -using System.Drawing; -using Artemis.Core.Models.Profile; +using Artemis.Core.Models.Profile; using Artemis.Core.Models.Surface; using Artemis.Core.Plugins.LayerElement; +using SkiaSharp; namespace Artemis.Plugins.LayerElements.Brush { @@ -9,7 +9,7 @@ namespace Artemis.Plugins.LayerElements.Brush { public BrushLayerElement(Layer layer, BrushLayerElementSettings settings, LayerElementDescriptor descriptor) : base(layer, settings, descriptor) { - Settings = settings ?? new BrushLayerElementSettings {Brush = new SolidBrush(Color.Red)}; + Settings = settings ?? new BrushLayerElementSettings(); } public new BrushLayerElementSettings Settings { get; } @@ -23,17 +23,16 @@ namespace Artemis.Plugins.LayerElements.Brush { } - public override void RenderPreProcess(ArtemisSurface surface, Graphics graphics) + public override void RenderPreProcess(ArtemisSurface surface, SKCanvas canvas) { } - public override void Render(ArtemisSurface surface, Graphics graphics) + public override void Render(ArtemisSurface surface, SKCanvas canvas) { - if (Settings?.Brush != null) - graphics.FillRectangle(Settings.Brush, Layer.RenderRectangle); + canvas.DrawRect(Layer.RenderRectangle, new SKPaint {Color = new SKColor(255, 255, 255, 255)}); } - public override void RenderPostProcess(ArtemisSurface surface, Graphics graphics) + public override void RenderPostProcess(ArtemisSurface surface, SKCanvas canvas) { } } diff --git a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementSettings.cs b/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementSettings.cs index b274810e8..e2d40a752 100644 --- a/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementSettings.cs +++ b/src/Artemis.Plugins.LayerTypes.Brush/BrushLayerElementSettings.cs @@ -1,9 +1,16 @@ -using Artemis.Core.Plugins.LayerElement; +using System.Collections.Generic; +using Artemis.Core.Plugins.LayerElement; +using SkiaSharp; namespace Artemis.Plugins.LayerElements.Brush { public class BrushLayerElementSettings : LayerElementSettings { - public System.Drawing.Brush Brush { get; set; } + public BrushLayerElementSettings() + { + Colors = new List(); + } + + public List Colors { get; set; } } } \ No newline at end of file diff --git a/src/Artemis.Plugins.LayerTypes.Brush/app.config b/src/Artemis.Plugins.LayerTypes.Brush/app.config index 0edb16ded..983b4f4d9 100644 --- a/src/Artemis.Plugins.LayerTypes.Brush/app.config +++ b/src/Artemis.Plugins.LayerTypes.Brush/app.config @@ -13,7 +13,7 @@ - + diff --git a/src/Artemis.Plugins.LayerTypes.Brush/packages.config b/src/Artemis.Plugins.LayerTypes.Brush/packages.config index 4ea1f6565..66df08a60 100644 --- a/src/Artemis.Plugins.LayerTypes.Brush/packages.config +++ b/src/Artemis.Plugins.LayerTypes.Brush/packages.config @@ -2,10 +2,10 @@ - - + + - - + + \ No newline at end of file diff --git a/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj b/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj index 3208678a8..d7fbc09be 100644 --- a/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj +++ b/src/Artemis.Plugins.Modules.General/Artemis.Plugins.Modules.General.csproj @@ -47,23 +47,23 @@ ..\packages\SkiaSharp.1.68.1\lib\net45\SkiaSharp.dll - - ..\packages\Stylet.1.2.0\lib\net45\Stylet.dll + + ..\packages\Stylet.1.3.0\lib\net45\Stylet.dll - - ..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll + + ..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll ..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll - - ..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll - - ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll diff --git a/src/Artemis.Plugins.Modules.General/ColorHelpers.cs b/src/Artemis.Plugins.Modules.General/ColorHelpers.cs index 61e0d063b..df07d6012 100644 --- a/src/Artemis.Plugins.Modules.General/ColorHelpers.cs +++ b/src/Artemis.Plugins.Modules.General/ColorHelpers.cs @@ -1,5 +1,4 @@ using System; -using System.Drawing; namespace Artemis.Plugins.Modules.General { @@ -11,29 +10,5 @@ namespace Artemis.Plugins.Modules.General { return Rand.Next(0, 360); } - - public static Color ColorFromHSV(double hue, double saturation, double value) - { - var hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6; - var f = hue / 60 - Math.Floor(hue / 60); - - value = value * 255; - var v = Convert.ToInt32(value); - var p = Convert.ToInt32(value * (1 - saturation)); - var q = Convert.ToInt32(value * (1 - f * saturation)); - var t = Convert.ToInt32(value * (1 - (1 - f) * saturation)); - - if (hi == 0) - return Color.FromArgb(255, v, t, p); - if (hi == 1) - return Color.FromArgb(255, q, v, p); - if (hi == 2) - return Color.FromArgb(255, p, v, t); - if (hi == 3) - return Color.FromArgb(255, p, q, v); - if (hi == 4) - return Color.FromArgb(255, t, p, v); - return Color.FromArgb(255, v, p, q); - } } } \ No newline at end of file diff --git a/src/Artemis.Plugins.Modules.General/GeneralModule.cs b/src/Artemis.Plugins.Modules.General/GeneralModule.cs index 35ba0da83..df2aa378e 100644 --- a/src/Artemis.Plugins.Modules.General/GeneralModule.cs +++ b/src/Artemis.Plugins.Modules.General/GeneralModule.cs @@ -1,15 +1,12 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Windows.Media; +using System.Diagnostics; using Artemis.Core.Models.Surface; using Artemis.Core.Plugins.Abstract; using Artemis.Core.Plugins.Models; using Artemis.Core.Services.Storage.Interfaces; using Artemis.Plugins.Modules.General.ViewModels; -using RGB.NET.Core; using SkiaSharp; -using Color = RGB.NET.Core.Color; namespace Artemis.Plugins.Modules.General { @@ -28,9 +25,9 @@ namespace Artemis.Plugins.Modules.General for (var i = 0; i < 9; i++) { if (i != 8) - RainbowColors.Add(SKColor.FromHsv(i * 32, 1, 1)); + RainbowColors.Add(SKColor.FromHsv(i * 32, 100, 100)); else - RainbowColors.Add(SKColor.FromHsv(0, 1, 1)); + RainbowColors.Add(SKColor.FromHsv(0, 100, 100)); } surfaceService.SurfaceConfigurationUpdated += (sender, args) => DeviceShaders.Clear(); @@ -62,62 +59,41 @@ namespace Artemis.Plugins.Modules.General public override void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas) { + return; foreach (var device in surface.Devices) { - if (!DeviceShaders.ContainsKey(device)) - DeviceShaders.Add(device, - SKShader.CreateLinearGradient(new SKPoint(0, 0), new SKPoint(device.RenderRectangle.Width, device.RenderRectangle.Height), RainbowColors.ToArray(), SKShaderTileMode.Clamp)); + using (var bitmap = new SKBitmap(new SKImageInfo((int) device.RenderRectangle.Width, (int) device.RenderRectangle.Height))) + { + using (var layerCanvas = new SKCanvas(bitmap)) + { + layerCanvas.Clear(); - var brush = DeviceShaders[device]; - brush.TranslateTransform((int) Math.Round(device.RenderRectangle.Width / 100.0 * MovePercentage), 0); - graphics.FillPath(brush, device.RenderPath); - brush.TranslateTransform((int) Math.Round(device.RenderRectangle.Width / 100.0 * MovePercentage) * -1, 0); + var shader = SKShader.CreateLinearGradient( + new SKPoint(0, 0), + new SKPoint(device.RenderRectangle.Width, 0), + RainbowColors.ToArray(), + null, + SKShaderTileMode.Clamp); - graphics.DrawRectangle(new Pen(Color.Red), device.RenderRectangle); - } - } + // use the shader + var paint = new SKPaint + { + Shader = shader + }; - public void RenderPerDevice(ArtemisSurface surface, Graphics graphics) - { - foreach (var device in surface.Devices) - { - if (!DeviceShaders.ContainsKey(device)) - DeviceShaders.Add(device, new TextureBrush(RenderGradientForDevice(device), WrapMode.Tile)); + layerCanvas.DrawRect(0, 0, device.RenderRectangle.Width, device.RenderRectangle.Height, paint); + } - var brush = DeviceShaders[device]; - brush.TranslateTransform((int) Math.Round(device.RenderRectangle.Width / 100.0 * MovePercentage), 0); - graphics.FillPath(brush, device.RenderPath); - brush.TranslateTransform((int) Math.Round(device.RenderRectangle.Width / 100.0 * MovePercentage) * -1, 0); + var bitmapShader = SKShader.CreateBitmap(bitmap, SKShaderTileMode.Repeat, SKShaderTileMode.Repeat); - graphics.DrawRectangle(new Pen(Color.Red), device.RenderRectangle); - } - } + canvas.Save(); + canvas.ClipRect(device.RenderRectangle); - private Image RenderGradientForDevice(ArtemisDevice device) - { - var brush = new LinearGradientBrush(device.RenderRectangle, Color.Black, Color.Black, 0, false) - { - InterpolationColors = _rainbowColorBlend - }; - var bitmap = new Bitmap(device.RenderRectangle.Width, device.RenderRectangle.Height); - using (var g = Graphics.FromImage(bitmap)) - { - g.FillRectangle(brush, 0, 0, device.RenderRectangle.Width, device.RenderRectangle.Height); - } - - return bitmap; - } - - public void RenderPerLed(ArtemisSurface surface, Graphics graphics) - { - var index = 0; - foreach (var led in surface.Devices.SelectMany(d => d.Leds)) - { - if (led.RgbLed.Id == LedId.HeadsetStand1) - graphics.FillRectangle(new SolidBrush(Color.Red), led.AbsoluteRenderRectangle); - else - graphics.FillRectangle(new SolidBrush(ColorHelpers.ColorFromHSV(Hues[index], 1, 1)), led.AbsoluteRenderRectangle); - index++; + var scaledRect = SKRect.Create(device.RenderRectangle.Left, device.RenderRectangle.Top, device.RenderRectangle.Width * 2, device.RenderRectangle.Height * 2); + canvas.Translate(device.RenderRectangle.Width / 100 * MovePercentage * -1, 0); + canvas.DrawRect(scaledRect, new SKPaint {Shader = bitmapShader}); + canvas.Restore(); + } } } diff --git a/src/Artemis.Plugins.Modules.General/app.config b/src/Artemis.Plugins.Modules.General/app.config index 0edb16ded..983b4f4d9 100644 --- a/src/Artemis.Plugins.Modules.General/app.config +++ b/src/Artemis.Plugins.Modules.General/app.config @@ -13,7 +13,7 @@ - + diff --git a/src/Artemis.Plugins.Modules.General/packages.config b/src/Artemis.Plugins.Modules.General/packages.config index f2224df9b..865736c9f 100644 --- a/src/Artemis.Plugins.Modules.General/packages.config +++ b/src/Artemis.Plugins.Modules.General/packages.config @@ -2,11 +2,11 @@ - - + + - - + + \ No newline at end of file diff --git a/src/Artemis.UI/App.config b/src/Artemis.UI/App.config index 056019794..15f01e053 100644 --- a/src/Artemis.UI/App.config +++ b/src/Artemis.UI/App.config @@ -100,7 +100,7 @@ - + diff --git a/src/Artemis.UI/Artemis.UI.csproj b/src/Artemis.UI/Artemis.UI.csproj index 713c2785f..d9a6e68e6 100644 --- a/src/Artemis.UI/Artemis.UI.csproj +++ b/src/Artemis.UI/Artemis.UI.csproj @@ -120,27 +120,34 @@ ..\packages\SkiaSharp.1.68.1\lib\net45\SkiaSharp.dll + + ..\packages\SkiaSharp.Views.Desktop.Common.1.68.1\lib\net45\SkiaSharp.Views.Desktop.Common.dll + + + ..\packages\SkiaSharp.Views.WPF.1.68.1\lib\net45\SkiaSharp.Views.WPF.dll + ..\packages\Stylet.1.3.0\lib\net45\Stylet.dll - - ..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll + + ..\packages\System.Buffers.4.5.0\lib\netstandard2.0\System.Buffers.dll ..\packages\System.ComponentModel.Annotations.4.6.0\lib\net461\System.ComponentModel.Annotations.dll + ..\packages\System.Memory.4.5.3\lib\netstandard2.0\System.Memory.dll - - ..\packages\System.Numerics.Vectors.4.4.0\lib\net46\System.Numerics.Vectors.dll + + ..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll - - ..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + + ..\packages\System.Runtime.CompilerServices.Unsafe.4.6.0\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll ..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll diff --git a/src/Artemis.UI/Screens/Settings/Debug/DebugViewModel.cs b/src/Artemis.UI/Screens/Settings/Debug/DebugViewModel.cs index 72d6b088b..7179b8a65 100644 --- a/src/Artemis.UI/Screens/Settings/Debug/DebugViewModel.cs +++ b/src/Artemis.UI/Screens/Settings/Debug/DebugViewModel.cs @@ -1,12 +1,11 @@ using System; -using System.Drawing; -using System.Runtime.InteropServices; using System.Windows; -using System.Windows.Interop; using System.Windows.Media; using System.Windows.Media.Imaging; using Artemis.Core.Events; using Artemis.Core.Services.Interfaces; +using SkiaSharp; +using SkiaSharp.Views.WPF; using Stylet; namespace Artemis.UI.Screens.Settings.Debug @@ -35,12 +34,27 @@ namespace Artemis.UI.Screens.Settings.Debug private void CoreServiceOnFrameRendered(object sender, FrameRenderedEventArgs e) { - if (e.Bitmap == null) - return; + Execute.PostToUIThread(() => + { + if (!(CurrentFrame is WriteableBitmap writeableBitmap)) + { + CurrentFrame = e.GraphicsDecorator.Bitmap.ToWriteableBitmap(); + return; + } - var imageSource = ImageSourceFromBitmap(e.Bitmap); - imageSource.Freeze(); - Execute.PostToUIThread(() => { CurrentFrame = imageSource; }); + using (var skiaImage = SKImage.FromPixels(e.GraphicsDecorator.Bitmap.PeekPixels())) + { + var info = new SKImageInfo(skiaImage.Width, skiaImage.Height); + writeableBitmap.Lock(); + using (var pixmap = new SKPixmap(info, writeableBitmap.BackBuffer, writeableBitmap.BackBufferStride)) + { + skiaImage.ReadPixels(pixmap, 0, 0); + } + + writeableBitmap.AddDirtyRect(new Int32Rect(0, 0, info.Width, info.Height)); + writeableBitmap.Unlock(); + } + }); } private void CoreServiceOnFrameRendering(object sender, FrameRenderingEventArgs e) @@ -61,23 +75,5 @@ namespace Artemis.UI.Screens.Settings.Debug _coreService.FrameRendering -= CoreServiceOnFrameRendering; base.OnDeactivate(); } - - // This is much quicker than saving the bitmap into a memory stream and converting it - private static ImageSource ImageSourceFromBitmap(Bitmap bmp) - { - var handle = bmp.GetHbitmap(); - try - { - return Imaging.CreateBitmapSourceFromHBitmap(handle, IntPtr.Zero, Int32Rect.Empty, BitmapSizeOptions.FromEmptyOptions()); - } - finally - { - DeleteObject(handle); - } - } - - [DllImport("gdi32.dll", EntryPoint = "DeleteObject")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool DeleteObject([In] IntPtr hObject); } } \ No newline at end of file diff --git a/src/Artemis.UI/packages.config b/src/Artemis.UI/packages.config index f120873e0..799e332f9 100644 --- a/src/Artemis.UI/packages.config +++ b/src/Artemis.UI/packages.config @@ -17,11 +17,13 @@ + + - + - - + + \ No newline at end of file