Я использую SharpDx для захвата экрана (от 1 до 60 кадров в секунду). Некоторые кадры прозрачны и в конечном итоге обрабатываются и сохраняются кодом.
Есть ли какой-нибудь простой / быстрый способ обнаружить пропадание этих кадров без необходимости открывать сгенерированное растровое изображение и искать значения альфа?
Вот что я использую (сохраняет захват как изображение):
try
{
//Try to get duplicated frame within given time.
_duplicatedOutput.AcquireNextFrame(MinimumDelay, out var duplicateFrameInformation, out var screenResource);
//Copy resource into memory that can be accessed by the CPU.
using (var screenTexture2D = screenResource.QueryInterface<Texture2D>())
_device.ImmediateContext.CopySubresourceRegion(screenTexture2D, 0, new ResourceRegion(Left, Top, 0, Left + Width, Top + Height, 1), _screenTexture, 0);
//Get the desktop capture texture.
var mapSource = _device.ImmediateContext.MapSubresource(_screenTexture, 0, MapMode.Read, MapFlags.None); //, out var stream);
#region Get image data
var bitmap = new System.Drawing.Bitmap(Width, Height, PixelFormat.Format32bppArgb);
var boundsRect = new System.Drawing.Rectangle(0, 0, Width, Height);
//Copy pixels from screen capture Texture to GDI bitmap.
var mapDest = bitmap.LockBits(boundsRect, ImageLockMode.WriteOnly, bitmap.PixelFormat);
var sourcePtr = mapSource.DataPointer;
var destPtr = mapDest.Scan0;
for (var y = 0; y < Height; y++)
{
//Copy a single line
Utilities.CopyMemory(destPtr, sourcePtr, Width * 4);
//Advance pointers
sourcePtr = IntPtr.Add(sourcePtr, mapSource.RowPitch);
destPtr = IntPtr.Add(destPtr, mapDest.Stride);
}
//Release source and dest locks
bitmap.UnlockBits(mapDest);
//Bitmap is saved in here!!!
#endregion
_device.ImmediateContext.UnmapSubresource(_screenTexture, 0);
screenResource.Dispose();
_duplicatedOutput.ReleaseFrame();
}
catch (SharpDXException e)
{
if (e.ResultCode.Code != SharpDX.DXGI.ResultCode.WaitTimeout.Result.Code)
throw;
}
Это модифицированная версия с этой .
У меня также есть этоверсия (сохраняет захват в виде пиксельного массива):
//Get the desktop capture texture.
var data = _device.ImmediateContext.MapSubresource(_screenTexture, 0, MapMode.Read, MapFlags.None, out var stream);
var bytes = new byte[stream.Length];
//BGRA32 is 4 bytes.
for (var height = 0; height < Height; height++)
{
stream.Position = height * data.RowPitch;
Marshal.Copy(new IntPtr(stream.DataPointer.ToInt64() + height * data.RowPitch), bytes, height * Width * 4, Width * 4);
}
Я не уверен, что это лучший способ сохранить снимок экрана в виде изображения и / или пиксельного массива, но он несколько работает.
В любом случае, проблема в том, что некоторые захваченные кадры полностью прозрачны и бесполезны для меня. Мне нужно как-то вообще избегать их сохранения.
При захвате в виде массива пикселей я могу просто проверить массив bytes
, чтобы узнать, является ли 4-й элемент 255 или 0. При сохранении в качестве изображения я мог быиспользуйте bitmap.GetPixel(0,0).A
, чтобы узнать, содержит ли изображение содержимое.
Но обоими способами мне нужно закончить захват и получить полное содержимое изображения, прежде чем я смогу узнать, был ли кадр пропущен или нет.
Есть ли способ узнать, правильно ли был снят кадр?