[3rd week] cg_practice_supplementary_for_hw2

Download Report

Transcript [3rd week] cg_practice_supplementary_for_hw2

Supplementary for HW#2
Hanyang University
Jungsik Park
간단한 MFC APPLICATION 생성
Division of Electrical and Computer Engineering, Hanyang University
Division of Electrical and Computer Engineering, Hanyang University
Division of Electrical and Computer Engineering, Hanyang University
Division of Electrical and Computer Engineering, Hanyang University
Division of Electrical and Computer Engineering, Hanyang University
 CAboutDlg 및 프로젝트명을 접두어로 갖는
클래스들이 생성된다.



CSimpleDrawApp
 SimpleDraw 어플리케이션 클래스(특정 윈도우에 대한
것이 아닌 전체적인 어플리케이션에 대한 클래스)
CAboutDlg
 실행 후, About SimpleDraw… 메뉴를 클릭하면 열리는
어플리케이션 정보창에 대한 클래스
CSimpleDrawDlg
 메인 윈도우인 다이얼로그 박스에 대한 클래스
 이 클래스를 이용하여 윈도우에 그림을 그린다.
Division of Electrical and Computer Engineering, Hanyang University
Division of Electrical and Computer Engineering, Hanyang University
 빌드 후 실행하면 다음과 같은 단순한 윈도우가
만들어진다.
 붉은 네모부분을 “클라이언트 영역”이라고 하고, 이
부분에 그리게 된다.
Division of Electrical and Computer Engineering, Hanyang University
 클라이언트 영역을 640*480으로 변경
 다이얼로그박스 윈도우의 초기화 함수인
CSimpleDrawDlg::OnInitDialog() 에서 다음을 추가
 SetWindowPos(&wndTop, 0, 0, 640+6, 480+30,
SWP_NOZORDER);
 SetWindowPos()는 클라이언트 영역을 포함한 윈도우
전체크기를 지정하므로 제목 표시줄과 테두리를 더한
(640+6)*(480+30)으로 크기 지정
Division of Electrical and Computer Engineering, Hanyang University
Division of Electrical and Computer Engineering, Hanyang University
DC 객체를 이용하여 윈도우에
그리기
Division of Electrical and Computer Engineering, Hanyang University
 DC(Device Context)
 DC(Device Context)란 출력에 필요한 모든 정보를
가지는 데이터 구조체이며 GDI 모듈에 의해 관리
 화면 출력에 관한 정보들을 DC에 모으고 DC의 핸들을
넘겨받아 화면에 출력
 화면의 일정한 영역에만 출력을 하도록 제한
 정확한 화면 좌표를 계산
 장치 독립적인 출력을 할 수 있도록 한다.
Division of Electrical and Computer Engineering, Hanyang University
 윈도우의 크기가 변경되거나 가려졌다가 다시 나타난
경우, 윈도우를 새로 그리라는 WM_PAINT 메시지가
전달되고, 메시지를 처리하기 위한 함수인 OnPaint()
함수가 호출된다.

다이얼로그 박스의 OnPaint() 함수는 자동으로
생성되어 있다.
 DC(Device Context) 객체를 이용한 그리기
 윈도우에 무언가를 그리기 위해서는 OnPaint()
함수에서 먼저 해당 윈도우의 DC 객체를 얻어온 후, DC
객체를 이용하여 그린다.
 특정 GDI 객체를 이용하여 그리는 경우
 DC 객체에 CPen, CBrush, CFont, CBitmap 등의 GDI
객체를 attach한 후 DC객체의 그리기 함수를 호출하면
해당 객체로 윈도우에 그리게 된다.
 그리기를 수행할 영역 및 좌표를 지정하는 데에는
CPoint, CRect 등이 사용된다.
Division of Electrical and Computer Engineering, Hanyang University
 클라이언트 영역을 초기화(흰색으로 색칠)
 GetDC() 함수로 DC 객체를 얻어온다.
 CDC *pDC = GetDC();
 GetClientRect() 함수로 클라이언트 영역의 좌표범위를
얻어온다.
 CRect rect;
 GetClientRect(&rect);
 클라이언트 영역을 칠하기 위한 흰색 브러쉬를 생성
 CBrush whiteBrush(RGB(255,255,255));
 DC 객체의 FillRect() 함수로 사각형 영역을 브러쉬로
색칠
 pDC->FillRect(&rect, &whiteBrush);
Division of Electrical and Computer Engineering, Hanyang University
Division of Electrical and Computer Engineering, Hanyang University
 실행해 보면 원래의 클라이언트 영역이 회색에서
흰색으로 바뀌어 있다.
Division of Electrical and Computer Engineering, Hanyang University
 픽셀단위로 점을 찍어 선을 그리는 방법
 DC 객체의 SetPixel()함수를 이용
 루프를 이용하여 좌표를 변화시켜가며 SetPixel()
함수를 호출
 SetPixel(x, y, RGB(255,0,0));을 호출하면 클라이언트
영역의 (x,y)위치에 붉은 색의 점을 찍는다.
 X축에 평행한 붉은 선을 그리는 예
 OnPaint() 함수에 다음을 추가
 for ( int i = 0 ; i < 640 ; i++ )
 {

pDC->SetPixel(i, 200, RGB(255,0,0));
 }
Division of Electrical and Computer Engineering, Hanyang University
Division of Electrical and Computer Engineering, Hanyang University
 (0, 200) ~ (640,200)의 붉은 선을 그린다.
Division of Electrical and Computer Engineering, Hanyang University
임의의 선 그리기
 앞의 방법을 이용하여
640 pixel
P2(x2,y2)
480 pixel
P1(x1,y1)
 두 정점 P1과 P2를 연결하여 선분을 그린다.
 직선의 방정식 y=ax+b 를 활용한다.
 이때 a는 기울기, b는 상수를 의미한다.
 기울기 a=(y2-y1)/(x2-x1), 상수 b는 P1과 P2를 대입하여
구한다.
Division of Electrical and Computer Engineering, Hanyang University
임의의 선 그리기
P2(x2,y2)
P1(x1,y1)
 두 정점 P1과 P2의 x 좌표축 기준으로 연결하여 (x2-x1)개의
정점을 그린다.
 정점들의 y좌표축 값은 직선의 방정식 y=ax+b을 이용하여
구한다. (예, j = a*i + b;)
 소수점 이후의 값은 반올림하여 정수형으로 사용한다. (예,
j=(int)(j+0.5));)
Division of Electrical and Computer Engineering, Hanyang University
비트맵 객체를 이용한 그리기
Division of Electrical and Computer Engineering, Hanyang University
비트맵 객체
 영상의 한 픽셀 당 일정한 비트를 할당하여 표현하는
방법

일반적으로 24bit 비트맵은 한 픽셀을 BGR 3 채널로
채널 당 각각 8bit(1byte)씩 할당하여 사용하고 32bit
비트맵은 한 픽셀을 BGRA 4 채널로 채널당 1byte씩
할당하여 사용.
 비트맵 객체를 이용하면
 복잡한 그림의 경우 메모리에 먼저 그림을 그린 뒤 한
번에 화면에 출력하는 방법으로 빠르게 그릴 수 있다.
 선을 그릴 때 안티앨리어싱 등의 알고리즘을 적용하여
계단 현상을 없앨 수 있다.
 이미지를 로드하여 윈도우에 이미지를 그릴 수도 있다.
Division of Electrical and Computer Engineering, Hanyang University
비트맵 객체의 선언
 비트맵 객체와 비트맵으로 사용할 메모리 공간의
포인터를 다이얼로그박스의 멤버 변수로 선언
 비트맵으로 사용할 공간은 [width*height*channels]
byte로 할당하고, 각 채널은 1byte로서 0~255의 값을
가진다.
Division of Electrical and Computer Engineering, Hanyang University
비트맵 객체 초기화
 OnInitDialog()에서 비트맵 객체의 초기화 및 메모리
공간 할당.

640*480 크기의 BGRA 4채널의 비트맵을 저장할 공간
할당
Division of Electrical and Computer Engineering, Hanyang University
비트맵 객체의 제거
 Properties->messages에서 WM_DESTROY의 메시지
핸들러 추가
Division of Electrical and Computer Engineering, Hanyang University
비트맵 객체의 제거
 OnDestroy() 함수에서 윈도우가 종료될 때 메모리
공간을 반납하고 비트맵 객체를 제거한다.
Division of Electrical and Computer Engineering, Hanyang University
메모리 공간에 그리기
 검은 바탕의 중앙에 흰색 수직선(x=320)을 그리는 예


메모리 공간의 [((y * 너비) + x) * 채널수 + 채널] 위치에
접근하여 각 픽셀의 BGR 채널의 값을 변경한다.
변경된 메모리 공간을 비트맵 객체에 복사한다.
 m_Bitmap.SetBitmapBits(640*480*4, m_pBits);
Division of Electrical and Computer Engineering, Hanyang University
메모리 공간을 DC 객체를 통해 출력
 비트맵을 이용할 경우, 윈도우의 DC 객체로 바로 그리는
것이 아니라 메모리 DC를 이용한다.

윈도우의 DC와 호환되는 메모리 DC를 생성한다.




메모리 DC의 GDI 객체로 비트맵 객체를 선택한다. 이 때
CDC::SelectObject() 함수를 사용하면 원래 DC 객체에
사용중이던 GDI 객체를 리턴하는데, 이를 보존해 두었다가
그리기가 끝난 후 다시 DC 객체에 붙여준다. 교체된 객체의
포인터를 잃어버리면 메모리 누수 발생.


CBitmap *pOldBitmap = memDC.SelectObject(&m_Bitmap);
메모리 DC의 내용을 윈도우의 DC 객체로 복사하여 화면
출력


CDC *pDC = GetDC();
CDC memDC;
memDC.CreateCompatibleDC(pDC);
pDC->BitBlt(0, 0, 640, 480, &memDC, 0, 0, SRCCOPY);
보존했던 GDI객체를 메모리 DC에 붙인 뒤, 메모리 DC를
제거한다.


memDC.SelectObject(pOldBitmap);
memDC.DeleteDC();
Division of Electrical and Computer Engineering, Hanyang University
비트맵 객체를 이용한 그리기
Division of Electrical and Computer Engineering, Hanyang University
비트맵 객체를 이용한 그리기
Division of Electrical and Computer Engineering, Hanyang University