Ekran Capture

0

Witam serdecznie!
Czy wie ktos z forumowiczow w jaki sposob rozwiazac zapisywanie do avi (nie koniecznie z kodekiem)
aktualnego obrazu wyswietlanego na pulpicie?

0

Moze robic 25 razy na sekunde zrzut ekranu i zapisywac do pliku? Mozna by tez pomyslec o jakims uproszczeniu, zeby np. zapisywac tylko zmiany obrazu, a nie Ciag podobnych klatek.

0

Nic prostszego: jednofunkcyjny program zapisujący desktop razem z kursorem do avi.
Z kodekiem XVID ustawionym jak w komentażu - przy WXGA | 5 FPS | 1minuta = 4.2MB z bardzo dobrą jakością. Ustawiony format kompresora można zapisać by nie ustawiać go za każdym razem.

#include "stdafx.h"
#include <vfw.h>
#pragma comment(lib,"Vfw32.lib")


int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
{
	int src_w = GetSystemMetrics(SM_CXSCREEN);
	int src_h = GetSystemMetrics(SM_CYSCREEN);
	int video_w = src_w;
	int video_h = src_h;

	HRESULT hr;
	IAVIFile *avifile;
	CoInitialize(0);

	DeleteFile(TEXT("c:\\capture.avi"));
	hr = AVIFileOpen(&avifile, TEXT("c:\\capture.avi"), OF_WRITE | OF_CREATE, NULL);
	if (hr)
	{
		CoUninitialize();
		return MessageBox(0, TEXT("AVIFileOpen failed"),0,0);
	}
	HDC dcDesktop = GetDC(0);
	HDC cdc = CreateCompatibleDC(dcDesktop);

	BITMAPINFOHEADER bihdr;
	ZeroMemory(&bihdr, sizeof(bihdr));
	bihdr.biSize     = sizeof(bihdr);
	bihdr.biWidth    = video_w;
	bihdr.biHeight   = video_h;
	bihdr.biPlanes   = 1;
	bihdr.biBitCount = 24;
	int biSizeImage  = video_w * video_h * 3; // later compressor->Write
	void *pBits;
	HGDIOBJ bmp = SelectObject(cdc, CreateDIBSection(dcDesktop, (BITMAPINFO*)&bihdr, DIB_RGB_COLORS, &pBits, 0, 0));

	AVISTREAMINFOW strhdr;
	ZeroMemory(&strhdr, sizeof(strhdr));
	strhdr.fccType = streamtypeVIDEO;
	strhdr.dwScale = 1;
	strhdr.dwRate  = 5; // 5 klatek na sekundę
	SetRect(&strhdr.rcFrame, 0, 0, bihdr.biWidth, bihdr.biHeight);

	IAVIStream *pstream;
	if (avifile->CreateStream(&pstream, &strhdr))
	{
		MessageBox(0, TEXT("CreateStream failed"),0,0);
	}
	else
	{
		// add compression filter (XVID MPEG4: Single Pass; Quantizer:4; Profile:unrestricted; QualityPreset:realtime)
		IAVIStream *compressor;
		AVICOMPRESSOPTIONS DefaultOpts;
		ZeroMemory(&DefaultOpts, sizeof(DefaultOpts)); // no compression
		// load saved options
		AVICOMPRESSOPTIONS *psavedopts = &DefaultOpts;
		//LoadCompressOptions(TEXT("c:\\capture.options"), &psavedopts);

		if (AVISaveOptions(0,ICMF_CHOOSE_KEYFRAME|ICMF_CHOOSE_DATARATE,1,&pstream,&psavedopts))
		//	SaveCompressOptions(psavedopts, "c:\\capture.options");

		hr = AVIMakeCompressedStream(&compressor, pstream, psavedopts, NULL);
		if (!hr)
		{
			AVISaveOptionsFree(1, &psavedopts);
			//if (psavedopts != DefaultOpts)
			//	delete psavedopts;

			hr = compressor->SetFormat(0, &bihdr, sizeof(bihdr));

			// ograniczenie czasu filmu - jedna minuta
			int NumFrames = strhdr.dwRate * /*seconds*/60 * /*minutes*/1;

			for (int frameno=0; frameno<NumFrames; frameno++)
			{
				//SetConsoleTitle(sprint(frameno*100/NumFrames,"%"));
				if (video_w==src_w && video_h==src_h)
					BitBlt(cdc, 0, 0, video_w, video_h, dcDesktop, 0, 0, SRCCOPY|CAPTUREBLT);
				else
					//
					StretchBlt(cdc, 0, 0, video_w, video_h, dcDesktop, 0, 0, src_w, src_h, SRCCOPY|CAPTUREBLT);

				// rysuj kursor ?
				CURSORINFO cursor;
				cursor.cbSize = sizeof(cursor);
				if (GetCursorInfo(&cursor) && (cursor.flags == CURSOR_SHOWING))
				{
					DrawIcon(cdc, cursor.ptScreenPos.x, cursor.ptScreenPos.y, cursor.hCursor);
				}

				// trial info?
				TextOut(cdc,10,10,TEXT("zdjełano w cccp"), 15);
				hr = compressor->Write(frameno, 1, pBits, biSizeImage, AVIIF_KEYFRAME, NULL, NULL);
				if (hr)
				{
					MessageBox(0, TEXT("Write failed"),0,0);
					break;
				}

				Sleep(10); // prymitywne
			}
			compressor->Release();
		}
		pstream->Release();
	}
	avifile->Release();
	DeleteObject(SelectObject(cdc, bmp));
	DeleteDC(cdc);
	ReleaseDC(0, dcDesktop);
	CoUninitialize();
	return 0;
}

1 użytkowników online, w tym zalogowanych: 0, gości: 1