mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-31 09:43:46 +00:00
Improved calculation and performance of the ambilight
This commit is contained in:
parent
fc723d8e38
commit
a46e2096a7
@ -409,6 +409,10 @@
|
|||||||
</Compile>
|
</Compile>
|
||||||
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbientLightPropertiesViewModel.cs" />
|
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbientLightPropertiesViewModel.cs" />
|
||||||
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbientLightType.cs" />
|
<Compile Include="Profiles\Layers\Types\AmbientLight\AmbientLightType.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\AmbientLight\Model\BlackBarDetectionMode.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\AmbientLight\Model\Extensions\AvgColorExtension.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\AmbientLight\Model\Extensions\PixelDataExtension.cs" />
|
||||||
|
<Compile Include="Profiles\Layers\Types\AmbientLight\Model\FlipMode.cs" />
|
||||||
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\DX9ScreenCapture.cs" />
|
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\DX9ScreenCapture.cs" />
|
||||||
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\IScreenCapture.cs" />
|
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\IScreenCapture.cs" />
|
||||||
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\ScreenCaptureManager.cs" />
|
<Compile Include="Profiles\Layers\Types\AmbientLight\ScreenCapturing\ScreenCaptureManager.cs" />
|
||||||
|
|||||||
@ -1,31 +1,50 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using Artemis.Profiles.Layers.Types.AmbientLight.Model;
|
||||||
|
using Artemis.Profiles.Layers.Types.AmbientLight.Model.Extensions;
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator
|
namespace Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator
|
||||||
{
|
{
|
||||||
public class AmbienceCreatorMirror : IAmbienceCreator
|
public class AmbienceCreatorMirror : IAmbienceCreator
|
||||||
{
|
{
|
||||||
#region Properties & Fields
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Constructors
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Methods
|
#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);
|
AvgColor[] colors = new AvgColor[targetWidth * targetHeight];
|
||||||
int sourceHeightOffset = sourceHeight - heightPixelCount;
|
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;
|
int targetHeightIndex = 0;
|
||||||
double heightCounter = heightPixels;
|
double heightCounter = heightPixels;
|
||||||
|
|
||||||
for (int y = 0; y < heightPixelCount; y += 2)
|
for (int y = 0; y < relevantSourceHeight; y += 2)
|
||||||
{
|
{
|
||||||
if (y >= heightCounter)
|
if (y >= heightCounter)
|
||||||
{
|
{
|
||||||
@ -36,7 +55,7 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator
|
|||||||
int targetWidthIndex = 0;
|
int targetWidthIndex = 0;
|
||||||
double widthCounter = widthPixels;
|
double widthCounter = widthPixels;
|
||||||
|
|
||||||
for (int x = 0; x < sourceWidth; x += 2)
|
for (int x = 0; x < effectiveSourceWidth; x += 2)
|
||||||
{
|
{
|
||||||
if (x >= widthCounter)
|
if (x >= widthCounter)
|
||||||
{
|
{
|
||||||
@ -44,56 +63,18 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator
|
|||||||
targetWidthIndex++;
|
targetWidthIndex++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int newOffset = (targetHeightIndex * targetWidth) + targetWidthIndex;
|
int colorsOffset = (targetHeightIndex * targetWidth) + targetWidthIndex;
|
||||||
int offset = ((((sourceHeightOffset + y) * sourceWidth) + x) * 4);
|
int sourceOffset = ((((relevantOffsetTop + y) * sourceWidth) + offsetLeft + x) * 4);
|
||||||
|
|
||||||
if (avgData[newOffset] == null)
|
AvgColor color = colors[colorsOffset];
|
||||||
avgData[newOffset] = new AvgColor();
|
color.AddB(pixels[sourceOffset]);
|
||||||
|
color.AddG(pixels[sourceOffset + 1]);
|
||||||
AvgColor avgDataObject = avgData[newOffset];
|
color.AddR(pixels[sourceOffset + 2]);
|
||||||
|
|
||||||
avgDataObject.AddB(data[offset]);
|
|
||||||
avgDataObject.AddG(data[offset + 1]);
|
|
||||||
avgDataObject.AddR(data[offset + 2]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
avgData = FlipVertical(avgData, targetWidth);
|
colors = colors.Flip(targetWidth, settings.FlipMode);
|
||||||
return ToByteArray(avgData, targetWidth, targetHeight);
|
return colors.ToBGRArray();
|
||||||
}
|
|
||||||
|
|
||||||
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>(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>(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@ -11,9 +11,9 @@
|
|||||||
private int _bCount = 0;
|
private int _bCount = 0;
|
||||||
private int _b = 0;
|
private int _b = 0;
|
||||||
|
|
||||||
public byte R => (byte)(_r / _rCount);
|
public byte R => (byte)(_rCount > 0 ? (_r / _rCount) : 0);
|
||||||
public byte G => (byte)(_g / _gCount);
|
public byte G => (byte)(_gCount > 0 ? (_g / _gCount) : 0);
|
||||||
public byte B => (byte)(_b / _bCount);
|
public byte B => (byte)(_bCount > 0 ? (_b / _bCount) : 0);
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
|||||||
@ -2,6 +2,6 @@
|
|||||||
{
|
{
|
||||||
public interface IAmbienceCreator
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
using Artemis.Profiles.Layers.Models;
|
using Artemis.Profiles.Layers.Models;
|
||||||
|
using Artemis.Profiles.Layers.Types.AmbientLight.Model;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.AmbientLight
|
namespace Artemis.Profiles.Layers.Types.AmbientLight
|
||||||
@ -12,6 +13,16 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight
|
|||||||
[JsonIgnore]
|
[JsonIgnore]
|
||||||
public Brush AmbientLightBrush { get; set; }
|
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
|
#endregion
|
||||||
|
|
||||||
#region Constructors
|
#region Constructors
|
||||||
|
|||||||
@ -9,6 +9,7 @@ using Artemis.Profiles.Layers.Models;
|
|||||||
using Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator;
|
using Artemis.Profiles.Layers.Types.AmbientLight.AmbienceCreator;
|
||||||
using Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing;
|
using Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing;
|
||||||
using Artemis.ViewModels.Profiles;
|
using Artemis.ViewModels.Profiles;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
namespace Artemis.Profiles.Layers.Types.AmbientLight
|
namespace Artemis.Profiles.Layers.Types.AmbientLight
|
||||||
{
|
{
|
||||||
@ -20,7 +21,10 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight
|
|||||||
public bool ShowInEdtor => true;
|
public bool ShowInEdtor => true;
|
||||||
public DrawType DrawType => DrawType.Keyboard;
|
public DrawType DrawType => DrawType.Keyboard;
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
private IAmbienceCreator _lastAmbienceCreator;
|
private IAmbienceCreator _lastAmbienceCreator;
|
||||||
|
|
||||||
|
[JsonIgnore]
|
||||||
private byte[] _lastData;
|
private byte[] _lastData;
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@ -45,15 +49,18 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight
|
|||||||
|
|
||||||
public void Update(LayerModel layerModel, IDataModel dataModel, bool isPreview = false)
|
public void Update(LayerModel layerModel, IDataModel dataModel, bool isPreview = false)
|
||||||
{
|
{
|
||||||
int width = (int)Math.Round(layerModel.Properties.Width);
|
AmbientLightPropertiesModel properties = layerModel?.Properties as AmbientLightPropertiesModel;
|
||||||
int height = (int)Math.Round(layerModel.Properties.Height);
|
if (properties == null) return;
|
||||||
|
|
||||||
|
int width = (int)Math.Round(properties.Width);
|
||||||
|
int height = (int)Math.Round(properties.Height);
|
||||||
|
|
||||||
byte[] data = ScreenCaptureManager.GetLastScreenCapture();
|
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;
|
int stride = (width * ScreenCaptureManager.LastCapturePixelFormat.BitsPerPixel + 7) / 8;
|
||||||
((AmbientLightPropertiesModel)layerModel.Properties).AmbientLightBrush = new DrawingBrush(
|
properties.AmbientLightBrush = new DrawingBrush(new ImageDrawing
|
||||||
new ImageDrawing(BitmapSource.Create(width, height, 96, 96, ScreenCaptureManager.LastCapturePixelFormat, null, _lastData, stride), new Rect(0, 0, width, height)));
|
(BitmapSource.Create(width, height, 96, 96, ScreenCaptureManager.LastCapturePixelFormat, null, _lastData, stride), new Rect(0, 0, width, height)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Draw(LayerModel layer, DrawingContext c)
|
public void Draw(LayerModel layer, DrawingContext c)
|
||||||
@ -62,7 +69,7 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight
|
|||||||
layer.Properties.Y * 4,
|
layer.Properties.Y * 4,
|
||||||
layer.Properties.Width * 4,
|
layer.Properties.Width * 4,
|
||||||
layer.Properties.Height * 4);
|
layer.Properties.Height * 4);
|
||||||
|
|
||||||
c.DrawRectangle(((AmbientLightPropertiesModel)layer.Properties).AmbientLightBrush, null, rect);
|
c.DrawRectangle(((AmbientLightPropertiesModel)layer.Properties).AmbientLightBrush, null, rect);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -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,
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,6 +12,8 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
|
|||||||
#region Properties & Fields
|
#region Properties & Fields
|
||||||
|
|
||||||
private Device _device;
|
private Device _device;
|
||||||
|
private Surface _surface;
|
||||||
|
private byte[] _buffer;
|
||||||
|
|
||||||
public int Width { get; }
|
public int Width { get; }
|
||||||
public int Height { 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);
|
_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
|
#endregion
|
||||||
@ -41,22 +45,19 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
|
|||||||
|
|
||||||
public byte[] CaptureScreen()
|
public byte[] CaptureScreen()
|
||||||
{
|
{
|
||||||
using (Surface s = Surface.CreateOffscreenPlain(_device, Width, Height, Format.A8R8G8B8, Pool.Scratch))
|
_device.GetFrontBufferData(0, _surface);
|
||||||
{
|
|
||||||
_device.GetFrontBufferData(0, s);
|
|
||||||
DataRectangle dr = s.LockRectangle(LockFlags.None);
|
|
||||||
|
|
||||||
byte[] buffer = new byte[Width * Height * 4];
|
DataRectangle dr = _surface.LockRectangle(LockFlags.None);
|
||||||
Marshal.Copy(dr.DataPointer, buffer, 0, buffer.Length);
|
Marshal.Copy(dr.DataPointer, _buffer, 0, _buffer.Length);
|
||||||
|
_surface.UnlockRectangle();
|
||||||
|
|
||||||
s.UnlockRectangle();
|
return _buffer;
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
_device?.Dispose();
|
_device?.Dispose();
|
||||||
|
_surface?.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|||||||
@ -9,9 +9,6 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
|
|||||||
{
|
{
|
||||||
#region Properties & Fields
|
#region Properties & Fields
|
||||||
|
|
||||||
// ReSharper disable once InconsistentNaming
|
|
||||||
private static readonly IScreenCapture _screenCapture;
|
|
||||||
|
|
||||||
private static Thread _worker;
|
private static Thread _worker;
|
||||||
private static DateTime _lastCaptureAccess;
|
private static DateTime _lastCaptureAccess;
|
||||||
private static volatile byte[] _lastScreenCapture;
|
private static volatile byte[] _lastScreenCapture;
|
||||||
@ -26,53 +23,59 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
|
|||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Constructors
|
|
||||||
|
|
||||||
static ScreenCaptureManager()
|
|
||||||
{
|
|
||||||
_screenCapture = new DX9ScreenCapture();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Methods
|
#region Methods
|
||||||
|
|
||||||
private static void Update()
|
private static IScreenCapture GetScreenCapture()
|
||||||
{
|
{
|
||||||
while ((DateTime.Now - _lastCaptureAccess).TotalSeconds < StandByTime)
|
return new DX9ScreenCapture();
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void CaptureScreen()
|
private static void Update(IScreenCapture screenCapture)
|
||||||
{
|
{
|
||||||
_lastScreenCapture = _screenCapture.CaptureScreen();
|
try
|
||||||
LastCaptureWidth = _screenCapture.Width;
|
{
|
||||||
LastCaptureHeight = _screenCapture.Height;
|
while ((DateTime.Now - _lastCaptureAccess).TotalSeconds < StandByTime)
|
||||||
LastCapturePixelFormat = _screenCapture.PixelFormat;
|
{
|
||||||
|
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()
|
private static void StartLoop()
|
||||||
{
|
{
|
||||||
|
IScreenCapture screenCapture = GetScreenCapture();
|
||||||
if (_isRunning) return;
|
if (_isRunning) return;
|
||||||
|
|
||||||
|
// DarthAffe 31.10.2016: _lastScreenCapture should be always initialized!
|
||||||
|
CaptureScreen(screenCapture);
|
||||||
|
|
||||||
_isRunning = true;
|
_isRunning = true;
|
||||||
_worker = new Thread(Update);
|
_worker = new Thread(() => Update(screenCapture));
|
||||||
_worker.Start();
|
_worker.Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,11 +83,7 @@ namespace Artemis.Profiles.Layers.Types.AmbientLight.ScreenCapturing
|
|||||||
{
|
{
|
||||||
_lastCaptureAccess = DateTime.Now;
|
_lastCaptureAccess = DateTime.Now;
|
||||||
if (!_isRunning)
|
if (!_isRunning)
|
||||||
{
|
|
||||||
// DarthAffe 29.10.2016: Make sure, that _lastScreenCapture is newer returned without data.
|
|
||||||
CaptureScreen();
|
|
||||||
StartLoop();
|
StartLoop();
|
||||||
}
|
|
||||||
return _lastScreenCapture;
|
return _lastScreenCapture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user