// DicAnnDoc.cpp : implementation of the CDicAnnDoc class // #include "stdafx.h" #include "DICANN.H" #include "MainFrm.h" #include "ANNDOC.H" #include "ANNVVIEW.H" #ifdef _DEBUG #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif ///////////////////////////////////////////////////////////////////////////// // CDicAnnDoc IMPLEMENT_DYNCREATE(CDicAnnDoc, CDocument) BEGIN_MESSAGE_MAP(CDicAnnDoc, CDocument) //{{AFX_MSG_MAP(CDicAnnDoc) ON_UPDATE_COMMAND_UI(IDM_FILE_SAVE, OnUpdateFileSave) ON_COMMAND(IDM_FILE_SAVE, OnFileSave) ON_COMMAND(ID_FILE_OPEN, OnFileOpen) ON_COMMAND(ID_PS_SET, OnPsSet) ON_UPDATE_COMMAND_UI(ID_PS_SET, OnUpdatePSSet) //}}AFX_MSG_MAP END_MESSAGE_MAP() ///////////////////////////////////////////////////////////////////////////// // CDicAnnDoc construction/destruction CDicAnnDoc::CDicAnnDoc() { // TODO: add one-time construction code here m_bDSIsLoaded = FALSE; m_bTrueSize = TRUE; } CDicAnnDoc::~CDicAnnDoc() { } BOOL CDicAnnDoc::OnNewDocument() { if (!CDocument::OnNewDocument()) return FALSE; // TODO: add reinitialization code here // (SDI documents will reuse this document) return TRUE; } ///////////////////////////////////////////////////////////////////////////// // CDicAnnDoc serialization void CDicAnnDoc::Serialize(CArchive& ar) { if (ar.IsStoring()) { // TODO: add storing code here } else { // TODO: add loading code here } } ///////////////////////////////////////////////////////////////////////////// // CDicAnnDoc diagnostics #ifdef _DEBUG void CDicAnnDoc::AssertValid() const { CDocument::AssertValid(); } void CDicAnnDoc::Dump(CDumpContext& dc) const { CDocument::Dump(dc); } #endif //_DEBUG ///////////////////////////////////////////////////////////////////////////// // CDicAnnDoc commands BOOL CDicAnnDoc::OnOpenDocument(LPCTSTR lpszPathName) { L_INT nRet = FAILURE; // TODO: Add your specialized creation code here if (!CDocument::OnOpenDocument(lpszPathName)) return FALSE; CDicAnnApp * pTheApp = (CDicAnnApp*) AfxGetApp(); CDicAnnView * pView = (CDicAnnView*) GetView(); if((pTheApp!=NULL) && (pView!=NULL)) { L_UINT16 uDicomRet; BITMAPHANDLE DICOMBitmap; uDicomRet = m_DS.LoadDS((char * )lpszPathName, DS_LOAD_CLOSE); if(uDicomRet != DICOM_SUCCESS) { AfxMessageBox("Load Failed"); return FALSE; } uDicomRet = m_DS.GetImage( NULL, &DICOMBitmap, sizeof (BITMAPHANDLE), 0, 0, ORDER_BGR, DICOM_GETIMAGE_AUTO_APPLY_MODALITY_LUT| DICOM_GETIMAGE_AUTO_APPLY_VOI_LUT| DICOM_GETIMAGE_ALLOW_RANGE_EXPANSION, NULL, NULL); if(uDicomRet != DICOM_SUCCESS) { AfxMessageBox("Load Failed"); return FALSE; } pView->m_LAnnWnd.SetHandle(&DICOMBitmap); m_bDSIsLoaded = TRUE; } return (TRUE); } CView * CDicAnnDoc::GetView() { POSITION pos = GetFirstViewPosition(); return(GetNextView(pos)); } void CDicAnnDoc::OnUpdateFileSave(CCmdUI* pCmdUI) { pCmdUI->Enable(m_bDSIsLoaded); } void CDicAnnDoc::OnUpdatePSSet(CCmdUI* pCmdUI) { pCmdUI->Enable(m_bDSIsLoaded); } void CDicAnnDoc::OnFileSave() { L_UINT16 nRet; OnPsSet(); TCHAR szFilters[] =_T ("DICOM Files (*.dcm)|*.dcm|DICOM Files (*.dic)|*.dic|All files (*.*)|*.*||"); CFileDialog dlg ( FALSE, _T ("dic"), NULL, OFN_OVERWRITEPROMPT, szFilters); // Get file name if (dlg.DoModal () == IDOK) { CWaitCursor Wait; //Save dataset into file CString strFileName = dlg.GetPathName(); nRet = m_DS.SaveDS((L_CHAR *)(LPCTSTR)strFileName, DS_GROUP_LENGTHS|DS_METAHEADER_PRESENT); if (nRet != DICOM_SUCCESS) { AfxMessageBox("Save Failed"); return; } // Remove all annotations in the PS if any FreeAllDICOMAnnInPS(); // Add the Annotations to the PS DoConvertLeadToDicom(); ///////////////////////////// L_CHAR szPath[MAX_PATH] = "\0"; L_CHAR szFileName[MAX_PATH] = "\0"; _splitpath((L_CHAR*)(LPCTSTR)strFileName, NULL, szPath, szFileName, NULL); ///////////////////////////// // Save the presentation state file L_INT iPos = strFileName.Find("."); if (iPos < 0) { // Inform the user that a template PS will be cretaed AfxMessageBox("Saving Presentation State file failed!", MB_OK | MB_ICONERROR); return; } strFileName = strFileName.Left(iPos); strFileName = strFileName + ".pre"; // Set the Presentation State info DICOMPRESSTATEINFO PresStateInfo; PresStateInfo.uStructSize = sizeof(DICOMPRESSTATEINFO); PresStateInfo.nInstanceNumber = m_PSDlg.m_iInstanceNumber; PresStateInfo.pszPresLabel = (L_CHAR*)(LPCTSTR) m_PSDlg.m_strPSLabel; PresStateInfo.pszPresDescription = (L_CHAR*)(LPCTSTR) m_PSDlg.m_strPSDescription; PresStateInfo.pszPresCreator = (L_CHAR*)(LPCTSTR) m_PSDlg.m_strPSCreator; SYSTEMTIME SysTime; GetLocalTime(&SysTime); VALUEDATE Date; VALUETIME Time; Date.nYear = SysTime.wYear; Date.nMonth = SysTime.wMonth; Date.nDay = SysTime.wDay; Time.nHours = SysTime.wHour; Time.nMinutes = SysTime.wMinute; Time.nSeconds = SysTime.wSecond; Time.nFractions = 0; PresStateInfo.pPresCreationDate = &Date; PresStateInfo.pPresCreationTime = &Time; m_CurPSDataSet.SetPresStateInfo(&PresStateInfo); // END: Set the Presentation State info nRet = m_CurPSDataSet.SaveDS((L_CHAR *)(LPCTSTR)strFileName, 0); if (nRet != DICOM_SUCCESS) { AfxMessageBox("Saving Presentation State file failed!", MB_OK | MB_ICONERROR); return; } m_PSDlg.m_strPSDate.Format("%u/%u/%u", Date.nMonth, Date.nDay, Date.nYear); m_PSDlg.m_strPSTime.Format("%u:%u:%u", Time.nHours, Time.nMinutes, Time.nSeconds); } } void CDicAnnDoc::OnFileOpen() { TCHAR szFilters[] =_T ("DICOM Files (*.dcm)|*.dcm|DCM Files (*.dic)|*.dic|All files (*.*)|*.*||"); L_INT nLoadFlags = 0; CFileDialog dlg ( TRUE, _T ("All Files"), NULL, OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilters); if (dlg.DoModal () == IDOK) { L_INT nRet = FAILURE; CDicAnnView * pView = NULL; CMainFrame * pMainFrame = (CMainFrame * )AfxGetMainWnd( ); if(pMainFrame) { pView = (CDicAnnView*) pMainFrame->GetRightPane(); } if(pView!=NULL) { L_UINT16 uDicomRet; BITMAPHANDLE DICOMBitmap; CString strFileName = dlg.GetPathName(); uDicomRet = m_DS.LoadDS((CHAR * )(LPCSTR)strFileName, DS_LOAD_CLOSE); if(uDicomRet != DICOM_SUCCESS) { AfxMessageBox("Load Failed"); return ; } uDicomRet = m_DS.GetImage( NULL, &DICOMBitmap, sizeof (BITMAPHANDLE), 0, 0, ORDER_BGR, DICOM_GETIMAGE_AUTO_APPLY_MODALITY_LUT | DICOM_GETIMAGE_AUTO_APPLY_VOI_LUT | DICOM_GETIMAGE_ALLOW_RANGE_EXPANSION, NULL, NULL); if(uDicomRet != DICOM_SUCCESS) { AfxMessageBox("Load Failed"); return ; } pView->m_LAnnWnd.SetHandle(&DICOMBitmap); m_bDSIsLoaded = TRUE; UpdateAllViews (NULL); // Free all annotations drawn pView->FreeAllAnnotationObjects(); CString strImageName = strFileName; // Search for the Presentation State File L_CHAR szPath[MAX_PATH] = "\0"; L_CHAR szFileName[MAX_PATH] = "\0"; L_CHAR szDir[MAX_PATH] = "\0"; L_CHAR szPSFileName[2 * MAX_PATH] = "\0"; _splitpath((L_CHAR*)(LPCTSTR)strFileName, szDir, szPath, szFileName, NULL); sprintf(szPSFileName, "%s%s%s%s", szDir, szPath, szFileName, ".pre"); L_BOOL bFileExist = TRUE; CFileFind finder; bFileExist = finder.FindFile(szPSFileName); finder.Close(); if (bFileExist == FALSE) // No Presentation State file related to this Data set { // Inform the user that a template PS will be cretaed AfxMessageBox("No related Presentation State file (.pre) was found. A Grayscale " "Softcopy Presentation State object will be created for the loaded " "image.", MB_OK | MB_ICONINFORMATION); CreateTemplatePS(); // Add this image file as Referenced Image Sequence item in the presentation state module BasicModulesAttributesFromImage((L_CHAR*)(LPCTSTR)strImageName); m_PSDlg.m_strPSLabel = "LABEL"; m_PSDlg.m_iInstanceNumber = 1; m_PSDlg.m_strPSCreator = ""; m_PSDlg.m_strPSDescription = ""; m_PSDlg.m_strPSDate = ""; m_PSDlg.m_strPSTime = ""; } else { // Load the existed PS file into a DS m_CurPSDataSet.LoadDS(szPSFileName, DS_LOAD_CLOSE); // Get the SOP Instance UID of the image L_CHAR* pszImageSOPInsUID = NULL; pDICOMELEMENT pImageElement = m_DS.FindFirstElement(NULL, TAG_SOP_INSTANCE_UID, FALSE); if (pImageElement) { pszImageSOPInsUID = m_DS.GetStringValue(pImageElement, 0, 1); pView->GetDICOMObjectsToBeConverted(pszImageSOPInsUID); } DICOMPRESSTATEINFO PresState; L_INT iRet = m_CurPSDataSet.GetPresStateInfo(&PresState, sizeof(DICOMPRESSTATEINFO)); if (iRet == DICOM_SUCCESS) { m_PSDlg.m_iInstanceNumber = PresState.nInstanceNumber; m_PSDlg.m_strPSCreator = PresState.pszPresCreator; m_PSDlg.m_strPSLabel = PresState.pszPresLabel; m_PSDlg.m_strPSDescription = PresState.pszPresDescription; if (PresState.pPresCreationDate) { m_PSDlg.m_strPSDate.Format("%i/%i/%i", PresState.pPresCreationDate->nMonth,PresState.pPresCreationDate->nDay,PresState.pPresCreationDate->nYear); } if (PresState.pPresCreationTime) { m_PSDlg.m_strPSTime.Format("%i:%i:%i", PresState.pPresCreationTime->nHours, PresState.pPresCreationTime->nMinutes, PresState.pPresCreationTime->nSeconds); } } } } } } // Create a template Presentation state DS and load it into m_CurPSDataSet L_VOID CDicAnnDoc::CreateTemplatePS() { // Load the template Data set from the resource HRSRC hRsrc = FindResource(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDR_TEMPLATEPS), "TEMPLATEPS"); if (!hRsrc) { AfxMessageBox("Could not load the template Data Set!"); return; } DWORD dwResLen = SizeofResource(AfxGetInstanceHandle(), hRsrc) ; if (dwResLen == 0) { AfxMessageBox("Could not load the template Data Set!"); return; } HGLOBAL hGlobal = LoadResource(AfxGetInstanceHandle(), hRsrc); if (!hGlobal) { AfxMessageBox("Could not load the template Data Set!"); return; } L_CHAR* pszTemplatePS = (L_CHAR*)LockResource(hGlobal); if (!pszTemplatePS) { AfxMessageBox("Could not load the template Data Set!"); return; } // Create the file in the windows TEMP folder L_CHAR szTempPath[MAX_PATH] = "\0"; DWORD dWord = GetTempPath(sizeof(szTempPath), szTempPath); if(dWord == 0) { AfxMessageBox("Could not load the template Data Set!"); return; } L_CHAR* pszFullName = lstrcat(szTempPath, "TemplatePS.PRE"); if (!pszFullName) { AfxMessageBox("Could not load the template Data Set!"); return; } HANDLE hFile = CreateFile(pszFullName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if(hFile == INVALID_HANDLE_VALUE) { AfxMessageBox("Could not load the template Data Set!"); return; } DWORD dwWritten; if (!WriteFile(hFile, pszTemplatePS, dwResLen, &dwWritten, NULL)) { AfxMessageBox("Could not load the template Data Set!"); DeleteFile(pszFullName); return; } CloseHandle(hFile); // Loading the DS if (m_CurPSDataSet.LoadDS(pszFullName, DS_LOAD_CLOSE) != DICOM_SUCCESS) { AfxMessageBox("Could not load the template Data Set!"); return; } DeleteFile(pszFullName); FillDefaultTemplatePS(); } L_VOID CDicAnnDoc::FillDefaultTemplatePS() { // Remove all unneeded modules from Softcopy Grtayscale Presentation State IOD in the Dataset RemoveUnNeededModule(); // Set the attributes of the modules that should be filled without user interaction SetMandatoryModulesAttributes(); // Adding Single Diaplay Area Item in Diaplay Area Nodule AddingSingleDisplayArea(); } // Adding Single Diaplay Area Item in Diaplay Area Nodule L_VOID CDicAnnDoc::AddingSingleDisplayArea() { pDICOMELEMENT pElement = m_CurPSDataSet.FindFirstElement(NULL, TAG_DISPLAYED_AREA_SELECTION_SEQUENCE, FALSE); if (pElement) { pElement = m_CurPSDataSet.InsertElement(pElement, TRUE, TAG_ITEM, VR_CS, TRUE, ELEMENT_INDEX_MAX); if (pElement) { // TAG_DISPLAYED_AREA_TOP_LEFT_HAND_CORNER pElement = m_CurPSDataSet.InsertElement(pElement, TRUE, TAG_DISPLAYED_AREA_TOP_LEFT_HAND_CORNER, VR_SL, FALSE, ELEMENT_INDEX_MAX); // TAG_DISPLAYED_AREA_BOTTOM_RIGHT_HAND_CORNER pElement = m_CurPSDataSet.InsertElement(pElement, FALSE, TAG_DISPLAYED_AREA_BOTTOM_RIGHT_HAND_CORNER, VR_SL, FALSE, ELEMENT_INDEX_MAX); // TAG_PRESENTATION_SIZE_MODE pElement = m_CurPSDataSet.InsertElement(pElement, FALSE, TAG_PRESENTATION_SIZE_MODE, VR_CS, FALSE, ELEMENT_INDEX_MAX); // TAG_PRESENTATION_PIXEL_SPACING pElement = m_CurPSDataSet.InsertElement(pElement, FALSE, TAG_PRESENTATION_PIXEL_SPACING, VR_DS, FALSE, ELEMENT_INDEX_MAX); // TAG_PRESENTATION_PIXEL_ASPECT_RATIO pElement = m_CurPSDataSet.InsertElement(pElement, FALSE, TAG_PRESENTATION_PIXEL_ASPECT_RATIO, VR_IS, FALSE, ELEMENT_INDEX_MAX); // TAG_PRESENTATION_PIXEL_MAGNIFICATION_RATIO pElement = m_CurPSDataSet.InsertElement(pElement, FALSE, TAG_PRESENTATION_PIXEL_MAGNIFICATION_RATIO, VR_FL, FALSE, ELEMENT_INDEX_MAX); } // Set the default value for the newly created displayed area SetDefaulDisplayedAreaInfo(); } return; } L_VOID CDicAnnDoc::SetDefaulDisplayedAreaInfo() { //CDicAnnView* pView = (CDicAnnView*) GetView(); CDicAnnView* pView = NULL; CMainFrame* pMainFrame = (CMainFrame * )AfxGetMainWnd( ); if(pMainFrame) { pView = (CDicAnnView*) pMainFrame->GetRightPane(); } if (!pView) { AfxMessageBox("Could not set the Displayed area!"); return; } DISPLAYEDAREA DisplayedArea; memset(&DisplayedArea, 0, sizeof(DISPLAYEDAREA)); L_INT32 TLHCorner[2]; L_INT32 BRHCorner[2]; L_UINT uSizeMode; L_DOUBLE PixelSpacing[2]; L_INT32 AspectRatio[2]; L_FLOAT fMagnifyRatio; TLHCorner[0] = 0; TLHCorner[1] = 0; BRHCorner[0] = pView->m_LAnnWnd.GetWidth(); BRHCorner[1] = pView->m_LAnnWnd.GetHeight(); PixelSpacing[0] = 1.0; PixelSpacing[1] = 1.0; AspectRatio[0] = 1; AspectRatio[1] = 1; fMagnifyRatio = 1; uSizeMode = DICANN_SIZEMODE_SCALETOFIT; DisplayedArea.AspectRatio = AspectRatio; DisplayedArea.BRHCorner = BRHCorner; DisplayedArea.fMagnifyRatio = fMagnifyRatio; DisplayedArea.PixelSpacing = PixelSpacing; DisplayedArea.TLHCorner = TLHCorner; DisplayedArea.uSizeMode = uSizeMode; DisplayedArea.uStructSize = sizeof(DISPLAYEDAREA); SetDispalyedAreaInfo(&DisplayedArea); return; } // Update the information related to the Displayed Area item in the IOD L_VOID CDicAnnDoc::SetDispalyedAreaInfo(pDISPLAYEDAREA pDisplayedArea) { if (!pDisplayedArea) { return; } // Find the Diaplyed Area Sequence pDICOMELEMENT pElement = m_CurPSDataSet.FindFirstElement(NULL, TAG_DISPLAYED_AREA_SELECTION_SEQUENCE, TRUE); if (pElement) { pElement = m_CurPSDataSet.GetChildElement(pElement, TRUE); if (!pElement) { // Could not get the Dispalyed Area return; } pElement = m_CurPSDataSet.FindFirstElement(pElement, TAG_ITEM, TRUE); if (pElement) { pElement = m_CurPSDataSet.GetChildElement(pElement, TRUE); if (!pElement) { // Could not get the Dispalyed Area return; } // Dispalyed Area Top Left Hand Corner pElement = m_CurPSDataSet.FindFirstElement(pElement, TAG_DISPLAYED_AREA_TOP_LEFT_HAND_CORNER, TRUE); if (pElement) { if (pDisplayedArea->TLHCorner) { m_CurPSDataSet.SetLongValue(pElement, pDisplayedArea->TLHCorner, 2); } } // Dispalyed Area Bottom Right Hand Corner pElement = m_CurPSDataSet.FindFirstElement(pElement, TAG_DISPLAYED_AREA_BOTTOM_RIGHT_HAND_CORNER, TRUE); if (pElement) { if (pDisplayedArea->BRHCorner) { m_CurPSDataSet.SetLongValue(pElement, pDisplayedArea->BRHCorner, 2); } } // Presentation Pixel Spacing pElement = m_CurPSDataSet.FindFirstElement(pElement, TAG_PRESENTATION_PIXEL_SPACING, TRUE); if (pElement) { if (pDisplayedArea->PixelSpacing) { m_CurPSDataSet.SetDoubleValue(pElement, pDisplayedArea->PixelSpacing, 2); } } // Presentation Pixel Aspect Ratio pElement = m_CurPSDataSet.FindFirstElement(pElement, TAG_PRESENTATION_PIXEL_ASPECT_RATIO, TRUE); if (pElement) { if (pDisplayedArea->AspectRatio) { m_CurPSDataSet.SetLongValue(pElement, pDisplayedArea->AspectRatio, 2); } } // Presentation Size Mode pElement = m_CurPSDataSet.FindFirstElement(pElement, TAG_PRESENTATION_SIZE_MODE, TRUE); if (pElement) { L_CHAR* pszSizeMode = NULL; switch (pDisplayedArea->uSizeMode) { case DICANN_SIZEMODE_SCALETOFIT: pszSizeMode = "SCALE TO FIT"; break; case DICANN_SIZEMODE_TRUESIZE: pszSizeMode = "TRUE SIZE"; break; case DICANN_SIZEMODE_MAGNIFY: pszSizeMode = "MAGNIFY"; break; default: pszSizeMode = "SCALE TO FIT"; break; } if (pszSizeMode) { m_CurPSDataSet.SetStringValue(pElement, pszSizeMode, 1); } } // Presentation Pixel Magnification Ratio pElement = m_CurPSDataSet.FindFirstElement(pElement, TAG_PRESENTATION_PIXEL_MAGNIFICATION_RATIO, TRUE); if (pElement) { m_CurPSDataSet.SetFloatValue(pElement, &pDisplayedArea->fMagnifyRatio, 1); } } } return; } L_VOID CDicAnnDoc::SetMandatoryModulesAttributes() { // Softcopy Presentation LUT -- Presetation LUT Shape attribute is filled SetTagPresentationLUTShape(); // SOP Common -- Generate SOP Instance UID in SOP Common Module //GenerateSOPInstanceUID(TAG_SOP_INSTANCE_UID); // General Series Module -- Series instance UID for the presentation state GenerateSeriesInstanceUID(TAG_SERIES_INSTANCE_UID); // Set the date time in SOP Common Module //SetSOPCommonDataTime(); return; } L_VOID CDicAnnDoc::SetTagPresentationLUTShape() { L_CHAR* pszLUTShape = "IDENTITY"; pDICOMELEMENT pElement = m_CurPSDataSet.FindFirstElement(NULL, TAG_PRESENTATION_LUT_SHAPE, FALSE); while ((pElement) && (pElement->nLength == 0)) { m_CurPSDataSet.SetStringValue(pElement, pszLUTShape, 1); pElement = m_CurPSDataSet.FindNextElement(pElement, FALSE); } pElement = m_CurPSDataSet.FindFirstElement(NULL, TAG_PRESENTATION_LUT_SEQUENCE, FALSE); if (pElement) { m_CurPSDataSet.DeleteElement(pElement); } } // Set the date and time in the SOP Common module L_VOID CDicAnnDoc::SetSOPCommonDataTime() { VALUEDATE Date; VALUETIME Time; SYSTEMTIME SysTime; GetLocalTime(&SysTime); Date.nYear = SysTime.wYear; Date.nMonth = SysTime.wMonth; Date.nDay = SysTime.wDay; Time.nHours = SysTime.wHour; Time.nMinutes = SysTime.wMinute; Time.nSeconds = SysTime.wSecond; // SOP Class UID pDICOMELEMENT pElement = m_CurPSDataSet.FindFirstElement(NULL, TAG_SOP_CLASS_UID, FALSE); if (pElement) { m_CurPSDataSet.SetStringValue(pElement, UID_GRAYSCALE_SOFTCOPY_PRESENTATION_STATE_STORAGE, 1); } else { pElement = m_CurPSDataSet.InsertElement(NULL, FALSE, TAG_SOP_CLASS_UID, VR_UI, FALSE, ELEMENT_INDEX_MAX); if (pElement) { m_CurPSDataSet.SetStringValue(pElement, UID_GRAYSCALE_SOFTCOPY_PRESENTATION_STATE_STORAGE, 1); } } // Media Storage SOP Class UID pElement = m_CurPSDataSet.FindFirstElement(NULL, TAG_MEDIA_STORAGE_SOP_CLASS_UID, FALSE); if (pElement) { m_CurPSDataSet.SetStringValue(pElement, UID_GRAYSCALE_SOFTCOPY_PRESENTATION_STATE_STORAGE, 1); } else { pElement = m_CurPSDataSet.InsertElement(NULL, FALSE, TAG_MEDIA_STORAGE_SOP_CLASS_UID, VR_UI, FALSE, 0); if (pElement) { m_CurPSDataSet.SetStringValue(pElement, UID_GRAYSCALE_SOFTCOPY_PRESENTATION_STATE_STORAGE, 1); } } pElement = m_CurPSDataSet.FindFirstElement(NULL, TAG_INSTANCE_CREATION_DATE, FALSE); if (pElement) { m_CurPSDataSet.SetDateValue(pElement, &Date, 1); } else { pElement = m_CurPSDataSet.InsertElement(NULL, FALSE, TAG_INSTANCE_CREATION_DATE, VR_DA, FALSE, ELEMENT_INDEX_MAX); if (pElement) { m_CurPSDataSet.SetDateValue(pElement, &Date, 1); } } pElement = m_CurPSDataSet.FindFirstElement(NULL, TAG_INSTANCE_CREATION_TIME, FALSE); if (pElement) { m_CurPSDataSet.SetTimeValue(pElement, &Time, 1); } else { pElement = m_CurPSDataSet.InsertElement(NULL, FALSE, TAG_INSTANCE_CREATION_TIME, VR_TM, FALSE, ELEMENT_INDEX_MAX); if (pElement) { m_CurPSDataSet.SetTimeValue(pElement, &Time, 1); } } } // General Series Module -- Series instance UID for the presentation state L_VOID CDicAnnDoc::GenerateSeriesInstanceUID(L_UINT32 uTag) { pDICOMMODULE pModule = m_CurPSDataSet.FindModule(MODULE_GENERAL_SERIES); if (pModule) { for (L_UINT32 i = 0; i < pModule->nCount; i++) { if (pModule->pElement[i]->nTag == uTag) { L_CHAR szSeriesInstanceUID[MAX_PATH] = "\0"; CreateUniqueSeriesUID(szSeriesInstanceUID); m_CurPSDataSet.SetStringValue(pModule->pElement[i], szSeriesInstanceUID, 1); break; } } } } // Genenerates a SOP instance UID if not already present in the SOP Common Module L_VOID CDicAnnDoc::GenerateSOPInstanceUID(L_UINT32 uTag) { L_CHAR szSOPInstanceUID[MAX_PATH] = "\0"; CreateUniqueGUID(szSOPInstanceUID); pDICOMELEMENT pElement = m_CurPSDataSet.FindFirstElement(NULL, uTag, FALSE); if (pElement) { m_CurPSDataSet.SetStringValue(pElement, szSOPInstanceUID, 1); } else { pElement = m_CurPSDataSet.InsertElement(NULL, FALSE, uTag, VR_UI, FALSE, ELEMENT_INDEX_MAX); if (pElement) { m_CurPSDataSet.SetStringValue(pElement, szSOPInstanceUID, 1); } } } L_VOID CDicAnnDoc::CreateUniqueSeriesUID(L_CHAR* pszSeriesInstanceUID) { SYSTEMTIME SystemTime; FILETIME FileTime; GetLocalTime(&SystemTime); SystemTimeToFileTime(&SystemTime, &FileTime); DWORD Tick=GetTickCount(); DWORD HighWord=FileTime.dwHighDateTime+0x146BF4; L_CHAR szSeriesInstanceUID[MAX_PATH] = "\0"; sprintf(szSeriesInstanceUID, "1.2.840.114257.0.1%010u%05u%05u%05u%05u%05u%05u", FileTime.dwLowDateTime, LOWORD(HighWord), HIWORD(HighWord |0x10000000), LOWORD(rand()), HIWORD(Tick), LOWORD(Tick), LOWORD(rand())); lstrcpyn(pszSeriesInstanceUID, szSeriesInstanceUID, MAX_PATH); return; } L_VOID CDicAnnDoc::CreateUniqueGUID(L_CHAR* pszSOPInstanceUID) { SYSTEMTIME SystemTime; FILETIME FileTime; GetLocalTime(&SystemTime); SystemTimeToFileTime(&SystemTime, &FileTime); DWORD Tick=GetTickCount(); DWORD HighWord=FileTime.dwHighDateTime+0x146BF4; L_CHAR szSOPInstanceUID[256] = "\0"; sprintf(szSOPInstanceUID, "1.2.840.114257.0.1%010u%05u%05u%05u%05u%05u%05u", FileTime.dwLowDateTime, LOWORD(HighWord), HIWORD(HighWord |0x10000000), LOWORD(rand()), HIWORD(Tick), LOWORD(Tick), LOWORD(rand())); lstrcpyn(pszSOPInstanceUID, szSOPInstanceUID, MAX_PATH); return; } // Remove all unneeded modules from Softcopy Grtayscale Presentation State IOD in the Dataset L_VOID CDicAnnDoc::RemoveUnNeededModule() { // Patient Study Module -- Optional One RemoveCertianModule(MODULE_PATIENT_STUDY); // Mask Module RemoveCertianModule(MODULE_MASK); // Display Shutter RemoveCertianModule(MODULE_DISPLAY_SHUTTER); // Bitmap Display Shutter RemoveCertianModule(MODULE_BITMAP_DISPLAY_SHUTTER); // Overlay Plane RemoveCertianModule(MODULE_OVERLAY_PLANE); // Overlay/Curve Activation RemoveCertianModule(MODULE_OVERLAY_CURVE_ACTIVATION); // Spatial Transformation RemoveCertianModule(MODULE_SPATIAL_TRANSFORMATION); // Modality LUT RemoveCertianModule(MODULE_MODALITY_LUT); // Softcopy VOI LUT //RemoveCertianModule(MODULE_SOFTCOPY_PRESENTATION_LUT); return; } // Remove the module passed from the Dataset L_VOID CDicAnnDoc::RemoveCertianModule(L_UINT32 nModule) { pDICOMMODULE pModule = m_CurPSDataSet.FindModule(nModule); if (pModule) { m_CurPSDataSet.DeleteModule(nModule); } return; } L_VOID CDicAnnDoc::BasicModulesAttributesFromImage(L_CHAR* pszImageName) { if (!pszImageName) { return; } LDicomDS ImageDS; L_UINT16 nResult = ImageDS.LoadDS(pszImageName, 0); if (nResult != DICOM_SUCCESS) { // Not able to open the file AfxMessageBox("Could not add the image to the Referenced Image Sequence in the Presentation State Module!"); return; } // Add this image file as Referenced Image Sequence item in the presentation state module m_CurPSDataSet.AddPresStateImageRefByFileName(pszImageName); // Add this image to the Graphic Annotation Sequence L_CHAR* pszSOPInstance = m_CurPSDataSet.GetPresStateImageRefSOPInstance(m_CurPSDataSet.FindFirstPresStateRefSeriesItem() , 0); if (!pszSOPInstance) { AfxMessageBox("Load Failed", MB_OK | MB_ICONERROR); return; } // Determine which item in the Pres State DS, into which, the new objects will be inserted pDICOMELEMENT pElement = m_CurPSDataSet.FindFirstElement(NULL, TAG_GRAPHIC_ANNOTATION_SEQUENCE, TRUE); if (!pElement) { pElement = m_CurPSDataSet.InsertElement(NULL, FALSE, TAG_GRAPHIC_ANNOTATION_SEQUENCE, VR_SQ, TRUE, 0); } pDICOMELEMENT pItemElement = m_CurPSDataSet.GetChildElement(pElement, TRUE); if (!pItemElement) { // Add Item Node pItemElement = m_CurPSDataSet.InsertElement(pElement, TRUE, TAG_ITEM, VR_CS, TRUE, ELEMENT_INDEX_MAX); if (!pItemElement) { AfxMessageBox("Load Failed", MB_OK | MB_ICONERROR); return; } // TAG_TEXT_OBJECT_SEQUENCE pElement = m_CurPSDataSet.InsertElement(pItemElement, TRUE, TAG_TEXT_OBJECT_SEQUENCE, VR_SQ, TRUE, ELEMENT_INDEX_MAX); // TAG_GRAPHIC_OBJECT_SEQUENCE pElement = m_CurPSDataSet.InsertElement(pItemElement, TRUE, TAG_GRAPHIC_OBJECT_SEQUENCE, VR_SQ, TRUE, ELEMENT_INDEX_MAX); // TAG_REFERENCED_IMAGE_SEQUENCE pElement = m_CurPSDataSet.InsertElement(pItemElement, TRUE, TAG_REFERENCED_IMAGE_SEQUENCE, VR_SQ, TRUE, ELEMENT_INDEX_MAX); // TAG_GRAPHIC_LAYER pElement = m_CurPSDataSet.InsertElement(pItemElement, TRUE, TAG_GRAPHIC_LAYER, VR_CS, FALSE, ELEMENT_INDEX_MAX); if (pElement) { m_CurPSDataSet.SetStringValue(pElement, "LEAD OBJECTS LAYER", 1); } // Add graphic layer DICOMGRAPHICLAYER GraphicLayer; L_INT16 pGrayScle[1]; pGrayScle[0] = (L_INT16)65535; L_UINT uIndex; GraphicLayer.nLayerOrder = 1; GraphicLayer.pRGBLayerColors = NULL; GraphicLayer.pszLayerDescription = "Layer for LEAD objects"; GraphicLayer.pszLayerName = "LEAD OBJECTS LAYER"; GraphicLayer.puGrayscale = pGrayScle; GraphicLayer.uStructSize = sizeof(DICOMGRAPHICLAYER); m_CurPSDataSet.CreateLayer(&GraphicLayer, &uIndex); } m_CurPSDataSet.AddLayerImageRef(pItemElement , pszSOPInstance); // ------------- Patient Module ---------------// // Patient's Name CopyAttributeFromImage(TAG_PATIENT_NAME, &ImageDS); // TAG_PATIENT_ID CopyAttributeFromImage(TAG_PATIENT_ID, &ImageDS); // TAG_ISSUER_OF_PATIENT_ID CopyAttributeFromImage(TAG_ISSUER_OF_PATIENT_ID, &ImageDS); // TAG_PATIENT_BIRTH_DATE CopyAttributeFromImage(TAG_PATIENT_BIRTH_DATE, &ImageDS); // TAG_PATIENT_BIRTH_TIME CopyAttributeFromImage(TAG_PATIENT_BIRTH_TIME, &ImageDS); // TAG_PATIENT_SEX CopyAttributeFromImage(TAG_PATIENT_SEX, &ImageDS); // TAG_PATIENT_INSURANCE_PLAN_CODE_SEQUENCE CopyAttributeFromImage(TAG_PATIENT_INSURANCE_PLAN_CODE_SEQUENCE, &ImageDS); // TAG_PATIENT_PRIMARY_LANGUAGE_CODE_SEQUENCE CopyAttributeFromImage(TAG_PATIENT_PRIMARY_LANGUAGE_CODE_SEQUENCE, &ImageDS); // TAG_PATIENT_PRIMARY_LANGUAGE_CODE_MODIFIER_SEQUENCE CopyAttributeFromImage(TAG_PATIENT_PRIMARY_LANGUAGE_CODE_MODIFIER_SEQUENCE, &ImageDS); // TAG_OTHER_PATIENT_IDS CopyAttributeFromImage(TAG_OTHER_PATIENT_IDS, &ImageDS); // TAG_OTHER_PATIENT_NAMES CopyAttributeFromImage(TAG_OTHER_PATIENT_NAMES, &ImageDS); // TAG_PATIENT_BIRTH_NAME CopyAttributeFromImage(TAG_PATIENT_BIRTH_NAME, &ImageDS); // TAG_PATIENT_AGE CopyAttributeFromImage(TAG_PATIENT_AGE, &ImageDS); // TAG_PATIENT_SIZE CopyAttributeFromImage(TAG_PATIENT_SIZE, &ImageDS); // TAG_PATIENT_WEIGHT CopyAttributeFromImage(TAG_PATIENT_WEIGHT, &ImageDS); // TAG_PATIENT_ADDRESS CopyAttributeFromImage(TAG_PATIENT_ADDRESS, &ImageDS); // TAG_PATIENT_MOTHER_BIRTH_NAME CopyAttributeFromImage(TAG_PATIENT_MOTHER_BIRTH_NAME, &ImageDS); // TAG_ETHNIC_GROUP CopyAttributeFromImage(TAG_ETHNIC_GROUP, &ImageDS); // TAG_SMOKING_STATUS CopyAttributeFromImage(TAG_SMOKING_STATUS, &ImageDS); // TAG_OCCUPATION CopyAttributeFromImage(TAG_OCCUPATION, &ImageDS); // ------------- General Study Module ---------// // TAG_STUDY_INSTANCE_UID CopyAttributeFromImage(TAG_STUDY_INSTANCE_UID, &ImageDS); // TAG_STUDY_ID CopyAttributeFromImage(TAG_STUDY_ID, &ImageDS); // TAG_STUDY_DATE CopyAttributeFromImage(TAG_STUDY_DATE, &ImageDS); // TAG_STUDY_TIME CopyAttributeFromImage(TAG_STUDY_TIME, &ImageDS); // TAG_REFERRING_PHYSICIAN_NAME CopyAttributeFromImage(TAG_REFERRING_PHYSICIAN_NAME, &ImageDS); // TAG_ACCESSION_NUMBER CopyAttributeFromImage(TAG_ACCESSION_NUMBER, &ImageDS); // TAG_STUDY_DESCRIPTION CopyAttributeFromImage(TAG_STUDY_DESCRIPTION, &ImageDS); // TAG_PHYSICIAN_OF_RECORD CopyAttributeFromImage(TAG_PHYSICIAN_OF_RECORD, &ImageDS); // TAG_NAME_OF_PHYSICIAN_READING_STUDY CopyAttributeFromImage(TAG_NAME_OF_PHYSICIAN_READING_STUDY, &ImageDS); // ------------- Patient Study Module ---------// This optional module will not be implemented // ------------- General Series Module --------// // TAG_MODALITY SetModality(); // TAG_SERIES_INSTANCE_UID is generated previously in the General Series Module // TAG_SERIES_NUMBER CopyAttributeFromImage(TAG_SERIES_NUMBER, &ImageDS); // TAG_LATERALITY CopyAttributeFromImage(TAG_LATERALITY, &ImageDS); // TAG_SERIES_DATE CopyAttributeFromImage(TAG_SERIES_DATE, &ImageDS); // TAG_SERIES_TIME CopyAttributeFromImage(TAG_SERIES_TIME, &ImageDS); // TAG_PERFORMING_PHYSICIAN_NAME CopyAttributeFromImage(TAG_PERFORMING_PHYSICIAN_NAME, &ImageDS); // TAG_PROTOCOL_NAME CopyAttributeFromImage(TAG_PROTOCOL_NAME, &ImageDS); // TAG_SERIES_DESCRIPTION CopyAttributeFromImage(TAG_SERIES_DESCRIPTION, &ImageDS); // TAG_OPERATORS_NAME CopyAttributeFromImage(TAG_OPERATORS_NAME, &ImageDS); // TAG_BODY_PART_EXAMINED CopyAttributeFromImage(TAG_BODY_PART_EXAMINED, &ImageDS); // TAG_PATIENT_POSITION CopyAttributeFromImage(TAG_PATIENT_POSITION, &ImageDS); // TAG_SMALLEST_PIXEL_VALUE_IN_SERIES CopyAttributeFromImage(TAG_SMALLEST_PIXEL_VALUE_IN_SERIES, &ImageDS); // TAG_LARGEST_PIXEL_VALUE_IN_SERIES CopyAttributeFromImage(TAG_LARGEST_PIXEL_VALUE_IN_SERIES, &ImageDS); // ------------- Presentation Series Module ---// // This is setted previously with modality // ------------- General Equipment Module -----// // TAG_MANUFACTURER CopyAttributeFromImage(TAG_MANUFACTURER, &ImageDS); // TAG_INSTITUTION_NAME CopyAttributeFromImage(TAG_INSTITUTION_NAME, &ImageDS); // TAG_INSTITUTION_ADDRESS CopyAttributeFromImage(TAG_INSTITUTION_ADDRESS, &ImageDS); // TAG_STATION_NAME CopyAttributeFromImage(TAG_STATION_NAME, &ImageDS); // TAG_INSTITUTIONAL_DEPARTMENT_NAME CopyAttributeFromImage(TAG_INSTITUTIONAL_DEPARTMENT_NAME, &ImageDS); // TAG_MANUFACTURER_MODEL_NAME CopyAttributeFromImage(TAG_MANUFACTURER_MODEL_NAME, &ImageDS); // TAG_DEVICE_SERIAL_NUMBER CopyAttributeFromImage(TAG_DEVICE_SERIAL_NUMBER, &ImageDS); // TAG_SOFTWARE_VERSION CopyAttributeFromImage(TAG_SOFTWARE_VERSION, &ImageDS); // TAG_SPATIAL_RESOLUTION CopyAttributeFromImage(TAG_SPATIAL_RESOLUTION, &ImageDS); // TAG_DATE_OF_LAST_CALIBRATION CopyAttributeFromImage(TAG_DATE_OF_LAST_CALIBRATION, &ImageDS); // TAG_TIME_OF_LAST_CALIBRATION CopyAttributeFromImage(TAG_TIME_OF_LAST_CALIBRATION, &ImageDS); // TAG_PIXEL_PADDING_VALUE CopyAttributeFromImage(TAG_PIXEL_PADDING_VALUE, &ImageDS); // Create the Softcopy VOI LUT Sequence item //AddSoftCopyVOILUTItem(&ImageDS); return; } L_VOID CDicAnnDoc::AddSoftCopyVOILUTItem(LDicomDS* pDS) { L_CHAR* pszClassUID = NULL; L_CHAR* pszInstanceUID = NULL; L_DOUBLE* pdWindowWidth; L_DOUBLE* pdWindowCenter; if (!pDS) { return; } L_CHAR* pszText = NULL; pDICOMELEMENT pItemElement = NULL; pDICOMELEMENT pImageItemElement = NULL; // Get SOP Class UID and SOP Instance UID from the image pDICOMELEMENT pElement = pDS->FindFirstElement(NULL, TAG_SOP_CLASS_UID, FALSE); // TAG_REFERENCED_SOP_CLASS_UID if (pElement) { pszClassUID = pDS->GetStringValue(pElement, 0, 1); } pElement = pDS->FindFirstElement(NULL, TAG_SOP_INSTANCE_UID, FALSE); // TAG_REFERENCED_SOP_INSTANCE_UID if (pElement) { pszInstanceUID = pDS->GetStringValue(pElement, 0, 1); } pElement = pDS->FindFirstElement(NULL, TAG_WINDOW_WIDTH, FALSE); // TAG_WINDOW_WIDTH if (pElement) { pdWindowWidth = pDS->GetDoubleValue(pElement, 0, 1); } pElement = pDS->FindFirstElement(NULL, TAG_WINDOW_CENTER, FALSE); // TAG_WINDOW_CENTER if (pElement) { pdWindowCenter = pDS->GetDoubleValue(pElement, 0, 1); } // Add them to the Softcopy VOI module pElement = m_CurPSDataSet.FindFirstElement(NULL, TAG_SOFTCOPY_VOI_LUT_SEQUENCE, TRUE); if (!pElement) { pElement = m_CurPSDataSet.InsertElement(NULL, FALSE, TAG_SOFTCOPY_VOI_LUT_SEQUENCE, VR_SQ, TRUE, ELEMENT_INDEX_MAX); } if (pElement) { pItemElement = m_CurPSDataSet.InsertElement(pElement, TRUE, TAG_ITEM, VR_CS, TRUE, ELEMENT_INDEX_MAX); if (pItemElement) { // Window Width pElement = m_CurPSDataSet.InsertElement(pItemElement, TRUE, TAG_WINDOW_WIDTH, VR_DS, FALSE, ELEMENT_INDEX_MAX); if ((pElement) && (pdWindowWidth)) { m_CurPSDataSet.SetDoubleValue(pElement, pdWindowWidth, 1); } // Window Center pElement = m_CurPSDataSet.InsertElement(pItemElement, TRUE, TAG_WINDOW_CENTER, VR_DS, FALSE, ELEMENT_INDEX_MAX); if ((pElement) && (pdWindowCenter)) { m_CurPSDataSet.SetDoubleValue(pElement, pdWindowCenter, 1); } // Referenced Image Sequence Item pElement = m_CurPSDataSet.InsertElement(pItemElement, TRUE, TAG_REFERENCED_IMAGE_SEQUENCE, VR_SQ, TRUE, ELEMENT_INDEX_MAX); if (pElement) { pImageItemElement = m_CurPSDataSet.InsertElement(pElement, TRUE, TAG_ITEM, VR_CS, TRUE, ELEMENT_INDEX_MAX); if (pImageItemElement) { // Referenced SOP Class UID pElement = m_CurPSDataSet.InsertElement(pImageItemElement, TRUE, TAG_REFERENCED_SOP_CLASS_UID, VR_UI, FALSE, ELEMENT_INDEX_MAX); if ((pElement) && (pszClassUID)) { m_CurPSDataSet.SetStringValue(pElement, pszClassUID, 1); } // Referenced SOP Instance UID pElement = m_CurPSDataSet.InsertElement(pImageItemElement, TRUE, TAG_REFERENCED_SOP_INSTANCE_UID, VR_UI, FALSE, ELEMENT_INDEX_MAX); if ((pElement) && (pszInstanceUID)) { m_CurPSDataSet.SetStringValue(pElement, pszInstanceUID, 1); } // Referenced Frame Number pElement = m_CurPSDataSet.InsertElement(pImageItemElement, TRUE, TAG_REFERENCED_FRAME_NUMBER, VR_IS, FALSE, ELEMENT_INDEX_MAX); if (pElement) { L_INT32 FrameNo[1]; FrameNo[0] = 1; m_CurPSDataSet.SetLongValue(pElement, FrameNo, 1); } } } } } return; } // Set the modality to be PR L_VOID CDicAnnDoc::SetModality() { L_CHAR* pszModlaity = "PR"; pDICOMELEMENT pElement = m_CurPSDataSet.FindFirstElement(NULL, TAG_MODALITY, FALSE); while (pElement) { m_CurPSDataSet.SetConvertValue(pElement, pszModlaity, 1); pElement = m_CurPSDataSet.FindNextElement(pElement, FALSE); } return; } // Copy the attribute from Image's DS into Presentation State DS L_VOID CDicAnnDoc::CopyAttributeFromImage(L_UINT32 uTag, LDicomDS* pImageDS) { if (!pImageDS) { return; } // Check both VR and VM // To exclude the tension to VM, then use GetBinaryValue.. but in this way you should allocate a buffer length equal to pElement->Length pDICOMELEMENT pImageElement = pImageDS->FindFirstElement(NULL, uTag, FALSE); if (pImageElement) { L_UINT32 uLength = pImageElement->nLength; if (uLength != 0) { BYTE* byteAttributeValue = new BYTE[uLength]; if (!byteAttributeValue) { return; } if (pImageDS->GetBinaryValue(pImageElement, byteAttributeValue, uLength)) { pDICOMELEMENT pPSElement = m_CurPSDataSet.FindFirstElement(NULL, uTag, FALSE); if (pPSElement) { if (!m_CurPSDataSet.SetBinaryValue(pPSElement, byteAttributeValue, uLength)) { if (byteAttributeValue) { delete [] byteAttributeValue; } return; } } } if (byteAttributeValue) { delete [] byteAttributeValue; } } } return; } void CDicAnnDoc::OnPsSet() { // Load the dialog m_PSDlg.m_bSetMode = TRUE; m_PSDlg.DoModal(); } L_VOID CDicAnnDoc::DoConvertLeadToDicom() { CDicAnnView* pView = NULL; CMainFrame* pMainFrame = (CMainFrame * )AfxGetMainWnd( ); if(pMainFrame) { pView = (CDicAnnView*) pMainFrame->GetRightPane(); } // Set the date time in SOP Common Module SetSOPCommonDataTime(); // SOP Common -- Generate SOP Instance UID in SOP Common Module GenerateSOPInstanceUID(TAG_SOP_INSTANCE_UID); if (pView) { pView->ConvertLeadToDicom(); } } L_VOID CDicAnnDoc::FreeAllDICOMAnnInPS() { pDICOMELEMENT pGraphicAnnSQItem = m_CurPSDataSet.FindFirstGraphicAnnSQItem(); while (pGraphicAnnSQItem) { m_CurPSDataSet.RemoveAllGraphicObjects(pGraphicAnnSQItem); m_CurPSDataSet.RemoveAllTextObjects(pGraphicAnnSQItem); pGraphicAnnSQItem = m_CurPSDataSet.FindNextGraphicAnnSQItem(pGraphicAnnSQItem); } }