0
我一直在試圖製作一個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代碼(如有必要)。
創建SDL的質感和緩衝的代碼是:
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);
}
同樣,我用我的DLL函數create_array()在這種情況下,但我認爲你應該能夠告訴它做什麼。
產生的圖像是這樣的:
隨意添加更好的方法或這樣做的純SDL方法。我試過GetPixel(),並且它返回正確的值。儘管如此,多個呼叫的開銷仍然很高。
看起來像潛在的問題是您創建兼容位圖的位置。應該創建位圖的確切大小,而不是SDL位圖的大小。你永遠不想讓GDI縮小位圖,因爲你會得到像你看到的結果。 – BitBank
爲什麼在嘗試獲取簡單屏幕截圖時使用sdl。只用winapi就可以用最少的代碼完成相同的結果。 –
@BBBank我改變了它,但它沒有完全解決它,只是使圖像稍微好一點。 – Name