我正在尝试改进我整合在一起的1bpp图像搜索功能。
我引用了鲍勃·鲍威尔的出色网页,以及此处的一些答案,我能够将这个运行良好的例程组合在一起。
void PrintScreen()
{
keybd_event(VKey.VK_SNAPSHOT, 0, KEYEVENTF_EXTENDEDKEY, 0);
keybd_event(VKey.VK_SNAPSHOT, 0, KEYEVENTF_KEYUP, 0);
}
Bitmap PrintWindow()
{
PrintScreen();
Application.DoEvents();
if (Clipboard.ContainsImage())
{
using (Image img = Clipboard.GetImage())
{
if (img != null)
{
return new Bitmap(img);
}
}
}
return PrintWindow();
}
Bitmap GetBlackWhiteAt(Point On, Size PickArea)
{
// Create a new bitmap.
using (Bitmap bmp = PrintWindow())
return bmp.Clone(new Rectangle(On, PickArea), PixelFormat.Format1bppIndexed);
}
/// Credits Bob Powell 1bpp
int GetIndexedPixel(int x, int y, BitmapData data)
{
var index = (y * data.Stride) + (x >> 3);
var p = Marshal.ReadByte(data.Scan0, index);
var mask = (byte)(0x80 >> (x & 0x7));
return p &= mask;
}
/// Credits digEmAll https://stackoverflow.com/a/3530012/4433847
int SubListIndex(IEnumerable<bool> list, int start, IEnumerable<bool> sublist)
{
for (int listIndex = start; listIndex < list.Count() - sublist.Count() + 1; listIndex++)
{
int count = 0;
while (count < sublist.Count() && sublist.ElementAt(count).Equals(list.ElementAt(listIndex + count)))
count++;
if (count == sublist.Count())
return listIndex;
}
return -1;
}
/// Initialize Search image.
bool[][] ba1;
/// Take picture of visual studio save button on a 1920, x 1080 screen.
using (var bw = GetBlackWhiteAt(new Point(145, 37), new Size(16, 16)))
{
BitmapData data = bw.LockBits(new Rectangle(0, 0, 16, 16), ImageLockMode.ReadOnly, PixelFormat.Format1bppIndexed);
ba1 = new bool[bw.Height][];
for (int y = 0; y <= bw.Height - 1; y++)
{
ba1[y] = new bool[bw.Width];
for (int x = 0; x <= bw.Width - 1; x++)
{
if (GetIndexedPixel(x, y, data) > 0)
{
ba1[y][x] = true;
}
}
}
bw.UnlockBits(data);
}
int SkippedBlackLines = 0;
foreach (bool[] bl1 in ba1)
{
if (bl1.Any(x => x))
{
break;
}
else
{
SkippedBlackLines++;
}
}
using (Bitmap SearchWindow = PrintWindow().Clone(new Rectangle(0, 0,Screen.PrimaryScreen.Bounds.Width, Screen.PrimaryScreen.Bounds.Height), PixelFormat.Format1bppIndexed))
{
BitmapData data = SearchWindow.LockBits(new Rectangle(0, 0, SearchWindow.Width, SearchWindow.Height), ImageLockMode.ReadOnly, PixelFormat.Format1bppIndexed);
bool[][] ba2 = new bool[SearchWindow.Height][];
for (int y = 0; y <= SearchWindow.Height - 1; y++)
{
ba2[y] = new bool[SearchWindow.Width];
for (int x = 0; x <= SearchWindow.Width - 1; x++)
{
if (GetIndexedPixel(x, y, data) > 0)
{
ba2[y][x] = true;
}
}
}
var Base = ba1.Skip(SkippedBlackLines);
// Skip last
Base = Base.Take(Base.Count() - 1);
for (int i = ba2.GetUpperBound(0) - 1; i != 0; i--)
{
if (SubListIndex(ba2[i].AsEnumerable(), 0, Base.LastOrDefault()) != -1)
{
if (Base.Count() != 1)
{
Base = Base.Take(Base.Count() - 1);
}
else
{
MoveTo(
SubListIndex(ba2[i].AsEnumerable(), 0, Base.LastOrDefault()) + (Base.Count() /2),
i + (ba1.GetUpperBound(0) / 2));
ba2 = null;
ba1 = null;
break;
}
}
}
SearchWindow.UnlockBits(data);
}
所以如何减少GetIndexedPixel中对Marshal.ReadByte的调用?任何意见或想法都很好。