日記帳

日記です。

Win32でスクリーンキャプチャー

ちょっとわけあってデスクトップのスクリーンキャプチャを取得するプログラムを書いてみる.
まずは Win32 環境で.

  • CreateDIBSection() で 32bit RGB な DIBSection を作る
  • GetDesktopWindow() でデスクトップウィンドウ取ってくる
  • BitBlt() でデスクトップウィンドウを DIBSection にコピー
  • DIBSection はピクセルにアクセスできるのでそれを好きにいじる

簡単でよろしいです.上下逆っての以外は.


以下 PPM ASCII フォーマットに保存するサンプル.

/*
* gcc capture_screen_win32.c -mwindows
*/
#include <stdio.h>
#include <windows.h>

#define IMAGE_FILE_PATH "capture_screen_win32.ppm"

static
void
WriteImageToP3File(LPDWORD lpPixels, int width, int height, const char *file_path)
{
	int x, y;
	LPDWORD lpPixel;
	FILE *file;

	file = fopen(file_path, "wb");
	if (file != NULL)
	{
		fprintf(file, "P3\n");
		fprintf(file, "%d %d\n", width, height);
		fprintf(file, "255\n");
		for (y = height-1;y >= 0;y--)
		{
			lpPixel = lpPixels + (y * width);
			for (x = 0;x < width;x++)
			{
				fprintf(file, "%lu %lu %lu ",
					(*lpPixel & 0x00ff0000) >> 16,
					(*lpPixel & 0x0000ff00) >> 8,
					(*lpPixel & 0x000000ff) );
				lpPixel++;
			}
			fprintf(file, "\n");
		}
		fclose(file);
	}
}

int main(int argc, char *argv[])
{
	HWND hWndDesktop;
	HDC hDCDesktop;
	RECT rect;
	int width, height;
	BITMAPINFO bmpInfo;
	HBITMAP hBitmap;
	LPDWORD lpPixels;

	/* Get Desktop window and device context */
	hWndDesktop = GetDesktopWindow();
	hDCDesktop = GetDC(hWndDesktop);

	GetWindowRect(hWndDesktop, &rect);
	width = rect.right - rect.left;
	height = rect.bottom - rect.top;

	/* Create DIBSection */
	bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	bmpInfo.bmiHeader.biWidth = width;
	bmpInfo.bmiHeader.biHeight = height;
	bmpInfo.bmiHeader.biPlanes = 1;
	bmpInfo.bmiHeader.biBitCount = 32;
	bmpInfo.bmiHeader.biCompression = BI_RGB;
	hBitmap = CreateDIBSection(NULL, &bmpInfo,
		DIB_RGB_COLORS, (void **)&lpPixels, NULL, 0);

	if (hBitmap != NULL && lpPixels != NULL )
	{
		HDC hDC;

		/* Copy Desktop image to DIBSection */
		hDC = CreateCompatibleDC(hDCDesktop);
		SelectObject(hDC, hBitmap);
		BitBlt(hDC, 0, 0, width, height, hDCDesktop, 0, 0, SRCCOPY);

		/* Write to PPM file */
		WriteImageToP3File(lpPixels, width, height, IMAGE_FILE_PATH);

		DeleteDC(hDC);
		DeleteObject(hBitmap);
	}

	ReleaseDC(hWndDesktop, hDCDesktop);

	return 0;
}