더북(TheBook)

6.4.3 대화 상자에 히스토그램 그리기

히스토그램 대화 상자에 영상의 히스토그램을 그려주기 위해서는 CHistogramDlg 클래스에 몇 가지 작업을 해주어야 한다. 다음의 순서로 작업을 시작해보자.

① 히스토그램을 저장할 배열 추가

② 영상의 정보를 넘겨받아 히스토그램 구하기

③ 히스토그램을 그리기

먼저 히스토그램을 저장할 배열을 추가하자 히스토그램은 256개의 원소를 필요로 하고, 이를 화면에 출력하기 위해서는 int형의 배열이 적합할 것 같다. 그러므로 CHistogramDlg 클래스에 다음과 같은 멤버 변수를 하나 추가하자.

int m_Histogram[256];

그리고 CHistogramDlg 클래스의 생성자에 m_Histogram 배열을 초기화하는 코드를 추가하자. 소스 6-17을 참고하라.

소스 6-17 CHistogram 생성자에서 m_Histogram 배열 초기화(HistogramDlg.cpp)
CHistogramDlg::CHistogramDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(IDD_HISTOGRAM, pParent)
{
    memset(m_Histogram, 0, sizeof(int) * 256);
}

m_nHistogram 배열에는 입력 영상의 히스토그램 정보를 저장할 것이다. 그러나 m_nHistogram 배열은 히스토그램의 화면 출력을 목적으로 만든 멤버 변수이기 때문에, 최대 히스토그램의 값이 100이 되도록 크기를 정규화하여 저장할 것이다. 추후 실제 히스토그램을 그릴 때, 가장 큰 히스토그램의 크기가 100픽셀로 그려질 것이다.

다음으로 영상의 정보를 전달받을 멤버 함수를 하나 만들어보자. HistogramDLG.h 파일에 SetImage라는 이름의 멤버 함수 선언을 추가하자. 이때 SetImage 함수는 다른 클래스에서도 호출이 가능하도록 접근 지시자를 public으로 선언해야 한다.

public:
    void SetImage(IppDib* pDib);

SetImage 함수는 IppDib 클래스의 포인터를 인자로 받는다. 이 함수는 전달받은 영상으로부터 히스토그램을 구하여 그 결과를 m_Histogram 배열에 저장하는 역할을 담당한다. 만약 전달받은 포인터 인자가 NULL이거나 또는 가리키는 영상이 그레이스케일 영상이 아니면 m_Histogram 배열 값을 모두 0으로 초기화한다. SetImage 함수의 구현은 소스 6-18을 참고하라.

소스 6-18 SetImage 함수의 구현(HistogramDlg.cpp)
#include "IppImage\IppDib.h"
#include "IppImage\IppImage.h"
#include "IppImage\IppConvert.h"
#include "IppImage\IppEnhance.h"void CHistogramDlg::SetImage(IppDib* pDib)
{
    if (pDib != NULL && pDib->GetBitCount() == 8)
    {
        IppByteImage img;
        IppDibToImage(*pDib, img);

        // 정규화된 히스토그램을 구한다.
        float histo[256] = { 0.f, };
        IppHistogram(img, histo);

        // 정규화된 히스토그램에서 최댓값을 구한다.
        float max_histo = histo[0];
        for (int i = 1; i < 256; i++)
            if (histo[i] > max_histo) max_histo = histo[i];

        // m_Histogram 배열의 최댓값이 100이 되도록 전체 배열의 값을 조절한다.
        for (int i = 0; i < 256; i++)
        {
            m_Histogram[i] = static_cast<int>(histo[i] * 100 / max_histo);
        }
    }
    else
    {
        memset(m_Histogram, 0, sizeof(int) * 256);
    }
}

SetImage 함수에서는 먼저 float 자료를 256개 저장할 수 있는 배열 histo를 선언하였다. 그리고 앞에서 만든 IppHistogram 함수를 이용하여 정규화된 히스토그램을 histo 배열에 저장하였다. histo 배열에는 정규화된 히스토그램을 나타내는 0부터 1 사이의 실숫값이 저장되어 있기 때문에, 히스토그램을 그리기 위해서는 histo 배열을 적당한 크기로 스케일링 해주어야 한다. 그러므로 SetImage 함수에서는 히스토그램 확률 값 중에서 가장 큰 값이 100픽셀의 크기가 되도록 스케일을 변경한 후, 정수형 배열인 m_Histogram에 그 값들을 저장하였다.

신간 소식 구독하기
뉴스레터에 가입하시고 이메일로 신간 소식을 받아 보세요.