20140930 (C++ 함수 오버로딩, 평활화 최종)

149일차












--------------

C++

--------------






------- 오버로딩

함수의 반환값, 이름은 같은데 인자만 다른 것



예)

함수                        타입

int test(int );             int (*)(int);

int test(int, int);         int (*)(int, int);


-> C에서는 불가능 하지만 C++에서는 가능하다

     이것이 함수 오버로딩



함수                        타입

int test(int );             int (*)(int);            -> O

int test(int, int);         int (*)(int, int);      -> O

char test(int );          char (*)(int);         -> X

int test(char);           int (*)(char);         -> O


-> 3번째 같은 경우 반환값이 다르기 때문에 오버로딩이 불가능하다.

    함수 타입, 이름이 같으면 오버로딩이 된다.












------- 이전에 C와 asm을 함께 섞어 사용하였는데,

C++도 섞어 사용할 수 있다. 먼저 .asm 파일을 확인해야한다.



소스)

#include <iostream>


void swap(int *, int *);

void swap(float *, float *);

void test();


int main()

{

int iA = 100;

int iB = 200;

float fA = 100.1;

float fB = 200.2;


std::cout << "iA : " << iA << std::endl;

std::cout << "iB : " << iB << std::endl;


swap(&iA, &iB);


std::cout << "iA : " << iA << std::endl;

std::cout << "iB : " << iB << std::endl << std::endl;


std::cout << "fA : " << fA << std::endl;

std::cout << "fB : " << fB << std::endl;


swap(&fA, &fB);


std::cout << "fA : " << fA << std::endl;

std::cout << "fB : " << fB << std::endl;


test();


return 0;

}


void swap(int * a, int * b)

{

int temp;


temp = *a;

*a = *b;

*b = temp;

}


void swap(float * a, float * b)

{

float temp;


temp = *a;

*a = *b;

*b = temp;

}







위와 같이 컴파일 하고, asm 파일을 확인하면


- main.cpp

...

17 swap(&iA, &iB);

...

25 swap(&fA, &fB);

...

30 test();

...


- main.asm

; Line 17

lea edx, DWORD PTR _iB$[ebp]

push edx

lea eax, DWORD PTR _iA$[ebp]

push eax

call ?swap@@YAXPAH0@Z ; swap

add esp, 8

...

; Line 25

...

call ?swap@@YAXPAM0@Z ; swap

...

; Line 30

call ?test@@YAXXZ ; test


swap 함수와 test 함수의 이름이 이상하게 선언되어 있다.

보안코드와 디버깅 코드가 더 추가되어서 그렇다고 한다.


17 line의 swap과 25 line의 swap의 이름이 서로 다르다.

C++에서는 함수 오버로딩으로 같은 이름을 사용하지만,

결국 asm 에서 다른 이름을 사용한다.





------- C로 마지막에 호출한 test() 함수를 구현하는데,

main.cpp에서 구현한 swap() 함수를 사용하여 구현한다.


소스)

#include <stdio.h>


void test()

{

int iA = 50;

int iB = 25;


swap(&iA, &iB);


printf("iA = %d, iB = %d\n", iA, iB);

}




편의를 위해 ms cl을 사용한다.

cl /Fa test.c 이렇게 컴파일 후 asm파일을 확인




- main.cpp

...

PUBLIC _test

...

8 swap(&iA, &iB);

...


- main.asm

; Line 8

lea eax, DWORD PTR _iB$[ebp]

push eax

lea ecx, DWORD PTR _iA$[ebp]

push ecx

call _swap

add esp, 8



여기 test.c에서 test 함수 이름과 사용할 swap 함수의 이름이 main.cpp에서 함수의 이름이 다르다.

    C                    C++

_test        !=     ?test@@YAXXZ

_swap     !=     ?swap@@YAXPAH0@Z


이것을 통일 시켜줘야 서로 통용이 가능하다.

그렇게 하기 위해서 main.cpp 소스를 다음과 같이 수정한다.


소스)

- main.cpp

....

extern "C" void swap(int *, int *);

void swap(float *, float *);

extern "C" void test();

....



함수 선언부에서 외부 함수를 사용한다는 기호?를 선언해 주는데,

"C"를 붙였다. "C"는 C와 통용 가능한 함수 이름으로 선언해 준다는 뜻인 것 같다.


그리고 컴파일 하고 (cl /Fa main.cpp), .asm 파일을 확인해 본 결과...


- main.cpp

...

17 swap(&iA, &iB);

...

30 test();

...


- main.asm

...

; Line 17

lea edx, DWORD PTR _iB$[ebp]

push edx

lea eax, DWORD PTR _iA$[ebp]

push eax

call _swap

add esp, 8

...

; Line 30

call _test



이렇게 C와 통용이 가능한 이름으로 바뀌었다.



둘이 함께 .obj 파일을 합쳐 컴파일(cl main.obj test.obj) 후, 실행 결과.




이렇게 함께 사용하여 컴파일이 가능하다.












-----------------

평활화

-----------------


소스)

aaa.txt


관련 자료)

히스토그램을 이용한 화소 점 처리.pptx



- 다음과 같이 3단계를 통해 평활화가 이루어진다.




단계별 소스)


- 1단계

명암 값의 빈도 수를 계산해 입력 영상의 히스토그램 생성


ucpPixel = BMbuf + stpBFH->bfOffBits;

for(uiYcount = uiY; 0 < uiYcount; --uiYcount)

{

for(uiXcount = uiX; 0 < uiXcount; --uiXcount)

{

++uiRcnt[*(ucpPixel+2)];

++uiGcnt[*(ucpPixel+1)];

++uiBcnt[*ucpPixel];


SetPixel(MemDC, uiXcount-1, uiYcount-1,

RGB(*(ucpPixel+2), *(ucpPixel+1), *ucpPixel));

ucpPixel = ucpPixel + 3;

}

ucpPixel = ucpPixel + uiPad;

}



- 2단계

각 명암 값 x에서 0 ~ x까지의 누적 빈도 수(누적합)를 계산


uiXcount = 0;

uiRhisto[uiXcount] = uiRcnt[uiXcount];

uiGhisto[uiXcount] = uiGcnt[uiXcount];

uiBhisto[uiXcount] = uiBcnt[uiXcount];

for(uiXcount = 1; 256 > uiXcount; ++uiXcount)

{

uiRhisto[uiXcount] = (uiRhisto[uiXcount-1] + uiRcnt[uiXcount]);

uiGhisto[uiXcount] = (uiGhisto[uiXcount-1] + uiGcnt[uiXcount]);

uiBhisto[uiXcount] = (uiBhisto[uiXcount-1] + uiBcnt[uiXcount]);

}



- 3단계

2단계에서 구한 누적 빈도 수를 정규화(정규화 누적합, 공식 = 누적값 * 최대밝기 / 총픽셀수)


for(uiXcount = 0; 256 > uiXcount; ++uiXcount)

{

uiRhisto[uiXcount] = (uiRhisto[uiXcount] * 255) / (uiX*uiY);

uiGhisto[uiXcount] = (uiGhisto[uiXcount] * 255) / (uiX*uiY);

uiBhisto[uiXcount] = (uiBhisto[uiXcount] * 255) / (uiX*uiY);

}





결과)












설정

트랙백

댓글

20140929 (C++ cout, cin, winapi로 영상 평활화 처리)

148일차














--------------

C++

--------------



우선 .cpp 소스 파일을 생성합니다.


1.



2.



3.



4.











화면에 글자를 출력해 보는 기본 소스부터 시작합니다.


소스)


#include <iostream>  // stdio.h -> iostream으로 바뀜


int main()

{

    std::cout << "Hello\n";  // printf -> std::cout 으로 바뀜, std::cout 은 객체입니다.


    return 0;

}








--- C++.....


- C++은 C를 포함하기 때문에 C 문법, 함수를 다 사용할 수 있습니다.

- 소스 중간에 변수를 선언하여 사용할 수 있다. (단, 중간에 선언한 변수는 그 위에서 사용 불가)

- std::cout은 객체입니다. (console out)



소스)


#include <iostream>


int main()

{

    std::cout << "hello\n";


    printf("C 문법\n");  // C 함수 사용 가능


    int iA = 100;  // 소스 중간에 변수 선언 가능


    std::cout << iA;  // %d등 서식 문자를 사용하지 않고 숫자를 간단히 출력

    std::cout << "\n";


    std::cout << iA << "\n";  // 뒤에 엔터 서식 문자를 넣을 수도 있다.

    std::cout << iA << std::endl;  // "\n" 대신 std::endl 이라는 것도 있다. 개인의 취향


    return 0;

}







linux에서도 실습해 보았습니다.






(g++이 설치되어 있지 않을 시 "sudo apt-get install g++" 치면 자동으로 설치, 설정이 된다.)






- MS Visual Studio는 확장자로 .c는 C,  .cpp는 C++로 사용하는데,

Linux, Unix에서는 .cpp, .c++, .cc등 으로 사용한다고 합니다.


- MS Visual Studio는 확장자로( .c,  .cpp ) 소스 파일을 구분하여 컴파일 하는 반면,

Linux, Unix 에서는 확장자로 소스 파일을 구분하지 않고, C는 gcc로,  C++은 g++로 컴파일 합니다.









--- C++...


- "std::cin >> 변수"   입력을 받아 변수에 넣습니다. std::cout << 이랑 삿갓이 반대 모양입니다.



소스)

#include <iostream>


int main()

{

    int dan;

    int su;


    std::cout << "단을 입력하세요 : ";

    std::cin >> dan;


    for(; 10 > dan; ++dan)

    {

        for(su = 1; 10 > su; ++su)

        {

            std::cout << dan << " * " << su << " = " << dan * su << std::endl;  // 입력 받은 단부터 구구단 출력

        }

        std::cout << std::endl;

    }


    char buf[128];

    int number;


    std::cout << "문자열, 숫자 입력 : ";

    std::cin >> buf >> number;  // 입력을 연속해서 받을 수 있다.


    std::cout << "문자열 : " << buf << std::endl;

    std::cout << "숫자 : " << number << std::endl;

    std::cout << "문자열 + 1: " << buf + 1 << std::endl;  // 문자열 변수에 +1을 하면 주소가 +1 되어 출력된다.


    return 0;

}















---------------

평활화

---------------



- 어둡게 촬영된 영상의 히스토그램을 조절하여 명암 분포가 빈약한 영상을 균일하게 만드는 기법


- 히스토그램 평활화 3단계

1. 명암값의 빈도수 수치 계산

(uiRcnt[], uiGcnt[], uiBcnt[] 이 배열들이 명암값 빈수도 계산된 값이다.)


2. 각 명암값 누적수 계산



3. 총 화소와 최대 명도값으로 계산

n[i] = sum[i] * ( 1 / (총화소) ) * (최대 밝기)





추가된 소스)


...

//전역 변수 선언

unsigned int uiRhisto[256];  // 평활화로 사용할 변수

unsigned int uiGhisto[256];  // 평활화로 사용할 변수

unsigned int uiBhisto[256];  // 평활화로 사용할 변수

...




...

//히스토그램 세로축 수치 값을 조정하는 소스 밑에 추가


for(uiXcount = 0; 256 > uiXcount; ++uiXcount)

{

if(uiXcount != 0)

{

uiRhisto[uiXcount] = ((uiRhisto[uiXcount-1] + uiRcnt[uiXcount]) * 255) / (uiX*uiY);

}

else

{

uiRhisto[uiXcount] = (uiRcnt[uiXcount] * 255) / (uiX*uiY);

}

}









설정

트랙백

댓글

Java 설치 및 기본 설정

프로그래밍 언어/Java 2014. 9. 27. 07:57

1. 다음 사이트에 접속

http://www.oracle.com/us/downloads/index.html 



2. 아래 그림따라 클릭




3. 아래 그림따라 클릭




4.사용할 플랫폼에 맞는 버전 설치







5. 선택사항


source는 필요없다. (뭔지는 아직 모르겠음)

설치가 끝나면 "C:\Program Files\Java" 아마 이 경로에 아래와 같이 있을 것이다.







6. "C:\Program Files\Java\jdk1.8.0_20\bin" 이 경로를 PATH 환경변수에 추가해 주어야 한다.


Windows 7 경우 "윈도우"키 + "Pause break" 키  -> 왼쪽란에 "고급 시스템 설정" -> "환경 변수"

-> path 변수에 경로 추가.







7. 실행 화면



type 명령어는 텍스트 파일 내용을 읽는 명령어이다.

javac 명령어는 .java 소스 파일을 컴파일 명령어인데, 주의해야할 것은 class 이름이랑 파일 이름이랑 같아야 한다.

'프로그래밍 언어 > Java' 카테고리의 다른 글

Java SE, EE, ME 차이점  (0) 2014.09.27

설정

트랙백

댓글

Java SE, EE, ME 차이점

프로그래밍 언어/Java 2014. 9. 27. 07:52

JAVA SE (Java Platform Standard Edition)

데스크톱, 서버, 임베디드시스템을 위한 표준 자바 플랫폼. 자바 가상머신 규격 및 API집합을 포함

JAVA EE,ME는 목적에 따라 SE를 기반으로 기존의 일부를 택하거나 API를 추가하여 구성된다.

SE는 가장 일반적으로 사용된다. JDBC나 기본적인 기능이 모두 포함되어 있기 때문에 Android개발할때 주로 SE를 사용한다.

예전에는 J2SE로 불리어쓰나 버전 6.0 이후에는 Java SE로 변경되었다. 이전에는 썬 마이크로 시스템즈에서 관리하였으나 J2EE 1.4 이후는 JCP(Java Community Process)주도하에 개발되고 있다.


JDBC, Javadoc 도구, RMI, JNDI등을 포함.



 

JAVA EE (Java Platform EnterPrise Edition)

자바를 이용한 서버측 개발을 위한 플랫폼. 기존 SE에 웹 애플리케이션 서버에서 동작하는 분산 멀티미디어를 제공하는 자바의 기능을 추가한 서버를 위한 플랫폼.

JAVA SE에 서버측을 위한 기능을 부가하였기 때문에 SE기능을 모두 포함한다.

이전에는 J2EE로 불리었으나 버전 5.0 이후로는 Java EE로 개칭되었다.

기업용 분산 API를 개발할 때 사용하므로, 서버측의 서블릿(servlets), JTA, JMS, XML 등을 다룰 수 있는 API 제공.



 

JAVA ME (Java Platform Micro Edition)

이름에서 알 수 있듯이 임베디드를 위한 자바 플랫폼이다.

'프로그래밍 언어 > Java' 카테고리의 다른 글

Java 설치 및 기본 설정  (0) 2014.09.27

설정

트랙백

댓글

20140925

146일차



#include <windows.h>


#define BITMAP_MAXSIZE (1024*768*3+10)

#define XOFFSET 280

#define X_WIDTH_SIZE 150


LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

HINSTANCE g_hInst;

LPCTSTR lpszClass=TEXT("First");


int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance

 ,LPSTR lpszCmdParam,int nCmdShow)

{

HWND hWnd;

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;

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,NULL,0,0)) {

TranslateMessage(&Message);

DispatchMessage(&Message);

}

return (int)Message.wParam;

}


unsigned char * BMbuf;

HBITMAP Screen;


LRESULT CALLBACK WndProc(HWND hWnd,UINT iMessage,WPARAM wParam,LPARAM lParam)

{

HDC hdc;

static HDC MemDC;

PAINTSTRUCT ps;

HANDLE hFile;

DWORD dwRead;

TCHAR str[1024];

static BITMAPFILEHEADER * stpBFH;

static BITMAPINFOHEADER * stpBIH;

static unsigned int uiX;

static unsigned int uiY;

unsigned int uiXcount;

unsigned int uiYcount;

unsigned char * ucpPixel;

static unsigned int uiPad;

HBITMAP OldBitmap;

RECT rt;

switch (iMessage)

{

case WM_CREATE:

hFile = CreateFile(TEXT("image.bmp"),

GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);


BMbuf = (unsigned char *)malloc(BITMAP_MAXSIZE);

if(0 == BMbuf)

{

MessageBox(hWnd, TEXT("동적할당을 받을 수 없습니다."), TEXT("오류"), MB_OK);

DestroyWindow(hWnd);

}

if(INVALID_HANDLE_VALUE != hFile)

{

ReadFile(hFile, BMbuf, BITMAP_MAXSIZE, &dwRead, NULL);

CloseHandle(hFile);


stpBFH = (BITMAPFILEHEADER *)BMbuf;

stpBIH = (BITMAPINFOHEADER *)(BMbuf + sizeof(BITMAPFILEHEADER));


wsprintf(str, TEXT("[%c][%c]"), BMbuf[0], BMbuf[1]);

CreateWindow(TEXT("static"), TEXT("파일 타입 : "), WS_CHILD | WS_VISIBLE,

20, 20, 90, 20, hWnd, (HMENU)-1, g_hInst, NULL);

CreateWindow(TEXT("static"), str, WS_CHILD | WS_VISIBLE,

110, 20, X_WIDTH_SIZE, 20, hWnd, (HMENU)-1, g_hInst, NULL);


wsprintf(str, TEXT("[%d byte]"), stpBFH->bfSize);

CreateWindow(TEXT("static"), TEXT("파일 크기 : "), WS_CHILD | WS_VISIBLE,

20, 40, 90, 20, hWnd, (HMENU)-1, g_hInst, NULL);

CreateWindow(TEXT("static"), str, WS_CHILD | WS_VISIBLE,

110, 40, X_WIDTH_SIZE, 20, hWnd, (HMENU)-1, g_hInst, NULL);


wsprintf(str, TEXT("[%u]"), stpBIH->biWidth);

CreateWindow(TEXT("static"), TEXT("가로 크기 : "), WS_CHILD | WS_VISIBLE,

20, 60, 90, 20, hWnd, (HMENU)-1, g_hInst, NULL);

CreateWindow(TEXT("static"), str, WS_CHILD | WS_VISIBLE,

110, 60, X_WIDTH_SIZE, 20, hWnd, (HMENU)-1, g_hInst, NULL);

uiX = (unsigned int)(stpBIH->biWidth);

uiPad = uiX%4;


wsprintf(str, TEXT("[%u]"), stpBIH->biHeight);

CreateWindow(TEXT("static"), TEXT("세로 크기 : "), WS_CHILD | WS_VISIBLE,

20, 80, 90, 20, hWnd, (HMENU)-1, g_hInst, NULL);

CreateWindow(TEXT("static"), str, WS_CHILD | WS_VISIBLE,

110, 80, X_WIDTH_SIZE, 20, hWnd, (HMENU)-1, g_hInst, NULL);

uiY = (unsigned int)(stpBIH->biHeight);


wsprintf(str, TEXT("[%08X]"), stpBFH->bfOffBits);

CreateWindow(TEXT("static"), TEXT("bfOffbits : "), WS_CHILD | WS_VISIBLE,

20, 100, 90, 20, hWnd, (HMENU)-1, g_hInst, NULL);

CreateWindow(TEXT("static"), str, WS_CHILD | WS_VISIBLE,

110, 100, X_WIDTH_SIZE, 20, hWnd, (HMENU)-1, g_hInst, NULL);

hdc = GetDC(hWnd);

MemDC = CreateCompatibleDC(hdc);

GetClientRect(hWnd, &rt);

Screen = CreateCompatibleBitmap(hdc, rt.right, rt.bottom);

OldBitmap = (HBITMAP)SelectObject(MemDC, Screen);

ucpPixel = BMbuf + stpBFH->bfOffBits;

for(uiYcount = uiY; 0 < uiYcount; --uiYcount)

{

for(uiXcount = 0; uiX > uiXcount; ++uiXcount)

{

SetPixel(MemDC, uiXcount + XOFFSET, uiYcount-1, RGB(*(ucpPixel+2), *(ucpPixel+1), *ucpPixel));

ucpPixel = ucpPixel + 3;

}

ucpPixel = ucpPixel + uiPad;

}

SelectObject(MemDC, OldBitmap);

DeleteDC(MemDC);

ReleaseDC(hWnd, hdc);

free(BMbuf);

}

else

{

MessageBox(hWnd, TEXT("파일을 열 수 없습니다."), TEXT("오류"), MB_OK);

DestroyWindow(hWnd);

}

return 0;

case WM_PAINT:

hdc = BeginPaint(hWnd, &ps);

MemDC = CreateCompatibleDC(hdc);

OldBitmap = (HBITMAP)SelectObject(MemDC, Screen);


GetClientRect(hWnd, &rt);

BitBlt(hdc, 0, 0, rt.right, rt.bottom, MemDC, 0, 0, SRCCOPY);


SelectObject(MemDC, OldBitmap);

DeleteDC(MemDC);

EndPaint(hWnd, &ps);

return 0;

case WM_DESTROY:

DeleteObject(Screen);

PostQuitMessage(0);

return 0;

}

return(DefWindowProc(hWnd,iMessage,wParam,lParam));

}



설정

트랙백

댓글

20140924 (비트맵 파일 구조)

145일차





-------------------

비트맵 파일 구조

-------------------











1. 파일 헤더

typedef struct tagBITMAPFILEHEADER

{

    WORD    bfType;    // "BM"이라고  bitmap을 나타내는 값 저장됨

    DWORD    bfSize;    // 바이트 단위로 전체 파일 크기

    WORD    bfReserved1;    // 예약된 변수

    WORD    bfReserved2;    // 예약된 변수

    DWORD    bfOffBits;    // 실제 데이터 위치까지의 거리

}BITMAPFILEHEADER;



WORD (unsigned short) 2byte, DWORD (unsigned long) 4byte.




2. 이미지 헤더

typedef struct tagBITMAPINFOHEADER

{

    DWORD    biSize;    // 이 구조체의 크기

    LONG    biWidth;    // 픽셀 단위 이미지 폭

    LONG    biHeight;    // 이미지 높이

    WORD    biPlanes;    // 비트 플레인 수 (항상 1, 움직이는 그림은 다른수라 하던데..?)

    WORD    biBitCount;    // 픽셀당 비트 수 (컬러, 흑백 구별)

    DWORD    biCompression;    // 압축유무

    DWORD    biSizeImage;    // 이미지 크기 (바이트 단위)

    LONG    biXPelsPermeter;    // 가로 해상도

    LONG    biYPelsPermeter;    // 세로 해상도

    DWORD    biClrUsed;    // 실제 사용 색상 수

    DWORD    biClrImportant;    // 중요한 색상 인덱스

}BITMAPINFOHEADER;



설정

트랙백

댓글

[WinApi]VFW함수 자료정리

프로그래밍 언어/WinApi 2014. 9. 18. 12:08

비디오 캡쳐를 하기 위해서 먼저 vfw32.lib 를 프로젝트에서 포함 해주어야 하며 작성 소스 상단에 Vfw.h를

include 해주어야 한다.

 

비디오 캡쳐를 위한 작업 순서를 간단히 다음과 같다.

 

캡쳐 윈도우를 생성

윈도우와 캡쳐 드라이버를 연결

캡쳐된 비디오 프레임을 캡쳐 윈도우를 통해서 출력

캡쳐된 비디오 프레임을 캡쳐 윈도우에 보여주기 위해서는 한 프레임이 캡쳐 될 때마다 특정 함수를 호출하도록 한 다음에 호출된 함수에서 그 프레임을 화면에 출력한다.

이러한 작업을 수행하기 위해서는 VFW 라이브러리 중에서 다음과 같은 함수들을 사용해야 한다.

capGetDriverDescription()

CapCreateCaptureWindow()

capDriverConnect()

capPreviewRate()

capSetVideoFormat()

capDriverDisconnect()

capSetCallbackOnFrame()

 

 - 함수의 원형

 

HWND VFWAPI capCreateCaptureWindowW (
        LPCWSTR lpszWindowName,
        DWORD dwStyle,
        int x, int y, int nWidth, int nHeight,
        HWND hwndParent, int nID);

이 함수는 캡쳐 윈도우를 생성한다. name 에는 윈도우위 이름을 지정한다. style 윈도우위 스타일을 지정한다. (x,y)에는 캡쳐 윈도우의 좌측 상단의 좌표를 지정한다. width height에는 캡쳐 윈도우의 크기를 지정한다. hWnd에는 부모윈도우의 핸들값을 입력한다. id에는 윈도우의 식별 번호를 입력한다. 캡쳐 윈도우가 정상적으로 생성되면 캡쳐 윈도우의 핸들의 함수 결과값으로 반환되고 그렇지 않으면 NULL값이 반환된다.

 

 

BOOL VFWAPI capGetDriverDescriptionW (UINT wDriverIndex,
        LPWSTR lpszName, int cbName,
        LPWSTR lpszVer, int cbVer);

이 함수는 캡쳐 드라이버의 이름 및 버전 정보를 검색한다. 첫 번째 매개변수인 index는 검색하고자 하는 드라이버의 번호를 나타내는데, 0부터 9까지의 값을 가질 수 있다.

즉, 한 컴퓨터에서 9대의 캡쳐 장치가 사용될 수 있다고 가정하고 있다. 검색하고자 하는 번호의 드라이버가 존재하면 이 함수는 name에 드라이버의 이름을 저장하고 version에 드라이버 버전을 저장한 다음에 함수 결과값으로 TURE 값을 반환한다. 

 

capDriverConnect(hWnd, index);

이 함수는 아래 처럼 디파인 되어 있으며

#define capDriverConnect(hwnd, i)          ((BOOL)AVICapSM(hwnd, WM_CAP_DRIVER_CONNECT, (WPARAM)(i), 0L))

AVICapSM 역시 아래 처럼 디파인 되어 있다.( 윈도우 메시지인 WM_CAP_DRIVER_CONNECT 를 사용 하는듯 하다.)

#define AVICapSM(hwnd,m,w,l) ( (::IsWindow(hwnd)) ? ::SendMessage(hwnd,m,w,l) : 0)

이 함수는 캡쳐 윈도우를 캡쳐 드라이버에 연결한다. hWnd는 캡쳐 윈도우의 핸들을 나타내고 index는 캡쳐 드라이버의 번호를 나타낸다. 이 함수는 캡쳐 장치가 정상적으로 작동하여 연결이 성공되면 TURE 값을 반환하고 그렇지 않으면 FALSE 값을 반환한다.

 

 

capPreviewRate(hWnd, rate);

이 함수는 아래 처럼 디파인 되어 있으며

#define capPreviewRate(hwnd, wMS)   ((BOOL)AVICapSM(hwnd, WM_CAP_SET_PREVIEWRATE, (WPARAM)(wMS), 0))

AVICapSM 역시 아래 처럼 디파인 되어 있다.( 윈도우 메시지인 WM_CAP_SET_PREVIEWRATE를 사용 하는듯 하다.)

#define AVICapSM(hwnd,m,w,l) ( (::IsWindow(hwnd)) ? ::SendMessage(hwnd,m,w,l) : 0)

이 함수는 미리보기 (preview)모드에서의 프레임 재생 속도를 설정한다. 여기에서 미리보기란 카메라에서 입력된 비디오를 파일에 저장하는 것이 아니라 화면에 보여준다는 것을 의미한다. hWnd는 캡쳐 윈도우의 핸들 값으로 설정하고 rate는 밀리초(ms) 단 위의 시간으로 설정한다. 예를 들어, rate 값을 66으로 설정하면 0.066초마다 새로운 비디오 프레임을 캡쳐해서 디스플레이 하게 도니다. 이와 같은 속도로 재생을 하면 1초에 15개의 비디오 프레임이 디스플레이된다.

 

capSetVideoFormat(hWnd, videoFormat, videoFormat_size);

#define capSetVideoFormat(hwnd,s,wSize)          ((BOOL)AVICapSM(hwnd,WM_CAP_SET_VIDEOFORMAT, (WPARAM)(wSize), (LPARAM)(LPVOID)(s)))

AVICapSM 역시 아래 처럼 디파인 되어 있다.( 윈도우 메시지인 WM_CAP_SET_VIDEOFORMAT를 사용 하는듯 하다.)

#define AVICapSM(hwnd,m,w,l) ( (::IsWindow(hwnd)) ? ::SendMessage(hwnd,m,w,l) : 0)

이 함수는 캡쳐된 비디오 데이터 형식을 설정한다. 사용자가 원하는 비디오 데이터형식이 캡쳐 장치에서 지원이 되면 이 함수는 TRUE 값을 반환하고 그렇지 않으면 FALSE 값을 반환하므로 반드시 이 함수의 결과값이 TRUE 인지 검사한 다음에 다음단계로 넘어가야 한다.

hWnd는 캡쳐 윈도우의 핸들 값으로 설정한다. videoFormat은 설정하고자 하는 비디오 데이터 형식을 나타내는데, 비디오 데이터의 각 프레임에 대한 비트맵 형식을 BITMAPINFO 구조로 기술한다.

 

BITMAPINFO 구조는 다음과 같다.

typedef struct tagBITMAPINFO{

BITMAPINFOHEADER bmiHeader;

RGBQUAD bmiColrs[1];

BITMAPINFO;  

BITMAPINFO는 BITMAPINFOHEADER와 RGBQUAD로 구성되는데, 여기에서는 다음과 같이 정의되는 BITMAPINFOHEADER 구조체의 값만 사용하면 된다.


pBmiInfo->bmiHeader.biSize = 40;  //BITMAPINFOHEADER 구조체의 크기

pBmiInfo->bmiHeader.biHeight = 480; //영상의 가로크기

pBmiInfo->bmiHeader.biWidth = 640;

//영상의 세로크기(양수:좌측 하단이 원점   음수:좌측 상단이 원점)

pBmiInfo->bmiHeader.biPlanes = 1; //목표 장치의 플레인 수(1로 설정해야함)

pBmiInfo->bmiHeader.biBitCount = (short) 24; //각 픽셀의 비트수

pBmiInfo->bmiHeader.biCompression = 0; //압축 방법(bi_rgb 또는 0:무압축 비트맵)

pBmiInfo->bmiHeader.biSizeImage =0; //비트맵 영상 크기(무압축인 경우 0으로 설정)

pBmiInfo->bmiHeader.biClrImportant = 0; // 비트맵 디스플레이에 사용되는 컬러수

pBmiInfo->bmiHeader.biClrUsed = 0; // 사용된 컬러의 수

pBmiInfo->bmiHeader.biXPelsPerMeter = 10000; //수평 해상도 (미터당 픽셀수)

pBmiInfo->bmiHeader.biYPelsPerMeter = 10000; //수직 해상도 (미터당 픽셀 수)

}BITMAPINFOHEADER;

비디오 캡쳐를 위해서는 다음과 같이 BITMAPINFOHEADER 구조체에서 biSize,biWidth, biHeight, biPlanes, biBitCount 값을 설정하고 나머지 값을은 0으로 설정하면된다.

BITMAPINFO bmi;

memset(&bmi.bmiHeader, 0, sizeof(bmiHeader));

pBmiInfo->bmiHeader.biSize = sizeof(bmi.bmiHeader);

pBmiInfo->bmiHeader.biWidth = 640;//영상의 세로크기(양수:좌측 하단이 원점

pBmiInfo->bmiHeader.biHeight = 480;//영상의 가로크기

pBmiInfo->bmiHeader.biPlanes = 1;//목표 장치의 플레인 수(1로 설정해야함)

pBmiInfo->bmiHeader.biBitCount =  24;//각 픽셀의 비트수

 

capDriverDisconnect(hWnd);

#define capDriverDisconnect(hwnd)       ((BOOL)AVICapSM(hwnd, WM_CAP_DRIVER_DISCONNECT, (WPARAM)0, 0L))

AVICapSM 역시 아래 처럼 디파인 되어 있다.( 윈도우 메시지인 WM_CAP_DRIVER_DISCONNECT를 사용 하는듯 하다.)

#define AVICapSM(hwnd,m,w,l) ( (::IsWindow(hwnd)) ? ::SendMessage(hwnd,m,w,l) : 0)

이 함수는 carDriverConnect() 함수에 의하여 연결한 캡쳐 윈도우와 캡쳐 장치를 분리하는 함수이다. hWnd에는 분리하고자 하는 캡쳐 윈도우의 핸들 값을 설정한다.

 

BOOL capSetCallbackOnFrame(hWnd, func);

#define capSetCallbackOnFrame(hwnd, fpProc)        ((BOOL)AVICapSM(hwnd,WM_CAP_SET_CALLBACK_FRAME, 0, (LPARAM)(LPVOID)(fpProc)))

AVICapSM 역시 아래 처럼 디파인 되어 있다.( 윈도우 메시지인 WM_CAP_SET_CALLBACK_FRAME를 사용 하는듯 하다.)

#define AVICapSM(hwnd,m,w,l) ( (::IsWindow(hwnd)) ? ::SendMessage(hwnd,m,w,l) : 0)

VFW 라이브러리에서는 캡쳐된 비디오 프레임을 화면에 보여주는 작업을 callback함수를 사용해서 처리하도록 하고 있다. capSetCallbackOnFrame()함수는 캡쳐 장치로부터 비디오 프레임이 캡쳐되었을때에 이를 화면에 보여주기 위해서 호출되는 callback 함수를 설정한다. hWnd는 캡쳐 윈도우의 핸들 값으로 설정하고 func는 호출될 함수 이름으로 설정한다.  

 

 

BOOL capOverlay(hWnd, f);
#define capOverlay(hwnd, f)          ((BOOL)AVICapSM(hwnd, WM_CAP_SET_OVERLAY, (WPARAM)(BOOL)(f), 0L))

#define AVICapSM(hwnd,m,w,l) ( (::IsWindow(hwnd)) ? ::SendMessage(hwnd,m,w,l) : 0)

이 함수는 비디오 오버레이를 사용 할것인지 아닌지를 설정한다. 설정 성공시 TRUE, 그렇지 않을경우 FALSE를 반환.
매개변수는 순서대로 윈도우 핸들, 설정시-true 미설정시 -false
비디오 오버레이를 사용하면 CPU자원이 요구 되지 않아 효과적이라고 한다. 
 
BOOL capPreview(hWnd, f);
#define capPreview(hwnd, f)       ((BOOL)AVICapSM(hwnd, WM_CAP_SET_PREVIEW, (WPARAM)(BOOL)(f), 0L))

#define AVICapSM(hwnd,m,w,l) ( (::IsWindow(hwnd)) ? ::SendMessage(hwnd,m,w,l) : 0)

이 함수는 미리보기 모드를 동작 시킬 것인지 아닌지를 설정한다. 설정을 하게 되면 영상 프레임이 시스템의 메모리로 전달되어 GDI함수를 사용하여 캠처 윈도우에 영상을 출력하게 된다.
매개 변수는 순서대로 윈도우 핸들, 설정시 -true, 미설정시 -false 










예제 소스>


#include "windows.h"
#include "Vfw.h"
#pragma comment (lib,"vfw32.lib")
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
LRESULT CALLBACK FramInfo(HWND hVFW, LPVIDEOHDR VideoHdr);
HINSTANCE g_hInst;
HWND hWndMain;
HBITMAP hBit;
BITMAPINFO Bm;
LPCSTR lpszClass=TEXT("Class");
//WinMain 시작
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance
      ,LPSTR lpszCmdParam,int nCmdShow)
{
 HWND hWnd;
 MSG Message;
 WNDCLASS WndClass;
 g_hInst=hInstance;
 //1. 윈도우 속성값 등록
 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;
 WndClass.lpszClassName=lpszClass;
 WndClass.lpszMenuName=NULL;
 WndClass.style=CS_HREDRAW | CS_VREDRAW;
 RegisterClass(&WndClass);  //주소에 Write
 
 //2. 윈도우 생성
 hWnd=CreateWindow(lpszClass,lpszClass,WS_OVERLAPPEDWINDOW,
  CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
  NULL, (HMENU)NULL,hInstance,NULL);
 ShowWindow(hWnd,nCmdShow); //화면에 뿌려줌
 
 //3. 메시지 처리(무한 반복)
 while (GetMessage(&Message,NULL,0,0))
 {
  TranslateMessage(&Message);
  DispatchMessage(&Message);
 }
 return (int)Message.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
 HDC hdc;
 HWND hVFW;
 PAINTSTRUCT ps;
 switch(iMessage)
 {
 case WM_CREATE:
  hWndMain=hWnd;
  hdc=GetDC(hWndMain);
  hVFW=capCreateCaptureWindow(TEXT("VFW"),WS_CHILD | WS_VISIBLE , 0,0,1,1,hWnd,0);
  capDriverConnect(hVFW,0);
  capPreviewRate(hVFW,1);
  capPreview(hVFW,TRUE);
  capGetVideoFormat(hVFW,&Bm, sizeof(Bm));
  hBit=CreateCompatibleBitmap(hdc, Bm.bmiHeader.biWidth,Bm.bmiHeader.biHeight);
  if (capSetCallbackOnFrame(hVFW,FramInfo)==FALSE)
  {
   return FALSE;
  }
  ReleaseDC(hWndMain, hdc);
  return 0;
 case WM_PAINT:
  hdc = BeginPaint(hWnd, &ps);
  EndPaint(hWnd, &ps);
  return 0;
 case WM_DESTROY:
  PostQuitMessage(0);
  return 0;
 }
 return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}
LRESULT CALLBACK FramInfo(HWND hVFW, LPVIDEOHDR VideoHdr)
{
 HDC hdc;
 HDC hMemDC;
 HBITMAP OldBitmap;
 int iCntX;
 int iCntY;
 int Jump;
 
 hdc = GetDC(hWndMain);
 hMemDC = CreateCompatibleDC(hdc);
 OldBitmap = (HBITMAP)SelectObject(hMemDC, hBit);
 
 Jump=0;
 for (iCntY=0 ; iCntY < Bm.bmiHeader.biHeight ; ++iCntY)
 {
  for (iCntX=0 ; iCntX < Bm.bmiHeader.biWidth ; ++iCntX)
  {
   //원영상
   SetPixel(hMemDC, iCntX,(Bm.bmiHeader.biHeight - iCntY)-1, RGB(VideoHdr->lpData[Jump+2],VideoHdr->lpData[Jump+1],VideoHdr->lpData[Jump]));
   Jump+=3;
  }
 }
 BitBlt(hdc, 0,0,Bm.bmiHeader.biWidth,Bm.bmiHeader.biHeight,hMemDC,0,0,SRCCOPY);
 SelectObject(hMemDC,OldBitmap);
 ReleaseDC(hWndMain,hdc);
 return 0;
}

설정

트랙백

댓글

microangel 마우스 커서, 아이콘 제작 툴

잡다 2014. 9. 16. 15:15


Microangelo v5.59 setup.exe


Microangelo v5.59.nfo



내가 만든 


cursor_point.zip


'잡다' 카테고리의 다른 글

PCB 설계/제작/조립 관련 사이트  (0) 2014.10.27
C++ Reference, Pointer  (0) 2014.10.13
map  (0) 2014.09.13
우분투 리눅스 text 모드 부팅  (0) 2014.09.01
헤더 파일에 있는 함수 모음  (0) 2014.08.28

설정

트랙백

댓글

보호글

map

잡다 2014. 9. 13. 17:08

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력해주세요.

embedded 기초 강좌 관련 사이트

Embedded 2014. 9. 2. 11:18

http://recipes.egloos.com/

'Embedded' 카테고리의 다른 글

ARM 컴파일 안될 시....  (0) 2014.10.23
makefile만들기, interrupt 전처리 과정  (0) 2014.06.18

설정

트랙백

댓글