TPCCLIB
Loading...
Searching...
No Matches
imgcutof.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 <unistd.h>
15#include <time.h>
16/*****************************************************************************/
17#include "libtpcmisc.h"
18#include "libtpcimgio.h"
19#include "libtpcimgp.h"
20#include "libtpcmodext.h"
21/*****************************************************************************/
22
23/*****************************************************************************/
24static char *info[] = {
25 "Cut off PET image (in ECAT, NIfTI, or Analyze format) pixel values that are",
26 "outside given range of values.",
27 "Original image file is modified, if file name for output is not given.",
28 " ",
29 "Usage: @P [Options] imgfile lowerlimit upperlimit [outputfile]",
30 " ",
31 "Options:",
32 " -zero",
33 " Set pixel value to zero if original value is outside of the range;",
34 " by default value is set to the limit.",
35 " -mask",
36 " Set pixel value to one or zero, depending whether original value is",
37 " inside or outside of the range.",
38 " --force",
39 " Optional output file is written even in the case that no pixel values",
40 " fell outside of limits; by default image is saved only if contents were",
41 " modified.",
42 " -stdoptions", // List standard options like --help, -v, etc
43 " ",
44 "Lower and upper limit can be given directly as values on the command line,",
45 "or as names of files containing only the value, or value with key 'lower' or",
46 "'upper', respectively.",
47 " ",
48 "See also: imgthrs, imgmask, imgqntls, imginteg, imgunit",
49 " ",
50 "Keywords: image, threshold, mask",
51 0};
52/*****************************************************************************/
53
54/*****************************************************************************/
55/* Turn on the globbing of the command line, since it is disabled by default in
56 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
57 In Unix&Linux wildcard command line processing is enabled by default. */
58/*
59#undef _CRT_glob
60#define _CRT_glob -1
61*/
62int _dowildcard = -1;
63/*****************************************************************************/
64
65/*****************************************************************************/
69int main(int argc, char **argv)
70{
71 int ai, help=0, version=0, verbose=1;
72 char petfile[FILENAME_MAX], outfile[FILENAME_MAX];
73 float lowerThreshold=+1.0, upperThreshold=-1.0;
74 int zeroMode=0; // 0=off; 1=on
75 int maskMode=0; // 0=off; 1=on
76 int forceMode=0; // 0=off; 1=on
77 char *cptr;
78 int ret=0;
79
80
81 /*
82 * Get arguments
83 */
84 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
85 petfile[0]=outfile[0]=(char)0;
86 /* Get options */
87 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
88 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
89 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
90 if(strncasecmp(cptr, "ZERO", 1)==0) {
91 zeroMode=1; continue;
92 } else if(strncasecmp(cptr, "MASK", 1)==0) {
93 maskMode=1; continue;
94 } else if(strcasecmp(cptr, "F")==0 || strcasecmp(cptr, "FORCE")==0) {
95 forceMode=1; continue;
96 }
97 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
98 return(1);
99 } else break;
100
101 /* Print help or version? */
102 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
103 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
104 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
105
106 /* Process other arguments, starting from the first non-option */
107 if(ai<argc) {strlcpy(petfile, argv[ai], FILENAME_MAX); ai++;}
108 if(ai<argc) {
109 double v;
110 char *s=iftReadValue(argv[ai], "lower", 0);
111 if(s!=NULL) {ret=atof_with_check(s, &v); free(s);}
112 else ret=atof_with_check(argv[ai], &v);
113 if(ret!=0) {
114 fprintf(stderr, "Error: invalid lower limit '%s'.\n", argv[ai]);
115 return(1);
116 }
117 lowerThreshold=v;
118 ai++;
119 } else {
120 fprintf(stderr, "Error: missing command-line argument; try %s --help\n", argv[0]);
121 return(1);
122 }
123 if(ai<argc) {
124 double v;
125 char *s=iftReadValue(argv[ai], "upper", 0);
126 if(s!=NULL) {ret=atof_with_check(s, &v); free(s);}
127 else ret=atof_with_check(argv[ai], &v);
128 if(ret!=0) {
129 fprintf(stderr, "Error: invalid lower limit '%s'.\n", argv[ai]);
130 return(1);
131 }
132 upperThreshold=v;
133 ai++;
134 } else {
135 fprintf(stderr, "Error: missing command-line argument; try %s --help\n", argv[0]);
136 return(1);
137 }
138 if(ai<argc) {strlcpy(outfile, argv[ai], FILENAME_MAX); ai++;}
139 if(ai<argc) {fprintf(stderr, "Error: too many arguments.\n"); return(1);}
140
141
142 /* Did we get all the information that we need? */
143 if(!petfile[0]) {
144 fprintf(stderr, "Error: missing command-line argument; try %s --help\n", argv[0]);
145 return(1);
146 }
147 if(lowerThreshold>upperThreshold) {
148 fprintf(stderr, "Error: invalid value range.\n");
149 return(1);
150 }
151 if(lowerThreshold==upperThreshold) {
152 /* Image data is stored with limited precision, therefore limits should not be equal */
153 float f;
154 f=0.001*lowerThreshold; lowerThreshold-=f; upperThreshold+=f;
155 if(verbose>1) printf("Threshold range: %g - %g\n", lowerThreshold, upperThreshold);
156 }
157 /* Overwrite original file, if output file name was not given */
158 if(!outfile[0]) strcpy(outfile, petfile);
159 /* Mask-mode overrides zero-mode */
160 if(maskMode) zeroMode=0;
161
162
163 /* In verbose mode print arguments and options */
164 if(verbose>1) {
165 printf("petfile := %s\n", petfile);
166 if(outfile[0]) printf("outfile := %s\n", outfile);
167 printf("upper_limit := %g\n", upperThreshold);
168 printf("lower_limit := %g\n", lowerThreshold);
169 printf("zeroMode := %d\n", zeroMode);
170 printf("maskMode := %d\n", maskMode);
171 }
172
173
174 /*
175 * Read the contents of the PET file to img data structure
176 */
177 IMG img; imgInit(&img);
178 if(verbose>0) printf("reading %s\n", petfile);
179 ret=imgRead(petfile, &img);
180 if(ret) {
181 fprintf(stderr, "Error: %s\n", img.statmsg);
182 if(verbose>1) printf("ret=%d\n", ret);
183 imgEmpty(&img); return(2);
184 }
185
186
187 /*
188 * Cut-off
189 */
190 if(verbose>0) fprintf(stdout, "verifying pixel values...\n");
191 if(maskMode==0) {
192 /* Report the number of cut-off pixels, in verbose mode in each plane and frame */
193 int fi, zi, xi, yi;
194 long long nr, total_nr=0;
195 if(verbose>1) printf("Nr of cut-off pixels:\n");
196 for(fi=0; fi<img.dimt; fi++) {
197 for(zi=0; zi<img.dimz; zi++) {
198 nr=0;
199 for(yi=0; yi<img.dimy; yi++) {
200 for(xi=0; xi<img.dimx; xi++) {
201 if(!isfinite(img.m[zi][yi][xi][fi]) || img.m[zi][yi][xi][fi]<lowerThreshold) {
202 if(zeroMode==0) img.m[zi][yi][xi][fi]=lowerThreshold; else img.m[zi][yi][xi][fi]=0.0;
203 nr++; continue;
204 }
205 if(!isfinite(img.m[zi][yi][xi][fi]) || img.m[zi][yi][xi][fi]>upperThreshold) {
206 if(zeroMode==0) img.m[zi][yi][xi][fi]=upperThreshold; else img.m[zi][yi][xi][fi]=0.0;
207 nr++; continue;
208 }
209 }
210 }
211 if(verbose>1 && img.dimz>1 && img.dimt>1)
212 printf(" frame %d plane %d: %lld\n", fi+1, zi+1, nr);
213 total_nr+=nr;
214 }
215 }
216 if(verbose>0) printf("cutoff_pixels := %lld\n", total_nr);
217
218 /* If no pixels were cut-off, and not in force mode, then do no more */
219 if(total_nr==0) {
220 if(forceMode) {
221 fprintf(stderr, "Warning: no pixels thresholded.\n");
222 } else {
223 fprintf(stderr, "Note: no pixels thresholded, image not saved.\n");
224 imgEmpty(&img);
225 return(0);
226 }
227 }
228
229 } else { // Mask mode
230 long long nr=0;
231 for(int fi=0; fi<img.dimt; fi++) {
232 for(int zi=0; zi<img.dimz; zi++) {
233 for(int yi=0; yi<img.dimy; yi++) {
234 for(int xi=0; xi<img.dimx; xi++) {
235 if(!isfinite(img.m[zi][yi][xi][fi]) || img.m[zi][yi][xi][fi]<lowerThreshold) {
236 img.m[zi][yi][xi][fi]=0.0; continue;}
237 if(!isfinite(img.m[zi][yi][xi][fi]) || img.m[zi][yi][xi][fi]>upperThreshold) {
238 img.m[zi][yi][xi][fi]=0.0; continue;}
239 img.m[zi][yi][xi][fi]=1.0; nr++;
240 }
241 }
242 }
243 }
244 if(verbose>0) printf("retained_pixels := %lld\n", nr);
245
246 /* If no pixels were retained, and not in force mode, then do no more */
247 if(nr==0) {
248 if(forceMode) {
249 fprintf(stderr, "Warning: no pixels retained.\n");
250 } else {
251 fprintf(stderr, "Note: no pixels retained, image not saved.\n");
252 imgEmpty(&img);
253 return(0);
254 }
255 }
256
257 }
258
259
260 /*
261 * Write the image
262 */
263 if(verbose>1) fprintf(stdout, "writing %s\n", outfile);
264 if(imgWrite(outfile, &img)) {
265 fprintf(stderr, "Error: %s\n", img.statmsg);
266 if(verbose>1) printf("ret=%d\n", ret);
267 imgEmpty(&img);
268 return(11);
269 }
270 if(verbose>0) printf("Written %s\n", outfile);
271 imgEmpty(&img);
272
273 return(0);
274}
275/*****************************************************************************/
276
277/*****************************************************************************/
int atof_with_check(char *double_as_string, double *result_value)
Definition decpoint.c:107
char * iftReadValue(char *filename, char *keystr, int verbose)
Definition iftfile.c:180
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
Header file for libtpcimgio.
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
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
Header file for libtpcmodext.
unsigned short int dimx
float **** m
unsigned short int dimt
unsigned short int dimz
unsigned short int dimy
const char * statmsg