eDICOMViewer

DICOM Tag Hierarchy 출력하기 (Javascript)

2월 21, 2018 eDICOMViewer No comments

기존 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);
}

DICOM Tag Hierarchy 출력 (c example)

2월 19, 2018 eDICOMViewer 1 comment

DICOM file의 tag를 Hierarchy 형태로 출력, Test용 Dump 함수를 수정

1.기존 test_loaddcm()함수에 DumpDcmTagHierarchy() 함수를 통한 출력으로 변경

void test_loaddcm(char* fileName)
{
	DcmFileFormat dcmfileFormat;
	OFCondition status = dcmfileFormat.loadFile(fileName);
	if (!status.good())
		return;

	//DumpDcmTag(&dcmfileFormat);
	DumpDcmTagHierarchy(&dcmfileFormat);
}

2. DumpDcmTagHierarchy()는 단순히 dicom 파일의 root dataset()에서 printHierarchy를 호출

int DumpDcmTagHierarchy(void* dcmPtr)
{
	DcmFileFormat* pDcmFileFormat = (DcmFileFormat*)dcmPtr;
	if (pDcmFileFormat == NULL)
		return 0;

	DcmDataset* dset = pDcmFileFormat->getDataset();
	printHierarchy(dset, dset->nextInContainer(NULL) /* gets first element in dataset */, 0 /* main level */);
	return 1;
}

3.printHierarchy를 재귀 호출 방식으로 leaf가 있는 ElementDcmStack을 이용하여 출력

void printHierarchy(DcmObject* container, DcmObject* current, unsigned int level)
{
	// Check if we are already done at the current level
	if ((container == NULL) || (current == NULL)) 
		return;

	OFBool isLeaf = current->isLeaf();
	// Print current object
	char buffer[256];
	sprintf(buffer, "%s %s %s", std::string(level * 2, ' ').c_str(), current->getTag().toString().c_str(), ((DcmTag&)current->getTag()).getTagName());
	OutputDebugStringA(buffer);
	// If the current object has childs, advance to first child
	if (!current->isLeaf())
	{
		DcmStack stack;
		current->nextObject(stack, OFTrue);
		printHierarchy(current, stack.top(), level + 1);
	}
	// Advance to next object on the same level as the current one
	printHierarchy(container, container->nextInContainer(current), level);
}

4.출력 화면

DataTables에 원하는 항목 add row

2월 12, 2018 eDICOMViewer No comments

0. index.html파일에 table id elements로 추가 및 table header추가

<table id="Elements" class="display" cellspacing="0" width="100%">
    <thead>
        <tr>
            <th>Elment Tag</th>
            <th>Tag Name</th>
            <th>Value</th>
        </tr>
    </thead>
</table>

1.먼저 최초 ready시에 초기 값 설정 시작

$(document).ready(function() {
...
}

2. DataTables의 object 생성

elementTable = $('#Elements').DataTable({
    paging: false,
    searching: false
});

3. DataTables에 나와있는 예제 형식으로 row add로 추가
draw(false) 추가 해야 함

var counter = 1;    
elementTable.row.add([
    counter +'.22',
    counter +'.33',
    counter +'.44'
] ).draw(false);

4.element 형식으로 출력하기 위해 임시 dictionary를 추가

var items = [
    {
        "Elment Tag": "0000:0001",
        "Tag Name":   "System Architect",
        "Value":      "$3,120",
    },
    {
        "Elment Tag": "0000:0002",
        "Tag Name":   "Test Architect",
        "Value":      "$2220",
    }
]

elementTable.row.add([
    items[0]["Elment Tag"],
    items[0]["Tag Name"],
    items[0]["Value"],
]).draw(false);

5.결과 화면

css에 포함된 png file에서 file not found error 해결

2월 12, 2018 eDICOMViewer No comments

1. datatables.net을 사용하기 위해 css loader를 import

import 'datatables.net-dt/css/jquery.dataTables.css';
var dataTables = require('datatables.net');

2. webpack 수행시 정상적으로 수행되고, build폴더에 png 파일이 hash code로 변환되어 저장됨

ex)
1fc418e33fd5a687290258b23fac4e98.png
9a6486086d09bb38cf66a57cc559ade3.png
...

3. electron에서 수행시 아래와 같은 Error 발생

4. error확인 결과, datatables.css에서 사용하는 png 파일이 build 폴더로 copy되었지만, css에서는 여전히 main path에서 참조하여 file not found error발생

5.file-loader의 설정을 build path로 참조되도록 변경 후 해결

options->publicPath 추가 후 해결

{ test: /\.(png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$/, 
  loader: 'file-loader', 
  options: {
      publicPath: './build/' 
  }
}

Element출력을 위한 Grid

2월 9, 2018 eDICOMViewer No comments

Element 출력을 위해 Grid Framework 탐색

1.https://jspreadsheets.com 에서 검색

2.Data tables가 적합 한듯함, 편집하는 module인 Editor도 있어 연동 수월 ( https://datatables.net)

3.npm으로 설치

$npm install datatables.net    # Core library
$npm install datatables.net-dt # Styling

4.index.js에 require추가

import $ from 'jquery';
var dt = require('datatables.net');

5.index.html에 간단한 table 추가 id는 Elements

<table id="Elements" class="display" cellspacing="0" width="100%">
    <thead>
        <tr>
            <th>Column 1</th>
            <th>Column 2</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Row 1 Data 1</td>
            <td>Row 1 Data 2</td>
        </tr>
        <tr>
            <td>Row 2 Data 1</td>
            <td>Row 2 Data 2</td>
        </tr>
    </tbody>
</table>

6.index.js에 Data Table 초기화

$(document).ready(function() {
    $('#Elements').DataTable();
} );

node ffi char* 연동

2월 9, 2018 eDICOMViewer No comments

Element의 Tag Name을 가져오기 위해 node ffi char* 연동

1.NodeDCMTK.dll에 GetElementTagName() 함수 구현

int GetElementTagName(void* elementPtr, char* tagName)
{
	DcmElement* pElement = (DcmElement*)elementPtr;
	if (pElement == NULL)
		return 0;

	char* name = (char*)((DcmTag&)pElement->getTag()).getTagName();
	strcpy(tagName, name);
	return 1;
}

2.javascript에서 함수 선언 추가 char*는 동일하게 'char*'로 선언

'GetElementTagName': ['int',[DcmElementPtr,'char*']]

3.javascript에서 Buffer를 사용하여 parameter 전달

var elementName = new Buffer(255);
nodeDCMTK.GetElementTagName(dcmElementPtr.deref(), elementName);

4.utf-8로 변환 후 출력

console.log("GetElementTagName=" + elementName.toString('utf8'));

int to hex string 변환

2월 8, 2018 eDICOMViewer No comments

javascript에서 int값을 hex string으로 변환

1. util.js에 toHex()함수 추가

function toHex(i, pad) {

    if (typeof(pad) === 'undefined' || pad === null) {
      pad = 2;
    } 

    var strToParse = i.toString(16).toUpperCase();
  
    while (strToParse.length < pad) {
      strToParse = "0" + strToParse;
    }
    return strToParse;
};

2. export를 통해서 toHex() 함수 노출

export {
    toHex
};

3.사용

var util = require('./util.js');

console.log("GetElement [{0}:{1}]".format(util.toHex(gtag.deref(),4), util.toHex(etag.deref(),4)));

4.결과 화면

GetElement [0008:0008]

Javascript에서 String.format() 사용

2월 8, 2018 eDICOMViewer No comments

c#의 string.format(“test0={0}, test1={1}”, test0, test1); 과 같은 형태를 javascript에서 사용

1. npm의 string-format module 설치

$ npm install -s string-format

2. javascript 앞에 선언

var format = require('string-format')
format.extend(String.prototype);

3. 아래와 같이 사용

console.log("GetElement [{0}:{1}]".format(gtag.deref(), etag.deref()));

ref를 활용한 int* 연동

2월 7, 2018 eDICOMViewer No comments

ref를 활용하여 int* 연동

1. NodeDCMTK.dll에서 element count를 구하는 함수에서 2번째 parameter로 element count를 넘겨 받는게 필요

int GetElementCount(void* dcmPtr, long* count)
{
	DcmFileFormat* pDcmFileFormat = (DcmFileFormat*)dcmPtr;
	if (pDcmFileFormat == NULL)
		return 0;

	*count = pDcmFileFormat->getDataset()->card();
	return 1;
}

2. javascript NodeDCMTK.js에서 long의 reftype을 선언 및 GetElementCount() 함수 선언

var longPtr = ref.refType('long');

var nodeDCMTK = ffi.Library('NodeDCMTK.dll', {
...
'GetElementCount': ['int',[DcmFileFormatPtr,longPtr]]
});

()
3. ref.alloc(‘long’)형태로 선언한 것이 long의 reference type임. GetElementCount() 함수에 전달 후 deref()로 사용

var elementCount = ref.alloc('long');
nodeDCMTK.GetElementCount(dcmFileFormat.deref(), elementCount);
console.log('elementCount=' + elementCount.deref());

javascript export 여러개 하기

2월 7, 2018 eDICOMViewer No comments

1.NodeDCMTK.js에서 DcmFileFormatPtrPtr, nodeDCMTK를 export 수행 하기 위해
아래와 같이 export {}안에 export하고자 하는 object추가

export { DcmFileFormatPtrPtr, nodeDCMTK };

2.index.js와 사용하고자 하는 javascript에서 아래와 같이 import 추가 후 사용 가능

import {nodeDCMTK, DcmFileFormatPtrPtr} from './nodeDCMTK.js';

3.사용 예제

var fileName = '..\\etc\\sampleDICOM\\0001.DCM';
var dcmFileFormat = ref.alloc(DcmFileFormatPtrPtr);

if(!nodeDCMTK.OpenDcmFileFormat(fileName, dcmFileFormat))
    console.error("OpenDcmFileFormat failed!");

또다른 방식은 export는 동일하고 import시 require() 접근 가능

var dcmTK = require('./nodeDCMTK.js');
dcmTK.nodeDCMTK.OpenDcmFileFormat(...);