MFC Dialog에 image load

예갈조·2024년 12월 4일

Tumor Track Project

목록 보기
1/25

결과



코드


CreateBItmapInfo()


  • 이미지 너비(w), 높이(h), 비트깊이(bpp)를 사용하여 BITMAPINFO 구조체 초기화하고 비트맵 정보를 생성
  • 이미지 형태를 BITMAPINFO 형식으로 변환하여 화면에 출력하기 위한 정보 설정을 도움
void COpenCVTest1Dlg::CreateBitmapInfo(int w, int h, int bpp) {
	// 1. 기존 메모리 삭제
	// m_pBitmapInfo가 이미 할당되어 있는 경우, 메모리를 해제하여 메모리 누수 방지
	// delete[]를 사용하여 배열 형태로 할당된 메모리 해제
	if (m_pBitmapInfo != NULL) {
		delete[] m_pBitmapInfo;
		m_pBitmapInfo = NULL;
	}
	
	/*================================*/
	// 2. 메모리 할당
	// bpp(비트 깊이)가 8비트인 경우 색상을 추가해줘야 함
	// + 뒤 코드: 색상 추가 코드
	if (bpp == 8) {
		m_pBitmapInfo = (BITMAPINFO *)new BYTE[sizeof(BITMAPINFO) + 255 * sizeof(RGBQUAD)];
	}
	// 24 or 32bit: 색상 팔레트 필요x
	else {
		m_pBitmapInfo = (BITMAPINFO *)new BYTE[sizeof(BITMAPINFO)];
	}
	
	/*================================*/
	// 3. BITMAPINFOHEADER 초기화
	m_pBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
	m_pBitmapInfo->bmiHeader.biPlanes = 1; // 비트맵 평면 수: 항상 1로 설정
	m_pBitmapInfo->bmiHeader.biBitCount = bpp;
	m_pBitmapInfo->bmiHeader.biCompression = BI_RGB; // 압축 방식 설정. 현재 압축 없음
	m_pBitmapInfo->bmiHeader.biSizeImage = 0;
	m_pBitmapInfo->bmiHeader.biXPelsPerMeter = 0;
	m_pBitmapInfo->bmiHeader.biYPelsPerMeter = 0;
	m_pBitmapInfo->bmiHeader.biClrUsed = 0;
	m_pBitmapInfo->bmiHeader.biClrImportant = 0;
	
	/*================================*/
	// 4. 색상 팔레트 초기화 (8비트 경우)
	if (bpp == 8)
	{
		for (int i = 0; i < 256; i++)
		{
			m_pBitmapInfo->bmiColors[i].rgbBlue = (BYTE)i;
			m_pBitmapInfo->bmiColors[i].rgbGreen = (BYTE)i;
			m_pBitmapInfo->bmiColors[i].rgbRed = (BYTE)i;
			m_pBitmapInfo->bmiColors[i].rgbReserved = 0;
		}
	}
	
	/*================================*/
	// 5. 비트맵 너비 및 높이 설정
	m_pBitmapInfo->bmiHeader.biWidth = w;
	// 이미지가 상하 반전 없이 위쪽에서 아래쪽으로 렌더링되도록 함
	m_pBitmapInfo->bmiHeader.biHeight = -h; 
}

DrawImage()


  • MFC 다이얼로그의 IDC_PC_VIEW에 OpenCV 이미지를 표시하기 위한 코드
  • OpenCV에서 사용하는 Mat 형식의 이미지 데이터를 MFC의 CDC 객체를 통해 출력
void COpenCVTest1Dlg::DrawImage() {
	// 1. CClientDC 생성 및 컨트롤 핸들 지정
	CClientDC dc(GetDlgItem(IDC_PC_VIEW));

	// 2. 컨트롤의 클라이언트 영역 크기 가져오기
	CRect rect;
	GetDlgItem(IDC_PC_VIEW)->GetClientRect(&rect);

	// 3. 이미지 출력 모드 설정
	SetStretchBltMode(dc.GetSafeHdc(), COLORONCOLOR);
	
	// 4. 이미지 출력
	StretchDIBits(dc.GetSafeHdc(), 0, 0, rect.Width(), rect.Height(), 
	0, 0, m_matImage.cols, m_matImage.rows, 
	m_matImage.data, m_pBitmapInfo, DIB_RGB_COLORS, SRCCOPY);
}

OnClickedBtnImageload()


  • 이벤트 핸들러
  • 사용자가 선택한 이미지를 불러와 다이얼로그의 특정 영역에 표시하는 역할
// Load Image 버튼에 클릭 이벤트 추가
void COpenCVTest1Dlg::OnClickedBtnImageload()
{
	// 1. 파일 다이얼로그 열기 
	CFileDialog fileDlg(TRUE, NULL, NULL, OFN_READONLY, 
		_T("image file(*.jpg;*.bmp;*.png;)|*.jpg;*.bmp;*.png;|All Files(*.*)|*.*||"));
	
	// 2. 파일 선택 여부 확인
	if (fileDlg.DoModal() == IDOK)
	{
		// 3. 파일 경로 가져오기
		CString path = fileDlg.GetPathName();

		// 4. CString을 string으로 변환
		CT2CA pszString(path);
		std::string strPath(pszString);
		
		// 5. OpenCv를 이용해 이미지 로드
		m_matImage = imread(strPath, IMREAD_UNCHANGED);
		
		// 6. 비트맵 정보 생성
		CreateBitmapInfo(m_matImage.cols, m_matImage.rows, m_matImage.channels() * 8);
		
		// 7. 이미지 출력
		DrawImage();
	}
}

참고자료


https://luckygg.tistory.com/117

0개의 댓글