태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

[Vision] View Manager Class - 뷰 관리자 클래스

Posted on 2008.05.25 22:10
Filed Under Project


 

1. 요 약#

MFC MDI Multi-View, Single-Document 구조로 프로젝트를 진행하면서 ChildWindow 의 인터페이스를 제공하는 클래스를 제작하였습니다.

사실 초기에는 ChildWindow 의 DC에 대한 입출력을 관리하는 목적으로 ViewManager 라고 네이밍을 달았는데 점점 여러가지 인터페이스가 추가되면서 의미가 완전 틀려졌네요. 이름을 짓자면 ChildManager 이 적당할 듯 합니다.


2. 구 현#

[code]/* 2008.04.03 Furyheimdall - View Manager Class */
#pragma once
#include "afxwin.h"
#include "../../ChildFrm.h"
#include <cv.h>
#include <highgui.h>

class CViewManager
{
public:
    void Init(CFrameWnd*);              //객체 초기화 (출력할 윈도우의 핸들)
    void IplRegister(IplImage* ptr);           //IPL 이미지 데이터 등록
    void ReleaseView();               //객체 해제
    void ShowImage(CDC* pDC = NULL);         //DC에 이미지 출력
    void SetImageSize(int mode, int x, int y=NULL);          //이미지 출력 비율 변경
    void UpdateScreen();              //윈도우 사이즈를 현재 비율에 맞도록 갱신

public:
 enum { modeAbsolute , modeRelative };


public:
    CChildFrame *IDentity;
    CView *View;
    IplImage* IplData;
    CClientDC* dc;
    LPBITMAPINFO  BitmapInfo;             //CViewOut 객체의 입/출력 비트맵 정보
    int m_iWidth;                  //출력공간 너비
    int m_iHeight;                  //출력공간 높이
    int m_RateWidth;                //너비 비율
    int m_RateHeight;                //높이 비율
};[/code]

ViewManager 클래스의 헤더입니다.

기본적으로 afxwin.h 를 포함하고 있으며 ChildFrame 의 헤더를 포함하고 있습니다.

그리고 OpenCV 자료구조를 사용하기 때문에 OpenCV 헤더도 포함합니다.

메소드, 속성정의, 변수(객체) 순으로 선언해놨습니다.

 [code]/* 2008.04.03 Furyheimdall - ViewManager Class */
#pragma once
#include "StdAfx.h"
#include "ViewManager.h"

void CViewManager::Init(CFrameWnd* Object)     //객체 초기화 (차일드프레임 포인터)
{
    //차일드 프레임에서 뷰포인터를 가져오고 차일드 포인터를 복사
    View = Object->GetActiveView();
    IDentity = dynamic_cast<CChildFrame*>(Object);
    //뷰 포인터에서 DC를 가져옴
    dc = new CClientDC(View);
    m_RateWidth = 100;
    m_RateHeight = 100;
    m_iHeight = 0;
    m_iWidth = 0;
    //Bitmap 구조체 초기화
    BitmapInfo=NULL;
    BitmapInfo = reinterpret_cast<BITMAPINFO*>(new char[sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD)]);
    BitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
    BitmapInfo->bmiHeader.biPlanes = 1;
    BitmapInfo->bmiHeader.biCompression = BI_RGB;   
    BitmapInfo->bmiHeader.biXPelsPerMeter = 0;
    BitmapInfo->bmiHeader.biYPelsPerMeter = 0;
    BitmapInfo->bmiHeader.biClrUsed = 256;
    BitmapInfo->bmiHeader.biClrImportant = 0;
    int i;
    for(i=0;i<256;i++)
    {
        BitmapInfo->bmiColors[i].rgbRed=(UINT8)i;
        BitmapInfo->bmiColors[i].rgbGreen=(UINT8)i;
        BitmapInfo->bmiColors[i].rgbBlue=(UINT8)i;
        BitmapInfo->bmiColors[i].rgbReserved=0;
    }
}

void CViewManager::IplRegister(IplImage* ptr)
{
    IplData = ptr;
    SetImageSize(CViewManager::modeAbsolute,100);
}

void CViewManager::ReleaseView()
{
    delete []BitmapInfo;
    dc->DeleteDC();
}

void CViewManager::ShowImage(CDC* pDC)     //DC에 이미지 출력
{
    /* IplImage 로 부터 비트카운트 계산후 비트맵 헤더 적용 */
    BitmapInfo->bmiHeader.biBitCount = IplData->depth * IplData->nChannels;
    BitmapInfo->bmiHeader.biWidth = m_iWidth;
    BitmapInfo->bmiHeader.biHeight =-m_iHeight;
    if(IplData->depth == 24)
        BitmapInfo->bmiHeader.biSizeImage = m_iWidth * m_iHeight * 3; 
    if(IplData->depth == 8)
        BitmapInfo->bmiHeader.biSizeImage = m_iWidth * m_iHeight;
    /* 리사이즈 이미지 계산 */
    IplImage* ResizeImage = cvCreateImage(cvSize(m_iWidth,m_iHeight),IplData->depth,IplData->nChannels);
    cvResize(IplData,ResizeImage);
    /* 화면에 출력 */
    if(pDC == NULL){
        View->OnPrepareDC(dc);
        ::StretchDIBits(dc->GetSafeHdc(),0,0,m_iWidth ,m_iHeight ,0,0,m_iWidth,m_iHeight,ResizeImage->imageData,BitmapInfo,DIB_RGB_COLORS,SRCCOPY);
    }
    else {
        ::StretchDIBits(pDC->GetSafeHdc(),0,0,m_iWidth ,m_iHeight ,0,0,m_iWidth,m_iHeight,ResizeImage->imageData,BitmapInfo,DIB_RGB_COLORS,SRCCOPY);
    }
    cvReleaseImage(&ResizeImage);
}

void CViewManager::SetImageSize(int mode, int x, int y)
{
    if(mode == CViewManager::modeRelative){
        m_RateHeight += x;
        m_RateWidth += y;
    }
    else if (mode == CViewManager::modeAbsolute) {
        m_RateHeight = x;
            m_RateWidth = x;
    }
    m_iHeight = static_cast<int>(IplData->height * (m_RateHeight/100.0));
    m_iWidth= static_cast<int>(IplData->width * (m_RateWidth/100.0));
}

void CViewManager::UpdateScreen()
{
    CRect r;
    IDentity->GetWindowRect(&r);
    r.top -= 160;  //Main Frame Ribbon Size
    r.left -= 5;   //Main Frame left boader size
    r.right = m_iWidth + r.left + BOADER_SIZE*2;
    r.bottom = m_iHeight + r.top + BOADER_SIZE+PANNEL_SIZE;
    IDentity->MoveWindow(&r);
    View->Invalidate();
}[/code]

Init 에서 ChildFrame 에 대한 포인터를 받아서 View 와 ChildFrame 그리고 DC 를 추출하여 ViewManager 에서 보관하게 됩니다.

그리고 2nd-Phase 생성자라고 볼 수 있는  IplRegister 메소드를 통해 ViewManager 클래스로 생성된 객체에게 자신이 그려야 할 이미지 정보를 넘겨줍니다.

이후 ShowImage() 를 통해 ChildWindow 에 이미지 출력이나 SetImageSize 를 통해 이미지 출력비율, 크기 변경, 그리고 추가적으로 인터페이스를 생성 할 수 있게 됩니다.


3. 문제점#

정리가 되지 않은 코드라 시험적으로 추가했던 흔적들이 많이 남아있습니다.

윈도우 위치, 사이즈 경우는 임의로 직접 픽셀값을 체크하여 정확하게 넣은건데 Windows XP 의 윈도우 크기에 영향을 받더군요.

결국 정확한 윈도우 사이즈를 구하기 위한 코드를 다른 어디에 추가하여 그 값을 기준으로 변경해야 할 듯 합니다.

그리고 전체적인 프로그래밍을 간편하기 위해 직접 OpenCV 자료형을 코드에서 사용하기 때문에 의존적인 클래스가 되었습니다.

댓글을 달아 주세요

About



모바일 페이지 QR 코드

Counter

· Total
: 510,599
· Today
: 15
· Yesterday
: 10


DNS server, DNS service