Busan IT/WinAPI2015. 11. 12. 17:43

WinAPI 기본형 코드


WinAPI기본형을 작성하고 분석해 보자.


#include <windows.h> //헤더 파일은 이것 하나면 된다.

LRESULT CALLBACK /* 인트형 반환값이다.*/ WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);

HINSTANCE g_hInst;
LPSTR lpszClass = "First";

/// 윈도우 창을 설정하는 함수
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)
{
  HWND hWnd;
  MSG Message;
  WNDCLASS WndClass;
  g_hInst = hInstance;
  
  /// class 구조체 초기화
  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;                  // 해당 구조체에 main의 초기값을 넣어준다.(must)
  WndClass.lpfnWndProc=(WNDPROC)WndProc;            // 함수의 주소를 넣는 자리, 응용 프로그램 관련 이벤트 메세지를 받을 함수의 주소, 함수 이름을 바꿔도 무관하다.
  WndClass.lpszClassName=lpszClass;                // 실행 단위를 class라 부른다. 프로그램 단위로 실행되는 명령어가 한정된다.
  WndClass.lpszMenuName=NULL;                  // 메뉴 
  WndClass.style=CS_HREDRAW | CS_VREDRAW;          // 윈도우 창 크기 조절
  RegisterClass(&WndClass);                    // 설정된 내용을 등록

  hWnd=CreateWindow(  lpszClass, 
            lpszClass,                 //창의 제목
            WS_OVERLAPPEDWINDOW,           //창의 속성값 지정
            CW_USEDEFAULT,               //가로, 세로 시작점(X, Y좌표)
            CW_USEDEFAULT, 
            CW_USEDEFAULT,               //가로, 세로 크기(X, Y좌표)
            CW_USEDEFAULT, 
            NULL,                   
            (HMENU)NULL, 
            hInstance, 
            NULL);
  
  ShowWindow(hWnd, nCmdShow);                // 화면의 출력 여부를 선택, 윈도우가 결정한다. 

  while(GetMessage(&Message, 000))              //윈도우가 보내는 메세지를 받는 함수, 가장 오래된 메세지를 가지고 온다.
  //// 창을 닫는 메세지는 '0'이다.
  {
    TranslateMessage(&Message);                //메세지를 해석
    DispatchMessage(&Message);                //윈도우가 처리하고 남은 값을 처리한다.
  }
  return Message.wParam;                    //리턴 값은 int, 윈도우 로그에 남는다.
}
//// 실제 프로그램을 실행시키는 함수
LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage,/*이벤트 번호가 온다*/ WPARAM wParam, LPARAM lParam)
{
  switch(iMessage)
  {
    case WM_DESTROY:      //Window Message Destroy 윈도우 종료
                  //프로그램 종료시 정리해야 할 것들을 수행한다.
        PostQuitMessage(0);  //종료
        return 0;
  }

  return(DefWindowProc(hWnd, iMessage, wParam, lParam));   //프로그램이 인식하지 못하는 메세지는 윈도오로 다시 보낸다.
  
}
  
    

 

#include <windows.h> //헤더 파일은 이것 하나면 된다.

 

LRESULT CALLBACK /* 인트형 반환값이다.*/ WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);

 

LRESULT CALLBACK: long result 내부 프로그램에서는 호출할 수 없다. 호출 방식이 STD call 혹인 CDECL인지...

HWND: Window Handler, 인트형이다.

WPARAM: Word(4byte) 인자, type define이 되어 있다.

LPRAMWPRAM의 용량의 크기는 없다. 과거 메모리 용량이 작을 때 구분하여 사용하던 것이다.

 

HINSTANCE g_hInst; g for global, h for handler

LPSTR lpszClass = "First"; //long pointer string: 캐릭터 포인터

 

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdParam, int nCmdShow)

 

APIENTRY : API entry, 컴파일러에게 call 방식이 무엇인지 알려준다.

두 번째 인자는 예전에 사용하던 것이여서 그대로 인자로 적어놓고 있지만 사용하지 않는다.

 

LPSTR lpszCmdParam: 명령어 입력

 

int nCmdShow: 명령어 표시 여부를 선택하는 인자

 

WNDCLASS WndClass; 구조체이다. struct

 

g_hInst = hInstance; //사용한 인자를 전역변수에 복사함으로써 데이터 공유

 

응용프로그램 창에 커서를 올리면 운영체제에서 이벤트를 발생하여 응용프로그램에게 전달한다.



 

 

사용자가 운영체제에서 명령하는 메시지의 수가 CPU의 능력을 초과할 경우 메시지는 지속적으로 쌓이지 않고 기존 메시지에 덮어쓰게 된다.

 

FIFO(First In First Out): Queue 구조

FILA(First In Last Out): Stack 구조

 

실시간 처리 시스템은 1개 이상의 프로그램을 실행하지 못한다.

작성한 소스코드를 그대로 복사하여 Visual Studio에 붙힌다.

 

새로운 프로젝트를 생성하고 Visual C++에서 console이 아닌 project를 선택한다. 소스파일을 ‘main.c'이름으로 추가한다.

 

F5를 눌러 실행한다. 새로운 창이 뜨면 제대로 컴파일이 된 것이다. 새로운 창의 이름이 한자로 뜬다. 이것을 해결하기 위해 전역 변수 LPSTR lpszClassL을 추가해준다.

 

LPSTR lpszClass = L"First"

 

 

나머지 설명은 내일...

반응형

'Busan IT > WinAPI' 카테고리의 다른 글

winsock을 사용한 서버/클라이언트 프로그램  (0) 2015.11.30
히스토그램 , 알파값  (0) 2015.11.25
WIN32API로 BMP뷰어  (0) 2015.11.22
20151118 윤재희 #5. 그래픽 & 게임  (0) 2015.11.18
입력  (0) 2015.11.16
Posted by newind2000
Busan IT/영상처리2015. 11. 9. 13:47

==================================Outline====================================

BMP파일 가로 크기 패딩 처리

컬러 BMP파일 회색 변환

히스토그램을 사용한 평활화

명암 증가

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

BMP파일 가로 크기 패딩 처리

 

BMP파일의 가로 크기는 4의 배수여야 하는 규칙을 가지고 있다. 가로의 크기가 4의 배수가 아닐 경우에 사용자가 임의적으로 파일을 쓰게 되면 패딩에 값이 들어가기 때문에 BMP파일의 이미지가 깨지게 된다.

 

RGB BMP파일을 가로 픽셀의 크기가 401, 세로 픽셀의 크기가 400일로 만들 경우 파일의 용량은 헤더파일 54byte까지 추가하여 481,254byte이다.

 

 

하지만 패딩이 발생하여 이미지의 크기는 481,654byte가 된다. 올바른 자리에 데이터를 삽입하기 위하여 패딩 값을 고려해주어야 한다.

패딩은 가로 픽셀의 크기를 4의 배수로 맞춰주기 위한 보수 값이다.

BMP파일의가로의 크기는 4의 배수일 때만 정상적으로 수정이 가능하기 때문에 패드 값을 처리해주는 코드를 삽입 한다.

 

가로의 값이 401일 경우를 생각해보자. 각 픽셀당 RGB3byte를 차지함으로 한 줄의 크기는 1203이되고 이 때 4의 배수를 위한 패딩의 값은 1이다.

 

402일 경우에는 패딩 값이 2, 403일 경우는 패딩 값이 3이다. , 4로 나눈 나머지의 값이 패딩이 된다.

 

uiPad = stBIHead.biWidth % 4; //패딩 값


패딩 값이 설정되고 나면 이 값을 데이터의 값을 입력하는 이중 for문에 삽입하여 패딩 값을 처리해 주어야한다. 패딩 값은 라인 수 * 패딩 값이 되는 것을 유의하여야 한다.

for(uiCntY=0; uiCntY < stBIHead.biHeight; ++uiCntY)
{
  for(uiCntX=0; uiCntX < stBIHead.biWidth; ++uiCntX)
  {  
    //평균값 연산
    uiAVG = ( ucpORG[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 0 + (uiCntY*uiPad)] +
      ucpORG[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 1 + (uiCntY*uiPad)] +
      ucpORG[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 2 + (uiCntY*uiPad)] )/3;



      ucpBuf[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 0 + (uiCntY*uiPad)] = uiAVG; 

//blue  
    ucpBuf[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 1 + (uiCntY*uiPad)] = uiAVG; 

//green
    ucpBuf[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 2 + (uiCntY*uiPad)] = uiAVG; 

//red                        

  }
}

패딩 설정을 해주고나면 가로 픽셀이 4의 배수가 아니더라도 데이터가 원하는대로 입력된다.

 

 

컬러 BMP파일 회색 변환


컬러 BMP사진을 흑백으로 변환해보자. 컬러를 흑백으로 변환하는 건 쉽다. 원래의 이미지를 저장한 다음 RGB의 각 값만을 추출하여 표시해보자.

 

동적할당을 받아 원래의 이미지를 저장한다. 이 때 메모리를 복사하는 ‘memcopy'함수를 사용한다.

 

 

원하는 색만 추출하기 위해서는 다른 값은 ‘0’을 삽입하고 원하는 색은 주석 처리해준다.


원하는 값이 나오는 것을 확인할 수 있다.

 

 

 

디지털 영상의 히스토그램

 

RGB의 값의 정도를 나타내주는 그래프이다. 히스토그램을 활용하여 평활화를 시켜보자. 히스토그램의 평활화는 비슷한 값의 집단을 하나로 합쳐준다.

 

평활화의 단계는 다음과 같다.

 

1단계: 각 픽셀의 명도수를 구한다.

 

 

2단계: 명도의 단계별로 누적합을 구하는 작업이다.

 

3단계: 누적된 값을 픽셀의 개수로 나눈 후 명도의 단계 - 1의 값으로 곱해준다.

 

 

요약하면 아래와 같다.




히스토그램을 사용한 평활화 

 

히스토그램을 위한 코딩을 해보자.

 

1. 히스토그램의 생성

//// Equialization
//// 1단계: 히스토그램 생성
for(uiCntY=0; uiCntY < stBIHead.biHeight; ++uiCntY)
{
  for(uiCntX=0; uiCntX < stBIHead.biWidth; ++uiCntX)
  {    
    ++uiCntB[ ucpBuf[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 0 + (uiCntY*uiPad)] ]; //blue      
    ++uiCntG[ ucpBuf[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 1 + (uiCntY*uiPad)] ]; //green      
    ++uiCntR[ ucpBuf[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 2 + (uiCntY*uiPad)] ]; //red  
  }
} 

각 픽셀 값의 RGB 값을 추출하여 각 값이 몇 개나 있는지 빈도수를 계산해준다.


2. 누적합 계산 

정규화를 연산을 위해 누적합을 계산해준다.

//// 2단계: 누적합 계산
uiSumR[0= uiCntR[0];
uiSumG[0= uiCntG[0];
uiSumB[0= uiCntB[0];

for(uiCntX = 1256 > uiCntX; ++uiCntX)
{
  uiSumR[uiCntX] = uiSumR[uiCntX-1] + uiCntR[uiCntX];
  uiSumG[uiCntX] = uiSumG[uiCntX-1] + uiCntG[uiCntX];
  uiSumB[uiCntX] = uiSumB[uiCntX-1] + uiCntB[uiCntX];
      
}

3. 정규화 

//// 3단계: 정규화
uiCntY = stBIHead.biWidth * stBIHead.biHeight;
for(uiCntX = 0256 > uiCntX; ++uiCntX)
{
  uiCntR[uiCntX] = (uiSumR[uiCntX]*255)/uiCntY;
  uiCntG[uiCntX] = (uiSumG[uiCntX]*255)/uiCntY;
  uiCntB[uiCntX] = (uiSumB[uiCntX]*255)/uiCntY;        

} 

정규화 계산식을 이용하여 정규화해준다.

 

4. 이미지에 적용

/// 이미지에 적용
for(uiCntY=0; uiCntY < stBIHead.biHeight; ++uiCntY)
{
  for(uiCntX=0; uiCntX < stBIHead.biWidth; ++uiCntX)
  {    
    ucpBuf[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 0 + (uiCntY*uiPad)] 
    = uiCntB[ucpBuf[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 0 + (uiCntY*uiPad)]]; //blue
    
    ucpBuf[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 1 + (uiCntY*uiPad)]
    = uiCntG[ucpBuf[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 1 + (uiCntY*uiPad)]]; //green      
      ucpBuf[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 2 + (uiCntY*uiPad)]
    = uiCntR[ucpBuf[uiCntY * (stBIHead.biWidth * 3) + (uiCntX * 3) + 2 + (uiCntY*uiPad)]]; //red  
  }

} 

정규화된 값을 이미지에 적용하여 평활화시킨다. 

 

 

 

 

 

 

명암 증가

 

RBG값에 50을 더하여 값을 삽입해보자. 값이 255를 넘을 경우 최대 값이 255가 되도록 설정한다.

//jpg파일은 압축기법을 공부하지 않고서는 BMP파일처럼 조작하기 어렵다.







반응형

'Busan IT > 영상처리' 카테고리의 다른 글

비트맵 파일 규격 규칙  (0) 2015.11.06
비트맵 구조체  (0) 2015.11.05
Posted by newind2000
Busan IT/영상처리2015. 11. 6. 16:50

==================================Outline====================================

비트맵 파일 규격 규칙

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

 비트맵 파일 규격 규칙

 

세로 줄과 가로 줄을 그어보자. 

비트맵 파일은 좌우는 유지되고 상하를 뒤집어서 저장하는 것을 알 수 있다.


 

영상처리에서 X, Y축 대칭 기술은 흔히 쓰인다.

 

비트맵 크기를 조절할 때 가로 축의 크기가 4의 배수가 아닐 경우에 데이터를 쓰게 되면 오류가 발생한다.



 

대신 가로의 값이 4의 배수일 경우 오류가 발생하지 않는다.

 

가로 1픽셀식 늘려서 값을 크기를 계산기로 계산해보고 실제 파일의 크기를 알아보자.

가로 축은 항상 4의 배수의 용량을 가져야 한다는 규칙을 가지고 있다. 가로 픽셀의 용량이 4의 배수가 아닐 경우 4의 배수로 채우기 위한 byte를 더해준다.

반응형
Posted by newind2000