1313 *
1414 * Module: dcmtkapp
1515 *
16- * Author: Tingyan Xu
16+ * Author: Tingyan Xu, Marco Eichelberg
1717 *
1818 * Purpose: dcmtk command line tool
1919 *
2525#include " dcmtk/ofstd/ofconsol.h" /* for COUT/CERR */
2626#include " dcmtk/ofstd/ofconapp.h" /* for OFConsoleApplication */
2727#include " dcmtk/dcmdata/dcuid.h" /* for dcmtk version name */
28+ #include " dcmtk/ofstd/ofwhere.h" /* for OFgetExecutablePath() */
2829
2930#define OFFIS_CONSOLE_APPLICATION " dcmtk"
3031#define OFFIS_CONSOLE_DESCRIPTION " Execute dcmtk command line tool"
@@ -35,94 +36,144 @@ OFFIS_DCMTK_VERSION " " OFFIS_DCMTK_RELEASEDATE " $";
3536// tool category for command line tools
3637enum DcmAppType
3738{
38- AT_conversion,
39- AT_compression,
40- AT_network,
41- AT_misc
39+ // internal type, only used for printTools()
40+ AT_anyType,
41+ // the following values denote specific categories
42+ AT_conversion,
43+ AT_compression,
44+ AT_network,
45+ AT_misc,
46+ AT_alias
4247};
4348
4449// struct for the list of tools
4550struct DcmToolEntry
4651{
47- OFString name;
48- OFString description;
49- DcmAppType apptype;
52+ OFString name;
53+ OFString command;
54+ OFString description;
55+ DcmAppType apptype;
5056};
5157
5258// list of DCMTK command line tools in alphabetical order
5359static DcmToolEntry tools[] =
5460{
55- {" dcm2img" , " Convert DICOM image to standard image format" , AT_conversion },
56- {" dcm2json" , " Convert DICOM file and data set to JSON" , AT_conversion },
57- {" dcm2xml" , " Convert DICOM file and data set to XML" , AT_conversion },
58- {" dcmcjpeg" , " Encode DICOM file to JPEG transfer syntax" , AT_compression },
59- {" dcmcjpls" , " Encode DICOM file to JPEG-LS transfer syntax" , AT_compression },
60- {" dcmconv" , " Convert DICOM file encoding" , AT_conversion },
61- {" dcmcrle" , " Encode DICOM file to RLE transfer syntax" , AT_compression },
62- {" dcmdecap" , " Extract file from DICOM encapsulated storage" , AT_conversion },
63- {" dcmdjpeg" , " Decode JPEG-compressed DICOM file" , AT_compression },
64- {" dcmdjpls" , " Decode JPEG-LS compressed DICOM file" , AT_compression },
65- {" dcmdrle" , " Decode RLE-compressed DICOM file" , AT_compression },
66- {" dcmdspfn" , " Export standard display curves to a text file" , AT_misc },
67- {" dcmdump" , " Dump DICOM file and data set" , AT_conversion },
68- {" dcmencap" , " Encapsulate document into DICOM format" , AT_conversion },
69- {" dcmftest" , " Test if file uses DICOM part 10 format" , AT_misc },
70- {" dcmicmp" , " Compare DICOM images and compute difference metrics" , AT_misc },
71- {" dcmmkcrv" , " Add 2D curve data to image" , AT_misc },
72- {" dcmmkdir" , " Create a DICOMDIR file" , AT_misc },
73- {" dcmmklut" , " Create DICOM look-up tables" , AT_misc },
74- {" dcmodify" , " Modify DICOM files" , AT_conversion },
75- {" dcmp2pgm" , " Read DICOM image and presentation state and render bitmap" , AT_conversion },
76- {" dcmprscp" , " DICOM basic grayscale print management SCP" , AT_network },
77- {" dcmprscu" , " Print spooler for presentation state viewer" , AT_network },
78- {" dcmpschk" , " Checking tool for presentation states" , AT_misc },
79- {" dcmpsmk" , " Create DICOM grayscale softcopy presentation state" , AT_misc },
80- {" dcmpsprt" , " Read DICOM images and presentation states and render print job" , AT_misc },
81- {" dcmpsrcv" , " Network receive for presentation state viewer" , AT_network },
82- {" dcmpssnd" , " Network send for presentation state viewer" , AT_network },
83- {" dcmqridx" , " Register a DICOM image file in an image database index file" , AT_misc },
84- {" dcmqrscp" , " DICOM image archive (central test node)" , AT_network },
85- {" dcmqrti" , " Telnet Initiator" , AT_misc },
86- {" dcmquant" , " Convert DICOM color images to palette color" , AT_misc },
87- {" dcmrecv" , " Simple DICOM storage SCP (receiver)" , AT_network },
88- {" dcmscale" , " Scale DICOM images" , AT_misc },
89- {" dcmsend" , " Simple DICOM storage SCU (sender)" , AT_network },
90- {" dcmsign" , " Sign and Verify DICOM Files" , AT_misc },
91- {" dcod2lum" , " Convert hardcopy characteristic curve file to softcopy format" , AT_misc },
92- {" dconvlum" , " Convert VeriLUM \" CCx_xx.dat\" files to DCMTK display files" , AT_misc },
93- {" drtdump" , " Dump DICOM RT file and data set" , AT_conversion },
94- {" dsr2html" , " Render DICOM SR file and data set to HTML/XHTML" , AT_conversion },
95- {" dsr2xml" , " Convert DICOM SR file and data set to XML" , AT_conversion },
96- {" dsrdump" , " Dump DICOM SR file and data set" , AT_conversion },
97- {" dump2dcm" , " Convert ASCII dump to DICOM file" , AT_conversion },
98- {" echoscu" , " DICOM verification (C-ECHO) SCU" , AT_network },
99- {" findscu" , " DICOM query (C-FIND) SCU" , AT_network },
100- {" getscu" , " DICOM retrieve (C-GET) SCU" , AT_network },
101- {" img2dcm" , " Convert standard image formats into DICOM format" , AT_conversion },
102- {" json2dcm" , " Convert JSON document to DICOM file or data set" , AT_conversion },
103- {" movescu" , " DICOM retrieve (C-MOVE) SCU" , AT_network },
104- {" storescp" , " DICOM storage (C-STORE) SCP" , AT_network },
105- {" storescu" , " DICOM storage (C-STORE) SCU" , AT_network },
106- {" termscu" , " DICOM termination SCU" , AT_network },
107- {" wlmscpfs" , " DICOM Basic Worklist Management SCP (based on data files)" , AT_network },
108- {" xml2dcm" , " Convert XML document to DICOM file or data set" , AT_conversion },
109- {" xml2dsr" , " Convert XML document to DICOM SR file" , AT_conversion }
61+ // the length of the first value ("name") should not exceed 8 characters
62+ {" dcm2img" , " dcm2img" , " Convert DICOM image to standard image format" , AT_conversion },
63+ {" dcm2json" , " dcm2json" , " Convert DICOM file and data set to JSON" , AT_conversion },
64+ {" dcm2xml" , " dcm2xml" , " Convert DICOM file and data set to XML" , AT_conversion },
65+ {" dcmcjpeg" , " dcmcjpeg" , " Encode DICOM file to JPEG transfer syntax" , AT_compression },
66+ {" dcmcjpls" , " dcmcjpls" , " Encode DICOM file to JPEG-LS transfer syntax" , AT_compression },
67+ {" dcmconv" , " dcmconv" , " Convert DICOM file encoding" , AT_conversion },
68+ {" dcmcrle" , " dcmcrle" , " Encode DICOM file to RLE transfer syntax" , AT_compression },
69+ {" dcmdecap" , " dcmdecap" , " Extract file from DICOM encapsulated storage" , AT_conversion },
70+ {" dcmdjpeg" , " dcmdjpeg" , " Decode JPEG-compressed DICOM file" , AT_compression },
71+ {" dcmdjpls" , " dcmdjpls" , " Decode JPEG-LS compressed DICOM file" , AT_compression },
72+ {" dcmdrle" , " dcmdrle" , " Decode RLE-compressed DICOM file" , AT_compression },
73+ {" dcmdspfn" , " dcmdspfn" , " Export standard display curves to a text file" , AT_misc },
74+ {" dcmdump" , " dcmdump" , " Dump DICOM file and data set" , AT_conversion },
75+ {" dcmencap" , " dcmencap" , " Encapsulate document into DICOM format" , AT_conversion },
76+ {" dcmftest" , " dcmftest" , " Test if file uses DICOM part 10 format" , AT_misc },
77+ {" dcmicmp" , " dcmicmp" , " Compare DICOM images and compute difference metrics" , AT_misc },
78+ {" dcmmkcrv" , " dcmmkcrv" , " Add 2D curve data to image" , AT_misc },
79+ {" dcmmkdir" , " dcmmkdir" , " Create a DICOMDIR file" , AT_misc },
80+ {" dcmmklut" , " dcmmklut" , " Create DICOM look-up tables" , AT_misc },
81+ {" dcmodify" , " dcmodify" , " Modify DICOM files" , AT_conversion },
82+ {" dcmp2pgm" , " dcmp2pgm" , " Read DICOM image and presentation state and render bitmap" , AT_conversion },
83+ {" dcmprscp" , " dcmprscp" , " DICOM basic grayscale print management SCP" , AT_network },
84+ {" dcmprscu" , " dcmprscu" , " Print spooler for presentation state viewer" , AT_network },
85+ {" dcmpschk" , " dcmpschk" , " Checking tool for presentation states" , AT_misc },
86+ {" dcmpsmk" , " dcmpsmk" , " Create DICOM grayscale softcopy presentation state" , AT_misc },
87+ {" dcmpsprt" , " dcmpsprt" , " Read DICOM images and presentation states and render print job" , AT_misc },
88+ {" dcmpsrcv" , " dcmpsrcv" , " Network receive for presentation state viewer" , AT_network },
89+ {" dcmpssnd" , " dcmpssnd" , " Network send for presentation state viewer" , AT_network },
90+ {" dcmqridx" , " dcmqridx" , " Register a DICOM image file in an image database index file" , AT_misc },
91+ {" dcmqrscp" , " dcmqrscp" , " DICOM image archive (central test node)" , AT_network },
92+ {" dcmqrti" , " dcmqrti" , " Telnet Initiator" , AT_misc },
93+ {" dcmquant" , " dcmquant" , " Convert DICOM color images to palette color" , AT_misc },
94+ {" dcmrecv" , " dcmrecv" , " Simple DICOM storage SCP (receiver)" , AT_network },
95+ {" dcmscale" , " dcmscale" , " Scale DICOM images" , AT_misc },
96+ {" dcmsend" , " dcmsend" , " Simple DICOM storage SCU (sender)" , AT_network },
97+ {" dcmsign" , " dcmsign" , " Sign and Verify DICOM Files" , AT_misc },
98+ {" dcod2lum" , " dcod2lum" , " Convert hardcopy characteristic curve file to softcopy format" , AT_misc },
99+ {" dconvlum" , " dconvlum" , " Convert VeriLUM \" CCx_xx.dat\" files to DCMTK display files" , AT_misc },
100+ {" drtdump" , " drtdump" , " Dump DICOM RT file and data set" , AT_conversion },
101+ {" dsr2html" , " dsr2html" , " Render DICOM SR file and data set to HTML/XHTML" , AT_conversion },
102+ {" dsr2xml" , " dsr2xml" , " Convert DICOM SR file and data set to XML" , AT_conversion },
103+ {" dsrdump" , " dsrdump" , " Dump DICOM SR file and data set" , AT_conversion },
104+ {" dump2dcm" , " dump2dcm" , " Convert ASCII dump to DICOM file" , AT_conversion },
105+ {" echoscu" , " echoscu" , " DICOM verification (C-ECHO) SCU" , AT_network },
106+ {" findscu" , " findscu" , " DICOM query (C-FIND) SCU" , AT_network },
107+ {" getscu" , " getscu" , " DICOM retrieve (C-GET) SCU" , AT_network },
108+ {" img2dcm" , " img2dcm" , " Convert standard image formats into DICOM format" , AT_conversion },
109+ {" json2dcm" , " json2dcm" , " Convert JSON document to DICOM file or data set" , AT_conversion },
110+ {" movescu" , " movescu" , " DICOM retrieve (C-MOVE) SCU" , AT_network },
111+ {" storescp" , " storescp" , " DICOM storage (C-STORE) SCP" , AT_network },
112+ {" storescu" , " storescu" , " DICOM storage (C-STORE) SCU" , AT_network },
113+ {" termscu" , " termscu" , " DICOM termination SCU" , AT_network },
114+ {" wlmscpfs" , " wlmscpfs" , " DICOM Basic Worklist Management SCP (based on data files)" , AT_network },
115+ {" xml2dcm" , " xml2dcm" , " Convert XML document to DICOM file or data set" , AT_conversion },
116+ {" xml2dsr" , " xml2dsr" , " Convert XML document to DICOM SR file" , AT_conversion },
117+
118+ // aliases for common tools
119+ {" convert" , " dcmconv" , " Changes the encoding of a DICOM file (calls dcmconv)" , AT_alias },
120+ {" dump" , " dcmdump" , " Dumps the contents of a DICOM file (calls dcmdump)" , AT_alias },
121+ {" echo" , " echoscu" , " Checks whether a DICOM server is accessible (calls echoscu)" , AT_alias },
122+ {" find" , " findscu" , " Queries a Q/R or Modality Worklist server (calls findscu)" , AT_alias },
123+ {" get" , " getscu" , " Downloads from a Q/R server using C-GET (calls getscu)" , AT_alias },
124+ {" mkdir" , " dcmmkdir" , " Creates a DICOMDIR file for storage media (calls dcmmkdir)" , AT_alias },
125+ {" modify" , " dcmodify" , " Modifies the contents of a DICOM file (calls dcmodify)" , AT_alias },
126+ {" move" , " movescu" , " Downloads from a Q/R server using C-MOVE (calls movescu)" , AT_alias },
127+ {" send" , " dcmsend" , " Transfers DICOM instances to a Storage server (calls dcmsend)" , AT_alias },
128+ {" sign" , " dcmsign" , " Creates and verifies digital signatures (calls dcmsign)" , AT_alias },
129+ {" toimg" , " dcm2img" , " Renders a DICOM image to another image format (calls dcm2img)" , AT_alias },
130+ {" tojson" , " dcm2json" , " Converts a DICOM file to JSON format (calls dcm2json)" , AT_alias },
131+ {" toxml" , " dcm2xml" , " Converts a DICOM file to XML format (calls dcm2xml)" , AT_alias }
132+
110133};
111134
112135static const size_t numTools = sizeof (tools) / sizeof (*tools);
113136
114- static void printTools (DcmAppType toolType)
137+ static OFBool getExecutablePath (OFString& dirname)
138+ {
139+ // get real path in which the stub executable is located
140+ int dirname_length = 0 ;
141+ int length = OFgetExecutablePath (NULL , 0 , &dirname_length);
142+ if (length == 0 )
143+ {
144+ fprintf (stderr, " F: Cannot determine location of dcmtk executable\n " );
145+ return OFFalse;
146+ }
147+ char *path = new char [length + 1 ];
148+ OFgetExecutablePath (path, length, &dirname_length);
149+ path[length] = ' \0 ' ;
150+ path[dirname_length] = ' \0 ' ;
151+ dirname = path;
152+ delete[] path;
153+ return OFTrue;
154+ }
155+
156+ static void printTools (DcmAppType toolType, OFString& dirname, OFBool& toolMissing)
115157{
116- size_t len = 0 ;
117- for (size_t i = 0 ; i < numTools; ++i)
158+ OFString executable_name ;
159+ for (size_t i = 0 ; i < numTools; ++i)
118160 {
119- if (tools[i].apptype == toolType)
161+ if ((toolType == AT_anyType && tools[i].apptype != AT_alias) || (tools[i]. apptype == toolType) )
120162 {
121- len = tools[i].name .size ();
122- COUT << " " << tools[i].name << " : " ;
123- for (size_t j = 1 ; j <= 8 - len; j++)
124- COUT << " " ;
125- COUT << tools[i].description << OFendl;
163+ executable_name = dirname;
164+ executable_name += PATH_SEPARATOR;
165+ executable_name += tools[i].command ;
166+ #ifdef _WIN32
167+ executable_name += " .exe" ;
168+ #endif
169+ const OFBool fileExists = OFStandard::fileExists (executable_name);
170+ COUT << " " << (toolType == AT_anyType ? " " : " " )
171+ << tools[i].name << (fileExists ? " " : " *" );
172+ // we assume that the maximum name length is 8 characters
173+ COUT << OFString (8 - tools[i].name .size (), ' ' );
174+ COUT << " - " << tools[i].description << OFendl;
175+ if (!fileExists)
176+ toolMissing = OFTrue;
126177 }
127178 }
128179}
@@ -142,30 +193,39 @@ static void printHelp(OFBool sorted)
142193 << " -d --debug debug mode, print debug information\n " << OFendl;
143194
144195 COUT << " tools:" << OFendl;
196+
197+ OFBool toolMissing = OFFalse;
198+ OFString dirname;
199+ OFBool result = getExecutablePath (dirname);
200+ if (!result) return ;
201+
145202 if (sorted)
146203 {
204+ // print tools sorted by category
147205 COUT << " conversion tools:" << OFendl;
148- printTools (AT_conversion);
206+ printTools (AT_conversion, dirname, toolMissing );
149207
150208 COUT << OFendl << " compression tools:" << OFendl;
151- printTools (AT_compression);
209+ printTools (AT_compression, dirname, toolMissing );
152210
153211 COUT << OFendl << " network tools:" << OFendl;
154- printTools (AT_network);
212+ printTools (AT_network, dirname, toolMissing );
155213
156214 COUT << OFendl << " miscellaneous tools:" << OFendl;
157- printTools (AT_misc);
215+ printTools (AT_misc, dirname, toolMissing);
216+
217+ COUT << OFendl << " aliases for common tools:" << OFendl;
218+ printTools (AT_alias, dirname, toolMissing);
158219 }
159220 else
160221 {
161- size_t len;
162- for (size_t i = 0 ; i < numTools; ++i) {
163- len = tools[i].name .size ();
164- COUT << " " << tools[i].name << " : " ;
165- for (size_t j = 1 ; j <= 8 - len; j++)
166- COUT << " " ;
167- COUT << tools[i].description << OFendl;
168- }
222+ // print all tools as a flat list
223+ printTools (AT_anyType, dirname, toolMissing);
224+ }
225+
226+ if (toolMissing)
227+ {
228+ COUT << " \n * denotes tools that cannot be called because they are not present\n in the directory where the '" << OFFIS_CONSOLE_APPLICATION << " ' tool is located." << OFendl;
169229 }
170230}
171231
@@ -218,16 +278,17 @@ int main(int argc, char* argv[])
218278 }
219279
220280 // find corresponding applet and call.
221- for (size_t i = 0 ; i < numTools; ++i) {
281+ for (size_t i = 0 ; i < numTools; ++i)
282+ {
222283 if (tool == tools[i].name )
223284 {
224- return OFstub_main (argc - offset, argv + offset, tool. c_str (), tool .c_str (), OFFalse /* printWarning */ , debug);
285+ return OFstub_main (argc - offset, argv + offset, tools[i]. command . c_str (), tools[i]. command .c_str (), OFFalse /* printWarning */ , debug);
225286 }
226287 }
227288
228- // If not in list, print error
289+ // if not in list, print error
229290 CERR << OFFIS_CONSOLE_APPLICATION << " : there is no DCMTK tool named \" " << tool
230- << " \" .\n To show the list of available tools, call \" " << OFFIS_CONSOLE_APPLICATION
231- << " --help\" ." << OFendl;
291+ << " \" .\n To show the list of available tools, call \" " << OFFIS_CONSOLE_APPLICATION
292+ << " --help\" ." << OFendl;
232293 return EXITCODE_COMMANDLINE_SYNTAX_ERROR;
233294}
0 commit comments