티스토리 뷰

프로그래밍/MFC 프로그래밍

[MFC C++] 이미지 RGB 분리

주식하는 개발자 2020. 1. 19. 17:02

[MFC C++] 이미지 RGB 분리

 

오늘은 사용자가 원하는 외부 이미지를 출력시키고

그이미지의 RGB를 분리해 각각 R이미지, G이미지, B이미지

3개를 출력시키는 예제를 만들어 보겠습니다.

 

 

[출력 결과]

 

좌 상 : 원본 이미지 , 우 상 : R값

좌 하 : G값           , 우 하 : B값

 

 

 

 

가장 먼저 앞선 예제에서 많이 했던

외부 이미지를 다이얼로그에 출력시키는 방법을 설명드리겠습니다.

 

 

[소스 코드]

 

(원본 이미지 출력)

변수를 설정해 주기위해

먼저 Dlg.h 파일이 있는 헤더파일에

아래처럼 변수를 추가시켜줍니다.

CImage 변수인 m_image

CImage는 이미지를 저장시켜줄 수 있는 변수입니다.

private 형식으로 추가시켜줍니다.

 

class CRGBexamDlg : public CDialogEx
{
private:
    CImage m_image;
cs

 

 

 

 

 

다음으로 Dlg.cpp 파일이 있는 소스 파일에

코드를 추가시켜줘야합니다.

Dlg.cpp 파일에 OnInitDialog()가 있는 곳에 가서

아래처럼 코드를 추가시켜줍니다.

m_image.Load(L"test.bmp");

사용자가 출력시킬 이미지가

소스파일이 있는 폴더에 저장되어있어야 합니다.

(또한, bmp 파일로 저장되어있어야 합니다.)

그러면 사용자가 저장해둔 이미지가 m_image에 로드까지 되게 됩니다.

 

BOOL CRGBexamDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
 
    SetIcon(m_hIcon, TRUE);          
    SetIcon(m_hIcon, FALSE);       
 
    m_image.Load(L"test.bmp");
 
    return TRUE;  
}
cs

 

 

 

 

 

그 후 사용자가 원하는 이미지를 출력시켜주기 위해

OnInitDialog() 아래쪽에 있는

OnPaint에 가서 아래와 같이 코드를 추가시켜줍니다.

 

CPaintDC를 else문에도 적용되게 밖으로 빼주었습니다.

그리고 else문의 CDialogEx::OnPaint(); 요거를

주석처리해줍니다.

마지막으로 m_image.draw를 사용해 0,0 좌표에 외부 이미지를 그려줍니다.

m_image.Draw(dc, 0, 0);

 

void CRGBexamDlg::OnPaint()
{
    CPaintDC dc(this); // 그리기를 위한 디바이스 컨텍스트입니다.
    if (IsIconic())
    {
        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
 
        // 클라이언트 사각형에서 아이콘을 가운데에 맞춥니다.
        int cxIcon = GetSystemMetrics(SM_CXICON);
        int cyIcon = GetSystemMetrics(SM_CYICON);
        CRect rect;
        GetClientRect(&rect);
        int x = (rect.Width() - cxIcon + 1/ 2;
        int y = (rect.Height() - cyIcon + 1/ 2;
 
        // 아이콘을 그립니다.
        dc.DrawIcon(x, y, m_hIcon);
    }
    else
    {
        m_image.Draw(dc, 00);
        //CDialogEx::OnPaint();
    }
}
cs

여기까지가 외부이미지를 출력시키는 방법이었습니다.

 


(RGB 분리한 이미지 출력)

 

다음으로 RGB가 분리된 이미지

3개를 출력시키는 방법에대해 소개드리겠습니다.

 

 

앞서 원본이미지를 저장하기위해 만들었던

헤더파일의 m_image 변수 밑에

이미지 변수 3개를 추가시켜 줍니다.

CImage m_r_image, m_g_image, m_b_image;

r이미지, g이미지, b이미지를 저장해줄 변수들입니다.

 

class CRGBexamDlg : public CDialogEx
{
private:
    CImage m_image;
    CImage m_r_image, m_g_image, m_b_image;
cs

 

 

 

 

다음 다시 소스파일의 cpp파일에 가줍니다.

cpp파일의 OnInitDialog()에 가서

방금 만들어준 m_r_image, m_g_image, m_b_image를 각각 create를 사용해

원본 이미지와 크기가 똑같은 빈 이미지를 create 해줍니다.

m_r_image.Create(m_image.GetWidth(), m_image.GetHeight(), m_image.GetBPP(), 0);

m_g_image.Create(m_image.GetWidth(), m_image.GetHeight(), m_image.GetBPP(), 0);

m_b_image.Create(m_image.GetWidth(), m_image.GetHeight(), m_image.GetBPP(), 0);

이렇게 하면 원본 이미지와 똑같은 크기의 빈 이미지가 만들어지게됩니다.

빈 도화지가 만들어진다고 생각하시면됩니다.

이제 도화지에 그림을 그려주는 방법에대해 설명드리겠습니다.

 

BOOL CRGBexamDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();
 
    // 이 대화 상자의 아이콘을 설정합니다.  응용 프로그램의 주 창이 대화 상자가 아닐 경우에는
    //  프레임워크가 이 작업을 자동으로 수행합니다.
    SetIcon(m_hIcon, TRUE);            // 큰 아이콘을 설정합니다.
    SetIcon(m_hIcon, FALSE);        // 작은 아이콘을 설정합니다.
 
    m_image.Load(L"test.bmp");
    m_r_image.Create(m_image.GetWidth(), m_image.GetHeight(), m_image.GetBPP(), 0);
    m_g_image.Create(m_image.GetWidth(), m_image.GetHeight(), m_image.GetBPP(), 0);
    m_b_image.Create(m_image.GetWidth(), m_image.GetHeight(), m_image.GetBPP(), 0);
 
    return TRUE;  // 포커스를 컨트롤에 설정하지 않으면 TRUE를 반환합니다.
}
cs

 

 

 

 

저는 버튼이 눌리면 3개의 이미지가 출력되게 만들어주겠습니다.

버튼을 만들기 위해 리소스 뷰의 Dialog에가줍니다.

도구 상자에 버튼 하나를 가져와 다이얼로그에 그려줍니다.

 

버튼이 눌렸을 때

rgb가 분리된 이미지가 출력되는 이벤트를 발생시키기 위해

함수를 만들어줘야 하는데

버튼을 더블클릭해주면 소스파일에 해당 함수가 생기게 됩니다.

더블클릭후 생기는 함수에 아래와 같이 코드를 추가시켜줍니다.

 

void CRGBexamDlg::OnBnClickedButton1()
{
 
    CClientDC dc(this);
    int h = m_image.GetHeight();
    int w = m_image.GetWidth();
 
    for (int i = 0; i < h; i++)
    {
        for (int j = 0; j < w; j++) {
            COLORREF color = m_image.GetPixel(j, i);
            m_r_image.SetPixel(j, i, RGB(GetRValue(color), 0, 0));
            m_g_image.SetPixel(j, i, RGB(0, GetGValue(color), 0));
            m_b_image.SetPixel(j, i, RGB(0, 0, GetBValue(color)));
        }
    }
    m_r_image.Draw(dc, 650, 0);
    m_g_image.Draw(dc, 0, 400);
    m_b_image.Draw(dc, 650, 400);
 
}
 
cs

 

위의 소스 코드를 설명드리겠습니다.

h, w 변수는 원본 이미지인 m_image의 가로길이와 세로 길이를 저장해줄 변수입니다.

GetHeight와 GetWidth를 사용하면 이미지의

높이와 가로 픽셀을 얻을 수 있습니다.

 

SetPixel을 사용하면 빈도화지에 그림을 그려넣어줄 수 있습니다.

아까 전 create해준 빈 이미지에

이중 for문을 돌리면서 픽셀 값을 넣어줍니다.

 

그러면 for문이 돌면서 해당 좌표에

각 이미지 변수에 바뀐 이미지가 들어가게 되고

draw를 사용해 원하는 좌표에 출력시켜줍니다.

여기서 GetRValue는 해당 픽셀의 R값을 가져오는 함수입니다.

GetGValue, GetBValue 도 마찬가지로 쓰입니다.

 

 

 

여기까지 코드 적용이 완료되었습니다.


[결과 출력]

 

그럼 위와 같은 그림이 출력되게 됩니다~:)