사용자 삽입 이미지





Win32 콘솔...
데이터 부분 한글 깨진다..
Tcp 구조체 좀 바깠음.. 비트연산자로 사용
메인에서 조건문 확인 요망.

내용들 주석처리 안했다.. 생각하면서 봐라 ㅋㅋ(나도 가물가물하니깐 -0-)
Posted by 응이

VFW (Video For Window)

영상처리 2008. 10. 23. 10:26


VFW (Video For Window)

VFW 라이브러리를 사용한 비디오 캡쳐 방법을 살펴보자. 비디오 캡쳐를 위해서는 먼저 캡쳐
윈도우를 생성하고 이 윈도우와 캡쳐 드라이버를 연결해야 한다. 그리고 캡쳐된 비디오 프레임을 캡쳐 윈도우에 보여주기 위해서는 한 프레임이 캡쳐 될 때마다 특정 함수를 호출하도록
한 다음에 호출된 함수에서 그 프레임을 화면에 출력한다. 이러한 작업을 수행하기 위해서는
VFW 라이브러리 중에서 다음과 같은 함수들을 사용해야 한다.

capGetDriverDescription()
CapCreateCaptureWindow()
capDriverConnect()
capPreviewRate()
capSetVideoFormat()
capDriverDisconnect()
capSetCallbackOnFrame()


●capGetDriverDescription()함수

BOOLcapGetDriverDescription(index, name, name_size, version, version_size);

이 함수는 캡쳐 드라이버의 이름 및 버전 정보를 검색한다. 첫 번째 매개변수인
index는 검색하고자 하는 드라이버의 번호를 나타내는데, 0부터 9까지의 값을 가질 수 있다.
즉, 한 컴퓨터에서 9대의 캡쳐 장치가 사용될 수 있다고 가정하고 있다. 검색하고자 하는 번호의
드라이버가 존재하면 이 함수는 name에 드라이버의 이름을 저장하고 version에
드라이버 버전을 저장한 다음에 함수 결과값으로 TURE 값을 반환한다.


●capCreateCaptureWindow()함수

H중 capCreateCaptureWindow(name, style, x, y, width, height, hWnd, id);

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


●capDriverConnect()함수

capDriverConnect(hWnd, index);

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


●capPreviewRate()함수

capPreviewRate(hWnd, rate);

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


●capSetVideFormat()함수

capSetVideoFormat(hWnd, videoFormat, videoFormat_size);

이 함수는 캡쳐된 비디오 데이터 형식을 설정한다. 사용자가 원하는 비디오 데이터형식이
캡쳐 장치에서 지원이 되면 이 함수는 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()함수;

capDriverDisconnect(hWnd);

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

●capSetCallbackOnFrame()함수

BOOL capSetCallbackOnFrame(hWnd, func);

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


Posted by 응이

Bitmap 파일 구조.

API 2008. 10. 1. 09:47

Bitmap 파일 구조

디바이스에 독립적인 영상파일을 저장하는 표준규격

JPEG, GIF, BMP, TIFF, PCX, PGM 등이 존재

보통 영상데이터는 정보량이 크기 때문에 압축을 통해 작은 크기로 변환하여 저장한다.

BMP파일 포맷은 압축을 수행하지 않으며 헤드가 있는 여러 형식의 파일 중에서

구조가 가장 간단하다.

파일 헤더

BITMAPFILEHEAER라는 구조체에 정의

사용자는 단지 구조체 변수를 선언해서 사용만 하면 된다.

현재의 파일 포맷이 정말 BMP인지에 대한 정보

BMP파일의 확장자 : *.BMP로 정의

다른 파일이 XX.BMP라고 썼을 수 있으므로, BMP디코더가 이를 분석

세가지 분석방법이 존재.

Bitmap 의 종류

DDB(Device-Dependent Bitmap) -> 장치종속 Bitmap

DIB(Device-Independent Bitmap) -> 장치독립 Bitmap

DIB 구조

BITMAPFILEHEADER -> File이 Bitmap File인지 구별하는 구조체.

BITMAPINFO -> Bitmap의 정보와 팔레트에 대한 정보를 제공하는 구조체.

BITMAPINFOHEADER -> Bitmap의 정보에 관한 구조체.

RGBQUAD -> 이미지의 색상 정보 구조체.

Image Data -> 실제자료가 pixel 로 구성되어 있음.

DIB 구조체

type struct tagBITMAPFILEHEADER

{

WORD bfType; // Bitmap파일을 나타내는 "BM" 문자의 ASCII값을 취함.

DWORD bfSize; // Bitmap파일의 크기

WORD bfReserved1; // 사용하지 않은 확장 예약변수

WORD bfReserved2; // 사용하지 않은 확장 예약변수

DWORD bfOffbits; // 실질 데이터(pixel)의 시작좌표를 나타냅니다.

}BITMAPFILEHEADER;

1. 파일의 첫 2바이트가 BM으로 시작하는가.

2. 바이트 단위의 정확한 파일크기와 헤더내의 bfSize가 있어야할 값과 일치하는가.

3. bfReserved1과 bfReserved2가 있어야 할 위치에 0값이 있는가.

세가지를 모두 체크, bmp파일 여부를 판명

디코더의 크기를 줄이기 위해, 첫 번째것만 체크하는 경우

파일의 헤더의 역할

포맷의 명확성을 표시

파일 내에 있어서 실질 데이터(pixel data)의 주소값을 나타내줍니다.

다시말해, 실질데이터의 파일 내 위치를 정의해 주는 역할

type struct tabBITMAPINFO

{

BITMAPINFOHEADER bmiHeader;

RGBQUAD bmicolors[1];

} BITMAPINFO;

type struct tagBITMAPINFOHEADER

{

DWORD biSize;// 비트맵 BITMAPINFOHEADER의 크기

LONG biWidth; // 이미지의 가로 길이.

LONG biHeight; // 이미지의 세로 길이.

WORD biPlanes;// 플레인수

WORD biBitCount; // 이미지의 컬러 비트수.

예) 8 이면 2의 8승이 되어 256컬러임을 알수 있음.

DWORD biCompression;// 압축 유무

DWORD biSizeImage;// 이미지 크기

LONG biXPelsPerMeter;// 미터당 가로 픽셀

LONG biYPelsPerMeter;// 미터당 세로 픽셀

DWORD biClrUsed;// 컬러 사용 유무

DWORD biClrImportant;// 중요하게 사용하는 색

} BITMAPINFOHEADER;

typedef struct tagRGBQUAD

{

BYTE rgbblue; // 파란색값

BYTE rgbGreen;// 녹색값

BYTE rgbRed;// 빨간색값

BYTE rgbReserved;// 항상 0

} RGBQUAD;

1. 팔레트는 인덱스에 의한 컬러값을 저장하기 위한 구조체.

2. 이 구조체를 사용하여 팔레트의 수 만큼 배열을 할당하여 저장.

3. 256컬러모드의 영상은 팔레트의배열 크기가 256개

4. 16비트 컬러영상은 팔레트 크기가 2의 16승개이다. biClrUsed변수를 참조하면 된다.

이미지는 모든색을 사용하는 것이 아니라 특정 색만을 사용한다.

예를 들어 8비트 Bitmap 이미지는 256색만을 사용한다.

Bitmap 이미지의 color정보를 이미지를 로드할 때마다 시스템에서 얻어오는 것보다 Bitmap 파일 안에 color 정보를 가지고, 그곳에서 얻어오는 것이 속도면에서 많은 이득이 있기 때문에 RGBQUAD 구조체를 사용하여 Bitmap 이미지의 color 정보를 저장한다.

이러한 color정보들의 모임을 다른 말로 '팔레트(Palette)라고 한다.

8비트 Bitmap이미지에서는 256개 color에 해당하는 256개의 RGBQUAD 배열, 즉 이미지 파일내에 팔레트가 존재하게 된다.

여기서는 문제점이 있는데 만약 Bitmap 이미지가 16비트 이상의 color 이미지이면 문제가 발생한다. 16비트 Bitmap 이미지는 컬러 수가 65536색 이며, 이것을 Bitmap 파일 내에 팔레트를 둔다면 65536개의 RGBQUAD배열을 만들어야 한다.

이는 배보다 배꼽이 큰 경우가 되기 때문에 조금 느리더라도 16비트 이상의 Bitmap 이미지에서는 내부 팔레트를 사용하지 않고, 시스템에서 제공하는 시스템 팔레트를 사용한다.

이미지의 저장 상태

이미지를 보는 그림과는 다르게 Image Data에는 상하가 뒤집어진 상태로 저장되어 있다.

이 때문에 Surface에 이미지를 로드 할 때 주의를 해야 한다.

이미지를 저장하거나 로드할 때는 항상 width, 즉 가로길이를 4의 배수로 맞추어야 한다.

예를 들어 이미지가 30 * 30 크기의 이미지이면 한 줄 읽을 때는 32byte를 읽어야 한다.

Bitmap 이미지는 항상 가로길이가 4의 배수이기 때문에 30byte는 이미지 data이고 나머지 2byte는 길이를 맞추기 위해 채워져야 한다.

이것을 모르고 그냥 이미지를 물러오면 이미지가 화면에 제대로 출력되지 않는다.

Posted by 응이

Dream come true.
응이

달력

태그목록