TPCCLIB
Loading...
Searching...
No Matches
imgbox.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/*****************************************************************************/
21
22/*****************************************************************************/
23static char *info[] = {
24 "Extract a box-like volume of 3D/4D PET image in ECAT format.",
25 "NIfTI-1 format is supported, except that SIF is not written.",
26 "Image is processed frame-by-frame, thus even large files can be processed.",
27 "Note that no backup is made of any previous output file.",
28 " ",
29 "Usage: @P [Options] imgfile [vrdfile outputfile]",
30 " ",
31 "Options:",
32 " -zero",
33 " Image is not cropped, but voxels outside of the given volume are",
34 " set to zero.",
35 " -stdoptions", // List standard options like --help, -v, etc
36 " ",
37 "Volume range definition (vrd) file is an ASCII text file, which containts",
38 "pixel coordinates (x y z; 1..dimension) of the two opposite corners of",
39 "the cropped image volume, for example:",
40 " corner1 := 63 57 26",
41 " corner2 := 84 71 44",
42 "If only input image filename is given, then program prints the image",
43 "dimensions.",
44 " ",
45 "See also: imgdim, imgslim, esplit, e7vplavg, imgshrink, pxl2tac, imgdelfr",
46 " ",
47 "Keywords: image, cropping, mask, compression, tool",
48 0};
49/*****************************************************************************/
50
51/*****************************************************************************/
52/* Turn on the globbing of the command line, since it is disabled by default in
53 mingw-w64 (_dowildcard=0); in MinGW32 define _CRT_glob instead, if necessary;
54 In Unix&Linux wildcard command line processing is enabled by default. */
55/*
56#undef _CRT_glob
57#define _CRT_glob -1
58*/
59int _dowildcard = -1;
60/*****************************************************************************/
61
62/*****************************************************************************/
66int main(int argc, char **argv)
67{
68 int ai, help=0, version=0, verbose=1;
69 int doCrop=1; // 0=zeroes; 1=crop
70 int ret, fi=0, xi, yi, zi, ti;
71 int newdimx, newdimy, newdimz;
72 char imgfile[FILENAME_MAX], outfile[FILENAME_MAX], vrdfile[FILENAME_MAX],
73 *cptr, temp[FILENAME_MAX];
74 IMG test_img, img, outimg;
75 VOL_RANGE vol_range={0,0,0,0,0,0};
76
77
78 /*
79 * Get arguments
80 */
81 if(argc==1) {tpcPrintUsage(argv[0], info, stderr); return(1);}
82 imgfile[0]=outfile[0]=vrdfile[0]=(char)0;
83 /* Options */
84 for(ai=1; ai<argc; ai++) if(*argv[ai]=='-') {
85 cptr=argv[ai]+1; if(*cptr=='-') cptr++; if(cptr==NULL) continue;
86 if(tpcProcessStdOptions(argv[ai], &help, &version, &verbose)==0) continue;
87 if(strcasecmp(cptr, "CROP")==0) {
88 doCrop=1; continue;
89 } else if(strcasecmp(cptr, "ZERO")==0) {
90 doCrop=0; continue;
91 }
92 fprintf(stderr, "Error: unknown option '%s'.\n", argv[ai]);
93 return(1);
94 } else break;
95
96 /* Print help or version? */
97 if(help==2) {tpcHtmlUsage(argv[0], info, ""); return(0);}
98 if(help) {tpcPrintUsage(argv[0], info, stdout); return(0);}
99 if(version) {tpcPrintBuild(argv[0], stdout); return(0);}
100
101 /* Process other arguments, starting from the first non-option */
102 if(ai<argc) {strlcpy(imgfile, argv[ai], FILENAME_MAX); ai++;}
103 if(ai<argc) {strlcpy(vrdfile, argv[ai], FILENAME_MAX); ai++;}
104 if(ai<argc) {strlcpy(outfile, argv[ai], FILENAME_MAX); ai++;}
105 if(ai<argc) {fprintf(stderr, "Error: too many arguments.\n"); return(1);}
106
107 /* Is something missing? */
108 if(!imgfile[0] || (vrdfile[0] && !outfile[0])) {
109 fprintf(stderr, "Error: missing command-line argument; use option --help\n");
110 return(1);
111 }
112
113
114 /* In verbose mode print arguments and options */
115 if(verbose>1) {
116 printf("imgfile := %s\n", imgfile);
117 if(outfile[0]) printf("outfile := %s\n", outfile);
118 if(vrdfile[0]) printf("vrdfile := %s\n", vrdfile);
119 printf("doCrop := %d\n", doCrop);
120 }
121 if(verbose>3) IMG_TEST=verbose-3; else IMG_TEST=0;
122
123
124 /*
125 * Read 'header' information from image
126 */
127 if(verbose>1) printf("reading header from %s\n", imgfile);
128 imgInit(&test_img);
129 ret=imgReadHeader(imgfile, &test_img, IMG_UNKNOWN);
130 if(ret!=0) {
131 fprintf(stderr, "Error: %s\n", test_img.statmsg);
132 return(2);
133 }
134 if(verbose>20) imgInfo(&test_img);
135
136 /*
137 * Print original image dimensions
138 */
139 if(verbose>0 || !vrdfile[0]) {
140 fprintf(stdout, "image_dimensions := %d %d %d\n",
141 test_img.dimx, test_img.dimy, test_img.dimz);
142 fprintf(stdout, "frame_nr := %d\n", test_img.dimt);
143 }
144
145 /*
146 * Quit if no VRD file
147 */
148 if(!vrdfile[0]) {imgEmpty(&test_img); return(0);}
149
150
151 /*
152 * Read Volume Range Definition File
153 */
154 ret=vrdRead(vrdfile, &vol_range, temp);
155 if(ret!=0) {
156 fprintf(stderr, "Error in reading %s: %s\n", vrdfile, temp);
157 imgEmpty(&test_img); return(3);
158 }
159 if(verbose>1) {
160 printf("volume_range.x := %d - %d\n", vol_range.x1, vol_range.x2);
161 printf("vol_range.y := %d - %d\n", vol_range.y1, vol_range.y2);
162 printf("vol_range.z := %d - %d\n", vol_range.z1, vol_range.z2);
163 }
164 /* Check that box is inside image volume */
165 if(vol_range.x1<1 || vol_range.x2>test_img.dimx) {
166 fprintf(stderr, "Error: invalid x range.\n");
167 imgEmpty(&test_img); return(4);
168 }
169 if(vol_range.y1<1 || vol_range.y2>test_img.dimy) {
170 fprintf(stderr, "Error: invalid y range.\n");
171 imgEmpty(&test_img); return(5);
172 }
173 if(vol_range.z1<1 || vol_range.z2>test_img.dimz) {
174 fprintf(stderr, "Error: invalid z range.\n");
175 imgEmpty(&test_img); return(6);
176 }
177
178 /* Calculate cropped image dimensions */
179 newdimx=1+vol_range.x2-vol_range.x1;
180 newdimy=1+vol_range.y2-vol_range.y1;
181 newdimz=1+vol_range.z2-vol_range.z1;
182 if(verbose>0 && doCrop!=0) {
183 printf(" new_dimx := %d\n", newdimx);
184 printf(" new_dimy := %d\n", newdimy);
185 printf(" new_dimz := %d\n", newdimz);
186 }
187 /* Check if anything needs to be done */
188 if(newdimx==test_img.dimx && newdimy==test_img.dimy && newdimz==test_img.dimz)
189 {
190 fprintf(stderr, "Error: whole image is included\n");
191 imgEmpty(&test_img); return(7);
192 }
193
194 /* Remove existing image file */
195 if(access(outfile, 0)!=-1 && remove(outfile)!=0) {
196 fprintf(stderr, "Error: cannot overwrite %s\n", outfile);
197 imgEmpty(&test_img); return(11);
198 }
199
200 /*
201 * Do the image cropping
202 */
203 if(doCrop!=0) {
204
205 /*
206 * Read (again) image frame-by-frame, and write the selected slices
207 */
208 if(verbose>0)
209 printf("cropping selected volume from %s to %s\n", imgfile, outfile);
210 fi=0; imgInit(&outimg); imgInit(&img);
211 for(ti=0; ti<test_img.dimt; ti++) {
212 if(verbose>2) printf(" frame %d\n", ti+1);
213 /* Read frame */
214 ret=imgReadFrame(imgfile, ti+1, &img, 0);
215 if(ret!=0) {
216 fprintf(stderr, "Error: %s\n", imgStatus(ret));
217 imgEmpty(&test_img); imgEmpty(&img);
218 return(9);
219 }
220 /* If this is the first frame, then create output IMG */
221 if(fi==0) {
222 if(verbose>4) printf(" creating output IMG\n");
223 ret=imgAllocateWithHeader(&outimg, newdimz, newdimy, newdimx, 1, &img);
224 } else { /* otherwise just copy the header */
225 if(verbose>4) printf(" copying header\n");
226 ret=imgCopyhdr(&img, &outimg);
227 }
228 if(ret!=0) {
229 fprintf(stderr, "Error: %s\n", imgStatus(ret));
230 imgEmpty(&test_img); imgEmpty(&img); imgEmpty(&outimg);
231 return(10);
232 }
233 /* Copy pixel data */
234 if(verbose>3) printf(" copying pixel data\n");
235 int nxi, nyi, nzi;
236 for(zi=vol_range.z1-1, nzi=0; zi<=vol_range.z2-1; zi++, nzi++) {
237 for(yi=vol_range.y1-1, nyi=0; yi<=vol_range.y2-1; yi++, nyi++) {
238 for(xi=vol_range.x1-1, nxi=0; xi<=vol_range.x2-1; xi++, nxi++) {
239 if(verbose>10) printf(" img1[%d][%d][%d]=%g -> img2[%d][%d][%d]\n",
240 zi, yi, xi, img.m[zi][yi][xi][0], nxi, nyi, nxi);
241 outimg.m[nzi][nyi][nxi][0]=img.m[zi][yi][xi][0];
242 }
243 }
244 }
245 /* Write the image frame */
246 if(verbose>3) printf(" writing frame %d\n", fi+1);
247 /* Notice that this function does not support Analyze format;
248 therefore write format is changed to NIfTI. */
249 if(outimg._fileFormat==IMG_ANA || outimg._fileFormat==IMG_ANA_L) {
250 if(verbose>10)
251 printf("outimg._fileFormat %d -> %d\n", outimg._fileFormat, IMG_NIFTI_1S);
253 }
254 ret=imgWriteFrame(outfile, fi+1, &outimg, 0); //printf("ret := %d\n", ret);
255 if(ret!=STATUS_OK) {
256 fprintf(stderr, "Error: %s\n", imgStatus(ret));
257 if(verbose>18) imgInfo(&outimg);
258 imgEmpty(&test_img); imgEmpty(&img); imgEmpty(&outimg);
259 return(13);
260 }
261 if(verbose>2) printf(" frame written.\n");
262 /* Prepare for the next frame */
263 fi++;
264 } // next frame
265 imgEmpty(&test_img); imgEmpty(&img); imgEmpty(&outimg);
266 if(verbose>0) printf("Specified image volume written in %s\n", outfile);
267 return(0);
268
269 } // cropping
270
271
272 /*
273 * Set voxels to zero outside the given volume
274 */
275 if(verbose>0)
276 printf("masking voxels outside selected volume from %s to %s\n", imgfile, outfile);
277 fi=0; imgInit(&img);
278 for(ti=0; ti<test_img.dimt; ti++) {
279 if(verbose>2) printf(" frame %d\n", ti+1);
280 /* Read frame */
281 ret=imgReadFrame(imgfile, ti+1, &img, 0);
282 if(ret!=0) {
283 fprintf(stderr, "Error: %s\n", imgStatus(ret));
284 imgEmpty(&test_img); imgEmpty(&img);
285 return(9);
286 }
287 /* Edit pixel data */
288 if(verbose>3) printf(" editing pixel data\n");
289 for(zi=0; zi<img.dimz; zi++)
290 for(yi=0; yi<img.dimy; yi++)
291 for(xi=0; xi<img.dimx; xi++) {
292 if(zi<vol_range.z1-1 || zi>vol_range.z2-1) {
293 img.m[zi][yi][xi][0]=0.0; continue;}
294 if(yi<vol_range.y1-1 || yi>vol_range.y2-1) {
295 img.m[zi][yi][xi][0]=0.0; continue;}
296 if(xi<vol_range.x1-1 || xi>vol_range.x2-1) {
297 img.m[zi][yi][xi][0]=0.0; continue;}
298 }
299 /* Write the image frame */
300 if(verbose>3) printf(" writing frame %d\n", fi+1);
301 ret=imgWriteFrame(outfile, fi+1, &img, 0); //printf("ret := %d\n", ret);
302 if(ret!=STATUS_OK) {
303 fprintf(stderr, "Error: %s\n", imgStatus(ret));
304 imgEmpty(&test_img); imgEmpty(&img);
305 return(13);
306 }
307 if(verbose>2) printf(" frame written.\n");
308 /* Prepare for the next frame */
309 fi++;
310 } // next frame
311 imgEmpty(&test_img); imgEmpty(&img);
312 if(verbose>0) printf("Masked image written in %s\n", outfile);
313
314 return(0);
315}
316/*****************************************************************************/
317
318/*****************************************************************************/
int IMG_TEST
Definition img.c:6
void imgInfo(IMG *image)
Definition img.c:359
char * imgStatus(int status_index)
Definition img.c:330
int imgCopyhdr(IMG *image1, IMG *image2)
Definition img.c:471
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 imgWriteFrame(const char *fname, int frame_to_write, IMG *img, int frame_index)
Definition imgfile.c:392
int imgReadFrame(const char *fname, int frame_to_read, IMG *img, int frame_index)
Definition imgfile.c:269
int imgReadHeader(const char *fname, IMG *img, int format)
Definition imgfile.c:199
Header file for libtpcimgio.
#define IMG_NIFTI_1S
#define IMG_ANA_L
#define IMG_UNKNOWN
#define IMG_ANA
int vrdRead(char *vdffile, VOL_RANGE *vol_range, char *status)
Definition vol.c:742
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
unsigned short int dimx
float **** m
int _fileFormat
unsigned short int dimt
unsigned short int dimz
unsigned short int dimy
const char * statmsg