소연의_개발일지
article thumbnail

 

 

이미지 오버레이로 그림 그리기

 

 

메모리 릭 제거하기

메모리 릭을 막기 위해 새로 생성한 m_pDlgImgResult 에 대해서도 생성 후 삭제를 해 준다.

안전하게 존재하는지 if문을 걸어 작성해 준다.

// 메모리 릭을 막기 위해 생성된 
void CgPrjDlg::OnDestroy()
{
	CDialogEx::OnDestroy();

	if(m_pDlgImage) delete m_pDlgImage;
	if(m_pDlgImgResult) delete m_pDlgImgResult;
}


타원 그리기

자식 다이얼로그에 타원을 그리는 코드를 만들어 볼 것이다.

 

 

먼저 헤더 폴더에 함수를  drawData를 정의해 주고 

 

선언만 해 줬으니 cpp 파일에서 정의를 해 준다.

CDlgImage 클래스 안에 있어야 하니 CDlgImage:: 를 함수 앞에 붙여 준다.

 

CRect rect(0, 0, 100, 100) 은 0, 0  위치에 100 * 100 사각형을 그린다는 뜻이다.

이 rect 변수를 Ellipse 메서드의 파라미터로 넣고 원을 그린다.

 

datwData 함수는 OnPaint() 함수 안에 넣어 준다.

void CDlgImage::datwData(CDC* pDC) 
{
	CRect rect(0, 0, 100, 100);
	pDC->Ellipse(rect);

}

 

이 다이얼로그 이미지 클래스는 두번 호출되므로(왼쪽, 오른쪽)

코드를 실행시키면 원 2개가 각각 다이얼로그의 (0, 0) 자리에 위치한 것을 볼 수 있다.

여기서 rect 변수의 뒤의 두 값을 변환하면 그 값 안에 꽉 찬 원이 그려진다. 

예를 들어 CRect rect(0, 0, 100, 100);

이렇게 값을 지정하면 각 다이얼로그만다 꽉 찬 원의 모습을 볼 수 있다.

 


왼쪽에서 오른쪽으로 값 넘겨주기

 

 

정보들을 헤더에 먼저 선언 해 준다.

int m_nDataCount = 0; // 몇개를 그릴 것인지
CPoint m_ptData[100]; // 배열(좌표값)

 

 

그리고 기존의 drawData  함수를 수정한다

m_nDataCount 값을 0으로 설정해 줬으므로 이 함수는 실행되지 않는다.

void CDlgImage::datwData(CDC* pDC) 
{
	CRect rect;
	
	for (int i = 0; i < m_nDataCount; i++) {
		rect.SetRect(m_ptData[i], m_ptData[i]);  // 좌표값 설정
		rect.InflateRect(5, 10); // 좌로 5만큼, 우로 10만큼 벌린다
		pDC->Ellipse(rect); //원을 그린다

	}

}

 

gPrjDlg.cpp 코드에서 test 버튼을 클릭했을 때 코드를 수정한다. 

영상이 이해가 빨리 안 되서 주석을 자세히 달았다.

void CgPrjDlg::OnBnClickedBtnTest()
{
	// 이미지 가져오기 
	// 화살표(->)는 포인터, 점(.)은 클래스를 의미
	unsigned char* fm = (unsigned char*)m_pDlgImage->m_image.GetBits(); // 리턴값을 unsigned cha로 받는다는 뜻
	
	// 가로 세로 피치 값 가져오기
	int nWidth = m_pDlgImage->m_image.GetWidth(); // 가로
	int nHeight = m_pDlgImage->m_image.GetHeight(); // 세로
	int nPitch = m_pDlgImage->m_image.GetPitch(); // 픽셀마다 행 간격을 나타내는 값

	// 값 리셋
	memset(fm, 0xff, nWidth * nHeight);

	// 점찍기
	for (int k = 0; k < 100; k++) {
		int x = rand() % nWidth;
		int y = rand() % nHeight;
		fm[y * nPitch + x] = 0;
	}

	// 인덱스 값 변수 선언(초기값 0)
	int nIndex = 0; 

	// 찍힌 점의 좌표를 m_ptData 배열에 저장
	// 모든 픽셀을 탐지하기 위한 이중 for문: 너비만큼, 높이만큼 반복: (i, j)는 픽셀의 (x, y)에 해당
	for (int j = 0; j < nHeight;j++) { 
		for (int i = 0; i < nWidth; i++) {
			if (fm[j * nPitch + i] == 0) { // 좌표의 픽셀 값이 0인지(점이 찍혀 있는지) 확인
				// 찍힌 점을 찾았다면, 그 점의 좌표를 m_ptData 배열에 저장함
				if (m_pDlgImgResult->m_nDataCount <= 100) { // 먼저 m_nDataCount가 100 이하인지 확인(배열의 크기가 100이므로)
					m_pDlgImgResult->m_ptData[nIndex].x = i; // 찾은 점의 x 좌표를 배열에 저장
					m_pDlgImgResult->m_ptData[nIndex].y = j; // 찾은 점의 y 좌표를 배열에 저장
					// m_nDataCount 값을 1씩 증가시키며, 동시에 nIndex값을 1 증가시킨다. (++nIndex의 결과는 nIndex 증가 후의 값이므로)
					m_pDlgImgResult->m_nDataCount = ++nIndex; 
				}	
			}
		}
	}

	// 이미지 잘 가져왔는지 테스트
	// 뒤의 숫자는 얼만큼 칠할것인지
	// memset(fm, 0, 640 * 480); // 메모리셋에 fm(이미지포인터), 뒤에오는 것은 값: 

	// 화면에 업데이트
	m_pDlgImage->Invalidate(); // 왼쪽 화면 업데이트
	m_pDlgImgResult->Invalidate(); // 오른쪽 화면 업데이트
}

 

그리고 코드를 실행하면 Test 버튼을 클릭할 때마다 왼쪽에 찍힌 랜덤값에 따라 오른쪽에 원이 생성된다.


CPen Class로 색 변경, 굵기 바꾸기

void CDlgImage::datwData(CDC* pDC) 
{
	CRect rect;
	CPen pen; // 선 객체 생성
	pen.CreatePen(PS_SOLID, 1, RGB(0xff, 0, 0)); // 실선, 두께, 빨간색
	CPen* pOldPen = pDC->SelectObject(&pen); // 현재 펜 저장

	for (int i = 0; i < m_nDataCount; i++) {
		rect.SetRect(m_ptData[i], m_ptData[i]);  // 좌표값 설정
		rect.InflateRect(5, 10); // 좌로 5만큼, 우로 10만큼 벌린다
		pDC->Ellipse(rect); //원을 그린다

	}

	pDC->SelectObject(pOldPen); // 저장해 둔 펜 가져오기
}

 

profile

소연의_개발일지

@ssoyxon

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!