From a46e2096a72b7d14e68eda6f935c44c44c78d63f Mon Sep 17 00:00:00 2001 From: Darth Affe Date: Mon, 31 Oct 2016 16:32:15 +0100 Subject: [PATCH] Improved calculation and performance of the ambilight --- Artemis/Artemis/Artemis.csproj | 4 + .../AmbienceCreator/AmbienceCreatorMirror.cs | 105 +++++++----------- .../AmbientLight/AmbienceCreator/AvgColor.cs | 6 +- .../AmbienceCreator/IAmbienceCreator.cs | 2 +- .../AmbientLightPropertiesModel.cs | 11 ++ .../Types/AmbientLight/AmbientLightType.cs | 23 ++-- .../Model/BlackBarDetectionMode.cs | 14 +++ .../Model/Extensions/AvgColorExtension.cs | 59 ++++++++++ .../Model/Extensions/PixelDataExtension.cs | 85 ++++++++++++++ .../Types/AmbientLight/Model/FlipMode.cs | 12 ++ .../ScreenCapturing/DX9ScreenCapture.cs | 19 ++-- .../ScreenCapturing/ScreenCaptureManager.cs | 81 +++++++------- 12 files changed, 297 insertions(+), 124 deletions(-) create mode 100644 Artemis/Artemis/Profiles/Layers/Types/AmbientLight/Model/BlackBarDetectionMode.cs create mode 100644 Artemis/Artemis/Profiles/Layers/Types/AmbientLight/Model/Extensions/AvgColorExtension.cs create mode 100644 Artemis/Artemis/Profiles/Layers/Types/AmbientLight/Model/Extensions/PixelDataExtension.cs create mode 100644 Artemis/Artemis/Profiles/Layers/Types/AmbientLight/Model/FlipMode.cs diff --git a/Artemis/Artemis/Artemis.csproj b/Artemis/Artemis/Artemis.csproj index fba35fc88..985856c87 100644 --- a/Artemis/Artemis/Artemis.csproj +++ b/Artemis/Artemis/Artemis.csproj @@ -409,6 +409,10 @@ + + + + diff --git a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbienceCreator/AmbienceCreatorMirror.cs b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbienceCreator/AmbienceCreatorMirror.cs index 93a447847..da10a29e0 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbienceCreator/AmbienceCreatorMirror.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbienceCreator/AmbienceCreatorMirror.cs @@ -1,31 +1,50 @@ using System; +using Artemis.Profiles.Layers.Types.AmbientLight.Model; +using Artemis.Profiles.Layers.Types.AmbientLight.Model.Extensions; namespace Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator { public class AmbienceCreatorMirror : IAmbienceCreator { - #region Properties & Fields - - #endregion - - #region Constructors - - #endregion - #region Methods - public byte[] GetAmbience(byte[] data, int sourceWidth, int sourceHeight, int targetWidth, int targetHeight) + public byte[] GetAmbience(byte[] pixels, int sourceWidth, int sourceHeight, + int targetWidth, int targetHeight, + AmbientLightPropertiesModel settings) { - int heightPixelCount = (int)Math.Round(sourceHeight * 0.1); - int sourceHeightOffset = sourceHeight - heightPixelCount; + AvgColor[] colors = new AvgColor[targetWidth * targetHeight]; + for (int i = 0; i < colors.Length; i++) + colors[i] = new AvgColor(); + + int offsetLeft = settings.OffsetLeft + (settings.BlackBarDetectionMode.HasFlag(BlackBarDetectionMode.Left) + ? pixels.DetectBlackBarLeft(sourceWidth, sourceHeight, settings.OffsetLeft, settings.OffsetRight, settings.OffsetTop, settings.OffsetBottom) + : 0); + int offsetRight = settings.OffsetRight + (settings.BlackBarDetectionMode.HasFlag(BlackBarDetectionMode.Right) + ? pixels.DetectBlackBarRight(sourceWidth, sourceHeight, settings.OffsetLeft, settings.OffsetRight, settings.OffsetTop, settings.OffsetBottom) + : 0); + int offsetTop = settings.OffsetTop + (settings.BlackBarDetectionMode.HasFlag(BlackBarDetectionMode.Top) + ? pixels.DetectBlackBarTop(sourceWidth, sourceHeight, settings.OffsetLeft, settings.OffsetRight, settings.OffsetTop, settings.OffsetBottom) + : 0); + int offsetBottom = settings.OffsetBottom + (settings.BlackBarDetectionMode.HasFlag(BlackBarDetectionMode.Bottom) + ? pixels.DetectBlackBarBottom(sourceWidth, sourceHeight, settings.OffsetLeft, settings.OffsetRight, settings.OffsetTop, settings.OffsetBottom) + : 0); + + int effectiveSourceWidth = sourceWidth - offsetLeft - offsetRight; + int effectiveSourceHeight = sourceHeight - offsetTop - offsetBottom; + + int relevantSourceHeight = (int)Math.Round(effectiveSourceHeight * settings.MirroredAmount); + int relevantOffsetTop = sourceHeight - offsetBottom - relevantSourceHeight; + + double widthPixels = effectiveSourceWidth / (double)targetWidth; + double heightPixels = relevantSourceHeight / (double)targetHeight; + + if (widthPixels <= 0 || heightPixels <= 0 || (relevantSourceHeight + relevantOffsetTop > sourceHeight) || effectiveSourceWidth > sourceWidth) + return colors.ToBGRArray(); - AvgColor[] avgData = new AvgColor[targetWidth * targetHeight]; - double widthPixels = (sourceWidth / (double)targetWidth); - double heightPixels = (heightPixelCount / (double)targetHeight); int targetHeightIndex = 0; double heightCounter = heightPixels; - for (int y = 0; y < heightPixelCount; y += 2) + for (int y = 0; y < relevantSourceHeight; y += 2) { if (y >= heightCounter) { @@ -36,7 +55,7 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator int targetWidthIndex = 0; double widthCounter = widthPixels; - for (int x = 0; x < sourceWidth; x += 2) + for (int x = 0; x < effectiveSourceWidth; x += 2) { if (x >= widthCounter) { @@ -44,56 +63,18 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator targetWidthIndex++; } - int newOffset = (targetHeightIndex * targetWidth) + targetWidthIndex; - int offset = ((((sourceHeightOffset + y) * sourceWidth) + x) * 4); + int colorsOffset = (targetHeightIndex * targetWidth) + targetWidthIndex; + int sourceOffset = ((((relevantOffsetTop + y) * sourceWidth) + offsetLeft + x) * 4); - if (avgData[newOffset] == null) - avgData[newOffset] = new AvgColor(); - - AvgColor avgDataObject = avgData[newOffset]; - - avgDataObject.AddB(data[offset]); - avgDataObject.AddG(data[offset + 1]); - avgDataObject.AddR(data[offset + 2]); + AvgColor color = colors[colorsOffset]; + color.AddB(pixels[sourceOffset]); + color.AddG(pixels[sourceOffset + 1]); + color.AddR(pixels[sourceOffset + 2]); } } - avgData = FlipVertical(avgData, targetWidth); - return ToByteArray(avgData, targetWidth, targetHeight); - } - - private byte[] ToByteArray(AvgColor[] colors, int width, int height) - { - byte[] newData = new byte[width * height * 3]; - int counter = 0; - foreach (AvgColor color in colors) - { - newData[counter++] = color.B; - newData[counter++] = color.G; - newData[counter++] = color.R; - } - - return newData; - } - - private T[] FlipVertical(T[] data, int width) - { - T[] flipped = new T[data.Length]; - for (int i = 0, j = data.Length - width; i < data.Length; i += width, j -= width) - for (int k = 0; k < width; ++k) - flipped[i + k] = data[j + k]; - - return flipped; - } - - private T[] FlipHorizontal(T[] data, int width) - { - T[] flipped = new T[data.Length]; - for (int i = 0; i < data.Length; i += width) - for (int j = 0, k = width - 1; j < width; ++j, --k) - flipped[i + j] = data[i + k]; - - return flipped; + colors = colors.Flip(targetWidth, settings.FlipMode); + return colors.ToBGRArray(); } #endregion diff --git a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbienceCreator/AvgColor.cs b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbienceCreator/AvgColor.cs index d7d85a162..9cef78a27 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbienceCreator/AvgColor.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbienceCreator/AvgColor.cs @@ -11,9 +11,9 @@ private int _bCount = 0; private int _b = 0; - public byte R => (byte)(_r / _rCount); - public byte G => (byte)(_g / _gCount); - public byte B => (byte)(_b / _bCount); + public byte R => (byte)(_rCount > 0 ? (_r / _rCount) : 0); + public byte G => (byte)(_gCount > 0 ? (_g / _gCount) : 0); + public byte B => (byte)(_bCount > 0 ? (_b / _bCount) : 0); #endregion diff --git a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbienceCreator/IAmbienceCreator.cs b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbienceCreator/IAmbienceCreator.cs index d36d6c8ae..df84941bd 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbienceCreator/IAmbienceCreator.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbienceCreator/IAmbienceCreator.cs @@ -2,6 +2,6 @@ { public interface IAmbienceCreator { - byte[] GetAmbience(byte[] data, int sourceWidth, int sourceHeight, int targetWidth, int targetHeight); + byte[] GetAmbience(byte[] pixels, int sourceWidth, int sourceHeight, int targetWidth, int targetHeight, AmbientLightPropertiesModel settings); } } diff --git a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbientLightPropertiesModel.cs b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbientLightPropertiesModel.cs index b561b0e1f..a741e05d9 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbientLightPropertiesModel.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbientLightPropertiesModel.cs @@ -1,5 +1,6 @@ using System.Windows.Media; using Artemis.Profiles.Layers.Models; +using Artemis.Profiles.Layers.Types.AmbientLight.Model; using Newtonsoft.Json; namespace Artemis.Profiles.Layers.Types.AmbientLight @@ -12,6 +13,16 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight [JsonIgnore] public Brush AmbientLightBrush { get; set; } + public int OffsetLeft { get; set; } = 0; + public int OffsetRight { get; set; } = 0; + public int OffsetTop { get; set; } = 0; + public int OffsetBottom { get; set; } = 0; + + public double MirroredAmount { get; set; } = 0.1; + + public BlackBarDetectionMode BlackBarDetectionMode { get; set; } = BlackBarDetectionMode.Bottom; + public FlipMode FlipMode { get; set; } = FlipMode.Vertical; + #endregion #region Constructors diff --git a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbientLightType.cs b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbientLightType.cs index c96dca32d..0d09fa58f 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbientLightType.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/AmbientLightType.cs @@ -9,6 +9,7 @@ using Artemis.Profiles.Layers.Models; using Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator; using Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing; using Artemis.ViewModels.Profiles; +using Newtonsoft.Json; namespace Artemis.Profiles.Layers.Types.AmbientLight { @@ -20,7 +21,10 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight public bool ShowInEdtor => true; public DrawType DrawType => DrawType.Keyboard; + [JsonIgnore] private IAmbienceCreator _lastAmbienceCreator; + + [JsonIgnore] private byte[] _lastData; #endregion @@ -45,15 +49,18 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight public void Update(LayerModel layerModel, IDataModel dataModel, bool isPreview = false) { - int width = (int)Math.Round(layerModel.Properties.Width); - int height = (int)Math.Round(layerModel.Properties.Height); - + AmbientLightPropertiesModel properties = layerModel?.Properties as AmbientLightPropertiesModel; + if (properties == null) return; + + int width = (int)Math.Round(properties.Width); + int height = (int)Math.Round(properties.Height); + byte[] data = ScreenCaptureManager.GetLastScreenCapture(); - _lastData = GetAmbienceCreator().GetAmbience(data, ScreenCaptureManager.LastCaptureWidth, ScreenCaptureManager.LastCaptureHeight, width, height); - + _lastData = GetAmbienceCreator().GetAmbience(data, ScreenCaptureManager.LastCaptureWidth, ScreenCaptureManager.LastCaptureHeight, width, height, properties); + int stride = (width * ScreenCaptureManager.LastCapturePixelFormat.BitsPerPixel + 7) / 8; - ((AmbientLightPropertiesModel)layerModel.Properties).AmbientLightBrush = new DrawingBrush( - new ImageDrawing(BitmapSource.Create(width, height, 96, 96, ScreenCaptureManager.LastCapturePixelFormat, null, _lastData, stride), new Rect(0, 0, width, height))); + properties.AmbientLightBrush = new DrawingBrush(new ImageDrawing + (BitmapSource.Create(width, height, 96, 96, ScreenCaptureManager.LastCapturePixelFormat, null, _lastData, stride), new Rect(0, 0, width, height))); } public void Draw(LayerModel layer, DrawingContext c) @@ -62,7 +69,7 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight layer.Properties.Y * 4, layer.Properties.Width * 4, layer.Properties.Height * 4); - + c.DrawRectangle(((AmbientLightPropertiesModel)layer.Properties).AmbientLightBrush, null, rect); } diff --git a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/Model/BlackBarDetectionMode.cs b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/Model/BlackBarDetectionMode.cs new file mode 100644 index 000000000..31a3cfbfc --- /dev/null +++ b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/Model/BlackBarDetectionMode.cs @@ -0,0 +1,14 @@ +using System; + +namespace Artemis.Profiles.Layers.Types.AmbientLight.Model +{ + [Flags] + public enum BlackBarDetectionMode + { + None = 0, + Left = 1 << 0, + Right = 1 << 1, + Top = 1 << 2, + Bottom = 1 << 3, + } +} diff --git a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/Model/Extensions/AvgColorExtension.cs b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/Model/Extensions/AvgColorExtension.cs new file mode 100644 index 000000000..a729ae89f --- /dev/null +++ b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/Model/Extensions/AvgColorExtension.cs @@ -0,0 +1,59 @@ +using System.Linq; +using Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator; + +namespace Artemis.Profiles.Layers.Types.AmbientLight.Model.Extensions +{ + public static class AvgColorExtension + { + public static AvgColor[] Flip(this AvgColor[] colors, int width, FlipMode flipMode) + { + if (colors == null || width <= 0) return colors; + + if (flipMode.HasFlag(FlipMode.Vertical)) + return flipMode.HasFlag(FlipMode.Horizontal) ? colors.Reverse().ToArray() : colors.FlipVertical(width); + + if (flipMode.HasFlag(FlipMode.Horizontal)) + return colors.FlipHorizontal(width); + + return colors; + } + + public static AvgColor[] FlipVertical(this AvgColor[] colors, int width) + { + if (colors == null || width <= 0) return colors; + + AvgColor[] flipped = new AvgColor[colors.Length]; + for (int i = 0, j = colors.Length - width; i < colors.Length; i += width, j -= width) + for (int k = 0; k < width; ++k) + flipped[i + k] = colors[j + k]; + + return flipped; + } + + public static AvgColor[] FlipHorizontal(this AvgColor[] colors, int width) + { + if (colors == null || width <= 0) return colors; + + AvgColor[] flipped = new AvgColor[colors.Length]; + for (int i = 0; i < colors.Length; i += width) + for (int j = 0, k = width - 1; j < width; ++j, --k) + flipped[i + j] = colors[i + k]; + + return flipped; + } + + public static byte[] ToBGRArray(this AvgColor[] colors) + { + byte[] newData = new byte[colors.Length * 3]; + int counter = 0; + foreach (AvgColor color in colors) + { + newData[counter++] = color.B; + newData[counter++] = color.G; + newData[counter++] = color.R; + } + + return newData; + } + } +} diff --git a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/Model/Extensions/PixelDataExtension.cs b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/Model/Extensions/PixelDataExtension.cs new file mode 100644 index 000000000..cd1fbf690 --- /dev/null +++ b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/Model/Extensions/PixelDataExtension.cs @@ -0,0 +1,85 @@ +namespace Artemis.Profiles.Layers.Types.AmbientLight.Model.Extensions +{ + public static class PixelDataExtension + { + public static int DetectBlackBarLeft(this byte[] pixels, int width, int height, int offsetLeft, int offsetRight, int offsetTop, int offsetBottom) + { + int bottomBorder = height - offsetBottom; + int rightBorder = width - offsetRight; + + int blackBarWidth = 0; + for (int x = rightBorder - 1; x >= offsetLeft; x--) + { + for (int y = offsetTop; y < bottomBorder; y++) + { + int offset = ((y * width) + x) * 4; + if (pixels[offset] > 15 || pixels[offset + 1] > 15 || pixels[offset + 2] > 15) + return blackBarWidth; + } + blackBarWidth++; + } + + return width; + } + + public static int DetectBlackBarRight(this byte[] pixels, int width, int height, int offsetLeft, int offsetRight, int offsetTop, int offsetBottom) + { + int bottomBorder = height - offsetBottom; + int rightBorder = width - offsetRight; + + int blackBarWidth = 0; + for (int x = offsetLeft; x < rightBorder; x++) + { + for (int y = offsetTop; y < bottomBorder; y++) + { + int offset = ((y * width) + x) * 4; + if (pixels[offset] > 15 || pixels[offset + 1] > 15 || pixels[offset + 2] > 15) + return blackBarWidth; + } + blackBarWidth++; + } + + return width; + } + + public static int DetectBlackBarTop(this byte[] pixels, int width, int height, int offsetLeft, int offsetRight, int offsetTop, int offsetBottom) + { + int bottomBorder = height - offsetBottom; + int rightBorder = width - offsetRight; + + int blackBarHeight = 0; + for (int y = offsetTop; y < bottomBorder; y++) + { + for (int x = offsetLeft; x < rightBorder; x++) + { + int offset = ((y * width) + x) * 4; + if (pixels[offset] > 15 || pixels[offset + 1] > 15 || pixels[offset + 2] > 15) + return blackBarHeight; + } + blackBarHeight++; + } + + return height; + } + + public static int DetectBlackBarBottom(this byte[] pixels, int width, int height, int offsetLeft, int offsetRight, int offsetTop, int offsetBottom) + { + int bottomBorder = height - offsetBottom; + int rightBorder = width - offsetRight; + + int blackBarHeight = 0; + for (int y = bottomBorder - 1; y >= offsetTop; y--) + { + for (int x = offsetLeft; x < rightBorder; x++) + { + int offset = ((y * width) + x) * 4; + if (pixels[offset] > 15 || pixels[offset + 1] > 15 || pixels[offset + 2] > 15) + return blackBarHeight; + } + blackBarHeight++; + } + + return height; + } + } +} diff --git a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/Model/FlipMode.cs b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/Model/FlipMode.cs new file mode 100644 index 000000000..540617a5e --- /dev/null +++ b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/Model/FlipMode.cs @@ -0,0 +1,12 @@ +using System; + +namespace Artemis.Profiles.Layers.Types.AmbientLight.Model +{ + [Flags] + public enum FlipMode + { + None = 0, + Vertical = 1 << 0, + Horizontal = 1 << 1 + } +} diff --git a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/ScreenCapturing/DX9ScreenCapture.cs b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/ScreenCapturing/DX9ScreenCapture.cs index 103ecf41a..5833fda07 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/ScreenCapturing/DX9ScreenCapture.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/ScreenCapturing/DX9ScreenCapture.cs @@ -12,6 +12,8 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing #region Properties & Fields private Device _device; + private Surface _surface; + private byte[] _buffer; public int Width { get; } public int Height { get; } @@ -33,6 +35,8 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing }; _device = new Device(new Direct3D(), 0, DeviceType.Hardware, IntPtr.Zero, CreateFlags.SoftwareVertexProcessing, presentParams); + _surface = Surface.CreateOffscreenPlain(_device, Width, Height, Format.A8R8G8B8, Pool.Scratch); + _buffer = new byte[Width * Height * 4]; } #endregion @@ -41,22 +45,19 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing public byte[] CaptureScreen() { - using (Surface s = Surface.CreateOffscreenPlain(_device, Width, Height, Format.A8R8G8B8, Pool.Scratch)) - { - _device.GetFrontBufferData(0, s); - DataRectangle dr = s.LockRectangle(LockFlags.None); + _device.GetFrontBufferData(0, _surface); - byte[] buffer = new byte[Width * Height * 4]; - Marshal.Copy(dr.DataPointer, buffer, 0, buffer.Length); + DataRectangle dr = _surface.LockRectangle(LockFlags.None); + Marshal.Copy(dr.DataPointer, _buffer, 0, _buffer.Length); + _surface.UnlockRectangle(); - s.UnlockRectangle(); - return buffer; - } + return _buffer; } public void Dispose() { _device?.Dispose(); + _surface?.Dispose(); } #endregion diff --git a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/ScreenCapturing/ScreenCaptureManager.cs b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/ScreenCapturing/ScreenCaptureManager.cs index de63faf41..bb28f4738 100644 --- a/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/ScreenCapturing/ScreenCaptureManager.cs +++ b/Artemis/Artemis/Profiles/Layers/Types/AmbientLight/ScreenCapturing/ScreenCaptureManager.cs @@ -9,9 +9,6 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing { #region Properties & Fields - // ReSharper disable once InconsistentNaming - private static readonly IScreenCapture _screenCapture; - private static Thread _worker; private static DateTime _lastCaptureAccess; private static volatile byte[] _lastScreenCapture; @@ -26,53 +23,59 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing #endregion - #region Constructors - - static ScreenCaptureManager() - { - _screenCapture = new DX9ScreenCapture(); - } - - #endregion - #region Methods - private static void Update() + private static IScreenCapture GetScreenCapture() { - while ((DateTime.Now - _lastCaptureAccess).TotalSeconds < StandByTime) - { - DateTime lastCapture = DateTime.Now; - try - { - CaptureScreen(); - } - catch (Exception ex) - { - Debug.WriteLine("[CaptureLoop]: " + ex.Message); - } - - int sleep = (int)((UpdateRate - (DateTime.Now - lastCapture).TotalSeconds) * 1000); - if (sleep > 0) - Thread.Sleep(sleep); - } - - _isRunning = false; + return new DX9ScreenCapture(); } - private static void CaptureScreen() + private static void Update(IScreenCapture screenCapture) { - _lastScreenCapture = _screenCapture.CaptureScreen(); - LastCaptureWidth = _screenCapture.Width; - LastCaptureHeight = _screenCapture.Height; - LastCapturePixelFormat = _screenCapture.PixelFormat; + try + { + while ((DateTime.Now - _lastCaptureAccess).TotalSeconds < StandByTime) + { + DateTime lastCapture = DateTime.Now; + try + { + CaptureScreen(screenCapture); + } + catch (Exception ex) + { + Debug.WriteLine("[CaptureLoop]: " + ex.Message); + } + + int sleep = (int)((UpdateRate - (DateTime.Now - lastCapture).TotalSeconds) * 1000); + if (sleep > 0) + Thread.Sleep(sleep); + } + } + finally + { + screenCapture.Dispose(); + _isRunning = false; + } + } + + private static void CaptureScreen(IScreenCapture screenCapture) + { + _lastScreenCapture = screenCapture.CaptureScreen(); + LastCaptureWidth = screenCapture.Width; + LastCaptureHeight = screenCapture.Height; + LastCapturePixelFormat = screenCapture.PixelFormat; } private static void StartLoop() { + IScreenCapture screenCapture = GetScreenCapture(); if (_isRunning) return; + // DarthAffe 31.10.2016: _lastScreenCapture should be always initialized! + CaptureScreen(screenCapture); + _isRunning = true; - _worker = new Thread(Update); + _worker = new Thread(() => Update(screenCapture)); _worker.Start(); } @@ -80,11 +83,7 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing { _lastCaptureAccess = DateTime.Now; if (!_isRunning) - { - // DarthAffe 29.10.2016: Make sure, that _lastScreenCapture is newer returned without data. - CaptureScreen(); StartLoop(); - } return _lastScreenCapture; }