Skip to content
This repository has been archived by the owner on Mar 9, 2023. It is now read-only.

Commit

Permalink
perf optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
MgAl2O4 committed Mar 11, 2021
1 parent 2de7e2e commit cf99a40
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 46 deletions.
30 changes: 23 additions & 7 deletions SINoCOLO/MainForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ public partial class MainForm : Form
private bool hasDetailCtrl = true;
private bool selectInstanceMode = false;
private int numHighFreqTicks = 0;
private int numScanDelayTicks = 0;
private int numScanProcessDelayTicks = 0;
private int numScanSnapshotDelayTicks = 0;
private int numTicksToResetStoryMode = -1;
private string cachedTitle;

Expand Down Expand Up @@ -120,6 +121,10 @@ private void GameLogic_OnStateChangeNotify(GameLogic.EState newState)
private void Scan()
{
gameLogic.OnScanPrep();
if (numScanSnapshotDelayTicks > 0)
{
return;
}

var srcScreenshot = screenReader.DoWork();
if (srcScreenshot != null)
Expand All @@ -128,7 +133,7 @@ private void Scan()
cachedSourceScreen = srcScreenshot.Clone(new Rectangle(0, 0, srcScreenshot.Width, srcScreenshot.Height), srcScreenshot.PixelFormat);

if (screenReader.GetState() != ScreenReader.EState.WindowTooSmall &&
numScanDelayTicks <= 0)
(numScanProcessDelayTicks <= 0))
{
var forcedSize = screenReader.GetExpectedSize();
var fastBitmap = ScreenshotUtilities.ConvertToFastBitmap(srcScreenshot, forcedSize.Width, forcedSize.Height);
Expand Down Expand Up @@ -387,10 +392,20 @@ private void UpdateTimerFreq()
}
}

numScanDelayTicks -= 1;
if (numScanDelayTicks < 0)
numScanProcessDelayTicks -= 1;
if (numScanProcessDelayTicks < 0)
{
// high freq: process in every timer tick, 10x per second
// otherwise: run recognition once every 1s
numScanProcessDelayTicks = (numHighFreqTicks > 0) ? 0 : 10;
}

numScanSnapshotDelayTicks -= 1;
if (numScanSnapshotDelayTicks < 0)
{
numScanDelayTicks = (numHighFreqTicks > 0) ? 0 : 20;
// can click: take screenshot in every timer tick, 10x per second
// otherwise: grab window once every 0.5s
numScanSnapshotDelayTicks = checkBoxClicks.Checked ? 0 : 5;
}
}

Expand All @@ -402,8 +417,9 @@ private void DetailLog()
}

var lines = new List<string>();
lines.Add(string.Format("Tick: high freq:{0}, delay:{1}{2}",
numHighFreqTicks, numScanDelayTicks, numScanDelayTicks <= 0 ? " (scan now)" : ""));
lines.Add(string.Format("Tick: HFreq:{0}, snap:{1}, process:{2} {3}",
numHighFreqTicks, numScanSnapshotDelayTicks, numScanProcessDelayTicks,
(numScanProcessDelayTicks <= 0 && numScanSnapshotDelayTicks <= 0) ? " (scan now)" : ""));
lines.Add(string.Format("Screenshot:{0} ({1})",
cachedSourceScreen != null ? string.Format("{0}x{1}", cachedSourceScreen.Width, cachedSourceScreen.Height) : "n/a",
screenReader.GetState()));
Expand Down
4 changes: 2 additions & 2 deletions SINoCOLO/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("26.0.0.0")]
[assembly: AssemblyFileVersion("26.0.0.0")]
[assembly: AssemblyVersion("27.0.0.0")]
[assembly: AssemblyFileVersion("27.0.0.0")]
2 changes: 1 addition & 1 deletion SINoCOLO/ScreenReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -393,7 +393,7 @@ private Bitmap TakeScreenshot()
Bitmap scaledBitmap = new Bitmap(finalSize.Width, finalSize.Height);
using (Graphics g = Graphics.FromImage(scaledBitmap))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.InterpolationMode = InterpolationMode.Bilinear;
g.DrawImage(bitmap, 0, 0, finalSize.Width, finalSize.Height);
}

Expand Down
8 changes: 4 additions & 4 deletions SINoVision/ScannerBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,14 +150,14 @@ protected void DrawRectangle(FastBitmapHSV bitmap, int posX, int posY, int width

for (int idxX = 0; idxX < width; idxX++)
{
bitmap.Pixels[(posX + idxX) + ((posY - border) * bitmap.Width)] = pixelOb;
bitmap.Pixels[(posX + idxX) + ((posY + height + border) * bitmap.Width)] = pixelOb;
bitmap.SetPixel(posX + idxX, posY - border, pixelOb);
bitmap.SetPixel(posX + idxX, posY + height + border, pixelOb);
}

for (int idxY = 0; idxY < height; idxY++)
{
bitmap.Pixels[(posX - border) + ((posY + idxY) * bitmap.Width)] = pixelOb;
bitmap.Pixels[(posX + width + border) + ((posY + idxY) * bitmap.Width)] = pixelOb;
bitmap.SetPixel(posX - border, posY + idxY, pixelOb);
bitmap.SetPixel(posX + width + border, posY + idxY, pixelOb);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion SINoVision/ScannerColoPurify.cs
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ protected void ScanActionSlot(FastBitmapHSV bitmap, Point slotPos, ScreenData sc
byte color = (byte)(pixelInput[readIdx] * 255);
readIdx++;

bitmap.Pixels[(previewX + idxX) + ((previewY + idxY) * bitmap.Width)] = new FastPixelHSV(color, color, color);
bitmap.SetPixel(previewX + idxX, previewY + idxY, new FastPixelHSV(color, color, color));
}
}
}
Expand Down
143 changes: 112 additions & 31 deletions SINoVision/ScreenshotUtilities.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,21 @@ public struct FastPixelHSV
public byte Value;
public byte Monochrome;

public byte RawR;
public byte RawG;
public byte RawB;
public byte HasHSL;

public FastPixelHSV(byte colorR, byte colorG, byte colorB)
{
Color pixelColor = Color.FromArgb(colorR, colorG, colorB);

int Hue = (int)Math.Round(pixelColor.GetHue());
int Saturation = (int)Math.Round(pixelColor.GetSaturation() * 100);
HuePack = (byte)(Hue & 0xff);
SaturationPack = (byte)((Saturation & 0xff) | ((Hue & 0x100) >> 1));
Value = (byte)Math.Round(pixelColor.GetBrightness() * 100);
Monochrome = (byte)Math.Round((0.2125 * colorR) + (0.7154 * colorG) + (0.0721 * colorB));
HuePack = 0;
SaturationPack = 0;
Value = 0;
Monochrome = 0;
RawR = colorR;
RawG = colorG;
RawB = colorB;
HasHSL = 0;
}

public FastPixelHSV(bool patternMatch)
Expand All @@ -31,6 +36,10 @@ public FastPixelHSV(bool patternMatch)
SaturationPack = 0;
Value = 0;
Monochrome = patternMatch ? (byte)255 : (byte)0;
RawR = Monochrome;
RawG = Monochrome;
RawB = Monochrome;
HasHSL = 1;
}

public int GetHue()
Expand All @@ -56,11 +65,68 @@ public int GetMonochrome()
public void SetHSV(int hue, int saturation, int value)
{
HuePack = (byte)(hue & 0xff);
SaturationPack = (byte)((saturation & 0xff) | ((hue & 0x100) >> 1));
SaturationPack = (byte)((saturation & 0x7f) | ((hue & 0x100) >> 1));
Value = (byte)value;

ScreenshotUtilities.HsvToRgb(hue, saturation, value, out int colorR, out int colorG, out int colorB);
Monochrome = (byte)Math.Round((0.2125 * colorR) + (0.7154 * colorG) + (0.0721 * colorB));
RawR = (byte)colorR;
RawG = (byte)colorG;
RawB = (byte)colorB;
HasHSL = 1;
}

public void ExpandHSV()
{
float LinearR = (RawR / 255f);
float LinearG = (RawG / 255f);
float LinearB = (RawB / 255f);

float MinRG = (LinearR < LinearG) ? LinearR : LinearG;
float MaxRG = (LinearR > LinearG) ? LinearR : LinearG;
float MinV = (MinRG < LinearB) ? MinRG : LinearB;
float MaxV = (MaxRG > LinearB) ? MaxRG : LinearB;
float DeltaV = MaxV - MinV;

float H = 0;
float S = 0;
float L = (float)((MaxV + MinV) / 2.0f);

if (DeltaV != 0)
{
if (L < 0.5f)
{
S = (float)(DeltaV / (MaxV + MinV));
}
else
{
S = (float)(DeltaV / (2.0f - MaxV - MinV));
}

if (LinearR == MaxV)
{
H = (LinearG - LinearB) / DeltaV;
}
else if (LinearG == MaxV)
{
H = 2f + (LinearB - LinearR) / DeltaV;
}
else if (LinearB == MaxV)
{
H = 4f + (LinearR - LinearG) / DeltaV;
}
}

int HueV = (int)(H * 60f);
if (HueV < 0) HueV += 360;
int SaturationV = (int)(S * 100f);
int LightV = (int)(L * 100f);

HuePack = (byte)(HueV & 0xff);
SaturationPack = (byte)((SaturationV & 0x7f) | ((HueV & 0x100) >> 1));
Value = (byte)LightV;
Monochrome = (byte)((0.2125 * RawR) + (0.7154 * RawG) + (0.0721 * RawB));
HasHSL = 1;
}

public override string ToString()
Expand Down Expand Up @@ -176,9 +242,32 @@ public class FastBitmapHSV
public int Width;
public int Height;

public FastBitmapHSV(int width, int height)
{
Width = width;
Height = height;
Pixels = new FastPixelHSV[width * height];
}

public FastPixelHSV GetPixel(int X, int Y)
{
return Pixels[X + (Y * Width)];
int idx = X + (Y * Width);
if (Pixels[idx].HasHSL == 0)
{
Pixels[idx].ExpandHSV();
}

return Pixels[idx];
}

public void SetPixel(int X, int Y, FastPixelHSV pixel)
{
Pixels[X + (Y * Width)] = pixel;
}

public void SetPixel(int Idx, FastPixelHSV pixel)
{
Pixels[Idx] = pixel;
}

public override string ToString()
Expand All @@ -191,10 +280,9 @@ public class ScreenshotUtilities
{
public static FastBitmapHSV ConvertToFastBitmap(Bitmap image, int forcedWidth = -1, int forcedHeight = -1)
{
FastBitmapHSV result = new FastBitmapHSV();
result.Width = (forcedWidth > 0) ? forcedWidth : image.Width;
result.Height = (forcedHeight > 0) ? forcedHeight : image.Height;
result.Pixels = new FastPixelHSV[result.Width * result.Height];
int useWidth = (forcedWidth > 0) ? forcedWidth : image.Width;
int useHeight = (forcedHeight > 0) ? forcedHeight : image.Height;
FastBitmapHSV result = new FastBitmapHSV(useWidth, useHeight);

unsafe
{
Expand All @@ -209,7 +297,7 @@ public static FastBitmapHSV ConvertToFastBitmap(Bitmap image, int forcedWidth =
int IdxPixel = IdxY * result.Width;
for (int IdxByte = 0; IdxByte < bytesPerRow; IdxByte += bytesPerPixel)
{
result.Pixels[IdxPixel] = new FastPixelHSV(pixels[IdxByte + 2], pixels[IdxByte + 1], pixels[IdxByte]);
result.Pixels[IdxPixel] = new FastPixelHSV(pixels[IdxByte + 2], pixels[IdxByte + 1], pixels[IdxByte]);
IdxPixel++;
}
}
Expand All @@ -222,12 +310,10 @@ public static FastBitmapHSV ConvertToFastBitmap(Bitmap image, int forcedWidth =

public static FastBitmapHSV ConvertToFastBitmap(byte[] PixelsBGRA, int width, int height)
{
FastBitmapHSV result = new FastBitmapHSV();
result.Width = width;
result.Height = height;
result.Pixels = new FastPixelHSV[width * height];
FastBitmapHSV result = new FastBitmapHSV(width, height);

for (int IdxPx = 0; IdxPx < result.Pixels.Length; IdxPx++)
int numPx = width * height;
for (int IdxPx = 0; IdxPx < numPx; IdxPx++)
{
int IdxByte = IdxPx * 4;
result.Pixels[IdxPx] = new FastPixelHSV(PixelsBGRA[IdxByte + 2], PixelsBGRA[IdxByte + 1], PixelsBGRA[IdxByte]);
Expand Down Expand Up @@ -760,24 +846,19 @@ public static bool CreateFloodFillBitmap(FastBitmapHSV srcBitmap, Point floodOri
floodBounds = new Rectangle(minX, minY, maxX - minX + 1, maxY - minY + 1);
if (floodPoints.Count > 0)
{
FastPixelHSV[] bitmapPixels = new FastPixelHSV[floodBounds.Width * floodBounds.Height];
for (int Idx = 0; Idx < bitmapPixels.Length; Idx++)
floodBitmap = new FastBitmapHSV(floodBounds.Width, floodBounds.Height);
int numPx = floodBounds.Width * floodBounds.Height;

for (int Idx = 0; Idx < numPx; Idx++)
{
bitmapPixels[Idx] = new FastPixelHSV(false);
floodBitmap.SetPixel(Idx, new FastPixelHSV(false));
}

foreach (Point p in floodPoints)
{
int Idx = (p.X - minX) + ((p.Y - minY) * floodBounds.Width);
bitmapPixels[Idx] = new FastPixelHSV(true);
floodBitmap.SetPixel(Idx, new FastPixelHSV(true));
}

floodBitmap = new FastBitmapHSV()
{
Pixels = bitmapPixels,
Width = floodBounds.Width,
Height = floodBounds.Height,
};
}
else
{
Expand Down

0 comments on commit cf99a40

Please sign in to comment.