이전 포스팅 에서는 Z 방향으로 MIP 를 만들어 보았는데, X 방향 Y 방향 또는 어떤 방향에서도
MIP 를 만들 수 있다.
작업을 수행하기 전에,
코드를 유연하게 만들기 위해 Volume 이미지로 하는 작업을 클래스로 만들어 캡슐화 해보자.
이전 구조는 Doc 에서 Volume class 를 부르는 구조 였는데 이제 Doc 에서는 Renderer 클래스를 호출하고 Rendere 클래스가 Volume 관련 작업을 하도록 바꿔보자.
VolumeRendererDoc.h
#pragma once
// #include "Volume.h"
#include "Renderer.h"
#include <memory>
using namespace std ;
class CVolumeRendererDoc : public CDocument
{
private:
//shared_ptr<Volume> m_pVolume;
shared_ptr < Renderer > m_pRenderer ;
}
VolumeRendererDoc.cpp
...
BOOL CVolumeRendererDoc :: OnNewDocument ()
{
...
//m_pVolume = shared_ptr<Volume>(new Volume(temp_vol,width,height, depth));
m_pRenderer = shared_ptr < Renderer > ( new Renderer ( temp_vol , width , height , depth ));
...
}
이제 Rendere Class 를 만들자.
Renderer.h
#include "Volume.h"
#include <memory>
using namespace std ;
class Renderer
{
private:
shared_ptr < Volume > m_pVolume ;
public:
Renderer ();
Renderer ( unsigned char * volume , int width , int height , int depth );
~ Renderer ();
}
Renderer.cpp
#include "stdafx.h"
#include "Renderer.h"
Renderer :: Renderer ()
{
m_pVolume = nullptr ;
}
Renderer :: Renderer ( unsigned char * volume , int width , int height , int depth )
{
m_pVolume = shared_ptr < Volume > ( new Volume ( volume , width , height , depth ));
}
Renderer 클래스를 거의 다 만들었다. 이제 기능만 추가해서 넣어주면 된다.
X, Y, Z 방향으로 잘라서 보여주는 기능을 만들어보자.
VolumeRendererDoc.cpp
void CVolumeRendererDoc :: OnSlicerenderingXdirection ()
{
// 이미지 버퍼를 만들어 넣어주고
// Renderer 클래스 함수에서 채워서 바깥으로 던지는 방식으로 만들 것이다.
const int img_width = 256 ;
const int img_height = 256 ;
shared_ptr < unsigned char > image =
shared_ptr < unsigned char > ( new unsigned char [ img_width * img_height ]);
// x 좌표를 넣어주어서 x 좌표 중 어느 부분을 보여줄지 정한다.
m_pRenderer -> RenderSliceXDirection ( image . get (), img_width , img_height , 120 );
CVolumeRendererView * pView =
( CVolumeRendererView * )(( CMainFrame * )( AfxGetApp () -> m_pMainWnd )) -> GetActiveView ();
pView -> SetDrawImage ( image . get (), img_width , img_height , 1 );
pView -> OnInitialUpdate ();
}
Renderer.cpp
bool Renderer :: RenderSliceXDirection ( unsigned char * image ,
const int img_width , const int img_height , const int depth )
{
int vol_height = m_pVolume -> GetHeight ();
int vol_depth = m_pVolume -> GetDepth ();
for ( int i = 0 ; i < vol_height ; i ++ )
{
for ( int j = 0 ; j < vol_depth ; j ++ )
image [ j * img_width + i ] = m_pVolume -> GetVoxel ( depth , i , j );
}
return true ;
}
Y 방향 Z 방향은 위와 같으므로 알아서 만들어보자.
MIP 를 Y뱡향과 X 방향으로 만들어보자.
VolumeRendererDoc.cpp
void CVolumeRendererDoc :: OnMiprenderingXdirection ()
{
// TODO: 여기에 명령 처리기 코드를 추가합니다.
int img_width = 256 ;
int img_height = 256 ;
shared_ptr < unsigned char > image =
shared_ptr < unsigned char > ( new unsigned char [ img_width * img_height ]);
memset ( image . get (), 0 , sizeof ( unsigned char ) * img_width * img_height );
m_pRenderer -> RenderMIPXDirection ( image . get (), img_width , img_height );
CVolumeRendererView * pView =
( CVolumeRendererView * )(( CMainFrame * )( AfxGetApp () -> m_pMainWnd )) -> GetActiveView ();
pView -> SetDrawImage ( image . get (), img_width , img_height , 1 );
pView -> OnInitialUpdate ();
}
Renderer.cpp
bool Renderer :: RenderMIPXDirection ( unsigned char * image ,
const int width , const int height )
{
int vol_width = m_pVolume -> GetWidth ();
int vol_height = m_pVolume -> GetHeight ();
int vol_depth = m_pVolume -> GetDepth ();
for ( int j = 0 ; j < vol_depth ; j ++ )
{
for ( int i = 0 ; i < vol_height ; i ++ )
{
unsigned char max_value = 0 ;
for ( int k = 0 ; k < vol_width ; k ++ )
{
max = __max ( max_value , m_pVolume -> GetVoxel ( k , i , j ));
}
image [ width * j + i ] = max ;
}
}
}
같은 방식으로 Y 방향기능만 구현해보면 아래와 같다.
Renderer.cpp
bool Renderer :: RenderMIPYDirection ( unsigned char * image ,
const int width , const int height )
{
int vol_width = m_pVolume -> GetWidth ();
int vol_height = m_pVolume -> GetHeight ();
int vol_depth = m_pVolume -> GetDepth ();
for ( int j = 0 ; j < vol_depth ; j ++ )
{
for ( int i = 0 ; i < vol_width ; i ++ )
{
unsigned char max_value = 0 ;
for ( int k = 0 ; k < vol_height ; k ++ )
{
max = __max ( max_value , m_pVolume -> GetVoxel ( i , k , j ));
}
image [ width * j + i ] = max ;
}
}
}
MIP X-direction 은 아래와 같고
MIP Y-direction 은 아래와 같다.