Skip to content

Commit

Permalink
copy BitmapUtils.GetRegionColor to GdiBitmap and optimize with member…
Browse files Browse the repository at this point in the history
… values
  • Loading branch information
Aytackydln committed Oct 11, 2024
1 parent 19c7d4c commit a63fbe3
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 18 deletions.
85 changes: 81 additions & 4 deletions Project-Aurora/Project-Aurora/Bitmaps/GdiPlus/GdiBitmap.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using AuroraRgb.BrushAdapters;
using AuroraRgb.EffectsEngine;
using AuroraRgb.Settings;
using AuroraRgb.Utils;
using Common.Utils;

namespace AuroraRgb.Bitmaps.GdiPlus;

Expand All @@ -16,6 +18,7 @@ public sealed class GdiBitmap : IAuroraBitmap
private TextureBrush? _textureBrush;

private readonly Bitmap _bitmap;
private readonly RectangleF _dimension;

public Bitmap Bitmap => _bitmap;

Expand All @@ -28,6 +31,12 @@ public sealed class GdiBitmap : IAuroraBitmap

public float Opacity { get; set; } = 1;

//B, G, R, A
private static readonly long[] ColorData = [0L, 0L, 0L, 0L];
private static readonly Dictionary<Size, BitmapData> Bitmaps = new();
// ReSharper disable once CollectionNeverQueried.Local //to keep reference
private static readonly Dictionary<Size, int[]> BitmapBuffers = new();

internal TextureBrush TextureBrush
{
get
Expand Down Expand Up @@ -57,7 +66,10 @@ internal TextureBrush TextureBrush

public GdiBitmap(int canvasWidth, int canvasHeight)
{
var graphicsUnit = GraphicsUnit.Pixel;

_bitmap = new Bitmap(canvasWidth, canvasHeight);
_dimension = _bitmap.GetBounds(ref graphicsUnit);
_graphics = Graphics.FromImage(_bitmap);
Dimension = new Rectangle(0, 0, canvasWidth, canvasHeight);

Expand All @@ -72,10 +84,75 @@ private void SetGraphics()
_graphics.InterpolationMode = InterpolationMode.NearestNeighbor;
_graphics.PixelOffsetMode = PixelOffsetMode.HighSpeed;
}

public Color GetRegionColor(Rectangle keyRectangleRectangle)

/**
* Gets average color of region, ignoring transparency
* NOT thread-safe
*/
public Color GetRegionColor(Rectangle rectangle)
{
return BitmapUtils.GetRegionColor(_bitmap, keyRectangleRectangle);
if (rectangle.Width == 0 || rectangle.Height == 0 || !_dimension.Contains(rectangle))
return Color.Black;

ColorData[0] = 0L;
ColorData[1] = 0L;
ColorData[2] = 0L;
ColorData[3] = 0L;

if (!Bitmaps.TryGetValue(rectangle.Size, out var buff))
{
var bitmapBuffer = new int[rectangle.Width * rectangle.Height];
BitmapBuffers[rectangle.Size] = bitmapBuffer;

var buffer = Marshal.AllocHGlobal(bitmapBuffer.Length * sizeof(int));
Marshal.Copy(bitmapBuffer, 0, buffer, bitmapBuffer.Length);
// Create new bitmap data.
buff = new BitmapData
{
Width = rectangle.Width,
Height = rectangle.Height,
PixelFormat = PixelFormat.Format32bppArgb,
Stride = rectangle.Width * sizeof(int),
Scan0 = buffer
};

Bitmaps[rectangle.Size] = buff;
}

var srcData = _bitmap.LockBits(
rectangle,
(ImageLockMode)5, //ImageLockMode.UserInputBuffer | ImageLockMode.ReadOnly
PixelFormat.Format32bppRgb, buff);
var scan0 = srcData.Scan0;

var rectangleHeight = rectangle.Height;
var rectangleWidth = rectangle.Width;
unsafe
{
var p = (byte*)(void*)scan0;

var j = 0;
for (var y = 0; y < rectangleHeight; y++)
{
for (var x = 0; x < rectangleWidth; x++)
{
ColorData[0] += p[j++];
ColorData[1] += p[j++];
ColorData[2] += p[j++];
ColorData[3] += p[j++];
}
}
}
_bitmap.UnlockBits(srcData);

var area = ColorData[3] / 255;
if (area == 0)
{
return Color.Transparent;
}
return CommonColorUtils.FastColor(
(byte) (ColorData[2] / area), (byte) (ColorData[1] / area), (byte) (ColorData[0] / area)
);
}

public void Reset()
Expand Down
2 changes: 1 addition & 1 deletion Project-Aurora/Project-Aurora/Bitmaps/IAuroraBitmap.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public interface IAuroraBitmap : IDisposable
{
float Opacity { get; set; }

Color GetRegionColor(Rectangle keyRectangleRectangle);
Color GetRegionColor(Rectangle rectangle);

void Reset();
void DrawRectangle(Brush brush, Rectangle dimension);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ public RuntimeChangingBitmap(int canvasWidth, int canvasHeight, bool readable)
_bitmap = new GdiBitmap(canvasWidth, canvasHeight);
}

public Color GetRegionColor(Rectangle keyRectangleRectangle)
public Color GetRegionColor(Rectangle rectangle)
{
return _bitmap.GetRegionColor(keyRectangleRectangle);
return _bitmap.GetRegionColor(rectangle);
}

public void Reset()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ public AuroraCpuSkiaBitmap(int canvasWidth, int canvasHeight) : base(canvasWidth
Canvas = new SKCanvas(_bitmap);
}

public override Color GetRegionColor(Rectangle keyRectangleRectangle)
public override Color GetRegionColor(Rectangle rectangle)
{
var skiaRectangle = SkiaRectangle(keyRectangleRectangle);
var skiaRectangle = SkiaRectangle(rectangle);
return GetAverageColorInRectangle(_bitmap, skiaRectangle);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ protected override void Invalidate()
_invalidated = true;
}

public override Color GetRegionColor(Rectangle keyRectangleRectangle)
public override Color GetRegionColor(Rectangle rectangle)
{
if (_invalidated)
{
LoadBitmap();
}
var skiaRectangle = SkiaRectangle(keyRectangleRectangle);
var skiaRectangle = SkiaRectangle(rectangle);
return GetAverageColorInRectangle(_localBitmap, skiaRectangle);
}

Expand Down
12 changes: 5 additions & 7 deletions Project-Aurora/Project-Aurora/Utils/BitmapUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ namespace AuroraRgb.Utils;

public static class BitmapUtils
{
//B, G, R, A
private static readonly long[] ColorData = [0L, 0L, 0L, 0L];
private static readonly Dictionary<Size, BitmapData> Bitmaps = new();
// ReSharper disable once CollectionNeverQueried.Local //to keep reference
private static readonly Dictionary<Size, int[]> BitmapBuffers = new();
Expand All @@ -19,13 +17,13 @@ public static class BitmapUtils
* Gets average color of region, ignoring transparency
* NOT thread-safe if optional parameters are null
*/
public static Color GetRegionColor(Bitmap map, Rectangle rectangle, long[]? color = null)
public static Color GetRegionColor(Bitmap map, Rectangle rectangle, long[] color)
{
var graphicsUnit = GraphicsUnit.Pixel;
if (rectangle.Width == 0 || rectangle.Height == 0 || !map.GetBounds(ref graphicsUnit).Contains(rectangle))
return Color.Black;

color ??= ColorData;
//B, G, R, A
color[0] = 0L;
color[1] = 0L;
color[2] = 0L;
Expand All @@ -51,15 +49,15 @@ public static Color GetRegionColor(Bitmap map, Rectangle rectangle, long[]? colo
Bitmaps[rectangle.Size] = buff;
}

if (!map.GetBounds(ref graphicsUnit).Contains(rectangle))
return Color.Black;

var srcData = map.LockBits(
rectangle,
(ImageLockMode)5, //ImageLockMode.UserInputBuffer | ImageLockMode.ReadOnly
PixelFormat.Format32bppRgb, buff);
var scan0 = srcData.Scan0;

if (!map.GetBounds(ref graphicsUnit).Contains(rectangle))
return Color.Black;

var rectangleHeight = rectangle.Height;
var rectangleWidth = rectangle.Width;
unsafe
Expand Down

0 comments on commit a63fbe3

Please sign in to comment.