1 /*****************************************************************************
2 Major portions of this software are copyrighted by the Medical College
3 of Wisconsin, 1994-2000, and are released under the Gnu General Public
4 License, Version 2. See the file README.Copyright for details.
5 ******************************************************************************/
6
7 #include "mrilib.h"
8
9 #define XYNUM 0
10 #define YXNUM 1
11 #define XDOTYNUM 2
12 #define YDOTXNUM 3
prog_usage(int detail)13 void prog_usage(int detail)
14 {
15 printf(
16 "Usage: 2dcat [options] fname1 fname2 etc.\n"
17 "Puts a set images into an image matrix (IM) \n"
18 " montage of NX by NY images.\n"
19 " The minimum set of input is N images (N >= 1).\n"
20 " If need be, the default is to reuse images until the desired\n"
21 " NX by NY size is achieved. \n"
22 " See options -zero_wrap and -image_wrap for more detail.\n"
23 " \n"
24 "OPTIONS:\n"
25 " ++ Options for editing, coloring input images:\n"
26 " -scale_image SCALE_IMG: Multiply each image IM(i,j) in output\n"
27 " image matrix IM by the color or intensity\n"
28 " of the pixel (i,j) in SCALE_IMG.\n"
29 " -scale_pixels SCALE_PIX: Multiply each pixel (i,j) in output image\n"
30 " by the color or intensity\n"
31 " of the pixel (i,j) in SCALE_IMG.\n"
32 " SCALE_IMG is automatically resized to the\n"
33 " resolution of the output image.\n"
34 " -scale_intensity: Instead of multiplying by the color of \n"
35 " pixel (i,j), use its intensity \n"
36 " (average color)\n"
37 " -gscale FAC: Apply FAC in addition to scaling of -scale_* options\n"
38 " -rgb_out: Force output to be in rgb, even if input is bytes.\n"
39 " This option is turned on automatically in certain cases.\n"
40 " -res_in RX RY: Set resolution of all input images to RX by RY pixels.\n"
41 " Default is to make all input have the same\n"
42 " resolution as the first image.\n"
43 " -respad_in RPX RPY: Like -res_in, but resample to the max while respecting\n"
44 " the aspect ratio, and then pad to achieve desired \n"
45 " pixel count.\n"
46 " -pad_val VAL: Set the padding value, should it be needed by -respad_in\n"
47 " to VAL. VAL is typecast to byte, default is 0, max is 255.\n"
48 " -crop L R T B: Crop images by L (Left), R (Right), T (Top), B (Bottom)\n"
49 " pixels. Cutting is performed after any resolution change, \n"
50 " if any, is to be done.\n"
51 " -autocrop_ctol CTOL: A line is eliminated if none of its R G B values \n"
52 " differ by more than CTOL%% from those of the corner\n"
53 " pixel.\n"
54 " -autocrop_atol ATOL: A line is eliminated if none of its R G B values \n"
55 " differ by more than ATOL%% from those of line\n"
56 " average.\n"
57 " -autocrop: This option is the same as using both of -autocrop_atol 20 \n"
58 " and -autocrop_ctol 20\n"
59 " NOTE: Do not mix -autocrop* options with -crop\n"
60 " Cropping is determined from the 1st input image and applied to \n"
61 " to all remaining ones.\n"
62 " ++ Options for output:\n"
63 " -zero_wrap: If number of images is not enough to fill matrix\n"
64 " solid black images are used.\n"
65 " -white_wrap: If number of images is not enough to fill matrix\n"
66 " solid white images are used.\n"
67 " -gray_wrap GRAY: If number of images is not enough to fill matrix\n"
68 " solid gray images are used. GRAY must be between 0 and 1.0\n"
69 " -image_wrap: If number of images is not enough to fill matrix\n"
70 " images on command line are reused (default)\n"
71 " -rand_wrap: When reusing images to fill matrix, randomize the order\n"
72 " in refill section only.\n"
73 " -prefix ppp = Prefix the output files with string 'ppp'\n"
74 " Note: If the prefix ends with .1D, then a 1D file containing\n"
75 " the average of RGB values. You can view the output with\n"
76 " 1dgrayplot.\n"
77 " -matrix NX NY: Specify number of images in each row and column \n"
78 " of IM at the same time. \n"
79 " -nx NX: Number of images in each row (3 for example below)\n"
80 " -ny NY: Number of images in each column (4 for example below)\n"
81 " Example: If 12 images appearing on the command line\n"
82 " are to be assembled into a 3x4 IM matrix they\n"
83 " would appear in this order:\n"
84 " 0 1 2\n"
85 " 3 4 5\n"
86 " 6 7 8\n"
87 " 9 10 11\n"
88 " NOTE: The program will try to guess if neither NX nor NY \n"
89 " are specified.\n"
90 " -matrix_from_scale: Set NX and NY to be the same as the \n"
91 " SCALE_IMG's dimensions. (needs -scale_image)\n"
92 " -gap G: Put a line G pixels wide between images.\n"
93 " -gap_col R G B: Set color of line to R G B values.\n"
94 " Values range between 0 and 255.\n"
95 "\n"
96 "Example 0 (assuming afni is in ~/abin directory):\n"
97 " Resizing an image:\n"
98 " 2dcat -prefix big -res_in 1024 1024 \\\n"
99 " ~/abin/funstuff/face_zzzsunbrain.jpg \n"
100 " 2dcat -prefix small -res_in 64 64 \\\n"
101 " ~/abin/funstuff/face_zzzsunbrain.jpg \n"
102 " aiv small.ppm big.ppm \n"
103 "\n"
104 "Example 1:\n"
105 " Stitching together images:\n"
106 " (Can be used to make very high resolution SUMA images.\n"
107 " Read about 'Ctrl+r' in SUMA's GUI help.)\n"
108 " 2dcat -prefix cat -matrix 14 12 \\\n"
109 " ~/abin/funstuff/face_*.jpg\n"
110 " aiv cat.ppm\n"
111 "\n"
112 "Example 2:\n"
113 " Stitching together 3 images getting rid of annoying white boundary:\n"
114 "\n"
115 " 2dcat -prefix surfview_pry3b.jpg -ny 1 -autocrop surfview.000[789].jpg\n"
116 "\n"
117 "Example 20 (assuming afni is in ~/abin directory):\n"
118 " 2dcat -prefix bigcat.jpg -scale_image ~/abin/afnigui_logo.jpg \\\n"
119 " -matrix_from_scale -rand_wrap -rgb_out -respad_in 128 128 \\\n"
120 " -pad_val 128 ~/abin/funstuff/face_*.jpg \n"
121 " aiv bigcat.jpg bigcat.jpg \n"
122 " Crop/Zoom in to see what was done. In practice, you want to use\n"
123 " a faster image viewer to examine the result. Zooming on such\n"
124 " a large image is not fast in aiv.\n"
125 " Be careful with this toy. Images get real big, real quick.\n"
126 "\n"
127 "You can look at the output image file with\n"
128 " afni -im ppp.ppm [then open the Sagittal image window]\n"
129 "\n"
130 "Deprecation warning: The imcat program will be replaced by 2dcat in the future."
131 "\n"
132 ) ;
133 return;
134 }
135
136 #define ABS(a) ( (a) < 0 ? (-(a)):(a) )
main(int argc,char * argv[])137 int main( int argc , char * argv[] )
138 {
139 MRI_IMARR * imar, *inimar;
140 MRI_IMAGE * im ;
141 char prefix[240] = "cat" , fnam[256] ;
142 char suffix[50] = "\0";
143 char *scale_image = NULL, *scale_pixels = NULL;
144 int iarg , ii,jj , nx,ny , nxim,nyim ;
145 int nmode = XYNUM, nxin, nyin, nbad = 0;
146 int cutL=0, cutR=0, cutT=0, cutB=0, cutlev=0, cutlevu=0;
147 int gap = 0, ScaleInt=0, force_rgb_out = 0, matrix_size_from_scale = 0;
148 byte gap_col[3] = {255, 20, 128}, pval = 0 ;
149 MRI_IMAGE *imscl=NULL;
150 int kkk, nscl=-1, resix=-1, resiy=-1, force_rgb_at_input=0,
151 N_byte = 0, N_rgb = 0, ks = 1, wrapmode = 1;
152 float *scl=NULL, fac=1.0, ff=0;
153 byte *scl3=NULL, *rgb=NULL, *b1, *b2, *b3;
154 char name[100];
155 void *ggg=NULL;
156
157
158 mainENTRY("2dcat main"); machdep() ;
159
160 wrapmode = 1;
161 ScaleInt = 0;
162 resix=-1;
163 resiy=-1;
164 ks = 1;
165 cutL=0;
166 cutB=0;
167 cutT=0;
168 cutR=0;
169 cutlev =-2;
170 cutlevu=-2;
171 fac = 1.0;
172 force_rgb_out = 0;
173 iarg = 1 ;
174 pval = 0 ;
175 nx = -1; ny = -1;
176 while( iarg < argc && argv[iarg][0] == '-' ){
177 if( strcmp(argv[iarg],"-help") == 0 ||
178 strcmp(argv[iarg],"-h") == 0 ) {
179 prog_usage(strlen(argv[iarg])>2 ? 2:1);
180 exit(0); /* do not continue 18 Sep 2018 [rickr] */
181 }
182
183 if( strcmp(argv[iarg],"-rand_wrap") == 0 ) {
184 wrapmode = 2;
185 iarg++ ; continue ;
186 }
187
188 if( strcmp(argv[iarg],"-matrix") == 0 ){
189 if (iarg+2 >= argc) {
190 fprintf(stderr,"*** ERROR: Need two integers after -matrix\n");
191 exit(1);
192 }
193 nx = (int) strtod( argv[++iarg] , NULL ) ;
194 ny = (int) strtod( argv[++iarg] , NULL ) ;
195 iarg++ ; continue ;
196 }
197
198 if( strcmp(argv[iarg],"-crop") == 0 ){
199 if (iarg+4 >= argc) {
200 fprintf(stderr,
201 "*** ERROR: Need four positive integers after -crop\n");
202 exit(1);
203 }
204 cutL = (int) strtod( argv[++iarg] , NULL ) ;
205 cutR = (int) strtod( argv[++iarg] , NULL ) ;
206 cutT = (int) strtod( argv[++iarg] , NULL ) ;
207 cutB = (int) strtod( argv[++iarg] , NULL ) ;
208 iarg++ ; continue ;
209 }
210
211 if( strcmp(argv[iarg],"-autocrop") == 0 ){
212 cutlev = -1; cutlevu = -1;
213 iarg++ ; continue ;
214 }
215
216 if ( strcmp(argv[iarg],"-autocrop_ctol") == 0 ){
217 if (iarg+2 >= argc) {
218 fprintf(stderr,
219 "*** ERROR: Need one integer between 0 and 100 after"
220 " -autocrop_ctol\n");
221 exit(1);
222 }
223 cutlev = ((int)strtod( argv[++iarg] , NULL ) );
224 if (cutlev < 0 || cutlev > 100) {
225 fprintf(stderr,
226 "*** ERROR: Need one integer between 0 and 100 after -autocrop_ctol\n"
227 "Got %d\n", cutlevu);
228 exit(1);
229 }
230
231 iarg++ ; continue ;
232 }
233
234 if ( strcmp(argv[iarg],"-autocrop_atol") == 0 ){
235 if (iarg+2 >= argc) {
236 fprintf(stderr,
237 "*** ERROR: Need one integer between 0 and 100 after"
238 " -autocrop_atol\n");
239 exit(1);
240 }
241 cutlevu = ((int)strtod( argv[++iarg] , NULL ) );
242 if (cutlevu < 0 || cutlevu > 100) {
243 fprintf(stderr,
244 "*** ERROR: Need one integer between 0 and 100 after -autocrop_atol\n"
245 "Got %d\n", cutlevu);
246 exit(1);
247 }
248
249 iarg++ ; continue ;
250 }
251
252
253 if( strcmp(argv[iarg],"-res_in") == 0 ){
254 if (iarg+2 >= argc) {
255 fprintf(stderr,"*** ERROR: Need two integers after -res_in\n");
256 exit(1);
257 }
258 resix = (int) strtod( argv[++iarg] , NULL ) ;
259 resiy = (int) strtod( argv[++iarg] , NULL ) ;
260 iarg++ ; continue ;
261 }
262
263 if( strcmp(argv[iarg],"-gscale") == 0 ){
264 if (iarg+1 >= argc) {
265 fprintf(stderr,"*** ERROR: Need one float after -gscale\n");
266 exit(1);
267 }
268 fac = (float) strtod( argv[++iarg] , NULL ) ;
269 iarg++ ; continue ;
270 }
271
272
273 if( strcmp(argv[iarg],"-respad_in") == 0 ){
274 if (iarg+2 >= argc) {
275 fprintf(stderr,"*** ERROR: Need two integers after -respad_in\n");
276 exit(1);
277 }
278 resix = (int) strtod( argv[++iarg] , NULL ) ;
279 resiy = (int) strtod( argv[++iarg] , NULL ) ;
280 ks = -1;
281 iarg++ ; continue ;
282 }
283
284 if( strcmp(argv[iarg],"-pad_val") == 0 ){
285 if (iarg+1 >= argc) {
286 fprintf(stderr,"*** ERROR: Need one byte after -pad_val\n");
287 exit(1);
288 }
289 pval = (byte) strtod( argv[++iarg] , NULL ) ;
290 iarg++ ; continue ;
291 }
292
293 if( strcmp(argv[iarg],"-nx") == 0 ){
294 if (iarg+1 >= argc) {
295 fprintf(stderr,"*** ERROR: Need an integer after -nx\n");
296 exit(1);
297 }
298 nx = (int) strtod( argv[++iarg] , NULL ) ;
299 iarg++ ; continue ;
300 }
301
302 if( strcmp(argv[iarg],"-ny") == 0 ){
303 if (iarg+1 >= argc) {
304 fprintf(stderr,"*** ERROR: Need an integer after -ny\n");
305 exit(1);
306 }
307 ny = (int) strtod( argv[++iarg] , NULL ) ;
308 iarg++ ; continue ;
309 }
310
311 if( strcmp(argv[iarg],"-gap") == 0 ){
312 if (iarg+1 >= argc) {
313 fprintf(stderr,"*** ERROR: Need an integer after -gap\n");
314 exit(1);
315 }
316 gap = (int) strtod( argv[++iarg] , NULL ) ;
317 iarg++ ; continue ;
318 }
319 if( strcmp(argv[iarg],"-gap_col") == 0 ){
320 if (iarg+2 >= argc) {
321 fprintf(stderr,
322 "*** ERROR: Need three integers between 0 and 255 after -gap_col\n");
323 exit(1);
324 }
325 gap_col[0] = (byte) strtod( argv[++iarg] , NULL ) ;
326 gap_col[1] = (byte) strtod( argv[++iarg] , NULL ) ;
327 gap_col[2] = (byte) strtod( argv[++iarg] , NULL ) ;
328 iarg++ ; continue ;
329 }
330
331 if( strcmp(argv[iarg],"-scale_image") == 0 ){
332 if (iarg+1 >= argc) {
333 fprintf(stderr,"*** ERROR: Need an image after -scale_image\n");
334 exit(1);
335 }
336 scale_image = argv[++iarg];
337 iarg++ ; continue ;
338 }
339
340 if( strcmp(argv[iarg],"-scale_pixels") == 0 ){
341 if (iarg+1 >= argc) {
342 fprintf(stderr,"*** ERROR: Need an image after -scale_pixels\n");
343 exit(1);
344 }
345 scale_pixels = argv[++iarg];
346 if (!THD_is_ondisk(scale_pixels)) {
347 fprintf(stderr,"*** ERROR: Image %s not found\n", scale_pixels);
348 exit(1);
349 }
350 iarg++ ; continue ;
351 }
352
353 if( strcmp(argv[iarg],"-scale_intensity") == 0) {
354 ScaleInt = 1;
355 iarg++ ; continue ;
356 }
357
358 if( strcmp(argv[iarg],"-rgb_out") == 0) {
359 force_rgb_out = 1;
360 iarg++ ; continue ;
361 }
362
363 if( strcmp(argv[iarg],"-zero_wrap") == 0) {
364 mri_Set_OK_WrapZero(1);
365 iarg++ ; continue ;
366 }
367 if( strcmp(argv[iarg],"-white_wrap") == 0) {
368 mri_Set_OK_WrapZero(255);
369 iarg++ ; continue ;
370 }
371
372 if( strcmp(argv[iarg],"-gray_wrap") == 0) {
373 byte bb;
374 if (iarg+1 >= argc) {
375 fprintf(stderr,
376 "*** ERROR: Need a number between 0 and 1 for -gray_wrap\n");
377 exit(1);
378 }
379 ++iarg;
380 bb = (byte)(atof(argv[iarg])*255);
381 if (bb < 1) bb = 1;
382 mri_Set_OK_WrapZero(bb);
383 iarg++ ; continue ;
384 }
385 if( strcmp(argv[iarg],"-image_wrap") == 0) {
386 mri_Set_KO_WrapZero();
387 iarg++ ; continue ;
388 }
389 if( strcmp(argv[iarg],"-matrix_from_scale") == 0) {
390 matrix_size_from_scale = 1;
391 iarg++ ; continue ;
392 }
393
394 if( strcmp(argv[iarg],"-prefix") == 0 ){
395 MCW_strncpy( prefix , argv[++iarg] , 240 ) ;
396 iarg++ ; continue ;
397 }
398
399 fprintf(stderr,"*** ERROR: illegal option %s\n",argv[iarg]) ;
400 suggest_best_prog_option(argv[0], argv[iarg]);
401 exit(1) ;
402 }
403
404 if( argc < 4 ){
405 ERROR_message("Too few options");
406 prog_usage(0);
407 exit(1) ;
408 }
409
410 if (cutlevu == -1 && cutlev == -1) {
411 /* No params set, but autocrop desired*/
412 cutlev = 20;
413 cutlevu = 20;
414 }
415
416 if (scale_image) {
417 if (!(imscl = mri_read_just_one(scale_image))) {
418 fprintf(stderr,"*** Failed to read scale image.\n");
419 exit(1);
420 }else {
421 fprintf(stderr,"++Scale image prep\n");
422 rgb= MRI_BYTE_PTR(imscl);
423 nscl = imscl->nx*imscl->ny;
424 scl = (float *)malloc(sizeof(float)*nscl);
425 scl3 = (byte *)malloc(sizeof(byte)*nscl*3);
426 if (imscl->kind == MRI_rgb) {
427 for (kkk=0; kkk<nscl; ++kkk) {
428 scl[kkk] = ( (float)rgb[3*kkk ] +
429 (float)rgb[3*kkk+1] +
430 (float)rgb[3*kkk+2] ) / 3.0 * fac;
431 if ((ff = rgb[3*kkk ]* fac) > 255) ff = 255;
432 scl3[3*kkk ] = ff;
433 if ((ff = rgb[3*kkk+1]* fac) > 255) ff = 255;
434 scl3[3*kkk+1] = ff;
435 if ((ff = rgb[3*kkk+2]* fac) > 255) ff = 255;
436 scl3[3*kkk+2] = ff;
437 }
438 } else if (imscl->kind == MRI_byte) {
439 for (kkk=0; kkk<nscl; ++kkk) {
440 scl[kkk] = ((float)rgb[kkk ]* fac);
441 if ((ff=scl[kkk])>255) ff = 255;
442 scl3[3*kkk ] = scl3[3*kkk+1] = scl3[3*kkk+2] = ff;
443 }
444 } else {
445 fprintf(stderr,"*** Scale image must be RGB or byte type.\n");
446 exit(1);
447 }
448 }
449 }
450
451 if (matrix_size_from_scale) {
452 if (imscl) {
453 fprintf(stderr,"+++ Matrix size of %dx%d, based on scale image\n",
454 imscl->nx, imscl->ny);
455 nx = imscl->nx; ny = imscl->ny;
456 } else {
457 fprintf(stderr,
458 "*** Want matrix size from scale image but no scale image found.\n");
459 exit(1);
460 }
461 }
462 /* allow from catwrapping */
463 if (wrapmode == 2) mri_Set_OK_catrandwrap();
464 else mri_Set_OK_catwrap();
465
466 /* read all images */
467 inimar = mri_read_resamp_many_files( argc-iarg , argv+iarg,
468 resix, ks*resiy, pval) ;
469 if( inimar == NULL ){
470 fprintf(stderr,"*** no input images read!\a\n") ;
471 exit(1) ;
472 } else if( inimar->num < 1 ){
473 fprintf(stderr,"*** less than 1 input image read!\a\n") ;
474 exit(1) ;
475 }
476
477 /* Figure out cropping based on one image, written as loop in
478 case I change my mind */
479 if (cutlev >= 0 || cutlevu >= 0) {
480 MRI_IMAGE *imin;
481 byte *colav=NULL, *rowav=NULL;
482 int mis=0, kx=0, ky=0, e0, e1, e2;
483 double d0, d1, d2;
484 if (cutlev > 0) cutlev = (int)(cutlev *2.55);
485 if (cutlevu > 0) cutlevu = (int)(cutlevu*2.55);
486 cutL = 0;
487 for (kkk=0; kkk<1; ++kkk) {
488 imin = IMAGE_IN_IMARR(inimar,kkk);
489 rgb= MRI_BYTE_PTR(imin);
490 if (imin->kind == MRI_rgb) {
491 e0 = (imin->nx*imin->ny-1)*3;
492 e1 = e0+1;
493 e2 = e0+2;
494 kkk = 0;
495 /* fprintf(stderr,"RGB image nx=%d, ny=%d, cut lev %d, avg lev %d\n",
496 imin->nx, imin->ny, cutlev, cutlevu); */
497
498 /* Compute column and row averages */
499 if (cutlevu >= 0) {
500 colav = (byte *)calloc(3*imin->nx, sizeof(byte));
501 for (kx=0; kx<imin->nx; ++kx) {
502 d0 = d1 = d2 = 0.0;
503 for (ky=0; ky<imin->ny; ++ky) {
504 kkk = kx+imin->nx*ky;
505 d0 += rgb[3*kkk ];
506 d1 += rgb[3*kkk+1];
507 d2 += rgb[3*kkk+2];
508 }
509 colav[3*kx ] = (byte)(d0/imin->ny);
510 colav[3*kx+1] = (byte)(d1/imin->ny);
511 colav[3*kx+2] = (byte)(d2/imin->ny);
512 }
513 rowav = (byte *)calloc(3*imin->ny, sizeof(byte));
514 for (ky=0; ky<imin->ny; ++ky) {
515 d0 = d1 = d2 = 0.0;
516 for (kx=0; kx<imin->nx; ++kx) {
517 kkk = kx+imin->nx*ky;
518 d0 += rgb[3*kkk ];
519 d1 += rgb[3*kkk+1];
520 d2 += rgb[3*kkk+2];
521 }
522 rowav[3*ky ] = (byte)(d0/imin->nx);
523 rowav[3*ky+1] = (byte)(d1/imin->nx);
524 rowav[3*ky+2] = (byte)(d2/imin->nx);
525 }
526 }
527
528 /* Left */
529 cutL = 0;
530 mis = 0;
531 for (kx=0; kx<imin->nx && !mis; ++kx) {
532 for (ky=0; ky<imin->ny && !mis; ++ky) {
533 kkk = kx+imin->nx*ky;
534 if (cutlev >= 0) {
535 /* break if color changes from corner */
536 if (ABS(rgb[3*kkk ] - rgb[0]) > cutlev ||
537 ABS(rgb[3*kkk+1] - rgb[1]) > cutlev ||
538 ABS(rgb[3*kkk+2] - rgb[2]) > cutlev ) {
539 /* fprintf(stderr,
540 "Break from [%d %d %d] at %d %d with [%d %d %d]\n",
541 rgb[0], rgb[1], rgb[2], kx, ky,
542 rgb[3*kkk ], rgb[3*kkk+1], rgb[3*kkk+2]); */
543 mis = 1;
544 }
545 }
546 /* break if color changes from average of column */
547 if (cutlevu >= 0) {
548 if (ABS(rgb[3*kkk ] - colav[3*kx ]) > cutlevu ||
549 ABS(rgb[3*kkk+1] - colav[3*kx+1]) > cutlevu ||
550 ABS(rgb[3*kkk+2] - colav[3*kx+2]) > cutlevu ) {
551 /* fprintf(stderr,
552 "Break from colav [%d %d %d] at %d %d with [%d %d %d]\n",
553 colav[3*kx ], colav[3*kx+1], colav[3*kx+2], kx, ky,
554 rgb[3*kkk ], rgb[3*kkk+1], rgb[3*kkk+2]); */
555 mis = 1;
556 }
557 }
558 }
559 if (!mis) {
560 ++cutL;
561 /* fprintf(stderr,"Line at x=%d is cst\n", kx); */
562 }
563 }
564 /* Right */
565 cutR = 0;
566 mis = 0;
567 for (kx=imin->nx-1; kx>=0 && !mis; --kx) {
568 for (ky=0; ky<imin->ny && !mis; ++ky) {
569 kkk = kx+imin->nx*ky;
570 if (cutlev >= 0) {
571 if (ABS(rgb[3*kkk ] - rgb[e0]) > cutlev ||
572 ABS(rgb[3*kkk+1] - rgb[e1]) > cutlev ||
573 ABS(rgb[3*kkk+2] - rgb[e2]) > cutlev ) {
574 /* fprintf(stderr,
575 "Break from [%d %d %d] at %d %d with [%d %d %d]\n",
576 rgb[0], rgb[1], rgb[2], kx, ky,
577 rgb[3*kkk ], rgb[3*kkk+1], rgb[3*kkk+2]); */
578 mis = 1;
579 }
580 }
581 /* break if color changes from average of column */
582 if (cutlevu >= 0) {
583 if (ABS(rgb[3*kkk ] - colav[3*kx ]) > cutlevu ||
584 ABS(rgb[3*kkk+1] - colav[3*kx+1]) > cutlevu ||
585 ABS(rgb[3*kkk+2] - colav[3*kx+2]) > cutlevu ) {
586 /* fprintf(stderr,
587 "Break from colav [%d %d %d] at %d %d with [%d %d %d]\n",
588 colav[3*kx ], colav[3*kx+1], colav[3*kx+2], kx, ky,
589 rgb[3*kkk ], rgb[3*kkk+1], rgb[3*kkk+2]); */
590 mis = 1;
591 }
592 }
593 }
594 if (!mis) {
595 ++cutR;
596 /* fprintf(stderr,"Line at x=%d is cst\n", kx); */
597 }
598 }
599 /* Bottom */
600 cutB = 0;
601 mis = 0;
602 for (ky=imin->ny-1; ky>=0 && !mis; --ky) {
603 for (kx=imin->nx-1; kx>=0 && !mis; --kx) {
604 kkk = kx+imin->nx*ky;
605 if (cutlev >= 0) {
606 if (ABS(rgb[3*kkk ] - rgb[e0]) > cutlev ||
607 ABS(rgb[3*kkk+1] - rgb[e1]) > cutlev ||
608 ABS(rgb[3*kkk+2] - rgb[e2]) > cutlev ) {
609 /* fprintf(stderr,
610 "Break from [%d %d %d] at %d %d with [%d %d %d]\n",
611 rgb[0], rgb[1], rgb[2], kx, ky,
612 rgb[3*kkk ], rgb[3*kkk+1], rgb[3*kkk+2]); */
613 mis = 1;
614 }
615 }
616 /* break if color changes from average of column */
617 if (cutlevu >= 0) {
618 if (ABS(rgb[3*kkk ] - rowav[3*ky ]) > cutlevu ||
619 ABS(rgb[3*kkk+1] - rowav[3*ky+1]) > cutlevu ||
620 ABS(rgb[3*kkk+2] - rowav[3*ky+2]) > cutlevu ) {
621 /* fprintf(stderr,
622 "Break from colav [%d %d %d] at %d %d with [%d %d %d]\n",
623 rowav[3*ky ], rowav[3*ky+1], rowav[3*ky+2], kx, ky,
624 rgb[3*kkk ], rgb[3*kkk+1], rgb[3*kkk+2]); */
625 mis = 1;
626 }
627 }
628 }
629 if (!mis) {
630 ++cutB;
631 /* fprintf(stderr,"Line at y=%d is cst\n", ky); */
632 }
633 }
634 /* Top */
635 cutT = 0;
636 mis = 0;
637 for (ky=0; ky<imin->ny && !mis; ++ky) {
638 for (kx=imin->nx-1; kx>=0 && !mis; --kx) {
639 kkk = kx+imin->nx*ky;
640 if (cutlev >= 0) {
641 if (ABS(rgb[3*kkk ] - rgb[e0]) > cutlev ||
642 ABS(rgb[3*kkk+1] - rgb[e1]) > cutlev ||
643 ABS(rgb[3*kkk+2] - rgb[e2]) > cutlev ) {
644 /* fprintf(stderr,
645 "Break from [%d %d %d] at %d %d with [%d %d %d]\n",
646 rgb[0], rgb[1], rgb[2], kx, ky,
647 rgb[3*kkk ], rgb[3*kkk+1], rgb[3*kkk+2]); */
648 mis = 1;
649 }
650 }
651 /* break if color changes from average of column */
652 if (cutlevu >= 0) {
653 if (ABS(rgb[3*kkk ] - rowav[3*ky ]) > cutlevu ||
654 ABS(rgb[3*kkk+1] - rowav[3*ky+1]) > cutlevu ||
655 ABS(rgb[3*kkk+2] - rowav[3*ky+2]) > cutlevu ) {
656 /* fprintf(stderr,
657 "Break from colav [%d %d %d] at %d %d with [%d %d %d]\n",
658 rowav[3*ky ], rowav[3*ky+1], rowav[3*ky+2], kx, ky,
659 rgb[3*kkk ], rgb[3*kkk+1], rgb[3*kkk+2]); */
660 mis = 1;
661 }
662 }
663 }
664 if (!mis) {
665 ++cutT;
666 /* fprintf(stderr,"Line at y=%d is cst\n", ky); */
667 }
668 }
669 if (colav) free(colav); colav=NULL;
670 if (rowav) free(rowav); rowav=NULL;
671 } else if (imin->kind == MRI_byte) {
672 e0 = (imin->nx*imin->ny-1);
673 kkk = 0;
674 /* fprintf(stderr,"Byte image nx=%d, ny=%d, cut level %d, %d\n",
675 imin->nx, imin->ny, cutlev, cutlevu); */
676 /* Compute column and row averages */
677 if (cutlevu >= 0) {
678 colav = (byte *)calloc(imin->nx, sizeof(byte));
679 for (kx=0; kx<imin->nx; ++kx) {
680 d0 = 0.0;
681 for (ky=0; ky<imin->ny; ++ky) {
682 kkk = kx+imin->nx*ky;
683 d0 += rgb[kkk ];
684 }
685 colav[kx ] = (byte)(d0/imin->ny);
686 }
687 rowav = (byte *)calloc(imin->ny, sizeof(byte));
688 for (ky=0; ky<imin->ny; ++ky) {
689 d0 = 0.0;
690 for (kx=0; kx<imin->nx; ++kx) {
691 kkk = kx+imin->nx*ky;
692 d0 += rgb[kkk ];
693 }
694 rowav[ky ] = (byte)(d0/imin->nx);
695 }
696 }
697 /* Left */
698 cutL = 0;
699 mis = 0;
700 for (kx=0; kx<imin->nx && !mis; ++kx) {
701 for (ky=0; ky<imin->ny && !mis; ++ky) {
702 kkk = kx+imin->nx*ky;
703 if (cutlev >= 0) {
704 if (ABS(rgb[kkk] - rgb[0]) > cutlev) {
705 /* fprintf(stderr,
706 "Break from [%d] at %d %d with [%d]\n",
707 rgb[0], kx, ky, rgb[kkk]); */
708 mis = 1;
709 }
710 }
711 /* break if color changes from average of column */
712 if (cutlevu >= 0) {
713 if (ABS(rgb[kkk ] - colav[kx ]) > cutlevu) {
714 /* fprintf(stderr,
715 "Break from colav [%d] at %d %d with [%d]\n",
716 colav[kx ], kx, ky,
717 rgb[kkk ]); */
718 mis = 1;
719 }
720 }
721 }
722 if (!mis) {
723 ++cutL;
724 /* fprintf(stderr,"Line at x=%d is cst\n", kx); */
725 }
726 }
727 /* Right */
728 cutR = 0;
729 mis = 0;
730 for (kx=imin->nx-1; kx>=0 && !mis; --kx) {
731 for (ky=0; ky<imin->ny && !mis; ++ky) {
732 kkk = kx+imin->nx*ky;
733 if (cutlev >= 0) {
734 if (ABS(rgb[kkk] - rgb[e0]) > cutlev ) {
735 /* fprintf(stderr,
736 "Break from [%d] at %d %d with [%d]\n",
737 rgb[0], kx, ky, rgb[kkk]); */
738 mis = 1;
739 }
740 }
741 /* break if color changes from average of column */
742 if (cutlevu >= 0) {
743 if (ABS(rgb[kkk ] - colav[kx ]) > cutlevu) {
744 /* fprintf(stderr,
745 "Break from colav [%d] at %d %d with [%d]\n",
746 colav[kx ], kx, ky,
747 rgb[kkk ]); */
748 mis = 1;
749 }
750 }
751 }
752 if (!mis) {
753 ++cutR;
754 /* fprintf(stderr,"Line at x=%d is cst\n", kx); */
755 }
756 }
757 /* Bottom */
758 cutB = 0;
759 mis = 0;
760 for (ky=imin->ny-1; ky>=0 && !mis; --ky) {
761 for (kx=imin->nx-1; kx>=0 && !mis; --kx) {
762 kkk = kx+imin->nx*ky;
763 if (cutlev >= 0) {
764 if (ABS(rgb[kkk] - rgb[e0]) > cutlev ) {
765 /* fprintf(stderr,
766 "Break from [%d] at %d %d with [%d]\n",
767 rgb[0], kx, ky, rgb[kkk]); */
768 mis = 1;
769 }
770 }
771 /* break if color changes from average of column */
772 if (cutlevu >= 0) {
773 if (ABS(rgb[kkk ] - rowav[ky ]) > cutlevu) {
774 /* fprintf(stderr,
775 "Break from rowav [%d] at %d %d with [%d]\n",
776 rowav[ky ], kx, ky,
777 rgb[kkk ]); */
778 mis = 1;
779 }
780 }
781 }
782 if (!mis) {
783 ++cutB;
784 /* fprintf(stderr,"Line at y=%d is cst\n", ky); */
785 }
786 }
787 /* Top */
788 cutT = 0;
789 mis = 0;
790 for (ky=0; ky<imin->ny && !mis; ++ky) {
791 for (kx=imin->nx-1; kx>=0 && !mis; --kx) {
792 kkk = kx+imin->nx*ky;
793 if (cutlev >= 0) {
794 if (ABS(rgb[kkk ] - rgb[e0]) > cutlev) {
795 /* fprintf(stderr,
796 "Break from [%d] at %d %d with [%d]\n",
797 rgb[0], kx, ky, rgb[kkk]); */
798 mis = 1;
799 }
800 }
801 /* break if color changes from average of column */
802 if (cutlevu >= 0) {
803 if (ABS(rgb[kkk ] - rowav[ky ]) > cutlevu) {
804 /* fprintf(stderr,
805 "Break from rowav [%d] at %d %d with [%d]\n",
806 rowav[ky ], kx, ky,
807 rgb[kkk ]); */
808 mis = 1;
809 }
810 }
811 }
812 if (!mis) {
813 ++cutT;
814 /* fprintf(stderr,"Line at y=%d is cst\n", ky); */
815 }
816 }
817 if (colav) free(colav); colav=NULL;
818 if (rowav) free(rowav); rowav=NULL;
819 } else {
820 fprintf(stderr,"*** For autocrop image must be RGB or byte type.\n");
821 exit(1);
822 }
823
824 fprintf(stdout,"+++ Autocrop set to L%d R%d T%d B%d\n",
825 cutL, cutR, cutT, cutB);
826 }
827 }
828
829 /* crop all images if needed */
830 if (cutL || cutR || cutT || cutB) {
831 /* original image size */
832 nxin = IMAGE_IN_IMARR(inimar,0)->nx;
833 nyin = IMAGE_IN_IMARR(inimar,0)->ny;
834
835 nbad = mri_cut_many_2D(inimar, cutL, nxin-1-cutR, cutT, nyin-1-cutB);
836 if (nbad) {
837 fprintf(stderr,"*** failed (%d) in cropping operation!\a\n", nbad) ;
838 exit(1) ;
839 }
840 }
841
842 /* figure out the count */
843 if (nx < 0 && ny < 0) {
844 nx = ny = (int)sqrt((double)inimar->num+0.00001);
845 if (nx*ny != inimar->num) {
846 fprintf(stderr,"*** Can't guess at matrix layout for %d images.\n"
847 " Use -nx, -ny or -matrix\n", inimar->num);
848 exit(1);
849 }
850 } else if (nx < 0) {
851 if (inimar->num % ny) {
852 fprintf(stderr,"--- Have %d images, not divisible by %d\n"
853 " will pad to fill matrix.\n"
854 , inimar->num, ny);
855 nx = inimar->num / ny + 1;
856 } else {
857 nx = inimar->num / ny;
858 }
859 } else if (ny < 0) {
860 if (inimar->num % nx) {
861 fprintf(stderr,"--- Have %d images, not divisible by %d!\n"
862 " will pad to fill matrix.\n"
863 , inimar->num, nx);
864 ny = inimar->num / nx + 1;
865 } else {
866 ny = inimar->num / nx;
867 }
868 }
869
870 if( nx < 1 || ny < 1 ){
871 fprintf(stderr,"*** ERROR: illegal values nx=%d ny=%d\n",nx,ny);
872 exit(1) ;
873 }
874 if (nx*ny > inimar->num) {
875 fprintf(stderr,"+++ Have %d images. Will wrap to fill %dx%d matrix\n",
876 inimar->num, nx, ny);
877 } else if (nx*ny < inimar->num) {
878 fprintf(stderr,"+++ Have more images than needed to fill matrix.\n"
879 " Will ignore the last %d images.\n",
880 inimar->num- nx*ny);
881 }
882
883 nxin = IMAGE_IN_IMARR(inimar,0)->nx;
884 nyin = IMAGE_IN_IMARR(inimar,0)->ny;
885
886 fprintf(stdout, "+++ Arranging %d images (each %dx%d) into a %dx%d matrix.\n", inimar->num, nxin, nyin, nx, ny);
887
888 force_rgb_at_input = 0;
889 N_byte = 0; N_rgb = 0;
890 if (gap) force_rgb_at_input = 1; /* must go rgb */
891 else {
892 /* if have multiple types, must also go rgb */
893 for (kkk=0; kkk<inimar->num; ++kkk) {
894 if (IMAGE_IN_IMARR(inimar,kkk)->kind != MRI_byte &&
895 IMAGE_IN_IMARR(inimar,kkk)->kind != MRI_rgb) {
896 fprintf(stderr,"*** Unexpected image kind on input.\n"
897 " Only byte and rgb (3byte) images allowed.\n");
898 exit(1);
899 } else if (IMAGE_IN_IMARR(inimar,kkk)->kind == MRI_byte) {
900 ++N_byte;
901 } else if (IMAGE_IN_IMARR(inimar,kkk)->kind == MRI_rgb) {
902 ++N_rgb;
903 }
904 if (N_byte && N_rgb) { force_rgb_at_input = 1; continue; }
905 }
906 }
907
908 if (force_rgb_at_input) { /* make sure all images are rgb type */
909 MRI_IMAGE *imin, *newim;
910 int kkk, nmin;
911 if (nx*ny < inimar->num) nmin = nx*ny;
912 else nmin = inimar->num;
913 /* must transform input to rgb here to allow for gap option */
914 fprintf(stderr,"+++ Transforming all input to rgb for a good reason \n");
915 for (kkk=0; kkk<nmin; ++kkk) {
916 imin = IMAGE_IN_IMARR(inimar,kkk%inimar->num);
917 if(imin->kind == MRI_byte) {
918 newim = mri_3to_rgb( imin, imin, imin ) ;
919 MRI_COPY_AUX(newim,imin) ; mri_free(imin);
920 IMAGE_IN_IMARR(inimar,kkk%inimar->num) = newim;
921 } else if (imin->kind != MRI_rgb) {
922 fprintf(stderr,"*** Unexpected image kind.\n");
923 exit(1);
924 }
925 }
926 }
927
928
929 ggg = (void *)gap_col;
930
931 if (!(im = mri_cat2D( nx , ny , gap , ggg , inimar ))) {
932 fprintf(stderr,"*** ERROR: Failed to create image!\n");
933 exit(1) ;
934 }
935 FREE_IMARR(inimar) ; inimar = NULL;
936
937 if (force_rgb_out && im->kind == MRI_byte) {
938 MRI_IMAGE *newim=NULL;
939 fprintf(stderr,"+++ Forcing output to RGB\n");
940 newim = mri_3to_rgb( im, im, im ) ;
941 MRI_COPY_AUX(newim,im) ; mri_free(im);
942 im = newim;
943 }
944
945 /* image scaling needed, not very efficient in implementation but
946 mostly for fun */
947 if (scale_image && ( im->kind == MRI_rgb || im->kind == MRI_byte) ) {
948 MRI_IMARR *imtriple ;
949 MRI_IMAGE *rim, *gim, *bim, *tim, *imin, *newim;
950 fprintf(stderr,"+++ Scaling by image\n");
951 if (!imscl) {
952 fprintf(stderr,"*** No scale image!!!.\n");
953 exit(1);
954 }else {
955 rgb= MRI_BYTE_PTR(imscl);
956 nscl = imscl->nx*imscl->ny;
957 scl = (float *)malloc(sizeof(float)*nscl);
958 scl3 = (byte *)malloc(sizeof(byte)*nscl*3);
959 if (imscl->kind == MRI_rgb) {
960 for (kkk=0; kkk<nscl; ++kkk) {
961 scl[kkk] = ((float)rgb[3*kkk ] +
962 (float)rgb[3*kkk+1] +
963 (float)rgb[3*kkk+2] ) / 3.0 * fac ;
964
965 if ((ff = rgb[3*kkk ]* fac) > 255) ff=255 ;
966 scl3[3*kkk ] = ff;
967 if ((ff = rgb[3*kkk+1]* fac) > 255) ff=255;
968 scl3[3*kkk+1] = ff;
969 if ((ff = rgb[3*kkk+2]* fac) > 255) ff=255;
970 scl3[3*kkk+2] = ff;
971 }
972 } else if (imscl->kind == MRI_byte) {
973 for (kkk=0; kkk<nscl; ++kkk) {
974 scl[kkk] = ((float)rgb[kkk ]* fac) ;
975 if ((ff = rgb[kkk]* fac) > 255) ff = 255;
976 scl3[3*kkk ] = scl3[3*kkk+1] = scl3[3*kkk+2] = ff;
977 }
978 } else {
979 fprintf(stderr,"*** Scale image must be RGB or byte type.\n");
980 exit(1);
981 }
982 }
983
984 /* Now break the image again */
985 if (!(inimar = mri_uncat2D( nxin , nyin ,im ))) {
986 fprintf(stderr,"*** Failed to cut up image\n");
987 exit(1);
988 }
989 mri_free(im); im = NULL;
990
991 for (kkk=0; kkk<inimar->num; ++kkk) {
992 imin = IMAGE_IN_IMARR(inimar,kkk);
993 /* sprintf(name,"prescaled.%d.ppm", kkk);
994 mri_write(name,imin); */
995 if(imin->kind == MRI_rgb) {
996 imtriple = mri_rgb_to_3byte( imin ) ;
997 if( imtriple == NULL ){
998 fprintf(stderr,"*** mri_rgb_to_3byte fails!\n"); break;
999 }
1000 rim = IMAGE_IN_IMARR(imtriple,0) ;
1001 gim = IMAGE_IN_IMARR(imtriple,1) ;
1002 bim = IMAGE_IN_IMARR(imtriple,2) ; FREE_IMARR(imtriple) ;
1003 /* scale image */
1004 if (ScaleInt) {
1005 /* fprintf(stderr,"Scaling image %d by %f\n",
1006 kkk, scl[kkk%nscl]); */
1007 tim = mri_to_byte_scl(0.0, scl[kkk%nscl], rim );
1008 mri_free(rim); rim = tim;
1009 tim = mri_to_byte_scl(0.0, scl[kkk%nscl], gim );
1010 mri_free(gim); gim = tim;
1011 tim = mri_to_byte_scl(0.0, scl[kkk%nscl], bim );
1012 mri_free(bim); bim = tim;
1013 } else {
1014 /* fprintf(stderr,"Scaling image %d by [%.2f %.2f %.2f]\n",
1015 kkk, (float)scl3[3*(kkk%nscl) ],
1016 (float)scl3[3*(kkk%nscl)+1],
1017 (float)scl3[3*(kkk%nscl)+2]); */
1018 tim = mri_to_byte_scl(0.0, (float)scl3[3*(kkk%nscl) ], rim );
1019 mri_free(rim); rim = tim;
1020 tim = mri_to_byte_scl(0.0, (float)scl3[3*(kkk%nscl)+1], gim );
1021 mri_free(gim); gim = tim;
1022 tim = mri_to_byte_scl(0.0, (float)scl3[3*(kkk%nscl)+2], bim );
1023 mri_free(bim); bim = tim;
1024 }
1025 newim = mri_3to_rgb( rim, gim, bim ) ;
1026 mri_free(rim) ; mri_free(gim) ; mri_free(bim) ;
1027 MRI_COPY_AUX(newim,imin) ; mri_free(imin);
1028 IMAGE_IN_IMARR(inimar,kkk) = newim;
1029 } else if(imin->kind == MRI_byte) {
1030 /* scale image */
1031 /* fprintf(stderr,"Scaling byte image %d by %f\n",
1032 kkk, scl[kkk%nscl]); */
1033 newim = mri_to_byte_scl(0.0, (float)scl[kkk%nscl], imin );
1034 MRI_COPY_AUX(newim,imin) ; mri_free(imin);
1035 /* sprintf(name,"postscaled.%d.ppm", kkk);
1036 mri_write(name,newim); */
1037 IMAGE_IN_IMARR(inimar,kkk) = newim;
1038 } else {
1039 fprintf(stderr,
1040 "*** image %d is not rgb or byte. No scaling for you!\n",
1041 kkk%inimar->num);
1042 }
1043 }
1044 if (scl) free(scl); scl = NULL;
1045 if (scl3) free(scl3); scl3 = NULL;
1046 /* Now put it back together */
1047 /* fprintf(stderr,"Going to cat2D, again\n"); */
1048 if (!(im = mri_cat2D( nx , ny , gap , ggg , inimar ))) {
1049 fprintf(stderr,"*** ERROR: Failed to create image!\n");
1050 exit(1) ;
1051 }
1052 FREE_IMARR(inimar) ; inimar = NULL;
1053
1054 }
1055
1056 if (scale_pixels) {
1057 MRI_IMARR *imtriple ;
1058 MRI_IMAGE *rim, *gim, *bim, *tim, *newim;
1059 if (im->kind != MRI_rgb && im->kind != MRI_byte) {
1060 fprintf(stderr,"*** Output not MRI_rgb or MRI_byte. Cannot scale.\n");
1061 exit(1);
1062 }
1063 fprintf(stderr,"*** Pixel scaling ...\n");
1064 if (!(imar = mri_read_resamp_many_files( 1 , &scale_pixels,
1065 im->nx, ks*im->ny, pval )) ||
1066 imar->num != 1) {
1067 fprintf(stderr,"*** Failed to read 1 image from %s\n", scale_pixels);
1068 exit(1) ;
1069 }
1070
1071 if (imscl) mri_free(imscl); imscl=NULL;
1072 if (scl) free(scl); scl=NULL;
1073 if (scl3) free(scl3); scl3 = NULL;
1074
1075 imscl = IMAGE_IN_IMARR(imar,0);
1076 rgb= MRI_BYTE_PTR(imscl);
1077 nscl = imscl->nx*imscl->ny;
1078 scl = (float *)malloc(sizeof(float)*nscl);
1079 scl3 = (byte *)malloc(sizeof(byte)*nscl*3);
1080 if (imscl->kind == MRI_rgb) {
1081 for (kkk=0; kkk<nscl; ++kkk) {
1082 scl[kkk] = ( (float)rgb[3*kkk ] +
1083 (float)rgb[3*kkk+1] +
1084 (float)rgb[3*kkk+2] ) / 3.0;
1085 scl3[3*kkk ] = rgb[3*kkk ];
1086 scl3[3*kkk+1] = rgb[3*kkk+1];
1087 scl3[3*kkk+2] = rgb[3*kkk+2];
1088 }
1089 } else if (imscl->kind == MRI_byte) {
1090 for (kkk=0; kkk<nscl; ++kkk) {
1091 scl[kkk] = ((float)rgb[kkk ]);
1092 scl3[3*kkk ] = rgb[kkk]; /* inefficient, but makes life easy */
1093 scl3[3*kkk+1] = rgb[kkk];
1094 scl3[3*kkk+2] = rgb[kkk];
1095 }
1096 } else {
1097 fprintf(stderr,"*** Scale image must be RGB or byte type.\n");
1098 exit(1);
1099 }
1100 /* Now scale */
1101 if(im->kind == MRI_rgb) {
1102 imtriple = mri_rgb_to_3byte( im ) ;
1103 if( imtriple == NULL ){
1104 fprintf(stderr,"*** mri_rgb_to_3byte fails!\n"); exit(1);
1105 }
1106 rim = IMAGE_IN_IMARR(imtriple,0) ; b1 = MRI_BYTE_PTR(rim) ;
1107 gim = IMAGE_IN_IMARR(imtriple,1) ; b2 = MRI_BYTE_PTR(gim) ;
1108 bim = IMAGE_IN_IMARR(imtriple,2) ; b3 = MRI_BYTE_PTR(bim) ;
1109 FREE_IMARR(imtriple) ;
1110 /* scale image */
1111 if (ScaleInt) {
1112 for (kkk=0; kkk<im->nvox; ++kkk) {
1113 b1[kkk] = BYTEIZE((b1[kkk]*(float)scl[kkk])/255.0);
1114 b2[kkk] = BYTEIZE((b2[kkk]*(float)scl[kkk])/255.0);
1115 b3[kkk] = BYTEIZE((b3[kkk]*(float)scl[kkk])/255.0);
1116 }
1117 } else {
1118 /* fprintf(stderr,"Scaling image %d by [%.2f %.2f %.2f]\n",
1119 kkk, (float)scl3[3*(kkk%nscl) ],
1120 (float)scl3[3*(kkk%nscl)+1],
1121 (float)scl3[3*(kkk%nscl)+2]); */
1122 for (kkk=0; kkk<im->nvox; ++kkk) {
1123 b1[kkk] = BYTEIZE((b1[kkk]*(float)scl3[3*kkk ])/255.0);
1124 b2[kkk] = BYTEIZE((b2[kkk]*(float)scl3[3*kkk+1])/255.0);
1125 b3[kkk] = BYTEIZE((b3[kkk]*(float)scl3[3*kkk+2])/255.0);
1126 }
1127 }
1128 newim = mri_3to_rgb( rim, gim, bim ) ;
1129 mri_free(rim) ; mri_free(gim) ; mri_free(bim) ;
1130 MRI_COPY_AUX(newim,im) ; mri_free(im);
1131 im = newim; newim = NULL;
1132 } else if(im->kind == MRI_byte) {
1133 /* scale image */
1134 b1 = MRI_BYTE_PTR(im) ;
1135 for (kkk=0; kkk<im->nvox; ++kkk) {
1136 b1[kkk] = BYTEIZE((b1[kkk]*(float)scl[kkk])/255.0);
1137 }
1138 } else {
1139 fprintf(stderr,
1140 "*** image is not rgb or byte. No scaling for you!\n");
1141 }
1142 if (scl) free(scl); scl = NULL;
1143 if (scl3) free(scl3); scl3 = NULL;
1144 }
1145
1146 if (!(STRING_HAS_SUFFIX_CASE(prefix,".1D"))) {
1147 if (!(STRING_HAS_SUFFIX_CASE(prefix,".jpg")) &&
1148 !(STRING_HAS_SUFFIX_CASE(prefix,".ppm")) ) {
1149 sprintf(fnam,"%s.ppm",prefix);
1150 } else {
1151 sprintf(fnam,"%s",prefix);
1152 }
1153 fprintf(stderr,"+++ Writing image to %s\n", fnam);
1154 mri_write(fnam,im) ;
1155 fprintf(stdout, "You can view image %s with:\n aiv %s \n", fnam, fnam);
1156 } else { /* write a 1D out */
1157 FILE *fout=fopen(prefix,"w");
1158 float *fff=NULL;
1159 MRI_IMAGE *tim;
1160 if (!fout) {
1161 fprintf(stderr,"*** ERROR: Failed to open %s for output!\n", prefix);
1162 exit(1) ;
1163 }
1164 if (!(tim = mri_to_float(im))) {
1165 fprintf(stderr,"*** ERROR: Failed to convert output image.\n");
1166 exit(1) ;
1167 }
1168 fff= MRI_FLOAT_PTR(tim);
1169 for (jj=0; jj<tim->ny; ++jj) {
1170 for (ii=0; ii<tim->nx; ++ii) {
1171 fprintf(fout,"%.4f ", fff[jj*tim->nx+ii]);
1172 }
1173 fprintf(fout,"\n");
1174 }
1175 fclose(fout);
1176 mri_free(tim); tim = NULL;
1177 fprintf(stdout, "You can view image %s with:\n 1dgrayplot %s \n",
1178 fnam, prefix);
1179 }
1180
1181 mri_free(im); im = NULL;
1182 exit(0) ;
1183 }
1184