- 이 부분에 대한 소스 코드는 다음 파일에서 찾을 수 있다
- Examples/IO/ImageReadWrite.cxx
- 이미지를 읽고 쓰는 책임을 지는 클래스들은 데이터 처리 파이프 라인의 시작과 끝에 위치한다
- 이 클래스들은 데이터 소스 (readers)와 데이터 싱크 (writers)로 알려져 있다
- 일반적으로 말해서 그것들은 필터로 언급되지만 reader는 어떤 파이프 라인 입력도 갖지 않고, writer 는 어떤 파이프라인 출력도 갖지 않는다
- 이미지의 읽기는 itk::ImageFileReader 클래스에 의해 관리되는 반면에 쓰기는 itk::ImageFileWriter 클래스에 의해 수행된다
- 이 두 개의 클래스들은 어떤 특별한 파일 포맷에 독립적이다
- 특별한 파일 포맷을 읽고 쓰는 실제 낮은 레벨의 일은 itk::ImageIO 타입의 클래스 그룹에의 해 씬 뒤에서 수행된다
- 읽기와 쓰기를 수행하는 첫번째 단계는 다음 헤더를 포함한다
#include "itkImageFileReader.h"
#include "itkImageFileWriter.h"
- 그리고 나서 보통 결정은 파이프 라인에 의 해 진행되는 이미지를 나타내는데 사용되는 픽셀의 타입에 관해 만들어져야 한다
- 이미지를 읽고 쓸 때 이미지의 픽셀 타입이 파일에 저장하는 픽셀 타입과 필수적으로 같지 않아도 된다는 것에 주목하라
- 픽셀 타입에 대한 선택(과 템플릿 파라미터)은 두 가지 요인에 의해 주로 유도되어야 한다
- 파일에서 파일 픽셀 타입을 선택한 픽셀로 변경하는 것이 가능해야만 한다 이 변환은 표준 C 언어 규칙을 사용하여 수행될 것이고, 그래서 변경이 정보를 손실하는 결과가 안 되도록 확실하게 해야 할 것이다
- 메모리에서 픽셀 타입은 이미지에 적용하기 위해 의도된 처리 과정의 타입으로 적절하게 수행되어야 한다
- 의료 이미지에 대한 전형적인 선택은 다음 줄에서 예시를 볼 수 있다
typedef unsigned short PixelType;
const unsigned int Dimension = 2;
typedef itk::Image< PixelType, Dimension > ImageType
- 메모리에서 이미지의 차원은 파일에서 이미지의 차원에 대응해야 한다
- 여기에서 조건이 완화되는 두 가지의 경우가 있지만, 일반적으로 차원을 둘 다 일치시키는 것을 보장하는 것이 더 낫다
- reader와 writer의 타입의 예를 볼 수 있다 이 두 개의 클래스는 이미지 타입에 의해 파라미터화 된다
typedef itk::ImageFileReader<ImageType> ReaderType;
typedef itk::ImageFileWriter<ImageType> WriterType;
- 그리고 나서, New() 메서드를 사용하여 각 타입의 객체를 생성하고 itk::SmartPointer 에 결과를 할당한다
ReaderType::Pointer reader = ReaderType::New();
WriterType::Pointer writer = WriterType::New();
- 읽거나 또는 쓰려는 파일의 이름이 SetFileName() 메서드로 넘겨진다
reader->SetFileName( inputFileName );
writer->SetFileName( outputFileName );
- 이 reader와 writer를 파이프 라인을 생성하기 위해 필터에 연결할 수 있다
- 예를 들면, writer의 입력에 직접 reader의 출력을 넘기므로써 짧은 파이프 라인을 생성할 수 있다
writer->SetInput( reader->GetOutput() );
- 첫 번째에서 이것은 매우 쓸모없는 프로그램처럼 보일 수도 있지만, 실제로 강력한 파일 포맷 변경 도구를 구현하는 중이다
- 파이프 라인의 실행은 마지막 객체 중의 하나에서 Update 메서드를 호출함으로써 일으킨다
- 이 경우에, 마지막 데이터 파이프라인 객체는 writer이다
- 파이프 라인의 실행 동안 예외가 던져지는 경우에 try/catch 블록 안에 Update() 호출을 넣음으로써 방어적인 프로그래밍의 넓은 연습이다
try
{
writer->Update();
}
catch( itk::ExceptionObject& err)
{
std::cerr << "ExceptionObject caught ! " << std::endl;
std::cerr << err << std::endl;
return EXIT_FAILURE;
}
- 예외는 그것들을 가지고 무엇을 하는지 아기 위한 코드의 조각에 의해 오직 잡혀야만 한다는 것에 주목하라
- 전형적인 응용 프로그램에서 이 catch 블록은 GUI 코드 위에 아마도 올라가야 한다
- catch 블록에서의 액션은 IO 연산의 실패에 관해 사용자에게 알릴 수 있다
- 툴킷의 IO 아키텍처는 이미지를 읽기 또는 쓰기 위해 사용되는 파일 포맷의 명시적인 지정을 피하는 것을 가능하게 한다
- 객체 팩토리 메커니즘은 ImageFileRead와 ImageFileWriter가 어느 파일 포맷을 적용하는지 결정하는 것을 가능하게 한다
- 전형적으로, 파일 포맷은 파일 확장자에 기초하여 선택되지만, 아키텍처는 파일을 읽을 수, 또는 쓸 수 있는지 아닌지 결정하는 임의의 복잡한 과정을 지원한다
- 대안으로, 사용자는 명시적인 인스턴스화와 적절한 itk::ImageIO 서브 클래스를 할당에 의해 데이터 파일 포맷을 지정할 수 있다
- 역사적인 이유와 사용자에 대한 편리성으로, Update() 메서드에 대응하는 itk::ImageFileWriter 또한 Write() 메서드를 가진다
- 원칙적으로, 그것들 중에 하나를 사용할 수 있지만 Write() 메서드는 미래에 삭제될 수도 있기 때문에 Update() 메서드를 추천한다
다음에 나오는 장은 툴킷에서 제공하는 IO 아키텍처의 내부를 설명한다
댓글