DCMTK with CxImage in MFC
DCMTK는 DCMTK가 다루는 DCM 이미지의 DIB 비트맵핸들을 CxImage.CreateFromHBITMAP(HBITMAP) 함수의 파라미터로 전달하면 CxImage에 의해 DCM 이미지의 영상처리가 가능하다.
아래 코드 중에서 하늘색 배경으로 설정된 코드는 DCMTK와 CxImage 가 연결되는 부분이다
DicomImage *ptrDicomImage = NULL;
void* data = NULL;
BITMAPINFO bi;
HBITMAP hbmp = 0;
void CDCMTK_IMG_OutputView::OnDraw(CDC* pDC)
{
CDCMTK_IMG_OutputDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
if (!pDoc)
return;
// TODO: 여기에 원시 데이터에 대한 그리기 코드를 추가합니다.
//LPCTSTR lpstrFile = _T("D:\\test\\sample.dcm");
LPCTSTR lpstrFile = _T("D:\\test\\샘플2.dcm");
USES_CONVERSION;
char* filename = W2A(lpstrFile);
DcmFileFormat* ptrDcmFileFormat = new DcmFileFormat();
OFCondition cond = ptrDcmFileFormat->loadFile(filename);
if (cond.good())
{
//AfxMessageBox(_T("DCM파일 로드성공"));
}
else if(cond.bad())
{
AfxMessageBox(_T("DCM파일 로드실패"));
exit(0);
}
DJDecoderRegistration::registerCodecs(); // register JPEG codecs
DcmDataset *dataset = ptrDcmFileFormat->getDataset();
// decompress data set if compressed
dataset->chooseRepresentation(EXS_LittleEndianExplicit,NULL);
E_TransferSyntax xfer = ptrDcmFileFormat->getDataset()->getOriginalXfer();
/*
//환자의 이름을 가져와서 메시지박스에 출력하는 예
TCHAR tagValue[128];
DcmMetadata::Get(ptrDcmFileFormat, DCM_PatientName, tagValue);
//AfxMessageBox(tagValue);
*/
//주요한 메타데이타 5개를 PatientVO에 저장하여 리턴하는 예
PatientVO patientVO = DcmMetadata::GetMain(ptrDcmFileFormat);
/*
CString info;
info.Format(_T("%s, %s, %s, %s, %s"), patientVO.patientName, patientVO.patientID,
patientVO.patientSex, patientVO.studyDate, patientVO.institutionName);
AfxMessageBox(info);
*/
//dcm 파일의 모든 태그정보를 추출하는 예
/*
int tagCount = 0;
TagVO* tags = DcmMetadata::GetAllTags(ptrDcmFileFormat, &tagCount);
for(int i=0;i<tagCount;i++)
{
CString msg;
msg.Format(_T("%s, %s, %s, %s"), tags[i].tstrTagName, tags[i].tstrTagCode, tags[i].tstrVRName, tags[i].tstrTagValue);
AfxMessageBox(msg);
}
delete [] tags;
*/
if(ptrDicomImage==NULL)
ptrDicomImage = new DicomImage(ptrDcmFileFormat, xfer, CIF_AcrNemaCompatibility, 0, 1);
if(ptrDicomImage != NULL)
{
//AfxMessageBox(_T("DicomImage 인스턴스 생성 성공"));
}
else
{
AfxMessageBox(_T("DicomImage 인스턴스 생성 실패"));
exit(0);
}
if(ptrDicomImage->getStatus()!= EIS_Normal) exit(0);
int width = (int)ptrDicomImage->getWidth();
int height = (int)ptrDicomImage->getHeight();
int nResult = ptrDicomImage->setMinMaxWindow();
if(data==NULL)
{
ptrDicomImage->createWindowsDIB(data, width*height);
if(data!=NULL) // data 는 사용후 반드시 해제해야 함
{
//BITMAPINFO bi;
bi.bmiHeader.biSize = sizeof(bi);
bi.bmiHeader.biWidth = width;
bi.bmiHeader.biHeight = -height;
bi.bmiHeader.biPlanes = 1;
bi.bmiHeader.biBitCount = 24;
bi.bmiHeader.biCompression = BI_RGB;
bi.bmiHeader.biSizeImage = 0;
}
}
// hbmp 는 사용후 반드시 해제해야 함
hbmp = CreateDIBitmap(pDC->GetSafeHdc(), &bi.bmiHeader, CBM_INIT, data, &bi, DIB_RGB_COLORS);
// CxImage를 이용하는 예
CxImage cximage;
cximage.CreateFromHBITMAP(hbmp);
//cximage.Mirror();
//cximage.Flip();
//cximage.Rotate180();
//cximage.Resample(width*2.0, height*2.0, 2);
//hbmp = cximage.MakeBitmap();
BOOL savedOK = CxImageDCM::ConvertIntoJPG(hbmp, (TCHAR*)lpstrFile);
if(savedOK)
{
AfxMessageBox(_T("변환 성공"));
}
else
{
AfxMessageBox(_T("변환 실패"));
}
if(hbmp)
{
HDC memDC = CreateCompatibleDC(pDC->GetSafeHdc()); // memDC 는 사용후 반드시 해제해야 함
SelectObject(memDC, hbmp);
SetStretchBltMode(memDC, HALFTONE);
StretchBlt(pDC->GetSafeHdc(), 0, 0, width, height,
memDC, 0, 0, width, height, SRCCOPY);
//그림 위에 텍스트 출력
DcmMetadata::PrintPatientVO(pDC, &patientVO, width);
// 이미지의 크기를 스크롤바가 보여지는 화면의 크기로 설정한다
CSize imgSize;
imgSize.cx = width;
imgSize.cy = height;
SetScrollSizes(MM_TEXT, imgSize);
DeleteDC(memDC);
DeleteObject(hbmp);
}
//delete data;
// TODO: 여기에 원시 데이터에 대한 그리기 코드를 추가합니다.
}