// LMyDicomDS.cpp: implementation of the LMyDicomDS class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "dicommwl.h" #include "MyDicomDS.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// LMyDicomDS::LMyDicomDS() { } LMyDicomDS::~LMyDicomDS() { } CString LMyDicomDS::GetStringTag(L_UINT32 uTag) { CString strRet; strRet.Format("%04X:%04X", GETGROUP(uTag), GETELEMENT(uTag)); return strRet; } L_VOID LMyDicomDS::DeleteModulesType3(L_UINT32 uClass) { int nModuleCount = GetCountModule(); int i; pDICOMIOD pIOD; pDICOMMODULE pDicomModule; for (i=0; inModule); if ((pIOD != NULL) && (pIOD->nUsage == IOD_USAGE_U )) { DeleteModule(pDicomModule->nModule); } } } } // Traverse dataset as a list, and for each empty element do the following: // Type 3 sequence: if entire sequence empty, delete the sequence // Type 3 element: delete element L_VOID LMyDicomDS::DeleteEmptyElementsType3(L_UINT32 uClass) { pDICOMELEMENT pElementPrev = NULL; pDICOMELEMENT pElement; pDICOMIOD pIODClass = LDicomIOD::FindClass(uClass); if (pIODClass) { pDICOMIOD pIOD; pElement = GetFirstElement(NULL, FALSE, TRUE); pElementPrev = NULL; while (pElement) { pIOD = LDicomIOD::Find(pIODClass, pElement->nTag, IOD_TYPE_ELEMENT, FALSE); if ((pIOD) && (pIOD->nUsage == IOD_USAGE_3)) { // nLength==0 means (1) Sequence or (2)Empty Element // Case 1: Sequence if (pElement->nLength == ELEMENT_LENGTH_MAX) { int bEmptySequence = IsEmptySequence(pElement); if (bEmptySequence) { //if deleting the first element, pElementPrev is NULL //Therefore we must call GetFirstElement DeleteElement(pElement); pElement = pElementPrev; if (!pElement) pElement = GetFirstElement(NULL, FALSE, TRUE); } } // Case 2: Empty Element else if (pElement->nLength == 0) { //if deleting the first element, pElementPrev is NULL //Therefore we must call GetFirstElement DeleteElement(pElement); pElement = pElementPrev; if (!pElement) pElement = GetFirstElement(NULL, FALSE, TRUE); } } pElementPrev = pElement; pElement = GetNextElement(pElement, FALSE, TRUE); } } } L_INT LMyDicomDS::IsEmptySequence(pDICOMELEMENT pElementSequence) { pDICOMELEMENT pElementItem; pDICOMELEMENT pElement; int bEmpty; bEmpty = TRUE; pElementItem = GetChildElement(pElementSequence, TRUE); while (pElementItem) { pElement = GetChildElement(pElementItem, TRUE); while (pElement) { // If a sequence, make a recursive call if (pElement->nLength == ELEMENT_LENGTH_MAX) bEmpty = bEmpty && IsEmptySequence(pElement); else if (pElement->nLength != 0) { bEmpty = FALSE; } pElement = GetNextElement(pElement, TRUE, TRUE); } pElementItem = GetNextElement(pElementItem, TRUE, TRUE); } return bEmpty; } L_VOID LMyDicomDS::DeleteEmptyModulesOptional(L_UINT32 uClass) { int nCountModule = LDicomIOD::GetCountModule(uClass); pDICOMIOD pIOD; for (int i=0; inUsage == IOD_USAGE_U)) { pDICOMMODULE pModule = FindModule(pIOD->nCode); if ((pModule) && IsEmptyModule(pModule)) DeleteModule(pIOD->nCode); } } } L_INT LMyDicomDS::IsEmptyModule(L_UINT32 uModule) { int bEmpty = TRUE; pDICOMMODULE pModule; pModule = FindModule(uModule); if (pModule) bEmpty = IsEmptyModule(pModule); return bEmpty; } L_INT LMyDicomDS::IsEmptyModule(pDICOMMODULE pModule) { if (pModule == NULL) return TRUE; int bEmpty = TRUE; for (L_UINT32 i=0; i< pModule->nCount; i++) { if (pModule->pElement[i]->nLength == ELEMENT_LENGTH_MAX) bEmpty = bEmpty && IsEmptySequence(pModule->pElement[i]); else if (pModule->pElement[i]->nLength != 0) { bEmpty = FALSE; } } return bEmpty; } L_VOID LMyDicomDS::DisplayEmptyElementsType1(L_UINT32 uClass) { pDICOMELEMENT pElement; pDICOMIOD pIODClass = LDicomIOD::FindClass(uClass); if (pIODClass) { pDICOMIOD pIOD; pElement = GetFirstElement(NULL, FALSE, TRUE); while (pElement) { if ((pElement->nLength == 0) && (pElement->nLength != ELEMENT_LENGTH_MAX)) { pIOD = LDicomIOD::Find(pIODClass, pElement->nTag, IOD_TYPE_ELEMENT, FALSE); if ((pIOD) && (pIOD->nUsage == IOD_USAGE_1)) { CString strMsg; strMsg.Format("%04X:%04X %s\n", GETGROUP(pElement->nTag), GETELEMENT(pElement->nTag), pIOD->pszName); OutputDebugString(strMsg); } } pElement = GetNextElement(pElement, FALSE, TRUE); } } } pDICOMELEMENT LMyDicomDS::GetFirstEmptyElementType1(L_UINT32 uClass, CString &strTag, CString &strDesc) { pDICOMELEMENT pElement = NULL; pDICOMIOD pIODClass = LDicomIOD::FindClass(uClass); if (pIODClass) { pDICOMIOD pIOD; pElement = GetFirstElement(NULL, FALSE, TRUE); while (pElement != NULL) { pIOD = LDicomIOD::Find(pIODClass, pElement->nTag, IOD_TYPE_ELEMENT, FALSE); if ((pIOD) && (pIOD->nUsage == IOD_USAGE_1) && (pElement->nLength == 0) && (pElement->nLength != ELEMENT_LENGTH_MAX)) { strTag.Format("%04X:%04X", GETGROUP(pElement->nTag), GETELEMENT(pElement->nTag)); strDesc = pIOD->pszName; return pElement; } pElement = GetNextElement(pElement, FALSE, TRUE); } } return pElement; } pDICOMELEMENT LMyDicomDS::GetNextEmptyElementType1(pDICOMELEMENT pElement, L_UINT32 uClass, CString &strTag, CString &strDesc) { if (!pElement) return NULL; pDICOMIOD pIODClass = LDicomIOD::FindClass(uClass); if (pIODClass) { pDICOMIOD pIOD; pElement = GetNextElement(pElement, FALSE, TRUE); while (pElement != NULL) { pIOD = LDicomIOD::Find(pIODClass, pElement->nTag, IOD_TYPE_ELEMENT, FALSE); if ((pIOD) && (pIOD->nUsage == IOD_USAGE_1) && (pElement->nLength == 0) && (pElement->nLength != ELEMENT_LENGTH_MAX)) { strTag.Format("%04X:%04X", (pElement->nTag & 0xffff0000)>>16, pElement->nTag & 0xffff); strDesc = pIOD->pszName; return pElement; } pElement = GetNextElement(pElement, FALSE, TRUE); } } return pElement; } int LMyDicomDS::CopyElementData(pDICOMELEMENT pElementDst, pDICOMELEMENT pElementSrc, LDicomDS *pDSsrc) { if ((!pElementDst) || (!pElementSrc) || (!pDSsrc)) return FALSE; if ((pElementSrc->nLength == 0) || (pElementSrc->nLength == ELEMENT_LENGTH_MAX) || (pElementDst->nLength == ELEMENT_LENGTH_MAX)) return FALSE; L_VOID *pValue = NULL; pValue = malloc(pElementSrc->nLength); if (!pValue) return FALSE; pDSsrc->GetBinaryValue(pElementSrc, pValue, pElementSrc->nLength); SetBinaryValue(pElementDst, pValue, pElementSrc->nLength); free (pValue); return TRUE; } // Maps pElement from pDS_MWL to LDicomDS // If element does not exist in LMyDicomDS, the element is not created // Returns TRUE if successful // Returns FALSE if the element is not a mapped element int LMyDicomDS::MapElement(LDicomDS *pDS_MWL, pDICOMELEMENT pElement) { if ((!pDS_MWL) || (!pElement)) return FALSE; pDICOMELEMENT pElementDst; switch(pElement->nTag) { // This group is put under the sequence TAG_REQUESTED_PROCEDURE_ID case TAG_REQUESTED_PROCEDURE_ID: case TAG_SCHEDULED_PROCEDURE_STEP_ID: case TAG_SCHEDULED_PROCEDURE_STEP_DESCRIPTION: case TAG_SCHEDULED_ACTION_ITEM_CODE_SEQUENCE: { pDICOMELEMENT pElementReqProcID; pElementReqProcID = FindFirstElement(NULL, TAG_REQUEST_ATTRIBUTES_SEQUENCE, TRUE); if (pElementReqProcID) { //Get grandchild pElementDst = GetChildElement(pElementReqProcID, TRUE); if (!pElementDst) return FALSE; pElementDst = GetChildElement(pElementDst, TRUE); if (!pElementDst) return FALSE; pElementDst = FindFirstElement(pElementDst, pElement->nTag, TRUE); if (!pElementDst) return FALSE; CopyElementData(pElementDst,pElement, pDS_MWL); } } break; //This group maps one tag to a different tag case TAG_NAMES_OF_INTENDED_RECIPIENTS_OF_RESULTS: pElementDst = FindFirstElement(NULL, TAG_PHYSICIAN_OF_RECORD, TRUE); if (pElementDst) CopyElementData(pElementDst, pElement, pDS_MWL); break; case TAG_SCHEDULED_PERFORMING_PHYSICIAN_NAME: pElementDst = FindFirstElement(NULL, TAG_OPERATORS_NAME, TRUE); if (pElementDst) CopyElementData(pElementDst, pElement, pDS_MWL); break; case TAG_SCHEDULED_PROCEDURE_STEP_LOCATION: pElementDst = FindFirstElement(NULL, TAG_PERFORMED_PROCEDURE_STEP_ID, TRUE); if (pElementDst) CopyElementData(pElementDst, pElement, pDS_MWL); break; } return FALSE; } // Returns TRUE if element value should not be changed // Returns FALSE otherwise int LMyDicomDS::ReservedElement(pDICOMELEMENT pElement) { int bRet = FALSE; if (!pElement) return bRet; switch (pElement->nTag) { case TAG_MEDIA_STORAGE_SOP_CLASS_UID: case TAG_TRANSFER_SYNTAX_UID: //case TAG_SPECIFIC_CHARACTER_SET: case TAG_SOP_CLASS_UID: case TAG_SERIES_INSTANCE_UID: case TAG_SOP_INSTANCE_UID: // case TAG_STUDY_INSTANCE_UID: comment this out // if ModalityWorklist dataset has a TAG_STUDY_INSTANCE_UID, copy this bRet = TRUE; break; default: bRet = FALSE; break; } return bRet; } L_VOID LMyDicomDS::CopySequence(LDicomDS *pDS_MWL, pDICOMELEMENT pElementMWLSequence, pDICOMELEMENT pElementParent) { //DeleteElement(pElementParent); pDICOMELEMENT pNew = NULL; pDICOMELEMENT pDelete = FindFirstElement(pElementParent, pElementMWLSequence->nTag, TRUE); if (pDelete) { DeleteElement(pDelete); pNew = InsertElement( pElementParent, FALSE, pElementMWLSequence->nTag, pElementMWLSequence->nVR, pElementMWLSequence->nLength == ELEMENT_LENGTH_MAX, ELEMENT_INDEX_MAX ); } if (pNew) CopyDS(pNew, pDS_MWL, pElementMWLSequence); } // Copies pElement (and its value) into LMyDicomDS // If the element does not exist in LMyDicomDS, do not copy L_VOID LMyDicomDS::CopyElement(LDicomDS *pDS_MWL, pDICOMELEMENT pElementMWL, pDICOMELEMENT pElementParent) { if ((!pDS_MWL) || (!pElementMWL)) return; pDICOMELEMENT pElementDst = FindFirstElement(pElementParent, pElementMWL->nTag, TRUE); if (!pElementDst) return; // element present, but has not value if (pElementMWL->nLength == 0) return; // element is a sequence if (pElementMWL->nLength == ELEMENT_LENGTH_MAX) { CopySequence(pDS_MWL, pElementMWL, pElementParent); return; } CopyElementData(pElementDst, pElementMWL, pDS_MWL); } L_VOID LMyDicomDS::SetTagSpecificCharacterSet() { pDICOMELEMENT pElement = FindFirstElement(NULL, TAG_SPECIFIC_CHARACTER_SET, FALSE); if (pElement) SetStringValue(pElement, "ISO_IR 100", 1); } L_VOID LMyDicomDS::SetTagInstanceNumber(L_INT32 nInstance) { pDICOMELEMENT pElement = FindFirstElement(NULL, TAG_INSTANCE_NUMBER, FALSE); if ((pElement) && (pElement->nLength == 0)) { SetLongValue(pElement, &nInstance, 1); } } L_VOID LMyDicomDS::MapMWLtoDS(LDicomDS *pDS_MWL) { if (!pDS_MWL) return; pDICOMELEMENT pElement; pElement = pDS_MWL->GetFirstElement(NULL, TRUE, TRUE); while (pElement) { if (!ReservedElement(pElement)) { if (pElement->nTag == TAG_SCHEDULED_PROCEDURE_STEP_SEQUENCE) { pDICOMELEMENT pElementTmp; pElementTmp = pDS_MWL->FindFirstElement(pElement, TAG_SCHEDULED_PROCEDURE_STEP_ID, FALSE); if (pElementTmp) MapElement(pDS_MWL, pElementTmp); pElementTmp = pDS_MWL->FindFirstElement(pElement, TAG_SCHEDULED_PROCEDURE_STEP_DESCRIPTION, FALSE); if (pElementTmp) MapElement(pDS_MWL, pElementTmp); } else if (!MapElement(pDS_MWL, pElement)) { //Copy element directly CopyElement(pDS_MWL, pElement, NULL); } } // traverse as a tree pElement = pDS_MWL->GetNextElement(pElement, TRUE, TRUE); } } CString LMyDicomDS::CreateUniqueGUID() { CString strGUID; SYSTEMTIME SystemTime; FILETIME FileTime; GetSystemTime(&SystemTime); SystemTimeToFileTime(&SystemTime,&FileTime); DWORD Tick=GetTickCount(); DWORD HighWord=FileTime.dwHighDateTime+0x146BF4; strGUID.Format( TEXT("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())); return strGUID; } L_VOID LMyDicomDS::InsertUID(L_UINT32 uUID) { pDICOMELEMENT pElement; CString strUID; pElement = FindFirstElement(NULL, uUID, FALSE); if ((pElement)&&(pElement->nLength == 0)) { strUID = CreateUniqueGUID(); SetStringValue(pElement, (LPSTR)(LPCSTR)(strUID), 1); } } // Genenerates a study instance UID if not already present L_VOID LMyDicomDS::GenerateStudyInstanceUID() { pDICOMELEMENT pElement; CString strUID; pElement = FindFirstElement(NULL, TAG_STUDY_INSTANCE_UID, FALSE); if ((pElement) && (pElement->nLength == 0)) InsertUID(TAG_STUDY_INSTANCE_UID); } CString LMyDicomDS::GetModality() { CString strModality; pDICOMELEMENT pElementModality = NULL; char *pszValue = NULL; pDICOMELEMENT pElementRoot = FindFirstElement(NULL, TAG_SCHEDULED_PROCEDURE_STEP_SEQUENCE, FALSE); if (pElementRoot) { pElementModality = FindFirstElement(pElementRoot, TAG_MODALITY, FALSE); if (pElementModality) { pszValue = GetStringValue(pElementModality, 0, 1); if (pszValue) strModality = pszValue; } } return strModality; }