저는 전체 화면의 스크린 샷을 찍을 수있는 SDL 프로그램을 만들려고했습니다.이 경우 전체 모니터 화면의 라이브 피드를 표시합니다. 내가 GDI 함수를 사용하여 이미지를 검색 할 수있는 정도까지 성공했지만 GetDIBits() 함수가 반환 된 후 데이터 버퍼를 올바르게 처리하는 방법을 알지 못합니다. 지금까지 내 이미지가 예상 출력에서 벗어났습니다. 색상은 현재 시도한 모든 형식으로 엉망입니다. SDL 텍스처에 사용할 수있는 대부분의 32 비트 및 24 비트 픽셀 형식이었습니다. 내 win32 코드도 버그가있을 수 있습니다. 이미지가 올바르지 않기 때문에 완전히 확신 할 수 없습니다. 여기GetDIBits()에 의해 반환 된 픽셀 버퍼를 처리하는 적절한 방법은 무엇입니까?
내가 스크린 샷 얻는 방법은 다음과 같습니다
void WINAPI get_screenshot(app_data * app)
{
HDC desktop = GetDC(NULL);
int width = GetDeviceCaps(desktop, HORZRES);
int height = GetDeviceCaps(desktop, VERTRES);
HDC desktop_copy = CreateCompatibleDC(0);
HGDIOBJ old = NULL;
HBITMAP screenshot = CreateCompatibleBitmap(desktop_copy, app->viewport.w, app->viewport.h);
BITMAPINFOHEADER screenshot_header = { 0 };
screenshot_header.biSize = sizeof(BITMAPINFOHEADER);
screenshot_header.biWidth = app->viewport.w;
screenshot_header.biHeight = -app->viewport.h;
screenshot_header.biPlanes = 1;
screenshot_header.biBitCount = 32;
screenshot_header.biCompression = BI_RGB;
if (!screenshot)
{
ReleaseDC(NULL, desktop);
DeleteDC(desktop_copy);
DeleteObject(screenshot);
free_app_data(app);
win_error("Creating Bitmap", true);
}
SetStretchBltMode(desktop_copy, HALFTONE);
SetBrushOrgEx(desktop_copy, 0, 0, NULL);
old = SelectObject(desktop_copy, screenshot);
if (!StretchBlt(desktop_copy, 0, 0, app->viewport.w, app->viewport.h, desktop, 0, 0, width, height, SRCCOPY))
{
ReleaseDC(NULL, desktop);
DeleteDC(desktop_copy);
DeleteObject(screenshot);
free_app_data(app);
win_error("Stretching Screenshot to Window Size", true);
}
if (!GetDIBits(desktop_copy, screenshot, 0, app->viewport.h, app->pixels, (BITMAPINFO *)&screenshot_header, DIB_RGB_COLORS))
{
ReleaseDC(NULL, desktop);
DeleteDC(desktop_copy);
DeleteObject(screenshot);
free_app_data(app);
win_error("Getting Window RGB Values", true);
}
SelectObject(desktop_copy, old);
DeleteObject(screenshot);
ReleaseDC(NULL, desktop);
DeleteDC(desktop_copy);
return;
}
내가 내 DLL 함수를 호출하는 코드의 대부분은 자기 설명의 경우, 또는이 게시물에 대한 중요하지 않은 느낌,하지만 난 제공 드리겠습니다 의사 코드 또는 필요한 경우 순수한 Win32 API 코드. 나는이 경우 내 DLL 함수 create_array()를 사용하고, 다시
app->frame = SDL_CreateTexture(
app->renderer,
SDL_PIXELFORMAT_ABGR8888,
SDL_TEXTUREACCESS_STREAMING,
app->viewport.w,
app->viewport.h
);
if (!app->frame)
{
free_app_data(app);
SDL_errorexit("Creating texture", 1, TRUE);
}
app->pixels = (Uint32 *)create_array(NULL, (app->viewport.w * app->viewport.h), sizeof(Uint32), zero_array);
if (!app->pixels)
{
free_app_data(app);
std_error("Creating pixel buffer", TRUE);
}
,하지만 난 당신이 무엇을 말할 수 있어야한다고 생각 :
SDL에 질감과 버퍼를 생성하는 코드는 .
결과 이미지는 이것이다 :
더 나은 방법이나이 일을 순수 SDL 방법을 추가하시기 바랍니다. GetPixel() 시도하고 올바른 값을 반환합니다. 그것은 여러 호출에 대한 높은 오버 헤드가 있습니다.
잠재적 인 문제는 호환되는 비트 맵을 만드는 위치입니다. 비트 맵은 SDL 비트 맵의 크기가 아니라 디스플레이의 정확한 크기로 만들어야합니다. 당신은 당신이 보는 것처럼 결과를 얻을 수 있기 때문에 GDI가 비트 맵의 크기를 줄 이도록하고 싶지 않습니다. – BitBank
간단한 스크린 샷을 만들 때 sdl을 사용하는 이유는 무엇입니까? winapi를 사용하면 최소한의 코딩으로 동일한 결과를 얻을 수 있습니다. –
@BitBank 나는 그것을 바꿨지 만 그것을 완전히 고치지 못했고 이미지를 조금 더 좋게 만들었습니다. – Name