본문 바로가기
코스웨어/11년 내장형하드웨어

[내장형]김수만 111116

by 알 수 없는 사용자 2011. 11. 17.
728x90
반응형

● VS6.0 링크옵션에서 VFW 라이브러리 추가하는 법

image

프로젝트를 생성한 후 메뉴Project – Settings..을 선택하여 프로젝트 설정을 바꾼다.


image

빨간 사격형의 Win32 Debug는 개발단계에서 디버그를 위한 것이고,
                          Release는 제품을 판매할 때 불필요한 디버그정보를 제거하게 최적화한다는 것이다.



image

링크탭을 클릭한 후 Object/library modules에, lib파일(라이브러리)들을 추가한 곳에 vfw32.lib를 추가하자.
그럼 아래의 Project Options도 내용이 추가된다.
Project Options는 컴파일러와 링커를 구동할 때 들어가는 실제 옵션으로 상단의 체크박스와 에디트의 내용이 조합된 결과다.
                      세세한 설정을 할 때 여기를 수정하면 되나 복잡하니 모르면 건들지 말자!!

이렇게 설정을 한 후 소스코드에, #include <vfw.h>을 추가해 라이브러리 함수를 사용할 수 있게 하자.

이 방식의 장점은 쉽게 옵션을 추가하고 컴파일할 수 있다는 것이다.




● 소스코드에서 VFW라이브러리를 추가하는 법

   1: #include <vfw.h>
   2: #pragma comment(lib, "vfw32.lib")    // 수동식 라이브러리 추가

전처리문인 #pragma 다음에 오는 directive name에 comment를 사용해 출력되어지는 파일에 주석을 기록할 것을 지시하고,
comment type에 lib를 사용해 기록목표는 .OBJ(오브젝트)파일로 한다. “ “ 큰 따옴표 안에 들어가는 문자열이 라이브러리명이고,
2행은 vfw32.lib파일을 링크하라는 뜻이다.

이 방식의 장점은 소스코드에 컴파일 옵션이 포함된 격이므로 컴파일시 VS6.0 워크스페이스파일들을 필요로 하지 않는다.
(컴파일옵션을 고친 후 소스코드만 공개하면 어떻게 컴파일해야 하는지 모르므로 문제가 될 수 있다.)




● 전체소스코드...VFW라이브러리를 사용한 CAM영상 캡쳐 (수동식 라이브러리 추가)

   1: // 2011년 11월 16일 작성 
   2: #include <windows.h>        // 모든 API함수들의 원형과 사용하는 상수들이 정의되어 있음.
   3: #include <vfw.h>
   4:  
   5: #pragma comment(lib, "vfw32.lib")    // 수동식 라이브러리 추가
   6:  
   7: HBITMAP HBm;
   8: BITMAPINFO BInfo;
   9: HWND hVfw;
  10:  
  11: LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);    //메시지처리함수
  12: HINSTANCE g_hlnst;    //핸들 인스턴스
  13: LPCTSTR lpszClass = TEXT("ImageProcess");        //윈도우 제목으로 사용되는 const char * (문자열)
  14:  
  15: /***************************************************************************************************************************
  16: WinMain은 엔트리 포인트(시작함수)
  17: APIENTRY는 윈도우즈 표준호출규약 _stdcall(없어도 무방함)
  18: 
  19: WinMain의 인자들...
  20: ① hInstance: 프로그램의 인스턴스 핸들
  21: ② hPrevInstance: 바로 앞에 실행된 현재 프로그램의 인스턴스 핸들로 16비트와 호환성위한 것이니 무시하자. Win32는 NULL이다.
  22: ③ lpszCmdParam: 명령행으로 입력된 프로그램의 인수 (콘솔app에서 argv), 보통 실행직후에 열 파일의 경로가 전달됨.
  23: ④ nCmdShow: 프로그램이 실행될 형태이며 최소화, 보통 모양 등이 전달된다.
  24: ***************************************************************************************************************************/
  25: int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
  26: {
  27:     HWND hWnd;
  28:     MSG Message;
  29:     WNDCLASS WndClass;
  30:     g_hlnst = hInstance;
  31:  
  32:     WndClass.cbClsExtra = 0;
  33:     WndClass.cbWndExtra = 0;
  34:     WndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
  35:     WndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
  36:     WndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  37:     WndClass.hInstance = hInstance;
  38:     WndClass.lpfnWndProc = WndProc;
  39:     WndClass.lpszClassName = lpszClass;
  40:     WndClass.lpszMenuName = NULL;
  41:     WndClass.style = CS_HREDRAW | CS_VREDRAW;
  42:     RegisterClass(&WndClass);
  43:  
  44:     hWnd = CreateWindow(lpszClass, TEXT("Video for Windows"), WS_OVERLAPPEDWINDOW,
  45:         CW_USEDEFAULT, CW_USEDEFAULT, 500, 300,
  46:         NULL, (HMENU)NULL, hInstance, NULL);
  47:     ShowWindow(hWnd, nCmdShow);
  48:  
  49:     while(GetMessage(&Message, NULL, 0, 0)) {
  50:         TranslateMessage(&Message);
  51:         DispatchMessage(&Message);
  52:     }
  53:  
  54:     return (int)Message.wParam;
  55: }
  56:  
  57: LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
  58: {
  59:  
  60:     switch(iMessage) {
  61:     case WM_CREATE:
  62:         // 윈도우 만들기 
  63:         hVfw = capCreateCaptureWindow(  TEXT("CCC"),            // 클래스명
  64:                                         WS_CHILD | WS_VISIBLE,    // 자식, 바로표시
  65:                                         0,                        // x 위치 
  66:                                         0,                        // y 위치
  67:                                         320,                    // 가로폭
  68:                                         240,                    // 세로폭
  69:                                         hWnd,                    // 부모윈도우 핸들
  70:                                         0);                        // 윈도우 식별자
  71:         // 드라이버 연결...USB CAM 찾아 연결
  72:         capDriverConnect(hVfw,    // 윈도우 핸들
  73:                             0);    // 윈도우 식별자
  74:         // 화면에 보이는 속도
  75:         capPreviewRate(hVfw,    // 윈도우 핸들
  76:                         1);        // ms시간
  77:         // 비디오 형식을 비트맵 구조체에 넣어라.
  78:         capGetVideoFormat(  hVfw,                    // 캡쳐 윈도우
  79:                             &BInfo,                    // BITMAPINFO 구조체
  80:                             sizeof(BITMAPINFO));    // BITMAPINFO구조체 크기
  81:         // 가로세로 크기만 바꿈.
  82:         BInfo.bmiHeader.biWidth = 320;        // 가로
  83:         BInfo.bmiHeader.biHeight = 240;        // 세로
  84:         // 비디오 형식 적용
  85:         capSetVideoFormat(  hVfw,                    // 캡쳐 윈도우
  86:                             &BInfo,                    // BITMAPINFO 구조체
  87:                             sizeof(BITMAPINFO));    // BITMAPINFO구조체 크기
  88:         // 화면에 표시
  89:         capPreview(hVfw,    // 윈도우 핸들
  90:                     TRUE);        // ms시간
  91:  
  92:         return 0;
  93:  
  94:     case WM_DESTROY:
  95:         PostQuitMessage(0);
  96:         return 0;
  97:     
  98:     }
  99:  
 100:     return(DefWindowProc(hWnd, iMessage, wParam, lParam));
 101: }


▶ 소스코드설명

  62:         // 윈도우 만들기 
  63:         hVfw = capCreateCaptureWindow(  TEXT("CCC"),            // 클래스명
  64:                                         WS_CHILD | WS_VISIBLE,    // 자식, 바로표시
  65:                                         0,                        // x 위치 
  66:                                         0,                        // y 위치
  67:                                         320,                    // 가로폭
  68:                                         240,                    // 세로폭
  69:                                         hWnd,                    // 부모윈도우 핸들
  70:                                         0);                        // 윈도우 식별자

capCreateCaptureWindow( )는 캡쳐 윈도우를 생성하는 함수로,
CreateWindow( )와 비슷하게 첫 번째 인자로 클래스명을 적어준다. 타이틀바는 필요없으니 생략하고,
두 번째 인자로 윈도우의 스타일을 지정한다. 이어 (x, y)좌표와 윈도우의 크기, 부모윈도우 핸들과 ID를 넣으면 캡쳐 윈도우가 생성된다.
그 생성된 윈도우의 핸들을 반환한다.

아래의 링크를 클릭하면 man page비슷한 MSDN에서 해당함수에 대한 설명을 볼 수 있다.
참조URL: http://msdn.microsoft.com/en-us/library/windows/desktop/dd756879(v=vs.85).aspx




  71:         // 드라이버 연결...USB CAM 찾아 연결
  72:         capDriverConnect(hVfw,    // 윈도우 핸들
  73:                             0);    // 윈도우 식별자

capDriverConnect( )는 USB CAM 드라이버와 응용프로그램내의 0번 ID와 hVfw핸들을 가진 윈도우를 연결하는 매크로이다.
이 매크로를 사용하거나 WM_CAP_DRIVER_CONNECT 메시지를 보내면 된다고 나와있고,
반환형은 BOOL로 성공하면 TRUE를 반환하고 실패시 FALSE의 값을 반환한다. (BOOL은 int형이다. C++이 아니라 bool이 없다.)

참조URL: http://msdn.microsoft.com/en-us/library/windows/desktop/dd756885(v=vs.85).aspx




  74:         // 화면에 보이는 속도
  75:         capPreviewRate(hVfw,    // 윈도우 핸들
  76:                         1);        // ms시간

capPreviewRate( )는 CAM에서 보내오는 영상의 갱신속도를 지정하는 매크로이다.
이 매크로를 사용하거나 명시적으로 WM_CAP_SET_PREVIEWRATE 메시지를 호출하면 된다고 나와있고,
반환형은 BOOL로 성공하면 TRUE를 반환하고 실패시 FALSE의 값을 반환한다.

1ms는 1/1000초로 카메라에서는 굉장히 빠른 캡쳐 속도이다.
저질 웹캠이 보통 30프레임정도 찍고, 인간의 눈도 30프레임이상은 구분할 수 없으니 33ms와 1ms는 차이가 없다고 할 수 있다.
1000을 넣으면 1초로 매우 느리게 화면이 갱신되는 것을 확인할 수 있다.

참조URL: http://msdn.microsoft.com/en-us/library/windows/desktop/dd756925(v=vs.85).aspx





  77:         // 비디오 형식을 비트맵 구조체에 넣어라.
  78:         capGetVideoFormat(  hVfw,                    // 캡쳐 윈도우
  79:                             &BInfo,                    // BITMAPINFO 구조체
  80:                             sizeof(BITMAPINFO));    // BITMAPINFO구조체 크기

capGetVideoFormat( )는 해당 캡쳐 윈도우(hVfw)에서 비디오 형식을 얻어와 BITMAPINFO구조체에 저장하는 매크로다.
이 매크로를 사용하거나 명시적으로 WM_CAP_GET_VIDEOFORMAT 메시지를 호출할 수 있다.
반환형은 BOOL로 성공하면 TRUE를 반환하고 실패시 FALSE의 값을 반환한다.

참조URL: http://msdn.microsoft.com/en-us/library/windows/desktop/dd756913(v=vs.85).aspx





  81:         // 가로세로 크기만 바꿈.
  82:         BInfo.bmiHeader.biWidth = 320;        // 가로
  83:         BInfo.bmiHeader.biHeight = 240;        // 세로

BInfo구조체에 비디오형식에 대한 정보가 저장되어 있고, 그 중에서 가로와 세로폭만 수정한다.
(시리얼포트설정과 비슷하게 설정을 Get하고 수정한 뒤 설정을 Set한다. )




  84:         // 비디오 형식 적용
  85:         capSetVideoFormat(  hVfw,                    // 캡쳐 윈도우
  86:                             &BInfo,                    // BITMAPINFO 구조체
  87:                             sizeof(BITMAPINFO));    // BITMAPINFO구조체 크기

78행에 사용한 capGetVideoFormat( )와 쌍을 이루는 capSetVideoFormat( )로 비디오형식에 대한 정보를 바꾼다.
capGetVideoFormat( )과 사용법이 동일하므로 설명은 생략~

참조URL: http://msdn.microsoft.com/en-us/library/windows/desktop/dd756938(v=vs.85).aspx





  88:         // 화면에 표시
  89:         capPreview(hVfw,    // 윈도우 핸들
  90:                     TRUE);        // Preview 플래그

capPreview( ) 매크로의 두 번째 인자를 TRUE로 하여 사용하지 않으면 캡쳐윈도우는 동작을 하지 않는다. 디폴트가 FALSE인듯..
아래의 설명은 MSDN에서 퍼옴~

The capPreview macro enables or disables preview mode. In preview mode, frames are transferred from the capture hardware to system memory and then displayed in the capture window using GDI functions. You can use this macro or explicitly call the WM_CAP_SET_PREVIEW message.


capPreview 매크로 활성화 또는 미리보기 모드를 해제합니다. 미리보기 모드에서 프레임 캡처 하드웨어에서 시스템 메모리로 전송하고 다음 GDI 함수를 사용하여 캡처 윈도우에 표시됩니다. 이 매크로를 사용하거나 명시적으로 WM_CAP_SET_PREVIEW 메시지를 호출할 수 있습니다.

GDI함수를 사용하여 캡처 윈도우에 표시하는 기능을 하고,
캡처 속도는 상기의 capPreviewRate( ) 매크로로 조절한다. 실행 중에 조절할 수 있나?

수업시간에 배운 함수와 매크로외에도 많이 있다. (함수리스트는 찾아보겠음)
참조URL: http://msdn.microsoft.com/en-us/library/windows/desktop/dd743598(v=vs.85).aspx




● 실행결과

image

728x90