TPCCLIB
Loading...
Searching...
No Matches
imgslim.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 "libtpcmodel.h"
21/*****************************************************************************/
22
23/*****************************************************************************/
24static char *info[] = {
25 "Slice off empty parts (rows, columns, planes) in dynamic PET image file in",
26 "ECAT, NIfTI, or Analyze format.",
27 " ",
28 "Usage: @P [Options] imgfile [outputfile]",
29 " ",
30 "Options:",
31 " -limit=<value>",
32 " Slices, where average pixel value is less than the limit value,",
33 " are cut off; by default 0.1.",
34 " -keepframes | -slimframes",
35 " Selects whether time frames can be sliced off",
36 " (by default, frames are always kept).",
37 " -stdoptions", // List standard options like --help, -v, etc
38 " ",
39 "Example:",
40 " @P b123dy1.v b123dy1_slim.v",
41 " ",
42 "See also: imgdim, imgshrink, imgbkgrm, imgthrs, imgbox",
43 " ",
44 "Keywords: image, compression, cropping, threshold",
45 0};
46/*****************************************************************************/
47
48/*****************************************************************************/
49/* Turn on the globbing of the command line, since it is disabled by default in
50 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
51 In Unix&Linux wildcard command line processing is enabled by default. */
52/*
53#undef _CRT_glob
54#define _CRT_glob -1
55*/
56int _dowildcard = -1;
57/*****************************************************************************/
58
59/*****************************************************************************/
63int main(int argc, char **argv)
64{
65 int ai, help=0, version=0, verbose=1;
66 char petfile[FILENAME_MAX], outfile[FILENAME_MAX];
67 double limit_mean=nan("");
68 int keep_frames=1; // 0=off; 1=on
69
70
71 /*
72 * Get arguments
73 */
74 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
75 petfile[0]=outfile[0]=(char)0;
76 /* Get options */
77 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
78 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
79 char *cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
80 if(strncasecmp(cptr, "KEEPFRAMES", 5)==0) {
81 keep_frames=1; continue;
82 } else if(strncasecmp(cptr, "SLIMFRAMES", 5)==0) {
83 keep_frames=0; continue;
84 } else if(strncasecmp(cptr, "LIMIT=", 6)==0) {
85 if(!atof_with_check(cptr+6, &limit_mean)) continue;
86 }
87 fprintf(stderr, "Error: invalid option '%s'.\n", argv[ai]);
88 return(1);
89 } else break;
90
91 /* Print help or version? */
92 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
93 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
94 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
95
96 /* Process other arguments, starting from the first non-option */
97 if(ai<argc) {strlcpy(petfile, argv[ai], FILENAME_MAX); ai++;}
98 if(ai<argc) {strlcpy(outfile, argv[ai], FILENAME_MAX); ai++;}
99 if(ai<argc) {fprintf(stderr, "Error: too many arguments.\n"); return(1);}
100
101
102 /* Did we get all the information that we need? */
103 if(!petfile[0]) {
104 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
105 return(1);
106 }
107 if(!outfile[0]) strcpy(outfile, petfile);
108
109
110 /* In verbose mode print arguments and options */
111 if(verbose>1) {
112 printf("petfile := %s\n", petfile);
113 printf("outfile := %s\n", outfile);
114 if(!isnan(limit_mean)) printf("limit_mean := %g\n", limit_mean);
115 printf("keep_frames := %d\n", keep_frames);
116 }
117
118 if(isnan(limit_mean)) limit_mean=0.1;
119
120
121 /*
122 * Read the contents of the PET file to img data structure
123 */
124 IMG img; imgInit(&img);
125 if(verbose>0) printf("reading %s\n", petfile);
126 int ret=imgRead(petfile, &img);
127 if(ret) {
128 fprintf(stderr, "Error: %s\n", img.statmsg);
129 if(verbose>1) printf("ret=%d\n", ret);
130 imgEmpty(&img); return(2);
131 }
132 /* Check that PET data is image */
133 if(img.type!=IMG_TYPE_IMAGE) {
134 fprintf(stderr, "Error: %s is not an image.\n", petfile);
135 imgEmpty(&img); return(2);
136 }
137 /* Check that we have dynamic data */
138 if(img.dimt<2) {
139 fprintf(stderr, "Error: method works only for dynamic data.\n");
140 imgEmpty(&img); return(2);
141 }
142 if(imgNaNs(&img, 1)>0)
143 if(verbose>0) fprintf(stderr, "Warning: missing pixel values.\n");
144 /*
145 * Print original image dimensions
146 */
147 if(verbose>0) {
148 fprintf(stdout, "image_dimensions := %d %d %d\n", img.dimx, img.dimy, img.dimz);
149 fprintf(stdout, "frame_nr := %d\n", img.dimt);
150 }
151
152
153 /*
154 * Set tables for slimming
155 */
156 typedef struct {
157 double sum;
158 double weight;
159 char keep;
160 } SLIM_LIST;
161
162 SLIM_LIST xlist[img.dimx];
163 SLIM_LIST ylist[img.dimy];
164 SLIM_LIST zlist[img.dimz];
165 SLIM_LIST tlist[img.dimt];
166
167 for(int xi=0; xi<img.dimx; xi++) {
168 xlist[xi].sum=0.0;
169 xlist[xi].weight=0.0;
170 xlist[xi].keep=1;
171 }
172 for(int yi=0; yi<img.dimy; yi++) {
173 ylist[yi].sum=0.0;
174 ylist[yi].weight=0.0;
175 ylist[yi].keep=1;
176 }
177 for(int zi=0; zi<img.dimz; zi++) {
178 zlist[zi].sum=0.0;
179 zlist[zi].weight=0.0;
180 zlist[zi].keep=1;
181 }
182 for(int ti=0; ti<img.dimt; ti++) {
183 tlist[ti].sum=0.0;
184 tlist[ti].weight=0.0;
185 tlist[ti].keep=1;
186 }
187
188 /* Fill the slim tables */
189 for(int zi=0; zi<img.dimz; zi++) {
190 for(int yi=0; yi<img.dimy; yi++) {
191 for(int xi=0; xi<img.dimx; xi++) {
192 for(int fi=0; fi<img.dimt; fi++) {
193 xlist[xi].sum+=img.m[zi][yi][xi][fi]; xlist[xi].weight+=1.0;
194 ylist[yi].sum+=img.m[zi][yi][xi][fi]; ylist[yi].weight+=1.0;
195 zlist[zi].sum+=img.m[zi][yi][xi][fi]; zlist[zi].weight+=1.0;
196 tlist[fi].sum+=img.m[zi][yi][xi][fi]; tlist[fi].weight+=1.0;
197 }
198 }
199 }
200 }
201
202 /*
203 * Determine which slices are to be kept and which are not
204 */
205 /* check values against the limits */
206 for(int xi=0; xi<img.dimx; xi++) {
207 xlist[xi].keep=(xlist[xi].sum/xlist[xi].weight<limit_mean) ? 0 : 1 ;
208 }
209 for(int yi=0; yi<img.dimy; yi++) {
210 ylist[yi].keep=(ylist[yi].sum/ylist[yi].weight<limit_mean) ? 0 : 1 ;
211 }
212 for(int zi=0; zi<img.dimz; zi++) {
213 zlist[zi].keep=(zlist[zi].sum/zlist[zi].weight<limit_mean) ? 0 : 1 ;
214 }
215 for(int ti=0; ti<img.dimt; ti++) {
216 tlist[ti].keep=(tlist[ti].sum/tlist[ti].weight<limit_mean) ? 0 : 1 ;
217 }
218 if(verbose>3) { /* Show the initial slim lists */
219 printf("\nxlist:\n");
220 for(int xi=0; xi<img.dimx; xi++) {
221 printf(" %04d %20.5f %20.5f %d\n",
222 xi+1, xlist[xi].sum, xlist[xi].weight, xlist[xi].keep);
223 }
224 printf("ylist:\n");
225 for(int yi=0; yi<img.dimy; yi++) {
226 printf(" %04d %20.5f %20.5f %d\n",
227 yi+1, ylist[yi].sum, ylist[yi].weight, ylist[yi].keep);
228 }
229 printf("zlist:\n");
230 for(int zi=0; zi<img.dimz; zi++) {
231 printf(" %04d %20.5f %20.5f %d\n",
232 zi+1, zlist[zi].sum, zlist[zi].weight, zlist[zi].keep);
233 }
234 printf("tlist:\n");
235 for(int ti=0; ti<img.dimt; ti++) {
236 printf(" %04d %20.5f %20.5f %d\n",
237 ti+1, tlist[ti].sum, tlist[ti].weight, tlist[ti].keep);
238 }
239 }
240
241 /* keep all slices that are between slices that are kept */
242 int newdimx, newdimy, newdimz, newdimt;
243
244 {
245 int i, first, last;
246 i=0; while(i<img.dimx && xlist[i].keep==0) i++;
247 first=i;
248 i=img.dimx-1; while(i>=0 && xlist[i].keep==0) i--;
249 last=i;
250 if(first>last) {first=0; last=img.dimx-1;}
251 for(i=first; i<=last; i++) xlist[i].keep=1;
252 newdimx=1+last-first;
253 if(verbose>1) printf("x_first := %d\nx_last := %d", first, last);
254 }
255
256 {
257 int i, first, last;
258 i=0; while(i<img.dimy && ylist[i].keep==0) i++;
259 first=i;
260 i=img.dimy-1; while(i>=0 && ylist[i].keep==0) i--;
261 last=i;
262 if(first>last) {first=0; last=img.dimy-1;}
263 for(i=first; i<=last; i++) ylist[i].keep=1;
264 newdimy=1+last-first;
265 if(verbose>1) printf("y_first := %d\ny_last := %d", first, last);
266 }
267
268 {
269 int i, first, last;
270 i=0; while(i<img.dimz && zlist[i].keep==0) i++;
271 first=i;
272 i=img.dimz-1; while(i>=0 && zlist[i].keep==0) i--;
273 last=i;
274 if(first>last) {first=0; last=img.dimz-1;}
275 for(i=first; i<=last; i++) zlist[i].keep=1;
276 newdimz=1+last-first;
277 if(verbose>1) printf("z_first := %d\nz_last := %d", first, last);
278 }
279
280 {
281 int i, first, last;
282 i=0; while(i<img.dimt && tlist[i].keep==0) i++;
283 first=i;
284 i=img.dimt-1; while(i>=0 && tlist[i].keep==0) i--;
285 last=i;
286 if(first>last) {first=0; last=img.dimt-1;}
287 for(i=first; i<=last; i++) tlist[i].keep=1;
288 newdimt=1+last-first;
289 if(verbose>1) printf("t_first := %d\nt_last := %d", first, last);
290 }
291
292 /* If user wants to keep all time frames, then put them back */
293 if(keep_frames && newdimt<img.dimt) {
294 if(verbose>1) printf("keeping all time frames\n");
295 for(int ti=0; ti<img.dimt; ti++) tlist[ti].keep=1;
296 newdimt=img.dimt;
297 }
298
299 if(verbose>2) { /* Show the final slim lists */
300 printf("\nxlist:\n");
301 for(int xi=0; xi<img.dimx; xi++) {
302 printf(" %04d %20.5f %20.5f %d\n",
303 xi+1, xlist[xi].sum, xlist[xi].weight, xlist[xi].keep);
304 }
305 printf("ylist:\n");
306 for(int yi=0; yi<img.dimy; yi++) {
307 printf(" %04d %20.5f %20.5f %d\n",
308 yi+1, ylist[yi].sum, ylist[yi].weight, ylist[yi].keep);
309 }
310 printf("zlist:\n");
311 for(int zi=0; zi<img.dimz; zi++) {
312 printf(" %04d %20.5f %20.5f %d\n",
313 zi+1, zlist[zi].sum, zlist[zi].weight, zlist[zi].keep);
314 }
315 printf("tlist:\n");
316 for(int ti=0; ti<img.dimt; ti++) {
317 printf(" %04d %20.5f %20.5f %d\n",
318 ti+1, tlist[ti].sum, tlist[ti].weight, tlist[ti].keep);
319 }
320 }
321 if(verbose>0) {
322 printf(" new_dimx := %d\n", newdimx);
323 printf(" new_dimy := %d\n", newdimy);
324 printf(" new_dimz := %d\n", newdimz);
325 printf(" new_dimt := %d\n", newdimt);
326 }
327 /* Check if anything needs to be done */
328 if(newdimx==img.dimx && newdimy==img.dimy && newdimz==img.dimz && newdimt==img.dimt) {
329 fprintf(stderr, "Error: cannot slim-off anything from %s\n", petfile);
330 imgEmpty(&img); return(4);
331 }
332 /* Check that something is left */
333 if(newdimx==0 || newdimy==0 || newdimz==0 || newdimt==0) {
334 fprintf(stderr, "Error: this would result in empty image.\n");
335 imgEmpty(&img); return(5);
336 }
337
338
339 /*
340 * Create IMG for output data
341 */
342 IMG out; imgInit(&out);
343 if(imgAllocateWithHeader(&out, newdimz, newdimy, newdimx, newdimt, &img)!=0) {
344 fprintf(stderr, "Error: cannot make output image.\n");
345 imgEmpty(&img); imgEmpty(&out); return(8);
346 }
347 /* Copy pixel data */
348 for(int ti=0, nti=0; ti<img.dimt; ti++) if(tlist[ti].keep==1) {
349 for(int zi=0, nzi=0; zi<img.dimz; zi++) if(zlist[zi].keep==1) {
350 for(int yi=0, nyi=0; yi<img.dimy; yi++) if(ylist[yi].keep==1) {
351 for(int xi=0, nxi=0; xi<img.dimx; xi++) if(xlist[xi].keep==1) {
352 out.m[nzi][nyi][nxi][nti]=img.m[zi][yi][xi][ti];
353 nxi++;
354 }
355 nyi++;
356 }
357 nzi++;
358 }
359 out.start[nti]=img.start[ti]; out.end[nti]=img.end[ti];
360 nti++;
361 }
362
363 /* No need for original image */
364 imgEmpty(&img);
365
366
367 /*
368 * Save the slim image
369 */
370 if(verbose>1) fprintf(stdout, "writing image...\n");
371 ret=imgWrite(outfile, &out);
372 if(ret) {
373 fprintf(stderr, "Error: %s\n", out.statmsg);
374 imgEmpty(&out); return(11);
375 }
376 if(verbose==1) printf("Written image %s\n", outfile);
377
378 imgEmpty(&out);
379 if(verbose>0) printf("done.\n");
380 return(0);
381}
382/*****************************************************************************/
383
384/*****************************************************************************/
int atof_with_check(char *double_as_string, double *result_value)
Definition decpoint.c:107
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
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
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 libtpcmodel.
unsigned short int dimx
char type
float **** m
unsigned short int dimt
float * start
unsigned short int dimz
unsigned short int dimy
float * end
const char * statmsg