기존 dll에서 출력하던 post 참조 : DICOM Tag Hierarchy 출력

1.기존 dll에서 사용하던 DCMTK function중 Interface함수 추가, 총 4개 추가

int IsLeafElement(void* elementPtr, unsigned char* isLeaf);
int GetDcmDataSet(void* dcmPtr, void** pdataset);
int DcmObjectNextInContainer(void* pcontainer, void* pcurrent, void** pnextObject);
int DcmObjectNextObjectTop(void* pcurrent, void** pnextObject);

2.IsLeafElement() Leaf Element인지 check하는 함수 구현. Leaf false인경우가 sequence item을 의미하며, child element가 존재한다는 의미임.

int IsLeafElement(void* elementPtr, unsigned char* isLeaf)
{
	DcmElement* pElement = (DcmElement*)elementPtr;
	if (pElement == NULL)
		return 0;

	*isLeaf = pElement->isLeaf() == true ? 1 : 0;
	return 1;
}

3. GetDcmDataSet()DICOM File의 Dataset을 가져오는 함수

int GetDcmDataSet(void* dcmPtr, void** pdataset)
{
	DcmFileFormat* pDcmFileFormat = (DcmFileFormat*)dcmPtr;
	if (pDcmFileFormat == NULL)
		return 0;

	DcmObject** dataset = (DcmObject**)pdataset;
	if (dataset == NULL)
		return 0;
	
	*dataset = pDcmFileFormat->getDataset();
	return 1;
}

4. DcmObjectNextInContainer 다음 element 가져오는 함수

int DcmObjectNextInContainer(void* pcontainer, void* pcurrent, void** pnextObject)
{
	DcmObject* container = (DcmObject*)pcontainer;
	DcmObject* current = (DcmObject*)pcurrent;
	DcmObject** nextObject = (DcmObject**)pnextObject;
	if (container == NULL || nextObject == NULL)
		return 0;

	*nextObject = container->nextInContainer(current);
	return 1;
}

5. DcmObjectNextObjectTop() child element가 존재하는 경우 DcmStack을 이용하여 child element를 가져오는 함수

int DcmObjectNextObjectTop(void* pcurrent, void** pnextObject)
{
	DcmObject* current = (DcmObject*)pcurrent;
	DcmObject** nextObject = (DcmObject**)pnextObject;
	if (current == NULL || nextObject == NULL)
		return 0;

	DcmStack stack;
	current->nextObject(stack, OFTrue);
	*nextObject = stack.top();
	return 1;
}

6.위 4개 함수 선언을 javascript에도 추가

var DcmObject = ref.types.void 
var DcmObjectPtr = ref.refType(DcmObject);
var DcmObjectPtrPtr = ref.refType(DcmObjectPtr);
...
'IsLeafElement': ['int',[DcmElementPtr,ucharPtr]],
'GetDcmDataSet': ['int',[DcmFileFormatPtr, DcmObjectPtrPtr]],
'DcmObjectNextInContainer': ['int',[DcmObjectPtr, DcmObjectPtr, DcmObjectPtrPtr]],
'DcmObjectNextObjectTop': ['int',[DcmObjectPtr, DcmObjectPtrPtr]]
...

7. javascript에서 hierarchy 함수 추가. DcmFileFormat load 수행

function loadDICOMFileHierarchy(fileName){

    var dcmFileFormat = ref.alloc(DcmFileFormatPtrPtr);
    if(!nodeDCMTK.OpenDcmFileFormat(fileName, dcmFileFormat))
        console.error("OpenDcmFileFormat failed!");
   ...
}

8. DcmFileFormat을 이용하여 Dataset 구하기

var dataset = ref.alloc(DcmObjectPtrPtr);
nodeDCMTK.GetDcmDataSet(dcmFileFormat.deref(), dataset);

9.가장 root element를 가져오기

var nextObject = ref.alloc(DcmObjectPtrPtr);
nodeDCMTK.DcmObjectNextInContainer(dataset.deref(), ref.NULL, nextObject);

10. 재귀 함수 AddRowHierarchy()를 통해 Element를 탐색

AddRowHierarchy(dataset.deref(), nextObject.deref(), 0);

11.AddRowHierarchy()재귀 함수

function AddRowHierarchy(container, current, level){
    if(ref.isNull(container) || ref.isNull(current))
        return;

    AddTableRow(current, level);

    var isLeaf = ref.alloc('uchar');
    nodeDCMTK.IsLeafElement(current, isLeaf);
    if(isLeaf.deref() == 0)
    {
        var nextTopObject = ref.alloc(DcmObjectPtrPtr);
        nodeDCMTK.DcmObjectNextObjectTop(current, nextTopObject);
        AddRowHierarchy(current, nextTopObject.deref(), level+1);
    }
    
    var nextObject = ref.alloc(DcmObjectPtrPtr);
    nodeDCMTK.DcmObjectNextInContainer(container, current, nextObject);
    AddRowHierarchy(container, nextObject.deref(), level);
}