1 //  main.m dcm2niix
2 // by Chris Rorden on 3/22/14, see license.txt
3 //  Copyright (c) 2014 Chris Rorden. All rights reserved.
4 //  yaml batch support by Benjamin Irving, 2016 - maintains copyright
5 
6 #include <stdbool.h> //requires VS 2015 or later
7 #ifdef _MSC_VER
8 	#include  <io.h> //access()
9 	#ifndef F_OK
10 	#define F_OK 0 /* existence check */
11 	#endif
12 #else
13 	#include <unistd.h> //access()
14 #endif
15 #include <cmath>
16 #include <fstream>
17 #include <iostream>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string>
21 #include <time.h>  // clock_t, clock, CLOCKS_PER_SEC
22 #include <yaml-cpp/yaml.h>
23 #include "nii_dicom.h"
24 #include "nii_dicom_batch.h"
25 
removePath(const char * path)26 const char* removePath(const char* path) { // "/usr/path/filename.exe" -> "filename.exe"
27     const char* pDelimeter = strrchr (path, '\\');
28     if (pDelimeter)
29         path = pDelimeter+1;
30     pDelimeter = strrchr (path, '/');
31     if (pDelimeter)
32         path = pDelimeter+1;
33     return path;
34 } //removePath()
35 
rmainbatch(TDCMopts opts)36 int rmainbatch(TDCMopts opts) {
37     clock_t start = clock();
38     nii_loadDir(&opts);
39     printf ("Conversion required %f seconds.\n",((float)(clock()-start))/CLOCKS_PER_SEC);
40     return EXIT_SUCCESS;
41 } //rmainbatch()
42 
showHelp(const char * argv[])43 void showHelp(const char * argv[]) {
44     const char *cstr = removePath(argv[0]);
45     printf("Usage: %s <batch_config.yml>\n", cstr);
46     printf("\n");
47 	printf("The configuration file must be in yaml format as shown below\n");
48 	printf("\n");
49 	printf("### START YAML FILE ###\n");
50 	printf("Options:\n");
51 	printf("   isGz:             false\n");
52 	printf("   isFlipY:          false\n");
53 	printf("   isVerbose:        false\n");
54 	printf("   isCreateBIDS:     false\n");
55 	printf("   isOnlySingleFile: false\n");
56 	printf("Files:\n");
57 	printf("   -\n");
58 	printf("    in_dir:           /path/to/first/folder\n");
59 	printf("    out_dir:          /path/to/output/folder\n");
60 	printf("    filename:         dcemri\n");
61 	printf("   -\n");
62 	printf("    in_dir:           /path/to/second/folder\n");
63 	printf("    out_dir:          /path/to/output/folder\n");
64 	printf("    filename:         fa3\n");
65 	printf("### END YAML FILE ###\n");
66 	printf("\n");
67 #if defined(_WIN64) || defined(_WIN32)
68     printf(" Example :\n");
69     printf("  %s c:\\dir\\yaml.yml\n", cstr);
70 
71     printf("  %s \"c:\\dir with spaces\\yaml.yml\"\n", cstr);
72 #else
73     printf(" Examples :\n");
74     printf("  %s /Users/chris/yaml.yml\n", cstr);
75     printf("  %s \"/Users/dir with spaces/yaml.yml\"\n", cstr);
76 #endif
77 } //showHelp()
78 
main(int argc,const char * argv[])79 int main(int argc, const char * argv[]) {
80 	#if defined(__APPLE__)
81 		#define kOS "MacOS"
82 	#elif (defined(__linux) || defined(__linux__))
83 		#define kOS "Linux"
84 	#else
85 		#define kOS "Windows"
86 	#endif
87 	printf("dcm2niibatch using Chris Rorden's dcm2niiX version %s (%llu-bit %s)\n",kDCMvers, (unsigned long long) sizeof(size_t)*8, kOS);
88     if (argc != 2) {
89     	if (argc < 2)
90     		printf(" Please provide location of config file\n");
91     	else
92         	printf(" Do not include additional inputs with a config file\n");
93         printf("\n");
94         showHelp(argv);
95         return EXIT_FAILURE;
96     }
97 	if( access( argv[1], F_OK ) == -1 ) {
98         printf(" Please provide location of config file\n");
99         printf("\n");
100         showHelp(argv);
101         return EXIT_FAILURE;
102 	}
103     // Process it all via a yaml file
104     std::string yaml_file = argv[1];
105     std::cout << "yaml_path: " << yaml_file << std::endl;
106     YAML::Node config = YAML::LoadFile(yaml_file);
107     struct TDCMopts opts;
108     readIniFile(&opts, argv); //setup defaults, e.g. path to pigz
109     opts.isCreateBIDS = config["Options"]["isCreateBIDS"].as<bool>();
110     opts.isOnlySingleFile = config["Options"]["isOnlySingleFile"].as<bool>();
111     opts.isFlipY = config["Options"]["isFlipY"].as<bool>();
112     opts.isCreateText = false;
113     opts.isVerbose = 0;
114     opts.isGz = config["Options"]["isGz"].as<bool>(); //save data as compressed (.nii.gz) or raw (.nii)
115    	/*bool isInternalGz = config["Options"]["isInternalGz"].as<bool>();
116     if (isInternalGz) {
117         strcpy(opts.pigzname, "”); //do NOT use pigz: force internal compressor
118 		//in general, pigz is faster unless you have a very slow network, in which case the internal compressor is better
119     }*/
120     for (auto i: config["Files"]) {
121         std::string indir = i["in_dir"].as<std::string>();
122         strcpy(opts.indir, indir.c_str());
123         std::string outdir = i["out_dir"].as<std::string>();
124         strcpy(opts.outdir, outdir.c_str());
125         std::string filename = i["filename"].as<std::string>();
126         strcpy(opts.filename, filename.c_str());
127         rmainbatch(opts);
128     }
129     return EXIT_SUCCESS;
130 } // main()
131