TPCCLIB
Loading...
Searching...
No Matches
niinan.c
Go to the documentation of this file.
1
7/*****************************************************************************/
8#include "tpcclibConfig.h"
9/*****************************************************************************/
10#include <stdio.h>
11#include <stdlib.h>
12#include <math.h>
13#include <string.h>
14/*****************************************************************************/
15#include "tpcextensions.h"
16//#include "tpcift.h"
17//#include "tpccsv.h"
18//#include "tpctac.h"
19#include "tpcimage.h"
20//#include "tpcstatist.h"
21/*****************************************************************************/
22
23/*****************************************************************************/
24static char *info[] = {
25 "Check if NIfTI image has missing pixel values.",
26 "Optionally, set missing pixel values to zero.",
27 " ",
28 "Usage: @P niftifile",
29 " ",
30 "Options:",
31 " -fix",
32 " Set missing pixel values to zero.",
33 " -stdoptions", // List standard options like --help, -v, etc
34 " ",
35 "See also: tacdelna, nii_lhdr, nii_ehdr, imgmax, tac2nii",
36 " ",
37 "Keywords: image, NIfTI, tool",
38 0};
39/*****************************************************************************/
40
41/*****************************************************************************/
42/* Turn on the globbing of the command line, since it is disabled by default in
43 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
44 In Unix&Linux wildcard command line processing is enabled by default. */
45/*
46#undef _CRT_glob
47#define _CRT_glob -1
48*/
49int _dowildcard = -1;
50/*****************************************************************************/
51
52/*****************************************************************************/
56int main(int argc, char **argv)
57{
58 int ai, help=0, version=0, verbose=1;
59 char fname[FILENAME_MAX];
60 int mode=0; // 0=report, 1=report and fix
61
62 /*
63 * Get arguments
64 */
65 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
66 fname[0]=(char)0;
67 /* Options */
68 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
69 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
70 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(!*cptr) continue;
71 if(strcasecmp(cptr, "FIX")==0) {
72 mode=1; continue;
73 }
74 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
75 return(1);
76 } else break;
77
78 /* Print help or version? */
79 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
80 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
81 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
82
83 /* Process other arguments, starting from the first non-option */
84 if(ai<argc) strlcpy(fname, argv[ai++], FILENAME_MAX);
85 if(ai<argc) {fprintf(stderr, "Error: too many arguments: '%s'.\n", argv[ai]); return(1);}
86 /* Is something missing? */
87 if(!fname[0]) {tpcPrintUsage(argv[0], info, stdout); return(1);}
88
89 /* In verbose mode print arguments and options */
90 if(verbose>1) {
91 printf("fname := %s\n", fname);
92 printf("mode := %d\n", mode);
93 fflush(stdout);
94 }
95
96 TPCSTATUS status; statusInit(&status);
97 statusSet(&status, __func__, __FILE__, __LINE__, TPCERROR_OK);
98 status.verbose=verbose-1;
99
100
101 /* Get NIfTI filenames, check existence, and read header */
102 if(verbose>1) printf(" checking that %s exists and is NIfTI\n", fname);
103 char hdrfile[FILENAME_MAX], imgfile[FILENAME_MAX], siffile[FILENAME_MAX];
104 NIFTI_DSR dsr;
105 if(!niftiExists(fname, hdrfile, imgfile, siffile, &dsr, &status)) {
106 fprintf(stderr, "Error: cannot read %s\n", fname);
107 return(2);
108 }
109 if(verbose>1) printf(" NIfTI header read from %s\n", hdrfile);
110
111 /* Get data type and check that it is currently supported */
112 if(verbose>2) printf(" verifying datatype\n");
113 int datatype=0;
114 if(dsr.n==1) datatype=dsr.h1.datatype; else datatype=dsr.h2.datatype;
115 int bitpix=0;
116 if(dsr.n==1) bitpix=dsr.h1.bitpix; else bitpix=dsr.h2.bitpix;
117 if(verbose>2) printf(" bits per pixel := %d\n", bitpix);
118 if(datatype!=NIFTI_DT_FLOAT || bitpix!=32) {
119 fprintf(stderr, "Error: currently unsupported NIfTI datatype.\n");
120 return(2);
121 }
122 int bytepix=bitpix/8;
123 if(verbose>2) printf(" bytes per pixel := %d\n", bytepix);
124
125 /* Get the image dimensions */
126 int dimNr;
127 if(dsr.n==1) dimNr=dsr.h1.dim[0]; else dimNr=dsr.h2.dim[0];
128 if(dimNr<2 || dimNr>4) {
129 fprintf(stderr, "Error: currently unsupported NIfTI dimensions.\n");
130 return(2);
131 }
132 long long dimx, dimy, dimz=1, dimt=1;
133 if(dsr.n==1) {
134 dimx=dsr.h1.dim[1]; dimy=dsr.h1.dim[2];
135 if(dimNr>2) {dimz=dsr.h1.dim[3]; if(dimNr>3) dimt=dsr.h1.dim[4];}
136 } else {
137 dimx=dsr.h2.dim[1]; dimy=dsr.h2.dim[2];
138 if(dimNr>2) {dimz=dsr.h2.dim[3]; if(dimNr>3) dimt=dsr.h2.dim[4];}
139 }
140 long long pxlNr=dimx*dimy*dimz;
141 if(pxlNr<1 || dimt<0) {
142 fprintf(stderr, "Error: invalid NIfTI dimensions.\n");
143 return(2);
144 }
145 if(dimt==0) dimt=1;
146 if(verbose>1) {
147 printf(" image_dim := %llu x %llu x %llu\n", dimx, dimy, dimz);
148 printf(" frames := %llu\n", dimt);
149 }
150
151
152 /* Open file */
153 if(verbose>1) printf(" reading pixel data in %s\n", imgfile);
154 FILE *fp=fopen(imgfile, "r+b");
155 if(fp==NULL) {
156 fprintf(stderr, "Error: cannot open %s\n", imgfile);
157 return(3);
158 }
159
160
161 /* Set initial read position.
162 Get the image data start location from header, in case of single file format */
163 long long start_pos=0;
164 {
165 long long int s=0;
166 if(dsr.n==1) s=(int)dsr.h1.vox_offset; else s=(int)dsr.h2.vox_offset;
167 if(s<0) start_pos=-s; else start_pos=s;
168 }
169 if(verbose>2) printf(" image_start_pos := %llu\n", start_pos);
170 /* Seek the data position, jumping over possible header */
171 if(start_pos>0) {
172 fseeko(fp, start_pos, SEEK_SET);
173 if(ftello(fp)!=start_pos) {
174 fprintf(stderr, "Error: invalid NIfTI format.\n");
175 fclose(fp); return(3);
176 }
177 }
178
179 /* Allocate memory for one frame of raw data */
180 if(verbose>2) printf(" pixels/frame := %llu\n", pxlNr);
181 long long rawSize=pxlNr*(bitpix/8);
182 if(verbose>1) printf(" raw bytes per frame := %lld\n", rawSize);
183 if(verbose>1) printf(" allocating memory for raw binary data\n");
184 unsigned char *buf=(unsigned char*)malloc(rawSize);
185 if(buf==NULL) {
186 fprintf(stderr, "Error: cannot allocate memory.\n");
187 fclose(fp); return(3);
188 }
189
190
191 /* Read the data, frame-by-frame */
192 if(verbose>1) printf(" reading binary data\n");
193 int little=endianLittle(); // Are we on little endian platform?
194 int byteconv=0;
195 if(little!=dsr.byte_order) {
196 byteconv=1;
197 if(verbose>1) printf(" byte conversion needed\n");
198 }
199
200 /* Get scaling factors */
201 float scl_slope, scl_inter;
202 if(dsr.n==1) {scl_slope=dsr.h1.scl_slope; scl_inter=dsr.h1.scl_inter;}
203 else {scl_slope=dsr.h2.scl_slope; scl_inter=dsr.h2.scl_inter;}
204 if(!isfinite(scl_slope) || !isfinite(scl_inter)) {
205 if(mode==0) {
206 fprintf(stderr, "Error: missing scaling factors.\n");
207 fclose(fp); free(buf); return(4);
208 }
209 if(!isfinite(scl_slope)) scl_slope=1.0;
210 if(!isfinite(scl_inter)) scl_inter=0.0;
211 }
212 if(scl_slope==0.0) scl_slope=1.0;
213
214 long long NaNr=0;
215 for(int ti=0; ti<dimt; ti++) {
216 if(verbose>3) printf(" frame %d\n", 1+ti);
217 if(fread(buf, rawSize, 1, fp) < 1) {
218 fprintf(stderr, "Error: cannot read image frame %d.\n", 1+ti);
219 fclose(fp); free(buf); return(4);
220 }
221 /* Convert byte order if necessary */
222 if(byteconv) swap32ip(buf, pxlNr);
223
224 /* Get and check float pixel values, and put fixed ones back if requested */
225 long long frameNaNr=0;
226 unsigned char *bptr=buf;
227 for(int zi=0; zi<dimz; zi++) {
228 for(int yi=0; yi<dimy; yi++) {
229 for(int xi=0; xi<dimx; xi++) {
230 float a;
231 memcpy(&a, bptr, 4); // a=scl_inter+scl_slope*a;
232 if(!isfinite(a)) {
233 frameNaNr++;
234 if(mode!=0) {a=0.0; memcpy(bptr, &a, 4);}
235 }
236 bptr+=bytepix;
237 }
238 }
239 }
240 if(frameNaNr==0) continue; // next frame
241 NaNr+=frameNaNr;
242 if(verbose>1) printf(" %llu missing pixel(s) in frame %d\n", frameNaNr, 1+ti);
243 if(mode==0) continue; // next frame
244 /* Convert byte order back if necessary */
245 if(byteconv) swap32ip(buf, pxlNr);
246
247 /* Save modified raw buffer */
248 fseeko(fp, -pxlNr*bytepix, SEEK_CUR); // move to original position of frame data
249 if(fwrite(buf, rawSize, 1, fp) < 1) {
250 fprintf(stderr, "Error: cannot write image frame %d.\n", 1+ti);
251 fclose(fp); free(buf); return(11);
252 }
253 } // next frame
254 fclose(fp); free(buf);
255
256 if(mode==0 || verbose>0) {
257 printf("missing_pixel_values := %llu\n", NaNr);
258 }
259
260 return(0);
261}
262/*****************************************************************************/
263
264/*****************************************************************************/
void swap32ip(void *buf, unsigned long long size)
Definition endian.c:210
int endianLittle()
Definition endian.c:53
int niftiExists(const char *filename, char *hdrfile, char *imgfile, char *siffile, NIFTI_DSR *header, TPCSTATUS *status)
Definition niftiio.c:17
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:47
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:169
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:339
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:114
void statusInit(TPCSTATUS *s)
Definition statusmsg.c:104
void statusSet(TPCSTATUS *s, const char *func, const char *srcfile, int srcline, tpcerror error)
Definition statusmsg.c:142
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition stringext.c:632
short int datatype
Definition tpcnifti.h:243
short int bitpix
Definition tpcnifti.h:245
float vox_offset
Definition tpcnifti.h:251
float scl_inter
Definition tpcnifti.h:255
short int dim[8]
Definition tpcnifti.h:233
float scl_slope
Definition tpcnifti.h:253
int64_t vox_offset
Definition tpcnifti.h:333
int16_t datatype
Definition tpcnifti.h:317
int64_t dim[8]
Definition tpcnifti.h:323
double scl_inter
Definition tpcnifti.h:337
double scl_slope
Definition tpcnifti.h:335
int16_t bitpix
Definition tpcnifti.h:319
NIFTI_2_HEADER h2
Definition tpcnifti.h:406
NIFTI_1_HEADER h1
Definition tpcnifti.h:404
int byte_order
Definition tpcnifti.h:412
int verbose
Verbose level, used by statusPrint() etc.
Header file for library libtpcextensions.
@ TPCERROR_OK
No error.
Header file for libtpcimage.
#define NIFTI_DT_FLOAT
Definition tpcnifti.h:100