영상처리 - 영상에 이미지 파일 고정 출력 및 위치변환
내장형 하드웨어/WINAPI / 2011. 11. 24. 14:38
- 주사방식
→ NTSC, PAL 등이 방식이 있다.
- 테스트 1, 2
→ 첫번째로 복제된 영상에 BMP를 고정 위치로 출력시킨다.
→ 다음으로 원본 영상에 BMP를 고정 위치로 출력시킨다.
→ 실행 결과
→ 사실 원본 영상을 바꾸었으면 복제영상은 예외처리를 할 필요가 없다. 복제 영상은 원본 영상을 그대로 복제하기 때문에 BMP로 대체된 부분가지 그대로 복제하여 출력한다.
- 테스트 3
→ 출력되는 영상에 떠있는 BMP 출력 화면을 키보드의 방향키를 이용하여 이동시킨다.
→ NTSC, PAL 등이 방식이 있다.
- 테스트 1, 2
→ 첫번째로 복제된 영상에 BMP를 고정 위치로 출력시킨다.
→ 다음으로 원본 영상에 BMP를 고정 위치로 출력시킨다.
#include<windows.h>
#include<vfw.h>
HBITMAP hBm;
BITMAPINFO BInfo;
HWND hWnd;
HWND hVfw;
HDC hdc;
HANDLE hFile;
static TCHAR buf[640*480*3];
// 라이브러리를 추가하는 것을 comment - 수동식
// project setting을 변화시키면 project를 통채로 복사해야 하지만
// #pragama comment를 사용하면 소스만 복사해도 동작한다.
#pragma comment (lib, "vfw32.lib")
LRESULT CALLBACK Emb_Draw(HWND hWnd, LPVIDEOHDR lp);
/* 고정 형식 */
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // 메세지 처리 함수
HINSTANCE g_hInst; // instance 전역 변수 선언
LPCTSTR lpszClass = TEXT("VFW32"); // 윈도 클래스 이름 정의
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
MSG Message; // MSG 구조체 사용
WNDCLASS WndClass; // WndClass 구조체 사용
g_hInst = hInstance; // 윈도우 클래스를 등록하는 프로그램의 번호이며 WinMain의 인수로 전달된 hInstance값을 그대로 대입
/* 윈도우 클래스 정의 */
WndClass.cbClsExtra = 0; // 예약 영역, 사용하지 않을 경우는 0
WndClass.cbWndExtra = 0;
WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // HBRUSH 타입으로 형변환
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); // 윈도우가 사용할 마우스 커서지정
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 윈도우가 사용할 아이콘 지정
WndClass.hInstance = hInstance;
WndClass.lpfnWndProc = WndProc; // 윈도우의 메시지 처리 함수를 지정
WndClass.lpszClassName = lpszClass; // 윈도우 클래스의 이름을 문자열로 정의 - 여기서는 First라는 문자열을 보내준다.
WndClass.lpszMenuName = NULL; // 프로그램이 사용할 메뉴를 지정
WndClass.style = CS_HREDRAW|CS_VREDRAW; // 윈도우가 어떤 형태를 가질 것인가-윈도우의크기가 변할 경우 윈도우를 다시 그린다.
/* 윈도우 클래스 등록 */
RegisterClass(&WndClass); // WndClass 구조체의 번지를 전달
// 메모리 상에 윈도우 생성
hWnd=CreateWindow(lpszClass, TEXT("Video for Window"), WS_OVERLAPPEDWINDOW, 10, 0, 760, 740, NULL, (HMENU)NULL, hInstance, NULL);
/* 인자의 의미 -> (윈도우 클래스 이름, 타이틀바에 나타날 문자열-윈도우 네임(클래스 이름과 같게 하려면 lpszClass),
윈도우의 형태 지정, 윈도우의 크기와 위치(픽셀단위)-x, y, nWidth, nHeight,
부모 윈도우가 있을 경우 부모윈도우의 핸들-hWndParent, 윈도우에서 사용할 메뉴의 핸들-hmenu,
프로그램의 핸들 지정-hinst(프로그램이 종료될 때 파괴되지 않은 윈도우를 자동으로 파괴),
여러개의 윈도우를 만들때 각 윈도우에 고유의 파라미터를 전달하는 특수 목적에 사용-lpvParam)
*/
/* 화면에 윈도우 표시 */
ShowWindow(hWnd, nCmdShow); // CreateWindow 함수가 리턴한 핸들을 이용하여 출력
/* 사용자로부터의 메시지 처리*/
while(GetMessage(&Message, NULL, 0, 0)) // 메시지 큐에서 메시지 읽어옴,
// WN_QUIT이면 False 리턴 후 while문을 빠져나간다.
{
TranslateMessage(&Message); // 키보드 입력 처리
// 만약 A키를 누르면 A문자가 입력되었다는 메시지를 만들어 낸다.
DispatchMessage(&Message); // 큐에서 꺼낸 메시지를 WndProc 함수의 iMAssage로 전달
}
return (int)Message.wParam; // 메시지 루프 종료 후 이 프로그램을 실행시킨 OS로 리턴
}
// 사용자와 시스템이 보내오는 메시지를 처리
// 운영체제가 호출하는 함수는 CALLBACK 표시, LRESULT = 4byte long
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
switch(iMessage) // 운영체제로부터 들어온 메시지에 대한 처리
{
/* 고정 형식 */
case WM_CREATE:
hdc = GetDC(hWnd);
// 320x240으로 캡쳐, 부모 윈도우(hWnd),
// 창이 만들어 진다. - 실제 생성되지는 않는다.
hVfw = capCreateCaptureWindow(TEXT("Video for Window"), WS_CHILD|WS_VISIBLE, 10, 10, 320, 240, hWnd, 0);
// usb를 통해 연결된 카메라 장치를 찾아 연결해 준다.
capDriverConnect(hVfw, 0);
// hVfw, 1ms - 화면에 보이는 속도(Rate)
capPreviewRate(hVfw, 1);
// Video 포멧을 확인하고 정보를 넣는다.
capGetVideoFormat(hVfw, &BInfo, sizeof(BITMAPINFO));
BInfo.bmiHeader.biWidth = 320;
BInfo.bmiHeader.biHeight = 240;
capSetVideoFormat(hVfw, &BInfo, sizeof(BITMAPINFO));
// 자동으로 라이브러리에서 Emb_Draw()를 호출해 준다.
capSetCallbackOnFrame(hVfw, Emb_Draw);
// 화면에 띄운다.(TRUE)
capPreview(hVfw, TRUE);
return 0;
case WM_DESTROY: // 운영체제로부터 들어온 메시지에 대한 처리 - 여기서는 윈도우가 파괴되었음을 알린다.
ReleaseDC(hWnd, hdc);
PostQuitMessage(0); // WM_QUIT 메시지를 보냄
return 0;
}
// switch 문에서 처리하지 않은 메시지를 처리
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
// HWND, long *
LRESULT CALLBACK Emb_Draw(HWND hWnd, LPVIDEOHDR lp)
{
int xPos;
int yPos;
int iCnt=0;
int iCnt2=54;
DWORD dwRead;
hFile = CreateFile("1117.bmp", GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
ReadFile(hFile, buf, sizeof(buf), &dwRead, NULL);
// 원본 영상에 bmp파일 고정 출력
for(yPos=240;0<yPos;--yPos)
{
for(xPos=0;320>xPos;++xPos)
{
// 예외 처리
if((60<yPos && 120>=yPos) && (80<=xPos && 160>xPos))
{
// BMP
lp->lpData[iCnt+2] = buf[(iCnt2)+2];
lp->lpData[iCnt+1] = buf[(iCnt2)+1];
lp->lpData[iCnt] = buf[iCnt2];
iCnt2 = iCnt2 +3;
}
iCnt = iCnt+3;
}
}
iCnt = 0;
iCnt2 = 54;
// 복제 영상에 bmp파일 고정 출력
for(yPos=240;0<yPos;--yPos)
{
for(xPos=0;320>xPos;++xPos)
{
// 예외 처리
if((60<yPos && 120>=yPos) && (80<=xPos && 160>xPos))
{
// BMP
SetPixel(hdc, xPos+420, yPos+10, RGB(buf[(iCnt2)+2], buf[(iCnt2)+1], buf[(iCnt2)]));
iCnt2 = iCnt2 +3;
}
else
{
// 영상
SetPixel(hdc, xPos+420, yPos+10, RGB(lp->lpData[iCnt+2], lp->lpData[iCnt+1], lp->lpData[iCnt]));
}
iCnt = iCnt +3;
}
}
return 0;
}
→ 원본 영상과 복제 영상 양쪽에 각각 출력시킨다.#include<vfw.h>
HBITMAP hBm;
BITMAPINFO BInfo;
HWND hWnd;
HWND hVfw;
HDC hdc;
HANDLE hFile;
static TCHAR buf[640*480*3];
// 라이브러리를 추가하는 것을 comment - 수동식
// project setting을 변화시키면 project를 통채로 복사해야 하지만
// #pragama comment를 사용하면 소스만 복사해도 동작한다.
#pragma comment (lib, "vfw32.lib")
LRESULT CALLBACK Emb_Draw(HWND hWnd, LPVIDEOHDR lp);
/* 고정 형식 */
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // 메세지 처리 함수
HINSTANCE g_hInst; // instance 전역 변수 선언
LPCTSTR lpszClass = TEXT("VFW32"); // 윈도 클래스 이름 정의
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
MSG Message; // MSG 구조체 사용
WNDCLASS WndClass; // WndClass 구조체 사용
g_hInst = hInstance; // 윈도우 클래스를 등록하는 프로그램의 번호이며 WinMain의 인수로 전달된 hInstance값을 그대로 대입
/* 윈도우 클래스 정의 */
WndClass.cbClsExtra = 0; // 예약 영역, 사용하지 않을 경우는 0
WndClass.cbWndExtra = 0;
WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // HBRUSH 타입으로 형변환
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); // 윈도우가 사용할 마우스 커서지정
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 윈도우가 사용할 아이콘 지정
WndClass.hInstance = hInstance;
WndClass.lpfnWndProc = WndProc; // 윈도우의 메시지 처리 함수를 지정
WndClass.lpszClassName = lpszClass; // 윈도우 클래스의 이름을 문자열로 정의 - 여기서는 First라는 문자열을 보내준다.
WndClass.lpszMenuName = NULL; // 프로그램이 사용할 메뉴를 지정
WndClass.style = CS_HREDRAW|CS_VREDRAW; // 윈도우가 어떤 형태를 가질 것인가-윈도우의크기가 변할 경우 윈도우를 다시 그린다.
/* 윈도우 클래스 등록 */
RegisterClass(&WndClass); // WndClass 구조체의 번지를 전달
// 메모리 상에 윈도우 생성
hWnd=CreateWindow(lpszClass, TEXT("Video for Window"), WS_OVERLAPPEDWINDOW, 10, 0, 760, 740, NULL, (HMENU)NULL, hInstance, NULL);
/* 인자의 의미 -> (윈도우 클래스 이름, 타이틀바에 나타날 문자열-윈도우 네임(클래스 이름과 같게 하려면 lpszClass),
윈도우의 형태 지정, 윈도우의 크기와 위치(픽셀단위)-x, y, nWidth, nHeight,
부모 윈도우가 있을 경우 부모윈도우의 핸들-hWndParent, 윈도우에서 사용할 메뉴의 핸들-hmenu,
프로그램의 핸들 지정-hinst(프로그램이 종료될 때 파괴되지 않은 윈도우를 자동으로 파괴),
여러개의 윈도우를 만들때 각 윈도우에 고유의 파라미터를 전달하는 특수 목적에 사용-lpvParam)
*/
/* 화면에 윈도우 표시 */
ShowWindow(hWnd, nCmdShow); // CreateWindow 함수가 리턴한 핸들을 이용하여 출력
/* 사용자로부터의 메시지 처리*/
while(GetMessage(&Message, NULL, 0, 0)) // 메시지 큐에서 메시지 읽어옴,
// WN_QUIT이면 False 리턴 후 while문을 빠져나간다.
{
TranslateMessage(&Message); // 키보드 입력 처리
// 만약 A키를 누르면 A문자가 입력되었다는 메시지를 만들어 낸다.
DispatchMessage(&Message); // 큐에서 꺼낸 메시지를 WndProc 함수의 iMAssage로 전달
}
return (int)Message.wParam; // 메시지 루프 종료 후 이 프로그램을 실행시킨 OS로 리턴
}
// 사용자와 시스템이 보내오는 메시지를 처리
// 운영체제가 호출하는 함수는 CALLBACK 표시, LRESULT = 4byte long
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
switch(iMessage) // 운영체제로부터 들어온 메시지에 대한 처리
{
/* 고정 형식 */
case WM_CREATE:
hdc = GetDC(hWnd);
// 320x240으로 캡쳐, 부모 윈도우(hWnd),
// 창이 만들어 진다. - 실제 생성되지는 않는다.
hVfw = capCreateCaptureWindow(TEXT("Video for Window"), WS_CHILD|WS_VISIBLE, 10, 10, 320, 240, hWnd, 0);
// usb를 통해 연결된 카메라 장치를 찾아 연결해 준다.
capDriverConnect(hVfw, 0);
// hVfw, 1ms - 화면에 보이는 속도(Rate)
capPreviewRate(hVfw, 1);
// Video 포멧을 확인하고 정보를 넣는다.
capGetVideoFormat(hVfw, &BInfo, sizeof(BITMAPINFO));
BInfo.bmiHeader.biWidth = 320;
BInfo.bmiHeader.biHeight = 240;
capSetVideoFormat(hVfw, &BInfo, sizeof(BITMAPINFO));
// 자동으로 라이브러리에서 Emb_Draw()를 호출해 준다.
capSetCallbackOnFrame(hVfw, Emb_Draw);
// 화면에 띄운다.(TRUE)
capPreview(hVfw, TRUE);
return 0;
case WM_DESTROY: // 운영체제로부터 들어온 메시지에 대한 처리 - 여기서는 윈도우가 파괴되었음을 알린다.
ReleaseDC(hWnd, hdc);
PostQuitMessage(0); // WM_QUIT 메시지를 보냄
return 0;
}
// switch 문에서 처리하지 않은 메시지를 처리
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
// HWND, long *
LRESULT CALLBACK Emb_Draw(HWND hWnd, LPVIDEOHDR lp)
{
int xPos;
int yPos;
int iCnt=0;
int iCnt2=54;
DWORD dwRead;
hFile = CreateFile("1117.bmp", GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
ReadFile(hFile, buf, sizeof(buf), &dwRead, NULL);
// 원본 영상에 bmp파일 고정 출력
for(yPos=240;0<yPos;--yPos)
{
for(xPos=0;320>xPos;++xPos)
{
// 예외 처리
if((60<yPos && 120>=yPos) && (80<=xPos && 160>xPos))
{
// BMP
lp->lpData[iCnt+2] = buf[(iCnt2)+2];
lp->lpData[iCnt+1] = buf[(iCnt2)+1];
lp->lpData[iCnt] = buf[iCnt2];
iCnt2 = iCnt2 +3;
}
iCnt = iCnt+3;
}
}
iCnt = 0;
iCnt2 = 54;
// 복제 영상에 bmp파일 고정 출력
for(yPos=240;0<yPos;--yPos)
{
for(xPos=0;320>xPos;++xPos)
{
// 예외 처리
if((60<yPos && 120>=yPos) && (80<=xPos && 160>xPos))
{
// BMP
SetPixel(hdc, xPos+420, yPos+10, RGB(buf[(iCnt2)+2], buf[(iCnt2)+1], buf[(iCnt2)]));
iCnt2 = iCnt2 +3;
}
else
{
// 영상
SetPixel(hdc, xPos+420, yPos+10, RGB(lp->lpData[iCnt+2], lp->lpData[iCnt+1], lp->lpData[iCnt]));
}
iCnt = iCnt +3;
}
}
return 0;
}
→ 실행 결과
→ 사실 원본 영상을 바꾸었으면 복제영상은 예외처리를 할 필요가 없다. 복제 영상은 원본 영상을 그대로 복제하기 때문에 BMP로 대체된 부분가지 그대로 복제하여 출력한다.
- 테스트 3
→ 출력되는 영상에 떠있는 BMP 출력 화면을 키보드의 방향키를 이용하여 이동시킨다.
#include<windows.h>
#include<vfw.h>
HBITMAP hBm;
BITMAPINFO BInfo;
HWND hWnd;
HWND hVfw;
HDC hdc;
HANDLE hFile;
static TCHAR buf[640*480*3];
unsigned int xStart = 0;
unsigned int xEnd = 80;
unsigned int yStart = 0;
unsigned int yEnd = 60;
// 라이브러리를 추가하는 것을 comment - 수동식
// project setting을 변화시키면 project를 통채로 복사해야 하지만
// #pragama comment를 사용하면 소스만 복사해도 동작한다.
#pragma comment (lib, "vfw32.lib")
LRESULT CALLBACK Emb_Draw(HWND hWnd, LPVIDEOHDR lp);
/* 고정 형식 */
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // 메세지 처리 함수
HINSTANCE g_hInst; // instance 전역 변수 선언
LPCTSTR lpszClass = TEXT("VFW32"); // 윈도 클래스 이름 정의
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
MSG Message; // MSG 구조체 사용
WNDCLASS WndClass; // WndClass 구조체 사용
g_hInst = hInstance; // 윈도우 클래스를 등록하는 프로그램의 번호이며 WinMain의 인수로 전달된 hInstance값을 그대로 대입
/* 윈도우 클래스 정의 */
WndClass.cbClsExtra = 0; // 예약 영역, 사용하지 않을 경우는 0
WndClass.cbWndExtra = 0;
WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // HBRUSH 타입으로 형변환
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); // 윈도우가 사용할 마우스 커서지정
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 윈도우가 사용할 아이콘 지정
WndClass.hInstance = hInstance;
WndClass.lpfnWndProc = WndProc; // 윈도우의 메시지 처리 함수를 지정
WndClass.lpszClassName = lpszClass; // 윈도우 클래스의 이름을 문자열로 정의 - 여기서는 First라는 문자열을 보내준다.
WndClass.lpszMenuName = NULL; // 프로그램이 사용할 메뉴를 지정
WndClass.style = CS_HREDRAW|CS_VREDRAW; // 윈도우가 어떤 형태를 가질 것인가-윈도우의크기가 변할 경우 윈도우를 다시 그린다.
/* 윈도우 클래스 등록 */
RegisterClass(&WndClass); // WndClass 구조체의 번지를 전달
// 메모리 상에 윈도우 생성
hWnd=CreateWindow(lpszClass, TEXT("Video for Window"), WS_OVERLAPPEDWINDOW, 10, 0, 760, 740, NULL, (HMENU)NULL, hInstance, NULL);
/* 인자의 의미 -> (윈도우 클래스 이름, 타이틀바에 나타날 문자열-윈도우 네임(클래스 이름과 같게 하려면 lpszClass),
윈도우의 형태 지정, 윈도우의 크기와 위치(픽셀단위)-x, y, nWidth, nHeight,
부모 윈도우가 있을 경우 부모윈도우의 핸들-hWndParent, 윈도우에서 사용할 메뉴의 핸들-hmenu,
프로그램의 핸들 지정-hinst(프로그램이 종료될 때 파괴되지 않은 윈도우를 자동으로 파괴),
여러개의 윈도우를 만들때 각 윈도우에 고유의 파라미터를 전달하는 특수 목적에 사용-lpvParam)
*/
/* 화면에 윈도우 표시 */
ShowWindow(hWnd, nCmdShow); // CreateWindow 함수가 리턴한 핸들을 이용하여 출력
/* 사용자로부터의 메시지 처리*/
while(GetMessage(&Message, NULL, 0, 0)) // 메시지 큐에서 메시지 읽어옴,
// WN_QUIT이면 False 리턴 후 while문을 빠져나간다.
{
TranslateMessage(&Message); // 키보드 입력 처리
// 만약 A키를 누르면 A문자가 입력되었다는 메시지를 만들어 낸다.
DispatchMessage(&Message); // 큐에서 꺼낸 메시지를 WndProc 함수의 iMAssage로 전달
}
return (int)Message.wParam; // 메시지 루프 종료 후 이 프로그램을 실행시킨 OS로 리턴
}
// 사용자와 시스템이 보내오는 메시지를 처리
// 운영체제가 호출하는 함수는 CALLBACK 표시, LRESULT = 4byte long
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
switch(iMessage) // 운영체제로부터 들어온 메시지에 대한 처리
{
/* 고정 형식 */
case WM_CREATE:
hdc = GetDC(hWnd);
// 320x240으로 캡쳐, 부모 윈도우(hWnd),
// 창이 만들어 진다. - 실제 생성되지는 않는다.
hVfw = capCreateCaptureWindow(TEXT("Video for Window"), WS_CHILD|WS_VISIBLE, 10, 10, 320, 240, hWnd, 0);
// usb를 통해 연결된 카메라 장치를 찾아 연결해 준다.
capDriverConnect(hVfw, 0);
// hVfw, 1ms - 화면에 보이는 속도(Rate)
capPreviewRate(hVfw, 1);
// Video 포멧을 확인하고 정보를 넣는다.
capGetVideoFormat(hVfw, &BInfo, sizeof(BITMAPINFO));
BInfo.bmiHeader.biWidth = 320;
BInfo.bmiHeader.biHeight = 240;
capSetVideoFormat(hVfw, &BInfo, sizeof(BITMAPINFO));
// 자동으로 라이브러리에서 Emb_Draw()를 호출해 준다.
capSetCallbackOnFrame(hVfw, Emb_Draw);
// 화면에 띄운다.(TRUE)
capPreview(hVfw, TRUE);
return 0;
// 키를 움직여 bmp 파일의 출력 위치를 조절한다.
case WM_KEYDOWN:
switch(wParam)
{
case VK_LEFT:
if(0 == xStart)
{
xStart = 0;
xEnd = 80;
}
else
{
xStart = xStart - 10;
xEnd = xEnd - 10;
}
break;
case VK_RIGHT:
if(240 == xStart)
{
xStart = 240;
xEnd = 320;
}
else
{
xStart = xStart + 10;
xEnd = xEnd + 10;
}
break;
case VK_UP:
if(yStart == 0)
{
yStart = 0;
yEnd = 60;
}
else
{
yStart = yStart - 10;
yEnd = yEnd - 10;
}
break;
case VK_DOWN:
if(yStart == 180)
{
yStart = 180;
yEnd = 240;
}
else
{
yStart = yStart + 10;
yEnd = yEnd + 10;
}
break;
}
return 0;
case WM_DESTROY: // 운영체제로부터 들어온 메시지에 대한 처리 - 여기서는 윈도우가 파괴되었음을 알린다.
ReleaseDC(hWnd, hdc);
PostQuitMessage(0); // WM_QUIT 메시지를 보냄
return 0;
}
// switch 문에서 처리하지 않은 메시지를 처리
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
// HWND, long *
LRESULT CALLBACK Emb_Draw(HWND hWnd, LPVIDEOHDR lp)
{
unsigned int xPos;
unsigned int yPos;
unsigned int iCnt=0;
unsigned int iCnt2=54;
DWORD dwRead;
hFile = CreateFile("1117.bmp", GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
ReadFile(hFile, buf, sizeof(buf), &dwRead, NULL);
// 원본 영상에 bmp파일 고정 출력
for(yPos=240;0<yPos;--yPos)
{
for(xPos=0;320>xPos;++xPos)
{
// 예외 처리
if(((yStart<yPos) && (yEnd>=yPos)) && ((xStart<=xPos) && (xEnd>xPos)))
{
// BMP
lp->lpData[iCnt+2] = buf[(iCnt2)+2];
lp->lpData[iCnt+1] = buf[(iCnt2)+1];
lp->lpData[iCnt] = buf[iCnt2];
iCnt2 = iCnt2 +3;
}
iCnt = iCnt+3;
}
}
iCnt = 0;
iCnt2 = 54; return 0;
}
#include<vfw.h>
HBITMAP hBm;
BITMAPINFO BInfo;
HWND hWnd;
HWND hVfw;
HDC hdc;
HANDLE hFile;
static TCHAR buf[640*480*3];
unsigned int xStart = 0;
unsigned int xEnd = 80;
unsigned int yStart = 0;
unsigned int yEnd = 60;
// 라이브러리를 추가하는 것을 comment - 수동식
// project setting을 변화시키면 project를 통채로 복사해야 하지만
// #pragama comment를 사용하면 소스만 복사해도 동작한다.
#pragma comment (lib, "vfw32.lib")
LRESULT CALLBACK Emb_Draw(HWND hWnd, LPVIDEOHDR lp);
/* 고정 형식 */
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // 메세지 처리 함수
HINSTANCE g_hInst; // instance 전역 변수 선언
LPCTSTR lpszClass = TEXT("VFW32"); // 윈도 클래스 이름 정의
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
MSG Message; // MSG 구조체 사용
WNDCLASS WndClass; // WndClass 구조체 사용
g_hInst = hInstance; // 윈도우 클래스를 등록하는 프로그램의 번호이며 WinMain의 인수로 전달된 hInstance값을 그대로 대입
/* 윈도우 클래스 정의 */
WndClass.cbClsExtra = 0; // 예약 영역, 사용하지 않을 경우는 0
WndClass.cbWndExtra = 0;
WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // HBRUSH 타입으로 형변환
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); // 윈도우가 사용할 마우스 커서지정
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 윈도우가 사용할 아이콘 지정
WndClass.hInstance = hInstance;
WndClass.lpfnWndProc = WndProc; // 윈도우의 메시지 처리 함수를 지정
WndClass.lpszClassName = lpszClass; // 윈도우 클래스의 이름을 문자열로 정의 - 여기서는 First라는 문자열을 보내준다.
WndClass.lpszMenuName = NULL; // 프로그램이 사용할 메뉴를 지정
WndClass.style = CS_HREDRAW|CS_VREDRAW; // 윈도우가 어떤 형태를 가질 것인가-윈도우의크기가 변할 경우 윈도우를 다시 그린다.
/* 윈도우 클래스 등록 */
RegisterClass(&WndClass); // WndClass 구조체의 번지를 전달
// 메모리 상에 윈도우 생성
hWnd=CreateWindow(lpszClass, TEXT("Video for Window"), WS_OVERLAPPEDWINDOW, 10, 0, 760, 740, NULL, (HMENU)NULL, hInstance, NULL);
/* 인자의 의미 -> (윈도우 클래스 이름, 타이틀바에 나타날 문자열-윈도우 네임(클래스 이름과 같게 하려면 lpszClass),
윈도우의 형태 지정, 윈도우의 크기와 위치(픽셀단위)-x, y, nWidth, nHeight,
부모 윈도우가 있을 경우 부모윈도우의 핸들-hWndParent, 윈도우에서 사용할 메뉴의 핸들-hmenu,
프로그램의 핸들 지정-hinst(프로그램이 종료될 때 파괴되지 않은 윈도우를 자동으로 파괴),
여러개의 윈도우를 만들때 각 윈도우에 고유의 파라미터를 전달하는 특수 목적에 사용-lpvParam)
*/
/* 화면에 윈도우 표시 */
ShowWindow(hWnd, nCmdShow); // CreateWindow 함수가 리턴한 핸들을 이용하여 출력
/* 사용자로부터의 메시지 처리*/
while(GetMessage(&Message, NULL, 0, 0)) // 메시지 큐에서 메시지 읽어옴,
// WN_QUIT이면 False 리턴 후 while문을 빠져나간다.
{
TranslateMessage(&Message); // 키보드 입력 처리
// 만약 A키를 누르면 A문자가 입력되었다는 메시지를 만들어 낸다.
DispatchMessage(&Message); // 큐에서 꺼낸 메시지를 WndProc 함수의 iMAssage로 전달
}
return (int)Message.wParam; // 메시지 루프 종료 후 이 프로그램을 실행시킨 OS로 리턴
}
// 사용자와 시스템이 보내오는 메시지를 처리
// 운영체제가 호출하는 함수는 CALLBACK 표시, LRESULT = 4byte long
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
switch(iMessage) // 운영체제로부터 들어온 메시지에 대한 처리
{
/* 고정 형식 */
case WM_CREATE:
hdc = GetDC(hWnd);
// 320x240으로 캡쳐, 부모 윈도우(hWnd),
// 창이 만들어 진다. - 실제 생성되지는 않는다.
hVfw = capCreateCaptureWindow(TEXT("Video for Window"), WS_CHILD|WS_VISIBLE, 10, 10, 320, 240, hWnd, 0);
// usb를 통해 연결된 카메라 장치를 찾아 연결해 준다.
capDriverConnect(hVfw, 0);
// hVfw, 1ms - 화면에 보이는 속도(Rate)
capPreviewRate(hVfw, 1);
// Video 포멧을 확인하고 정보를 넣는다.
capGetVideoFormat(hVfw, &BInfo, sizeof(BITMAPINFO));
BInfo.bmiHeader.biWidth = 320;
BInfo.bmiHeader.biHeight = 240;
capSetVideoFormat(hVfw, &BInfo, sizeof(BITMAPINFO));
// 자동으로 라이브러리에서 Emb_Draw()를 호출해 준다.
capSetCallbackOnFrame(hVfw, Emb_Draw);
// 화면에 띄운다.(TRUE)
capPreview(hVfw, TRUE);
return 0;
// 키를 움직여 bmp 파일의 출력 위치를 조절한다.
case WM_KEYDOWN:
switch(wParam)
{
case VK_LEFT:
if(0 == xStart)
{
xStart = 0;
xEnd = 80;
}
else
{
xStart = xStart - 10;
xEnd = xEnd - 10;
}
break;
case VK_RIGHT:
if(240 == xStart)
{
xStart = 240;
xEnd = 320;
}
else
{
xStart = xStart + 10;
xEnd = xEnd + 10;
}
break;
case VK_UP:
if(yStart == 0)
{
yStart = 0;
yEnd = 60;
}
else
{
yStart = yStart - 10;
yEnd = yEnd - 10;
}
break;
case VK_DOWN:
if(yStart == 180)
{
yStart = 180;
yEnd = 240;
}
else
{
yStart = yStart + 10;
yEnd = yEnd + 10;
}
break;
}
return 0;
case WM_DESTROY: // 운영체제로부터 들어온 메시지에 대한 처리 - 여기서는 윈도우가 파괴되었음을 알린다.
ReleaseDC(hWnd, hdc);
PostQuitMessage(0); // WM_QUIT 메시지를 보냄
return 0;
}
// switch 문에서 처리하지 않은 메시지를 처리
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
// HWND, long *
LRESULT CALLBACK Emb_Draw(HWND hWnd, LPVIDEOHDR lp)
{
unsigned int xPos;
unsigned int yPos;
unsigned int iCnt=0;
unsigned int iCnt2=54;
DWORD dwRead;
hFile = CreateFile("1117.bmp", GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
ReadFile(hFile, buf, sizeof(buf), &dwRead, NULL);
// 원본 영상에 bmp파일 고정 출력
for(yPos=240;0<yPos;--yPos)
{
for(xPos=0;320>xPos;++xPos)
{
// 예외 처리
if(((yStart<yPos) && (yEnd>=yPos)) && ((xStart<=xPos) && (xEnd>xPos)))
{
// BMP
lp->lpData[iCnt+2] = buf[(iCnt2)+2];
lp->lpData[iCnt+1] = buf[(iCnt2)+1];
lp->lpData[iCnt] = buf[iCnt2];
iCnt2 = iCnt2 +3;
}
iCnt = iCnt+3;
}
}
iCnt = 0;
iCnt2 = 54; return 0;
}
→ 실행 결과
→ 키보드의 방향키를 입력하므로써 출력된 이미지를 영상 범위 내에서 이동시킬 수 있다.
→ 출력 영상의 범위를 벗어나지 않도록 예외 처리를 실시한다.
- 영상에서 RGB값에 따른 분리
→ 우선 화면의 정중앙(x축 160, y축 120)을 지정해 해당 픽셀의 RGB값을 추출하여 윈도우 상단 바에 뿌린다.
→ 카메라를 칠판에 맞추고 RGB 값을 추출한다.(오차범위 ±5 정도)
→ 값을 추출하면 소스를 수정하여 해당 값을 가지는 픽셀은 RED로 출력한다.
→ RED로의 변환에 성공하면 해당 범위에 이미지가 출력되도록 소스를 수정한다.
→ 소스 작성
→ 따라서 해당 범위를 RED로만 출력되도록 소스를 변경하였다.
→ 다음으로 RED로 바뀐 부분에 이미지가 출력되도록 소스를 수정하였다.
→ 키보드의 방향키를 입력하므로써 출력된 이미지를 영상 범위 내에서 이동시킬 수 있다.
→ 출력 영상의 범위를 벗어나지 않도록 예외 처리를 실시한다.
- 영상에서 RGB값에 따른 분리
→ 우선 화면의 정중앙(x축 160, y축 120)을 지정해 해당 픽셀의 RGB값을 추출하여 윈도우 상단 바에 뿌린다.
→ 카메라를 칠판에 맞추고 RGB 값을 추출한다.(오차범위 ±5 정도)
→ 값을 추출하면 소스를 수정하여 해당 값을 가지는 픽셀은 RED로 출력한다.
→ RED로의 변환에 성공하면 해당 범위에 이미지가 출력되도록 소스를 수정한다.
→ 소스 작성
#include<windows.h>
#include<vfw.h>
HBITMAP hBm;
BITMAPINFO BInfo;
HWND hWndMain;
HWND hVfw;
HDC hdc;
HANDLE hFile;
static TCHAR buf[640*480*3];
unsigned int xStart = 0;
unsigned int xEnd = 80;
unsigned int yStart = 0;
unsigned int yEnd = 60;
unsigned char Red;
unsigned char Green;
unsigned char Blue;
// 라이브러리를 추가하는 것을 comment - 수동식
// project setting을 변화시키면 project를 통채로 복사해야 하지만
// #pragama comment를 사용하면 소스만 복사해도 동작한다.
#pragma comment (lib, "vfw32.lib")
LRESULT CALLBACK Emb_Draw(HWND hWnd, LPVIDEOHDR lp);
/* 고정 형식 */
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // 메세지 처리 함수
HINSTANCE g_hInst; // instance 전역 변수 선언
LPCTSTR lpszClass = TEXT("VFW32"); // 윈도 클래스 이름 정의
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
MSG Message; // MSG 구조체 사용
WNDCLASS WndClass; // WndClass 구조체 사용
g_hInst = hInstance; // 윈도우 클래스를 등록하는 프로그램의 번호이며 WinMain의 인수로 전달된 hInstance값을 그대로 대입
/* 윈도우 클래스 정의 */
WndClass.cbClsExtra = 0; // 예약 영역, 사용하지 않을 경우는 0
WndClass.cbWndExtra = 0;
WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // HBRUSH 타입으로 형변환
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); // 윈도우가 사용할 마우스 커서지정
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 윈도우가 사용할 아이콘 지정
WndClass.hInstance = hInstance;
WndClass.lpfnWndProc = WndProc; // 윈도우의 메시지 처리 함수를 지정
WndClass.lpszClassName = lpszClass; // 윈도우 클래스의 이름을 문자열로 정의 - 여기서는 First라는 문자열을 보내준다.
WndClass.lpszMenuName = NULL; // 프로그램이 사용할 메뉴를 지정
WndClass.style = CS_HREDRAW|CS_VREDRAW; // 윈도우가 어떤 형태를 가질 것인가-윈도우의크기가 변할 경우 윈도우를 다시 그린다.
/* 윈도우 클래스 등록 */
RegisterClass(&WndClass); // WndClass 구조체의 번지를 전달
// 메모리 상에 윈도우 생성
hWndMain=CreateWindow(lpszClass, TEXT("Video for Window"), WS_OVERLAPPEDWINDOW, 10, 0, 760, 740, NULL, (HMENU)NULL, hInstance, NULL);
/* 인자의 의미 -> (윈도우 클래스 이름, 타이틀바에 나타날 문자열-윈도우 네임(클래스 이름과 같게 하려면 lpszClass),
윈도우의 형태 지정, 윈도우의 크기와 위치(픽셀단위)-x, y, nWidth, nHeight,
부모 윈도우가 있을 경우 부모윈도우의 핸들-hWndParent, 윈도우에서 사용할 메뉴의 핸들-hmenu,
프로그램의 핸들 지정-hinst(프로그램이 종료될 때 파괴되지 않은 윈도우를 자동으로 파괴),
여러개의 윈도우를 만들때 각 윈도우에 고유의 파라미터를 전달하는 특수 목적에 사용-lpvParam)
*/
/* 화면에 윈도우 표시 */
ShowWindow(hWndMain, nCmdShow); // CreateWindow 함수가 리턴한 핸들을 이용하여 출력
/* 사용자로부터의 메시지 처리*/
while(GetMessage(&Message, NULL, 0, 0)) // 메시지 큐에서 메시지 읽어옴,
// WN_QUIT이면 False 리턴 후 while문을 빠져나간다.
{
TranslateMessage(&Message); // 키보드 입력 처리
// 만약 A키를 누르면 A문자가 입력되었다는 메시지를 만들어 낸다.
DispatchMessage(&Message); // 큐에서 꺼낸 메시지를 WndProc 함수의 iMAssage로 전달
}
return (int)Message.wParam; // 메시지 루프 종료 후 이 프로그램을 실행시킨 OS로 리턴
}
// 사용자와 시스템이 보내오는 메시지를 처리
// 운영체제가 호출하는 함수는 CALLBACK 표시, LRESULT = 4byte long
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
static int X;
static int Y;
switch(iMessage) // 운영체제로부터 들어온 메시지에 대한 처리
{
/* 고정 형식 */
case WM_CREATE:
hdc = GetDC(hWnd);
// 320x240으로 캡쳐, 부모 윈도우(hWnd),
// 창이 만들어 진다. - 실제 생성되지는 않는다.
hVfw = capCreateCaptureWindow(TEXT("Video for Window"), WS_CHILD|WS_VISIBLE, 10, 10, 320, 240, hWnd, 0);
// usb를 통해 연결된 카메라 장치를 찾아 연결해 준다.
capDriverConnect(hVfw, 0);
// hVfw, 1ms - 화면에 보이는 속도(Rate)
capPreviewRate(hVfw, 1);
// Video 포멧을 확인하고 정보를 넣는다.
capGetVideoFormat(hVfw, &BInfo, sizeof(BITMAPINFO));
BInfo.bmiHeader.biWidth = 320;
BInfo.bmiHeader.biHeight = 240;
capSetVideoFormat(hVfw, &BInfo, sizeof(BITMAPINFO));
// 자동으로 라이브러리에서 Emb_Draw()를 호출해 준다.
capSetCallbackOnFrame(hVfw, Emb_Draw);
// 화면에 띄운다.(TRUE)
capPreview(hVfw, TRUE);
return 0;
case WM_DESTROY: // 운영체제로부터 들어온 메시지에 대한 처리 - 여기서는 윈도우가 파괴되었음을 알린다.
ReleaseDC(hWnd, hdc);
PostQuitMessage(0); // WM_QUIT 메시지를 보냄
return 0;
}
// switch 문에서 처리하지 않은 메시지를 처리
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
// HWND, long *
LRESULT CALLBACK Emb_Draw(HWND hWnd, LPVIDEOHDR lp)
{
unsigned int xPos;
unsigned int yPos;
unsigned int iCnt=0;
unsigned int iCnt2=54;
DWORD dwRead;
hFile = CreateFile("11.bmp", GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
ReadFile(hFile, buf, sizeof(buf), &dwRead, NULL);
// 원본 영상에 bmp파일 고정 출력
for(yPos=240;0<yPos;--yPos)
{
for(xPos=0;320>xPos;++xPos)
{
/* 화면 중앙(x축160, y축120)에서 RGB값을 읽어들인다.
if(160==xPos && 120==yPos)
{
Blue = lp->lpData[iCnt+2];
Green = lp->lpData[iCnt+1];
Red = lp->lpData[iCnt];
}*/
Blue = lp->lpData[iCnt+2];
Green = lp->lpData[iCnt+1];
Red = lp->lpData[iCnt];
if((185>Red&&160<Red)&&(185>Green&&160<Green)&&(185>Blue&&160<Blue))
{
// BMP 파일을 해당 픽셀에 출력한다.
lp->lpData[iCnt+2] = buf[(iCnt2)+2];
lp->lpData[iCnt+1] = buf[(iCnt2)+1];
lp->lpData[iCnt] = buf[iCnt2];
}
iCnt2 = iCnt2+3;
iCnt = iCnt+3;
}
}
// BMP 파일을 해당 픽셀에 출력한다.
wsprintf(buf, TEXT("R: %d, G: %d, B: %d"), Red , Green, Blue);
SetWindowText(hWndMain,buf);
return 0;
}
→ 우선 화면의 중앙 픽셀에서 읽어들인 값을 확인한 결과 RED, GREEN, BLUE가 각각 165에서 175 사이의 값 에서 변화하는 것을 확인할 수 있었다.#include<vfw.h>
HBITMAP hBm;
BITMAPINFO BInfo;
HWND hWndMain;
HWND hVfw;
HDC hdc;
HANDLE hFile;
static TCHAR buf[640*480*3];
unsigned int xStart = 0;
unsigned int xEnd = 80;
unsigned int yStart = 0;
unsigned int yEnd = 60;
unsigned char Red;
unsigned char Green;
unsigned char Blue;
// 라이브러리를 추가하는 것을 comment - 수동식
// project setting을 변화시키면 project를 통채로 복사해야 하지만
// #pragama comment를 사용하면 소스만 복사해도 동작한다.
#pragma comment (lib, "vfw32.lib")
LRESULT CALLBACK Emb_Draw(HWND hWnd, LPVIDEOHDR lp);
/* 고정 형식 */
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); // 메세지 처리 함수
HINSTANCE g_hInst; // instance 전역 변수 선언
LPCTSTR lpszClass = TEXT("VFW32"); // 윈도 클래스 이름 정의
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
MSG Message; // MSG 구조체 사용
WNDCLASS WndClass; // WndClass 구조체 사용
g_hInst = hInstance; // 윈도우 클래스를 등록하는 프로그램의 번호이며 WinMain의 인수로 전달된 hInstance값을 그대로 대입
/* 윈도우 클래스 정의 */
WndClass.cbClsExtra = 0; // 예약 영역, 사용하지 않을 경우는 0
WndClass.cbWndExtra = 0;
WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); // HBRUSH 타입으로 형변환
WndClass.hCursor = LoadCursor(NULL, IDC_ARROW); // 윈도우가 사용할 마우스 커서지정
WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); // 윈도우가 사용할 아이콘 지정
WndClass.hInstance = hInstance;
WndClass.lpfnWndProc = WndProc; // 윈도우의 메시지 처리 함수를 지정
WndClass.lpszClassName = lpszClass; // 윈도우 클래스의 이름을 문자열로 정의 - 여기서는 First라는 문자열을 보내준다.
WndClass.lpszMenuName = NULL; // 프로그램이 사용할 메뉴를 지정
WndClass.style = CS_HREDRAW|CS_VREDRAW; // 윈도우가 어떤 형태를 가질 것인가-윈도우의크기가 변할 경우 윈도우를 다시 그린다.
/* 윈도우 클래스 등록 */
RegisterClass(&WndClass); // WndClass 구조체의 번지를 전달
// 메모리 상에 윈도우 생성
hWndMain=CreateWindow(lpszClass, TEXT("Video for Window"), WS_OVERLAPPEDWINDOW, 10, 0, 760, 740, NULL, (HMENU)NULL, hInstance, NULL);
/* 인자의 의미 -> (윈도우 클래스 이름, 타이틀바에 나타날 문자열-윈도우 네임(클래스 이름과 같게 하려면 lpszClass),
윈도우의 형태 지정, 윈도우의 크기와 위치(픽셀단위)-x, y, nWidth, nHeight,
부모 윈도우가 있을 경우 부모윈도우의 핸들-hWndParent, 윈도우에서 사용할 메뉴의 핸들-hmenu,
프로그램의 핸들 지정-hinst(프로그램이 종료될 때 파괴되지 않은 윈도우를 자동으로 파괴),
여러개의 윈도우를 만들때 각 윈도우에 고유의 파라미터를 전달하는 특수 목적에 사용-lpvParam)
*/
/* 화면에 윈도우 표시 */
ShowWindow(hWndMain, nCmdShow); // CreateWindow 함수가 리턴한 핸들을 이용하여 출력
/* 사용자로부터의 메시지 처리*/
while(GetMessage(&Message, NULL, 0, 0)) // 메시지 큐에서 메시지 읽어옴,
// WN_QUIT이면 False 리턴 후 while문을 빠져나간다.
{
TranslateMessage(&Message); // 키보드 입력 처리
// 만약 A키를 누르면 A문자가 입력되었다는 메시지를 만들어 낸다.
DispatchMessage(&Message); // 큐에서 꺼낸 메시지를 WndProc 함수의 iMAssage로 전달
}
return (int)Message.wParam; // 메시지 루프 종료 후 이 프로그램을 실행시킨 OS로 리턴
}
// 사용자와 시스템이 보내오는 메시지를 처리
// 운영체제가 호출하는 함수는 CALLBACK 표시, LRESULT = 4byte long
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
static int X;
static int Y;
switch(iMessage) // 운영체제로부터 들어온 메시지에 대한 처리
{
/* 고정 형식 */
case WM_CREATE:
hdc = GetDC(hWnd);
// 320x240으로 캡쳐, 부모 윈도우(hWnd),
// 창이 만들어 진다. - 실제 생성되지는 않는다.
hVfw = capCreateCaptureWindow(TEXT("Video for Window"), WS_CHILD|WS_VISIBLE, 10, 10, 320, 240, hWnd, 0);
// usb를 통해 연결된 카메라 장치를 찾아 연결해 준다.
capDriverConnect(hVfw, 0);
// hVfw, 1ms - 화면에 보이는 속도(Rate)
capPreviewRate(hVfw, 1);
// Video 포멧을 확인하고 정보를 넣는다.
capGetVideoFormat(hVfw, &BInfo, sizeof(BITMAPINFO));
BInfo.bmiHeader.biWidth = 320;
BInfo.bmiHeader.biHeight = 240;
capSetVideoFormat(hVfw, &BInfo, sizeof(BITMAPINFO));
// 자동으로 라이브러리에서 Emb_Draw()를 호출해 준다.
capSetCallbackOnFrame(hVfw, Emb_Draw);
// 화면에 띄운다.(TRUE)
capPreview(hVfw, TRUE);
return 0;
case WM_DESTROY: // 운영체제로부터 들어온 메시지에 대한 처리 - 여기서는 윈도우가 파괴되었음을 알린다.
ReleaseDC(hWnd, hdc);
PostQuitMessage(0); // WM_QUIT 메시지를 보냄
return 0;
}
// switch 문에서 처리하지 않은 메시지를 처리
return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
// HWND, long *
LRESULT CALLBACK Emb_Draw(HWND hWnd, LPVIDEOHDR lp)
{
unsigned int xPos;
unsigned int yPos;
unsigned int iCnt=0;
unsigned int iCnt2=54;
DWORD dwRead;
hFile = CreateFile("11.bmp", GENERIC_READ, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
ReadFile(hFile, buf, sizeof(buf), &dwRead, NULL);
// 원본 영상에 bmp파일 고정 출력
for(yPos=240;0<yPos;--yPos)
{
for(xPos=0;320>xPos;++xPos)
{
/* 화면 중앙(x축160, y축120)에서 RGB값을 읽어들인다.
if(160==xPos && 120==yPos)
{
Blue = lp->lpData[iCnt+2];
Green = lp->lpData[iCnt+1];
Red = lp->lpData[iCnt];
}*/
Blue = lp->lpData[iCnt+2];
Green = lp->lpData[iCnt+1];
Red = lp->lpData[iCnt];
if((185>Red&&160<Red)&&(185>Green&&160<Green)&&(185>Blue&&160<Blue))
{
// BMP 파일을 해당 픽셀에 출력한다.
lp->lpData[iCnt+2] = buf[(iCnt2)+2];
lp->lpData[iCnt+1] = buf[(iCnt2)+1];
lp->lpData[iCnt] = buf[iCnt2];
}
iCnt2 = iCnt2+3;
iCnt = iCnt+3;
}
}
// BMP 파일을 해당 픽셀에 출력한다.
wsprintf(buf, TEXT("R: %d, G: %d, B: %d"), Red , Green, Blue);
SetWindowText(hWndMain,buf);
return 0;
}
→ 따라서 해당 범위를 RED로만 출력되도록 소스를 변경하였다.
→ 다음으로 RED로 바뀐 부분에 이미지가 출력되도록 소스를 수정하였다.
→ 문제점으로 해당 칠판에 대한 RGB 값의 변동이 심하고 생각한 만큼의 정확도로 칠판에 표시되지가 않았다.
→ RGB값의 범위를 조절하여 테스트를 반복하였으나 원하는 정도의 결과가 나오지 않았다.
→ RGB값의 범위를 조절하여 테스트를 반복하였으나 원하는 정도의 결과가 나오지 않았다.
'내장형 하드웨어 > WINAPI' 카테고리의 다른 글
영상 처리 - 복제 화면 띄우기, RGB값 변화에 따른 화면 출력 (1) | 2011.11.23 |
---|---|
WINAPI - sokoban (0) | 2011.10.10 |
WINAPI - 모델리스형 대화상자 (0) | 2011.10.06 |
WINAPI - DlgCheck (0) | 2011.09.29 |
WINAPI - 컨트롤과의 통신 (0) | 2011.09.28 |