如何捕捉屏幕的某个区域

时间:2016-02-10 15:44:29

标签: direct3d screen-capture

我要录制屏幕的某个区域并保存正在播放的视频的帧数(20-30fps)。目前我能够使用以下代码以所需的帧速率捕获屏幕,但是我不确定如何捕获某个区域。

HRESULT SavePixelsToFile32bppPBGRA(UINT width, UINT height, UINT stride, BYTE, *pixels, LPWSTR filePath, const GUID &format)
{
    if (!filePath || !pixels)
        return E_INVALIDARG;

    HRESULT hr = S_OK;
    IWICImagingFactory *factory = nullptr;
    IWICBitmapEncoder *encoder = nullptr;
    IWICBitmapFrameEncode *frame = nullptr;
    IWICStream *stream = nullptr;
    GUID pf = GUID_WICPixelFormat32bppPBGRA;
    BOOL coInit = CoInitialize(nullptr);

    CoCreateInstance(CLSID_WICImagingFactory, nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&factory));
    factory->CreateStream(&stream);
    stream->InitializeFromFilename(filePath, GENERIC_WRITE);
    factory->CreateEncoder(format, nullptr, &encoder);
    encoder->Initialize(stream, WICBitmapEncoderNoCache);
    encoder->CreateNewFrame(&frame, nullptr); // we don't use options here
    frame->Initialize(nullptr); // we dont' use any options here
    frame->SetSize(width, height);
    frame->SetPixelFormat(&pf);
    frame->WritePixels(height, stride, stride * height, pixels);
    frame->Commit();
    encoder->Commit();

    RELEASE(stream);
    RELEASE(frame);
    RELEASE(encoder);
    RELEASE(factory);
    if (coInit) CoUninitialize();
    return hr;
}


HRESULT Direct3D9TakeScreenshots(UINT adapter, int count)
{
    HRESULT hr = S_OK;
    IDirect3D9 *d3d = nullptr;
    IDirect3DDevice9 *device = nullptr;
    IDirect3DSurface9 *surface = nullptr;
    D3DPRESENT_PARAMETERS parameters = { 0 };
    D3DDISPLAYMODE mode;
    D3DLOCKED_RECT rc;

    UINT pitch;
    SYSTEMTIME st;
    BYTE *shot = nullptr;

    // init D3D and get screen size
    d3d = Direct3DCreate9(D3D_SDK_VERSION);
    d3d->GetAdapterDisplayMode(adapter, &mode);

    parameters.Windowed = TRUE;
    parameters.BackBufferCount = 1;
    parameters.BackBufferHeight = mode.Height;
    parameters.BackBufferWidth = mode.Width;
    parameters.SwapEffect = D3DSWAPEFFECT_DISCARD;
    parameters.hDeviceWindow = NULL;

    // create device & capture surface
    d3d->CreateDevice(adapter, D3DDEVTYPE_HAL, NULL, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &parameters, &device);
    device->CreateOffscreenPlainSurface(mode.Width, mode.Height, D3DFMT_A8R8G8B8, D3DPOOL_SYSTEMMEM, &surface, nullptr);

    // compute the required buffer size
    surface->LockRect(&rc, NULL, 0);
    pitch = rc.Pitch;
    surface->UnlockRect();

    // allocate screenshots buffers
    shot = new BYTE[pitch * mode.Height];

    // get the data
    device->GetFrontBufferData(0, surface);

    // copy it into our buffers
    surface->LockRect(&rc, NULL, 0);
    CopyMemory(shot, rc.pBits, rc.Pitch * mode.Height);
    surface->UnlockRect();

    WCHAR file[100];
    wsprintf(file, L"C:/Frames/cap%i.png", count);
    SavePixelsToFile32bppPBGRA(mode.Width, mode.Height, pitch, shot, file, GUID_ContainerFormatPng);
    if (shot != nullptr)
    {
        delete shot;
    }
    RELEASE(surface);
    RELEASE(device);
    RELEASE(d3d);
    return hr;
}

我知道我可以打开已保存的图像并裁剪它们然后再次保存它们,但这会花费额外的时间。有没有办法选择所需的区域

0 个答案:

没有答案