#include <windows.h> #include <Vfw.h> //#pragma comment (lib, "vfw32.lib")
#define X_SCALE 320 #define Y_SCALE 240
#define BACKGROUND_SIZE (X_SCALE * Y_SCALE * 3)
#define M_ALPHA 170 //미들 #define G_ALPHA 30 //Gap
//프로그램 할 때 쓰이는 애ㅑ들 #define H_ALPHA (M_ALPHA + G_ALPHA) //높이? #define L_ALPHA (M_ALPHA - G_ALPHA) //길이?
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); HINSTANCE g_hInst; LPSTR lpszClass = L"VFW";
LRESULT On_Destroy(WPARAM wParam, LPARAM lParam); LRESULT On_Create(WPARAM wParam, LPARAM lParam); LRESULT On_Paint(WPARAM wParam, LPARAM lParam); LRESULT CALLBACK Capture(HWND hWnd, LPVIDEOHDR lpVHdr);
typedef struct _stMsgMap { UINT uiMsg; LRESULT(*fp)(WPARAM, LPARAM); }StMsgMap;
StMsgMap msgMap[] = { { WM_DESTROY, On_Destroy }, { WM_CREATE, On_Create }, { WM_PAINT, On_Paint }, { WM_NULL, 0 } };
HWND hWnd;
BITMAPINFO stBmpInfo; static BYTE bData[BACKGROUND_SIZE]; //비트맵 파일 적재
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance , LPSTR lpszCmdParam, int nCmdShow) { MSG Message; WNDCLASS WndClass; g_hInst = hInstance;
WndClass.cbClsExtra = 0; WndClass.cbWndExtra = 0; WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); WndClass.hInstance = hInstance; WndClass.lpfnWndProc = (WNDPROC)WndProc; WndClass.lpszClassName = lpszClass; WndClass.lpszMenuName = NULL; WndClass.style = CS_HREDRAW | CS_VREDRAW; RegisterClass(&WndClass);
hWnd = CreateWindow(lpszClass, lpszClass, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, (HMENU)NULL, hInstance, NULL); ShowWindow(hWnd, nCmdShow);
while (GetMessage(&Message, 0, 0, 0)) { TranslateMessage(&Message); DispatchMessage(&Message); } return Message.wParam; }
LRESULT CALLBACK WndProc(HWND hWpWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) { StMsgMap *stpMap = msgMap;
hWnd = hWpWnd;
while ((*stpMap).uiMsg != WM_NULL) { if (iMessage == (*stpMap).uiMsg) { ((*stpMap).fp)(wParam, lParam);
return 0; }
++stpMap; }
return(DefWindowProc(hWpWnd, iMessage, wParam, lParam)); }
LRESULT On_Destroy(WPARAM wParam, LPARAM lParam) { PostQuitMessage(0);
return 0; }
LRESULT On_Create(WPARAM wParam, LPARAM lParam) { HWND hCamera; BOOL bRet; HANDLE hFile; // 한번 읽고 닫기 때문에 static x DWORD dwCount;
hFile = CreateFile(L"C:\\6666.bmp", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { MessageBox(hWnd, L"On_Create()의 CreateFile() 에러.", L"Button", MB_OK); PostQuitMessage(0); return 0; }
bRet = ReadFile(hFile, bData, (BACKGROUND_SIZE), &dwCount, NULL); if (bRet == FALSE) { CloseHandle(hFile); MessageBox(hWnd, L"On_Create()의 ReadFile() 에러. - .bmp 파일 읽기 실패", L"Button", MB_OK); PostQuitMessage(0); return 0; }
//1. 비디오캡처 윈도우를 지정된 영역에 원하는 크기로 생성 hCamera = capCreateCaptureWindowW(L"Camera", WS_CHILD | WS_VISIBLE, 0, 0, X_SCALE, Y_SCALE, hWnd, 0); if (hCamera == 0) { MessageBox(hWnd, "On_Create() 의 capCreateCaptureWindowW() 에러. 캡쳐 윈도우 생성 실패.", "Button", MB_OK); PostQuitMessage(0); } //2. 캡처 윈도우와 드라이버 연결 bRet = capDriverConnect(hCamera, 0); if (bRet == FALSE) { MessageBox(hWnd, "On_Create() 의 capDriverConnect() 에러. 드라이버에 연결할 수 없습니다.", "Button", MB_OK); PostQuitMessage(0); } //3. 캡처윈도우에 프리뷰 모드로 찍을 프레임 값 설정 capPreviewRate(hCamera, 1); //숫자가 작을 수록 화면에 보이는 속도가 빨라진다. //4. 캡처되는 이미지의 정보를 얻어냄 capGetVideoFormat(hCamera, &stBmpInfo, sizeof(stBmpInfo)); //5. 원하는 크기로 생성시킨 값으로 수정 stBmpInfo.bmiHeader.biWidth = X_SCALE; stBmpInfo.bmiHeader.biHeight = Y_SCALE; //6. 콜백 함수 호환을 위한 비디오 포맷 설정 capSetVideoFormat(hCamera, &stBmpInfo, sizeof(stBmpInfo)); //7. 콜백 함수 호출 capSetCallbackOnFrame(hCamera, Capture); //8. 캡쳐 윈도우에 프리뷰 모드로 보여줌 capPreview(hCamera, TRUE);
CloseHandle(hFile);
return 0; }
LRESULT On_Paint(WPARAM wParam, LPARAM lParam) { HDC hdc; PAINTSTRUCT ps;
hdc = BeginPaint(hWnd, &ps); EndPaint(hWnd, &ps);
return 0; }
//그림한장 호출될때마다 이 함수가 호출. 2번째 인자에 비디오 정보가 실려오기에 헤더를 분석해야한다. LRESULT CALLBACK Capture(HWND hWpWnd, LPVIDEOHDR lpVHdr) { HDC hdc; int iCountX; int iCountY; int iCal; //코드 줄이기 용 변수 WCHAR wcStr[50] = { 0, }; static BYTE vData[X_SCALE * Y_SCALE * 3]; //영상처리를 위해서 데이터 값을 그대로 가져올 것.
hdc = GetDC(hWnd);
//memcpy(vData, lpVHdr->lpData, lpVHdr->dwBufferLength); for (iCountY = 0; iCountY < Y_SCALE; ++iCountY) { for (iCountX = 0; iCountX < X_SCALE; ++iCountX) { iCal = (iCountY * X_SCALE + iCountX) * 3; vData[iCal + 0] = lpVHdr->lpData[iCal + 0]; vData[iCal + 1] = lpVHdr->lpData[iCal + 1]; vData[iCal + 2] = lpVHdr->lpData[iCal + 2];
if (vData[iCal + 0] > H_ALPHA) { continue; } if (vData[iCal + 0] < L_ALPHA) { continue; }
if (vData[iCal + 1] > H_ALPHA) { continue; } if (vData[iCal + 1] < L_ALPHA) { continue; }
if (vData[iCal + 2] > H_ALPHA) { continue; } if (vData[iCal + 2] < L_ALPHA) { continue; }
//칠판 비트맵 사진으로 교체 하기 vData[iCal + 0] = bData[iCal + 0]; vData[iCal + 1] = bData[iCal + 1]; vData[iCal + 2] = bData[iCal + 2]; } } StretchDIBits(hdc, X_SCALE, 0, X_SCALE, Y_SCALE, 0, 0, X_SCALE, Y_SCALE, vData, &stBmpInfo, DIB_RGB_COLORS, SRCCOPY);
ReleaseDC(hWnd, hdc);
return 0; } |