TPCCLIB
Loading...
Searching...
No Matches
imgidpvc.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#include <math.h>
15#include <time.h>
16/*****************************************************************************/
17#include "libtpcmisc.h"
18#include "libtpcimgio.h"
19#include "libtpcimgp.h"
20/*****************************************************************************/
21
22/*****************************************************************************/
23static char *info[] = {
24 "Iterative deconvolution method for partial volume correction of PET images",
25 "in ECAT 6.3, 7.x, and Analyze 7.5 and NIfTI-1 formats.",
26 "Not for production use!",
27 " ",
28 "Usage: @P [Options] image FWHMxy FWHMz pvcimage",
29 " ",
30 "Options:",
31 " -method=<VC|RL>",
32 " Use van Cittert or Richardson-Lucy method; VC by default.",
33 " -reblur=<yes|no>",
34 " Include reblurring step; by default yes.",
35 " -alpha=<value>",
36 " Converging rate parameter (0.0<alpha<10.0).",
37 " -beta=<value>",
38 " Upper limit for deconvolved image as a factor of image maximum value.",
39 " -iter=<number>",
40 " Maximum number of iterations.",
41 " -term=<value>",
42 " Limit for termination (0.0<term<1.0).",
43 " -stdoptions", // List standard options like --help, -v, etc
44 " ",
45 "FWHM can be given in mm (default) or in pixels. If image file does not",
46 "contain correct pixel sizes, then FWHM must be entered in pixels.",
47 " ",
48 "Example: FWHM in mm",
49 " @P i5998dy1.v 2.5 2.65 i5998dy1_pvc.v",
50 "Example: FWHM in pixels",
51 " @P i5998dy1.v 2.1pxl 1.7pxl i5998dy1_pvc.v",
52 " ",
53 "See also: imgfiltg, imgbox, imgmask",
54 " ",
55 "Keywords: image, PVC",
56 0};
57/*****************************************************************************/
58
59/*****************************************************************************/
60/* Turn on the globbing of the command line, since it is disabled by default in
61 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
62 In Unix&Linux wildcard command line processing is enabled by default. */
63/*
64#undef _CRT_glob
65#define _CRT_glob -1
66*/
67int _dowildcard = -1;
68/*****************************************************************************/
69
70/*****************************************************************************/
72
89 IMG *img1,
91 double FWHMxy,
93 double FWHMz,
95 int reblur,
97 double betaFactor,
99 double alpha,
101 int maxIterNr,
103 double termLimit,
107 IMG *img2,
109 int verbose
110) {
111 if(verbose>0) {
112 printf("%s(i, %g, %g, %d, %g, %g, %d, %g, ...)\n",
113 __func__, FWHMxy, FWHMz, reblur, betaFactor, alpha, maxIterNr, termLimit);
114 fflush(stdout);
115 }
116 if(img1==NULL || img2==NULL) return(1);
117 if(img1->dimz<1 || img1->dimy<8 || img1->dimx<8 || img1->dimt<1) return(2);
118 if(!(FWHMxy>0.0)) return(3);
119 if(img1->dimz<2) FWHMz=0.0;
120 if(!(betaFactor>0.0)) betaFactor=1.4;
121 if(maxIterNr<1) maxIterNr=25;
122 if(!(alpha>0.0)) alpha=1.6;
123 if(!(termLimit>0.0) || termLimit>=1) termLimit=0.005;
124
125 /* Convert FWHM into Gaussian SD */
126 float SDxy=FWHMxy/2.355;
127 float SDz=FWHMz/2.355;
128
129 int x, dimx=img1->dimx;
130 int y, dimy=img1->dimy;
131 int z, dimz=img1->dimz;
132 int t, dimt=img1->dimt;
133
134 /* Allocate output image and set headers */
135 {
136 int ret=imgAllocateWithHeader(img2, dimz, dimy, dimx, dimt, img1);
137 if(ret) return(10+ret);
138 }
139
140 /* Allocate image frame, for 'true' and correction matrices */
141 IMG tkm, cm; imgInit(&tkm); imgInit(&cm);
142 {
143 int ret=imgAllocateWithHeader(&tkm, dimz, dimy, dimx, 1, img1);
144 if(!ret) ret=imgAllocateWithHeader(&cm, dimz, dimy, dimx, 1, img1);
145 if(ret) {imgEmpty(&tkm); imgEmpty(&cm); return(5);}
146 }
147
148 /*
149 * One image frame at a time
150 */
151 for(t=0; t<dimt; t++) {
152 if(verbose>2 && dimt>1) {printf(" frame %d\n", 1+t); fflush(stdout);}
153
154 /* First, copy the original measured contents to "true" image matrix */
155 for(z=0; z<dimz; z++) for(y=0; y<dimy; y++) for(x=0; x<dimx; x++)
156 tkm.m[z][y][x][0]=img1->m[z][y][x][t];
157
158 /* Get image frame minimum and maximum for setting beta */
159 float omin, omax;
160 if(imgMinMax(&tkm, &omin, &omax)) {imgEmpty(&tkm); imgEmpty(&cm); return(6);}
161 if(!(omax>omin) || !(omax>0.0)) continue;
162 double beta=betaFactor*omax;
163 if(verbose>4) {
164 printf(" image_min := %g\n image_max := %g\n", omin, omax);
165 printf(" beta := %g\n", beta);
166 fflush(stdout);
167 }
168
169 /* Iterations */
170 int ret=0, iterNr=0;
171 for(iterNr=0; iterNr<maxIterNr; iterNr++) {
172 if(verbose>3) {printf(" iteration %d\n", 1+iterNr); fflush(stdout);}
173 /* Convolution of current estimate of true image with PSF (Gaussian filter) */
174 for(z=0; z<dimz; z++) for(y=0; y<dimy; y++) for(x=0; x<dimx; x++)
175 cm.m[z][y][x][0]=tkm.m[z][y][x][0];
176 ret=imgGaussianFIRFilter(&cm, SDxy, SDxy, SDz, 1.0E-03, verbose-5);
177 if(ret) {ret+=100; break;}
178 /* Divide the measured image matrix with it */
179 for(z=0; z<dimz; z++) for(y=0; y<dimy; y++) for(x=0; x<dimx; x++) {
180 float f=img1->m[z][y][x][t]/cm.m[z][y][x][0];
181 if(!isfinite(f)) {
182 if(fabs(img1->m[z][y][x][t])<1.0E-06) f=0.0; else f=1.0;
183 }
184 cm.m[z][y][x][0]=f;
185 }
186 /* Re-blurring the correction matrix with PSF (Gaussian filter) */
187 if(reblur) {
188 ret=imgGaussianFIRFilter(&cm, SDxy, SDxy, SDz, 1.0E-03, verbose-5);
189 if(ret) {ret+=200; break;}
190 }
191 /* Multiply the previous estimate of true image matrix; */
192 /* and calculate factor to check for termination */
193 double dsum=0.0, psum=0.0;
194 for(z=0; z<dimz; z++) for(y=0; y<dimy; y++) for(x=0; x<dimx; x++) {
195 double prev=tkm.m[z][y][x][0];
196 tkm.m[z][y][x][0]*=cm.m[z][y][x][0];
197 if(tkm.m[z][y][x][0]<=0.0 && img1->m[z][y][x][t]>0.0)
198 tkm.m[z][y][x][0]=0.01*img1->m[z][y][x][t];
199 if(tkm.m[z][y][x][0]>beta) tkm.m[z][y][x][0]=beta;
200 double d=tkm.m[z][y][x][0]-prev;
201 dsum+=d*d; psum+=prev*prev;
202 }
203 double dssqr=sqrt(dsum)/sqrt(psum); if(verbose>4) printf(" dssqr := %g\n", dssqr);
204 if(dssqr<termLimit) break;
205 } // next iteration
206 if(ret) {imgEmpty(&tkm); imgEmpty(&cm); return(ret);}
207 if(verbose>3) {printf(" iterNr := %d\n", (iterNr>=maxIterNr?maxIterNr:1+iterNr)); fflush(stdout);}
208
209 /* Copy the estimate of true matrix to output image */
210 for(z=0; z<dimz; z++) for(y=0; y<dimy; y++) for(x=0; x<dimx; x++)
211 img2->m[z][y][x][t]=tkm.m[z][y][x][0];
212
213 } // next frame
214
215 imgEmpty(&tkm); imgEmpty(&cm);
216 return(0);
217}
218/*****************************************************************************/
219
220/*****************************************************************************/
236 IMG *img1,
238 double FWHMxy,
240 double FWHMz,
242 int reblur,
244 double betaFactor,
246 double alpha,
248 int maxIterNr,
250 double termLimit,
254 IMG *img2,
256 int verbose
257) {
258 if(verbose>0) {
259 printf("%s(i, %g, %g, %d, %g, %g, %d, %g, ...)\n",
260 __func__, FWHMxy, FWHMz, reblur, betaFactor, alpha, maxIterNr, termLimit);
261 fflush(stdout);
262 }
263 if(img1==NULL || img2==NULL) return(1);
264 if(img1->dimz<1 || img1->dimy<8 || img1->dimx<8 || img1->dimt<1) return(2);
265 if(!(FWHMxy>0.0)) return(3);
266 if(img1->dimz<2) FWHMz=0.0;
267 if(!(betaFactor>0.0)) betaFactor=1.4;
268 if(maxIterNr<1) maxIterNr=25;
269 if(!(alpha>0.0)) alpha=1.6;
270 if(!(termLimit>0.0) || termLimit>=1) termLimit=0.005;
271
272 /* Convert FWHM into Gaussian SD */
273 float SDxy=FWHMxy/2.355;
274 float SDz=FWHMz/2.355;
275
276 int x, dimx=img1->dimx;
277 int y, dimy=img1->dimy;
278 int z, dimz=img1->dimz;
279 int t, dimt=img1->dimt;
280
281 /* Allocate output image and set headers */
282 {
283 int ret=imgAllocateWithHeader(img2, dimz, dimy, dimx, dimt, img1);
284 if(ret) return(10+ret);
285 }
286
287 /* Allocate image frame, for 'true' and correction matrices */
288 IMG tkm, cm; imgInit(&tkm); imgInit(&cm);
289 {
290 int ret=imgAllocateWithHeader(&tkm, dimz, dimy, dimx, 1, img1);
291 if(!ret) ret=imgAllocateWithHeader(&cm, dimz, dimy, dimx, 1, img1);
292 if(ret) {imgEmpty(&tkm); imgEmpty(&cm); return(5);}
293 }
294
295 /*
296 * One image frame at a time
297 */
298 for(t=0; t<dimt; t++) {
299 if(verbose>2 && dimt>1) {printf(" frame %d\n", 1+t); fflush(stdout);}
300
301 /* First, copy the original measured contents to "true" image matrix */
302 for(z=0; z<dimz; z++) for(y=0; y<dimy; y++) for(x=0; x<dimx; x++)
303 tkm.m[z][y][x][0]=img1->m[z][y][x][t];
304
305 /* Get image frame minimum and maximum for setting beta */
306 float omin, omax;
307 if(imgMinMax(&tkm, &omin, &omax)) {imgEmpty(&tkm); imgEmpty(&cm); return(6);}
308 if(!(omax>omin) || !(omax>0.0)) continue;
309 double beta=betaFactor*omax;
310 if(verbose>4) {
311 printf(" image_min := %g\n image_max := %g\n", omin, omax);
312 printf(" beta := %g\n", beta);
313 fflush(stdout);
314 }
315
316 /* Iterations */
317 int ret=0, iterNr=0;
318 for(iterNr=0; iterNr<maxIterNr; iterNr++) {
319 if(verbose>3) {printf(" iteration %d\n", 1+iterNr); fflush(stdout);}
320 /* Convolution of current estimate of true image with PSF (Gaussian filter) */
321 for(z=0; z<dimz; z++) for(y=0; y<dimy; y++) for(x=0; x<dimx; x++)
322 cm.m[z][y][x][0]=tkm.m[z][y][x][0];
323 ret=imgGaussianFIRFilter(&cm, SDxy, SDxy, SDz, 1.0E-03, verbose-5);
324 if(ret) {ret+=100; break;}
325 /* Subtract from measured image matrix */
326 for(z=0; z<dimz; z++) for(y=0; y<dimy; y++) for(x=0; x<dimx; x++)
327 cm.m[z][y][x][0]=img1->m[z][y][x][t]-cm.m[z][y][x][0];
328 /* Re-blurring the difference with PSF (Gaussian filter) */
329 if(reblur) {
330 ret=imgGaussianFIRFilter(&cm, SDxy, SDxy, SDz, 1.0E-03, verbose-5);
331 if(ret) {ret+=200; break;}
332 }
333 /* Add to the previous estimate of true image matrix, applying relaxation function; */
334 /* and calculate factor to check for termination */
335 double dsum=0.0, psum=0.0;
336 for(z=0; z<dimz; z++) for(y=0; y<dimy; y++) for(x=0; x<dimx; x++) {
337 double r=alpha*(1.0 - (2.0/beta)*fabs(tkm.m[z][y][x][0] - beta/2.0));
338 double d=r*cm.m[z][y][x][0]; dsum+=d*d; psum+=tkm.m[z][y][x][0]*tkm.m[z][y][x][0];
339 tkm.m[z][y][x][0]+=r*cm.m[z][y][x][0];
340 }
341 double dssqr=sqrt(dsum)/sqrt(psum); if(verbose>4) printf(" dssqr := %g\n", dssqr);
342 if(dssqr<termLimit) break;
343 } // next iteration
344 if(ret) {imgEmpty(&tkm); imgEmpty(&cm); return(ret);}
345 if(verbose>3) {printf(" iterNr := %d\n", (iterNr>=maxIterNr?maxIterNr:1+iterNr)); fflush(stdout);}
346
347 /* Copy the estimate of true matrix to output image */
348 for(z=0; z<dimz; z++) for(y=0; y<dimy; y++) for(x=0; x<dimx; x++)
349 img2->m[z][y][x][t]=tkm.m[z][y][x][0];
350
351 } // next frame
352
353 imgEmpty(&tkm); imgEmpty(&cm);
354 return(0);
355}
357/*****************************************************************************/
358
359/*****************************************************************************/
363int main(int argc, char **argv)
364{
365 int ai, help=0, version=0, verbose=1;
366 char petfile[FILENAME_MAX], outfile[FILENAME_MAX];
367 double FWHMxy=nan(""), FWHMz=nan("");
368 int FWHMxyUnit=1, FWHMzUnit=1; // 0=pixels, 1=mm, 2=cm
369 int method=0; // 0=VC; 1=RL
370 int reblur=1;
371 double betaFactor=1.4;
372 double alpha=1.5;
373 int maxIterNr=40;
374 double termLimit=0.01;
375
376
377 /*
378 * Get arguments
379 */
380 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
381 petfile[0]=outfile[0]=(char)0;
382 /* Get options */
383 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
384 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
385 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
386 if(strncasecmp(cptr, "METHOD=", 7)==0) {
387 cptr+=7;
388 if(strncasecmp(cptr, "VC", 1)==0) {method=0; continue;}
389 if(strncasecmp(cptr, "RL", 1)==0) {method=1; continue;}
390 } else if(strncasecmp(cptr, "REBLUR=", 7)==0) {
391 cptr+=7;
392 if(strncasecmp(cptr, "YES", 1)==0) {reblur=1; continue;}
393 if(strncasecmp(cptr, "NO", 1)==0) {reblur=0; continue;}
394 } else if(strncasecmp(cptr, "BETA=", 5)==0 && strlen(cptr)>5) {
395 betaFactor=atof_dpi(cptr+5); if(betaFactor>0.0) continue;
396 } else if(strncasecmp(cptr, "ALPHA=", 6)==0) {
397 alpha=atof_dpi(cptr+6); if(alpha>0.0) continue;
398 } else if(strncasecmp(cptr, "TERM=", 5)==0) {
399 termLimit=atof_dpi(cptr+5); if(termLimit>0.0 && termLimit<1) continue;
400 } else if(strncasecmp(cptr, "ITER=", 5)==0) {
401 maxIterNr=atoi(cptr+5); if(maxIterNr>0) continue;
402 }
403 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
404 return(1);
405 } else break;
406
407 /* Print help or version? */
408 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
409 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
410 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
411
412 /* Process other arguments, starting from the first non-option */
413 if(ai<argc) {strlcpy(petfile, argv[ai++], FILENAME_MAX);}
414 if(ai<argc) {
415 int ret=atof_with_check(argv[ai], &FWHMxy);
416 if(ret==0 && FWHMxy>=0.0) {
417 /* Check if unit was specified too */
418 if(strcasestr(argv[ai], "pxl")!=NULL) FWHMxyUnit=0;
419 if(strcasestr(argv[ai], "mm")!=NULL) FWHMxyUnit=1;
420 if(strcasestr(argv[ai], "cm")!=NULL) FWHMxyUnit=2;
421 ai++;
422 } else {
423 fprintf(stderr, "Error: invalid x,y FWHM.\n");
424 return(1);
425 }
426 }
427 if(ai<argc) {
428 int ret=atof_with_check(argv[ai], &FWHMz);
429 if(ret==0 && FWHMz>=0.0) {
430 /* Check if unit was specified too */
431 if(strcasestr(argv[ai], "pxl")!=NULL) FWHMzUnit=0;
432 if(strcasestr(argv[ai], "mm")!=NULL) FWHMzUnit=1;
433 if(strcasestr(argv[ai], "cm")!=NULL) FWHMzUnit=2;
434 ai++;
435 } else {
436 fprintf(stderr, "Error: invalid z FWHM.\n");
437 return(1);
438 }
439 }
440 if(ai<argc) {strlcpy(outfile, argv[ai++], FILENAME_MAX);}
441 if(ai<argc) {
442 fprintf(stderr, "Error: invalid argument '%s'.\n", argv[ai]);
443 return(1);
444 }
445
446 /* Did we get all the information that we need? */
447 if(!outfile[0]) {
448 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
449 return(1);
450 }
451 if(!(FWHMxy>0.0) && !(FWHMz>0.0)) {
452 fprintf(stderr, "Error: invalid FWHM.\n");
453 return(1);
454 }
455
456 /* In verbose mode print arguments and options */
457 if(verbose>1) {
458 printf("petfile := %s\n", petfile);
459 printf("FWHMxy := %g\n", FWHMxy);
460 printf("FWHMz := %g\n", FWHMz);
461 printf("outfile := %s\n", outfile);
462 if(method==1) printf("method := RL\n"); else printf("method := VC\n");
463 printf("reblur := %d\n", reblur);
464 printf("alpha := %g\n", alpha);
465 printf("betaFactor := %g\n", betaFactor);
466 printf("termLimit := %g\n", termLimit);
467 printf("maxIterNr := %d\n", maxIterNr);
468 }
469 if(verbose>9) IMG_TEST=verbose-10; else IMG_TEST=0;
470
471
472 /*
473 * Read image
474 */
475 if(verbose>0) fprintf(stdout, "reading image %s\n", petfile);
476 IMG img; imgInit(&img);
477 if(imgRead(petfile, &img)) {
478 fprintf(stderr, "Error: %s\n", img.statmsg); if(verbose>1) imgInfo(&img);
479 return(2);
480 }
481 if(verbose>1) {
482 printf("image dimensions[z y x]: %d %d %d\n", img.dimz, img.dimy, img.dimx);
483 printf("image voxel size[z y x]: %g %g %g\n", img.sizez, img.sizey, img.sizex);
484 printf("image frame nr: %d\n", img.dimt);
485 }
486 /* Check if PET data is raw or image */
487 if(img.type!=IMG_TYPE_IMAGE) {
488 fprintf(stderr, "Error: %s is not an image.\n", petfile);
489 imgEmpty(&img); return(2);
490 }
491 if(imgNaNs(&img, 1)>0)
492 if(verbose>0) fprintf(stderr, "Warning: missing pixel values.\n");
493
494 /*
495 * Convert FWHM into pixel units, if necessary
496 */
497 if((FWHMxyUnit!=0 && (!(img.sizex>0.0) || !(img.sizey>0.0))) || (FWHMzUnit!=0 && !(img.sizez>0.0)))
498 {
499 fprintf(stderr, "Error: unknown image pixel size.\n");
500 imgEmpty(&img); return(3);
501 }
502 /* Convert cm -> mm */
503 if(FWHMxyUnit==2) {FWHMxy*=10.0; FWHMxyUnit=1;}
504 if(FWHMzUnit==2) {FWHMz*=10.0; FWHMzUnit=1;}
505 /* Convert mm -> pixels */
506 if(FWHMxyUnit==1) {FWHMxy/=img.sizex; FWHMxyUnit=0; printf("FWHMxy[pxl] := %g\n", FWHMxy);}
507 if(FWHMzUnit==1) {FWHMz/=img.sizez; FWHMzUnit=0; printf("FWHMz[pxl] := %g\n", FWHMz);}
508
509
510 /*
511 * PVC
512 */
513 if(verbose>0) fprintf(stdout, "correcting...\n");
514 IMG out; imgInit(&out);
515 {
516 int ret=0;
517 if(method==1)
518 ret=imgPVCRRL(&img, FWHMxy, FWHMz, reblur, betaFactor, alpha, maxIterNr, termLimit,
519 &out, verbose-2);
520 else
521 ret=imgPVCRVC(&img, FWHMxy, FWHMz, reblur, betaFactor, alpha, maxIterNr, termLimit,
522 &out, verbose-2);
523 if(ret) {
524 fprintf(stderr, "Error: cannot correct image.\n");
525 if(verbose>1) printf("ret=%d\n", ret);
526 imgEmpty(&img); imgEmpty(&out); return(3);
527 }
528 }
529
530 /* Free memory allocated for original image */
531 imgEmpty(&img);
532
533
534 /*
535 * Save the image
536 */
537 if(verbose>1) fprintf(stdout, "writing image in %s\n", outfile);
538 {
539 int ret=imgWrite(outfile, &out);
540 if(ret) {
541 fprintf(stderr, "Error: %s\n", out.statmsg);
542 imgEmpty(&out); return(11);
543 }
544 if(verbose>0) fprintf(stdout, "Image was written in %s\n", outfile);
545 }
546
547 /* Free memory allocated for output image */
548 imgEmpty(&out);
549
550 return(0);
551}
552/*****************************************************************************/
553
554/*****************************************************************************/
int atof_with_check(char *double_as_string, double *result_value)
Definition decpoint.c:107
double atof_dpi(char *str)
Definition decpoint.c:59
int IMG_TEST
Definition img.c:6
void imgInfo(IMG *image)
Definition img.c:359
unsigned long long imgNaNs(IMG *img, int fix)
Definition img.c:658
int imgAllocateWithHeader(IMG *image, int planes, int rows, int columns, int frames, IMG *image_from)
Definition img.c:279
void imgEmpty(IMG *image)
Definition img.c:121
void imgInit(IMG *image)
Definition img.c:60
int imgRead(const char *fname, IMG *img)
Definition imgfile.c:26
int imgWrite(const char *fname, IMG *img)
Definition imgfile.c:136
int imgGaussianFIRFilter(IMG *img, float xsd, float ysd, float zsd, double tolerance, int verbose)
Definition imgfilter.c:18
int imgPVCRRL(IMG *img1, double FWHMxy, double FWHMz, int reblur, double betaFactor, double alpha, int maxIterNr, double termLimit, IMG *img2, int verbose)
Definition imgidpvc.c:87
int imgPVCRVC(IMG *img1, double FWHMxy, double FWHMz, int reblur, double betaFactor, double alpha, int maxIterNr, double termLimit, IMG *img2, int verbose)
Definition imgidpvc.c:234
int imgMinMax(IMG *img, float *minvalue, float *maxvalue)
Definition imgminmax.c:154
Header file for libtpcimgio.
#define IMG_TYPE_IMAGE
Header file for libtpcimgp.
Header file for libtpcmisc.
int tpcProcessStdOptions(const char *s, int *print_usage, int *print_version, int *verbose_level)
Definition proginfo.c:40
size_t strlcpy(char *dst, const char *src, size_t dstsize)
Definition strext.c:245
char * strcasestr(const char *haystack, const char *needle)
Definition strext.c:279
int tpcHtmlUsage(const char *program, char *text[], const char *path)
Definition proginfo.c:213
void tpcPrintBuild(const char *program, FILE *fp)
Definition proginfo.c:383
void tpcPrintUsage(const char *program, char *text[], FILE *fp)
Definition proginfo.c:158
float sizex
unsigned short int dimx
char type
float **** m
unsigned short int dimt
float sizey
unsigned short int dimz
unsigned short int dimy
const char * statmsg
float sizez