Attachment 'mri.c'
Download 1 /*
2 * FILE NAME: mri.c
3 *
4 * DESCRIPTION: utilities for MRI data structure
5 *
6 * AUTHOR: Bruce Fischl
7 * DATE: 1/8/97
8 *
9 */
10 // Warning: Do not edit the following four lines. CVS maintains them.
11 // Revision Author: $Author: nicks $
12 // Revision Date : $Date: 2006/01/17 22:16:34 $
13 // Revision : $Revision: 1.325 $
14 char *MRI_C_VERSION = "$Revision: 1.325 $";
15
16 /*-----------------------------------------------------
17 INCLUDE FILES
18 -------------------------------------------------------*/
19 #define USE_ELECTRIC_FENCE 1
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <math.h>
24 #include <string.h>
25 #include <memory.h>
26 #include <errno.h>
27 #include <ctype.h>
28 #include "error.h"
29 #include "proto.h"
30 #include "mri.h"
31 #include "macros.h"
32 #include "diag.h"
33 #include "volume_io.h"
34 #include "filter.h"
35 #include "box.h"
36 #include "region.h"
37 #include "mri_transform.h"
38 #include "utils.h"
39 #include "matrix.h"
40 #include "pdf.h"
41 #include "cma.h"
42 #include "talairachex.h"
43 #include "voxlist.h"
44
45 extern int errno;
46
47 /*-----------------------------------------------------
48 MACROS AND CONSTANTS
49 -------------------------------------------------------*/
50
51 #define DEBUG_POINT(x,y,z) (((x==8&&y==9) || (x==9&&y==8)) &&((z)==15))
52
53 /*-----------------------------------------------------
54 STATIC DATA
55 -------------------------------------------------------*/
56
57 static long mris_alloced = 0 ;
58
59 /*-----------------------------------------------------
60 STATIC PROTOTYPES
61 -------------------------------------------------------*/
62
63 /*-----------------------------------------------------
64 GLOBAL FUNCTIONS
65 -------------------------------------------------------*/
66
67 /*----------------------------------------------------------
68 MRIxfmCRS2XYZ() - computes the matrix needed to compute the
69 XYZ of the center of a voxel at a given Col, Row, and Slice
70 from the native geometry of the volume
71
72 x col
73 y = T * row
74 z slice
75 1 1
76
77 T = [Mdc*D Pxyz0]
78 [0 0 0 1 ]
79
80 Mdc = [Vcol Vrow Vslice]
81 V<dim> = the direction cosine pointing from the center of one voxel
82 to the center of an adjacent voxel in the next dim, where
83 dim is either colum, row, or slice. Vcol = [x_r x_a x_s],
84 Vrow = [y_r y_a y_s], Vslice = [z_r z_a z_s]. Vcol can also
85 be described as the vector normal to the plane formed by
86 the rows and slices of a given column (ie, the column normal).
87
88 D = diag([colres rowres sliceres])
89 dimres = the distance between adjacent dim, where colres = mri->xsize,
90 rowres = mri->ysize, and sliceres = mri->zsize.
91
92 Pxyz0 = the XYZ location at CRS=0. This number is not part of the
93 mri structure, so it is computed here according to the formula:
94 Pxyz0 = PxyzCenter - Mdc*D*PcrsCenter
95
96 PcrsCenter = the col, row, and slice at the center of the volume,
97 = [ ncols/2 nrows/2 nslices/2 ]
98
99 PxyzCenter = the X, Y, and Z at the center of the volume and does
100 exist in the header as mri->c_r, mri->c_a, and mri->c_s,
101 respectively.
102
103 Note: to compute the matrix with respect to the first voxel being
104 at CRS 1,1,1 instead of 0,0,0, then set base = 1. This is
105 necessary with SPM matrices.
106
107 See also: MRIxfmCRS2XYZtkreg, MRItkReg2Native
108 ------------------------------------------------------*/
109 MATRIX *MRIxfmCRS2XYZ(MRI *mri, int base)
110 {
111 MATRIX *m;
112 MATRIX *Pcrs, *PxyzOffset;
113
114 m = MatrixAlloc(4, 4, MATRIX_REAL);
115
116 /* direction cosine between columns scaled by
117 distance between colums */
118 *MATRIX_RELT(m, 1, 1) = mri->x_r * mri->xsize;
119 *MATRIX_RELT(m, 2, 1) = mri->x_a * mri->xsize;
120 *MATRIX_RELT(m, 3, 1) = mri->x_s * mri->xsize;
121
122 /* direction cosine between rows scaled by
123 distance between rows */
124 *MATRIX_RELT(m, 1, 2) = mri->y_r * mri->ysize;
125 *MATRIX_RELT(m, 2, 2) = mri->y_a * mri->ysize;
126 *MATRIX_RELT(m, 3, 2) = mri->y_s * mri->ysize;
127
128 /* direction cosine between slices scaled by
129 distance between slices */
130 *MATRIX_RELT(m, 1, 3) = mri->z_r * mri->zsize;
131 *MATRIX_RELT(m, 2, 3) = mri->z_a * mri->zsize;
132 *MATRIX_RELT(m, 3, 3) = mri->z_s * mri->zsize;
133
134 /* Preset the offsets to 0 */
135 *MATRIX_RELT(m, 1, 4) = 0.0;
136 *MATRIX_RELT(m, 2, 4) = 0.0;
137 *MATRIX_RELT(m, 3, 4) = 0.0;
138
139 /* Last row of matrix */
140 *MATRIX_RELT(m, 4, 1) = 0.0;
141 *MATRIX_RELT(m, 4, 2) = 0.0;
142 *MATRIX_RELT(m, 4, 3) = 0.0;
143 *MATRIX_RELT(m, 4, 4) = 1.0;
144
145 /* At this point, m = Mdc * D */
146
147 /* Col, Row, Slice at the Center of the Volume */
148 Pcrs = MatrixAlloc(4, 1, MATRIX_REAL);
149 *MATRIX_RELT(Pcrs, 1, 1) = mri->width/2.0 + base;
150 *MATRIX_RELT(Pcrs, 2, 1) = mri->height/2.0 + base;
151 *MATRIX_RELT(Pcrs, 3, 1) = mri->depth/2.0 + base;
152 *MATRIX_RELT(Pcrs, 4, 1) = 1.0;
153
154 /* XYZ offset the first Col, Row, and Slice from Center */
155 /* PxyzOffset = Mdc*D*PcrsCenter */
156 PxyzOffset = MatrixMultiply(m,Pcrs,NULL);
157
158 /* XYZ at the Center of the Volume is mri->c_r, c_a, c_s */
159
160 /* The location of the center of the voxel at CRS = (0,0,0)*/
161 *MATRIX_RELT(m, 1, 4) = mri->c_r - PxyzOffset->rptr[1][1];
162 *MATRIX_RELT(m, 2, 4) = mri->c_a - PxyzOffset->rptr[2][1];
163 *MATRIX_RELT(m, 3, 4) = mri->c_s - PxyzOffset->rptr[3][1];
164
165 MatrixFree(&Pcrs);
166 MatrixFree(&PxyzOffset);
167
168 return(m);
169 }
170 /*-------------------------------------------------------------
171 MRIxfmCRS2XYZtkreg() - computes the linear transform between the
172 column, row, and slice of a voxel and the x, y, z of that voxel as
173 expected by tkregister (or for when using a tkregister compatible
174 matrix). For tkregister, the column DC points in the "x" direction,
175 the row DC points in the "z" direction, and the slice DC points in
176 the "y" direction. The center of the coordinates is set to the
177 center of the FOV. These definitions are arbitrary (and more than a
178 little confusing). Since they are arbitrary, they must be applied
179 consistently.
180 -------------------------------------------------------------*/
181 MATRIX *MRIxfmCRS2XYZtkreg(MRI *mri)
182 {
183 MRI *tmp;
184 MATRIX *K;
185
186 tmp = MRIallocHeader(mri->width, mri->height, mri->depth, mri->type);
187
188 /* Set tkregister defaults */
189 /* column row slice center */
190 tmp->x_r = -1; tmp->y_r = 0; tmp->z_r = 0; tmp->c_r = 0.0;
191 tmp->x_a = 0; tmp->y_a = 0; tmp->z_a = 1; tmp->c_a = 0.0;
192 tmp->x_s = 0; tmp->y_s = -1; tmp->z_s = 0; tmp->c_s = 0.0;
193
194 /* Copy the voxel resolutions */
195 tmp->xsize = mri->xsize;
196 tmp->ysize = mri->ysize;
197 tmp->zsize = mri->zsize;
198
199 K = MRIxfmCRS2XYZ(tmp,0);
200
201 MRIfree(&tmp);
202
203 return(K);
204 }
205 /*-------------------------------------------------------------------
206 MRItkReg2Native() - converts a tkregister-compatible registration matrix
207 R to one that works with the geometry native to the two volumes. The
208 matrix R maps tkXYZ of the ref volume to tkXYZ of the mov volume. In
209 a typical application, ref is the anatomical volume and mov is the
210 functional volume. The purpose of this function is to be able to use
211 registration matrices computed by (or compatible with) tkregister
212 without losing the geometries native to the volumes. If R is null,
213 it is assumed to be the identity. R: MovXYZ = R*RefXYZ. Typically,
214 Ref is the Anatomical Reference, and Mov is the functional.
215
216 See also: MRItkRegMtx, MRIxfmCRS2XYZtkreg, MRIxfmCRS2XYZ
217 -------------------------------------------------------------------*/
218 MATRIX *MRItkReg2Native(MRI *ref, MRI *mov, MATRIX *R)
219 {
220 MATRIX *Kref, *Kmov;
221 MATRIX *Tref, *Tmov, *D;
222 MATRIX *invKmov, *invTref;
223
224 Tref = MRIxfmCRS2XYZ(ref,0);
225 Tmov = MRIxfmCRS2XYZ(mov,0);
226
227 Kref = MRIxfmCRS2XYZtkreg(ref);
228 Kmov = MRIxfmCRS2XYZtkreg(mov);
229
230 /* D = Tmov * inv(Kmov) * R * Kref *inv(Tref) */
231 invKmov = MatrixInverse(Kmov,NULL);
232 invTref = MatrixInverse(Tref,NULL);
233
234 D = MatrixMultiply(Tmov,invKmov,NULL);
235 if(R!=NULL) MatrixMultiply(D,R,D);
236 MatrixMultiply(D,Kref,D);
237 MatrixMultiply(D,invTref,D);
238
239 if(0) {
240 printf("MRITkReg2Native -----------------------------\n");
241 printf("Tref ----------------\n");
242 MatrixPrint(stdout,Tref);
243 printf("Tmov ----------------\n");
244 MatrixPrint(stdout,Tmov);
245 printf("Kref ----------------\n");
246 MatrixPrint(stdout,Kref);
247 printf("Kmov ----------------\n");
248 MatrixPrint(stdout,Kmov);
249 printf("------------------------------------------\n");
250 }
251
252 MatrixFree(&Kref);
253 MatrixFree(&Tref);
254 MatrixFree(&Kmov);
255 MatrixFree(&Tmov);
256 MatrixFree(&invKmov);
257 MatrixFree(&invTref);
258
259 return(D);
260 }
261 /*----------------------------------------------------------------
262 MRItkRegMtx() - creates a tkregsiter-compatible matrix from the
263 matrix D that aligns the two volumes assuming the native geometry.
264 This is the counterpart to MRITkReg2Native(). If D is null, it is
265 assumed to be the identity. R: MovXYZ = R*RefXYZ. Typically,
266 Ref is the Anatomical Reference, and Mov is the functional.
267 Use this function with D=NULL when the two volumes have been
268 aligned with SPM.
269 ---------------------------------------------------------------*/
270 MATRIX *MRItkRegMtx(MRI *ref, MRI *mov, MATRIX *D)
271 {
272 MATRIX *Kref, *Kmov;
273 MATRIX *Tref, *Tmov, *R;
274 MATRIX *invTmov, *invKref;
275
276 /* Native Goemetry */
277 Tref = MRIxfmCRS2XYZ(ref,0);
278 Tmov = MRIxfmCRS2XYZ(mov,0);
279
280 /* TkReg Goemetry */
281 Kref = MRIxfmCRS2XYZtkreg(ref);
282 Kmov = MRIxfmCRS2XYZtkreg(mov);
283
284 invTmov = MatrixInverse(Tmov,NULL);
285 invKref = MatrixInverse(Kref,NULL);
286
287 /* R = Kmov * inv(Tmov) * D * Tref *inv(Kref) */
288 R = MatrixMultiply(Kmov,invTmov,NULL);
289 if(D != NULL) MatrixMultiply(R,D,R);
290 MatrixMultiply(R,Tref,R);
291 MatrixMultiply(R,invKref,R);
292
293 MatrixFree(&Kref);
294 MatrixFree(&Tref);
295 MatrixFree(&Kmov);
296 MatrixFree(&Tmov);
297 MatrixFree(&invTmov);
298 MatrixFree(&invKref);
299
300 return(R);
301 }
302 /*-------------------------------------------------------------
303 MRIfixTkReg() - this routine will adjust a matrix created by the
304 "old" tkregister program. The old program had a problem in the way
305 it chose the CRS of a voxel in the functional volume based on a
306 point in the anatomical volume. The functional CRS of a point in
307 anatomical space rarely (if ever) falls directly on a functional
308 voxel, so it's necessary to choose a functional voxel given that the
309 point falls between functional voxels (or it can be interpolated).
310 The old tkregister program did not interpolate, rather it would
311 choose the CRS in the following way: iC = floor(fC), iR = ceil(fR),
312 and iS = floor(fS), where iC is the integer column number and fC is
313 the floating point column, etc. Unfortunately, this is not nearest
314 neighbor and it's not invertible. The right way to do it is to do
315 nearest neighbor (ie, round to the closest integer). Unfortunately,
316 there are a lot of data sets out there that have been regsitered
317 with the old program, and we don't want to force poeple to
318 reregister with the "new" program. This routine attempts to adjust
319 the matrix created with the old program so that it will work with
320 code that assumes that pure nearest neighbor was used.
321
322 It does this by randomly sampling the anatomical volume in xyz
323 and computing the tkreg'ed CRS for each point.
324
325 Pcrs = inv(Tmov)*R*Pxyz
326 PcrsTkReg = fcf(Pcrs) -- fcf is floor ceiling floor
327
328 We seek a new R (Rfix) define with
329
330 PcrsFix = inv(Tmov)*Rfix*Pxyz
331
332 such that that the difference between PcrsFix and PcrsTkReg are
333 minimized. To do this, we set
334
335 PcrsFix = PcrsTkReg = inv(Tmov)*Rfix*Pxyz
336
337 and solve for Rfix (this is an LMS solution):
338
339 Rfix = Tmov*(PcrsTkReg*Pxyz')*inv(Pxyz*Pxyz');
340
341 Applications that read in the registration matrix should detect the
342 truncation method used (see below), fix the matrix if necessary, and
343 proceed as if nearest neighbor/rounding was used. The type of
344 truncation can be determined from the last line of the registration
345 file (after the matrix itself). If there is nothing there or the
346 string "tkregister" is there, then the matrix should be
347 converted. Otherwise, the string "round" should be there. The
348 function regio_read_register (from registerio.c) will return the
349 type of matrix in the float2int variable. It will be either
350 FLT2INT_TKREG or FLT2INT_ROUND (constants defined in resample.h).
351 ---------------------------------------------------------------*/
352 MATRIX *MRIfixTkReg(MRI *mov, MATRIX *R)
353 {
354 int n, ntest = 1000;
355 MATRIX *Pxyz, *Pcrs, *PcrsTkReg;
356 MATRIX *PxyzT, *PxyzPxyzT, *invPxyzPxyzT;
357 MATRIX *Tmov,*invTmov,*Rfix;
358 MATRIX *tmp;
359 float xrange, yrange, zrange;
360
361 /* Assume a COR reference image */
362 xrange = 256.0;
363 yrange = 256.0;
364 zrange = 256.0;
365
366 Tmov = MRIxfmCRS2XYZtkreg(mov);
367 invTmov = MatrixInverse(Tmov,NULL);
368
369 Pxyz = MatrixAlloc(4,ntest,MATRIX_REAL);
370 PcrsTkReg = MatrixAlloc(4,ntest,MATRIX_REAL);
371
372 /* Fill xyz with rand within the reference volume range */
373 for(n=0;n<ntest;n++) {
374 Pxyz->rptr[1][n+1] = xrange * (drand48()-0.5);
375 Pxyz->rptr[2][n+1] = yrange * (drand48()-0.5);
376 Pxyz->rptr[3][n+1] = zrange * (drand48()-0.5);
377 Pxyz->rptr[4][n+1] = 1;
378 }
379
380 /* Compute floating mov CRS from targ XYZ */
381 /* Pcrs = inv(Tmov)*R*Pxyz */
382 tmp = MatrixMultiply(R,Pxyz,NULL);
383 Pcrs = MatrixMultiply(invTmov,tmp,NULL);
384 MatrixFree(&tmp);
385
386 /* Truncate floating mov CRS using tkregister method*/
387 for(n=0;n<ntest;n++) {
388 PcrsTkReg->rptr[1][n+1] = floor(Pcrs->rptr[1][n+1]);
389 PcrsTkReg->rptr[2][n+1] = ceil(Pcrs->rptr[2][n+1]);
390 PcrsTkReg->rptr[3][n+1] = floor(Pcrs->rptr[3][n+1]);
391 PcrsTkReg->rptr[4][n+1] = 1;
392 }
393 MatrixFree(&Pcrs);
394
395 //Rfix = Tmov*(PcrsTkreg*Pxyz')*inv(Pxyz*Pxyz');
396 PxyzT = MatrixTranspose(Pxyz,NULL);
397 PxyzPxyzT = MatrixMultiply(Pxyz,PxyzT,NULL);
398 invPxyzPxyzT = MatrixInverse(PxyzPxyzT,NULL);
399 tmp = MatrixMultiply(PcrsTkReg,PxyzT,NULL);
400 MatrixMultiply(Tmov,tmp,tmp);
401 Rfix = MatrixMultiply(tmp,invPxyzPxyzT,NULL);
402
403
404 MatrixFree(&Pxyz);
405 MatrixFree(&PcrsTkReg);
406 MatrixFree(&PxyzT);
407 MatrixFree(&PxyzPxyzT);
408 MatrixFree(&invPxyzPxyzT);
409 MatrixFree(&Tmov);
410 MatrixFree(&invTmov);
411 MatrixFree(&tmp);
412
413 return(Rfix);
414 }
415
416 /*-------------------------------------------------------------------
417 MRIfsl2TkReg() - converts an FSL registration matrix to one
418 compatible with tkregister. Note: the FSL matrix is assumed to map
419 from the mov to the ref whereas the tkreg matrix maps from the ref
420 to the mov.
421
422 mov voxel --(Tmov)--> tkRegXYZ(mov)
423 ^ ^
424 | inv(Dmov) |
425 | |
426 mov' physvox |
427 ^ |
428 | inv(Mfsl) | R
429 | |
430 ref' physvox |
431 ^ |
432 | Dref |
433 | |
434 ref voxel <--inv(Tref)--tkRegXYZ(ref)
435 -------------------------------------------------------------------*/
436 MATRIX *MRIfsl2TkReg(MRI *ref, MRI *mov, MATRIX *FSLRegMat)
437 {
438 MATRIX *RegMat=NULL, *invDmov, *Tmov, *Dref;
439 MATRIX *invFSLRegMat, *invTref, *Tref;
440
441 /* R = Tmov * inv(Dmov) * inv(Mfsl) * Dref * inv(Tref) */
442 invDmov = MatrixAlloc(4,4,MATRIX_REAL);
443 invDmov->rptr[1][1] = 1.0/mov->xsize;
444 invDmov->rptr[2][2] = 1.0/mov->ysize;
445 invDmov->rptr[3][3] = 1.0/mov->zsize;
446 invDmov->rptr[4][4] = 1.0;
447
448 Dref = MatrixAlloc(4,4,MATRIX_REAL);
449 Dref->rptr[1][1] = ref->xsize;
450 Dref->rptr[2][2] = ref->ysize;
451 Dref->rptr[3][3] = ref->zsize;
452 Dref->rptr[4][4] = 1.0;
453
454 Tmov = MRIxfmCRS2XYZtkreg(mov);
455 Tref = MRIxfmCRS2XYZtkreg(ref);
456 invTref = MatrixInverse(Tref,NULL);
457
458 invFSLRegMat = MatrixInverse(FSLRegMat,NULL);
459
460 RegMat = MatrixMultiply(Tmov,invDmov,RegMat);
461 RegMat = MatrixMultiply(RegMat,invFSLRegMat,RegMat);
462 RegMat = MatrixMultiply(RegMat,Dref,RegMat);
463 RegMat = MatrixMultiply(RegMat,invTref,RegMat);
464
465 MatrixFree(&invDmov);
466 MatrixFree(&FSLRegMat);
467 MatrixFree(&invFSLRegMat);
468 MatrixFree(&Tmov);
469 MatrixFree(&Tref);
470 MatrixFree(&invTref);
471 MatrixFree(&Dref);
472
473 return(RegMat);
474 }
475 /*-------------------------------------------------------------------
476 MRItkreg2FSL() - converts tkregister registration matrix to one
477 compatible with FSL. Note: the FSL matrix is assumed to map from the
478 mov to the ref whereas the tkreg matrix maps from the ref to the
479 mov.
480
481 mov voxel<--inv(Tmov)-- tkRegXYZ(mov)
482 | ^
483 | Dmov |
484 V |
485 mov' physvox |
486 | |
487 | Mfsl | R
488 V |
489 ref' physvox |
490 | |
491 | inv(Dref) |
492 V |
493 ref voxel -- Tref --> tkRegXYZ(ref)
494
495 -------------------------------------------------------------------*/
496 MATRIX *MRItkreg2FSL(MRI *ref, MRI *mov, MATRIX *tkRegMat)
497 {
498 MATRIX *FSLRegMat=NULL, *Dmov, *Tmov, *invTmov, *Tref, *Dref, *invDref;
499
500 /* R = Tmov * inv(Dmov) * inv(Mfsl) * Dref * inv(Tref) */
501 /* Mfsl = inv( Dmov * inv(Tmov) * R * Tref * inv(Dref)) */
502 Dmov = MatrixAlloc(4,4,MATRIX_REAL);
503 Dmov->rptr[1][1] = mov->xsize;
504 Dmov->rptr[2][2] = mov->ysize;
505 Dmov->rptr[3][3] = mov->zsize;
506 Dmov->rptr[4][4] = 1.0;
507
508 Dref = MatrixAlloc(4,4,MATRIX_REAL);
509 Dref->rptr[1][1] = ref->xsize;
510 Dref->rptr[2][2] = ref->ysize;
511 Dref->rptr[3][3] = ref->zsize;
512 Dref->rptr[4][4] = 1.0;
513 invDref = MatrixInverse(Dref,NULL);
514
515 Tmov = MRIxfmCRS2XYZtkreg(mov);
516 invTmov = MatrixInverse(Tmov,NULL);
517 Tref = MRIxfmCRS2XYZtkreg(ref);
518
519 FSLRegMat = MatrixMultiply(Dmov,invTmov,FSLRegMat);
520 FSLRegMat = MatrixMultiply(FSLRegMat,tkRegMat,FSLRegMat);
521 FSLRegMat = MatrixMultiply(FSLRegMat,Tref,FSLRegMat);
522 FSLRegMat = MatrixMultiply(FSLRegMat,invDref,FSLRegMat);
523 FSLRegMat = MatrixInverse(FSLRegMat,FSLRegMat);
524
525 if(0){
526 printf("--- Dmov ---------------------\n");
527 MatrixPrint(stdout,Dmov);
528 printf("--- Tmov ---------------------\n");
529 MatrixPrint(stdout,Tmov);
530 printf("--- R ---------------------\n");
531 MatrixPrint(stdout,tkRegMat);
532 printf("--- Tref ---------------------\n");
533 MatrixPrint(stdout,Tref);
534 printf("--- Dref ---------------------\n");
535 MatrixPrint(stdout,Dref);
536 printf("--- Rfsl ---------------------\n");
537 MatrixPrint(stdout,FSLRegMat);
538 printf("--- R (from Rfsl) ------------\n");
539 tkRegMat = MRIfsl2TkReg(ref,mov,FSLRegMat);
540 MatrixPrint(stdout,tkRegMat);
541 }
542
543 MatrixFree(&Dmov);
544 MatrixFree(&Tmov);
545 MatrixFree(&invTmov);
546 MatrixFree(&Tref);
547 MatrixFree(&Dref);
548 MatrixFree(&invDref);
549
550 return(FSLRegMat);
551 }
552
553 /*--------------------------------------------------------------------------
554 MtxCRS1toCRS0() - generates a matrix that will convert 1-based CRS (as
555 found in SPM matrices) to 0-based CRS, ie, CRS0 = Q*CRS1 (assuming that
556 CRS1 has been packed with a 1 in the 4th component.
557 --------------------------------------------------------------------------*/
558 MATRIX *MtxCRS1toCRS0(MATRIX *Q)
559 {
560 int r,c;
561
562 if(Q == NULL) Q = MatrixAlloc(4,4,MATRIX_REAL);
563 else{
564 if(Q->rows != 4 || Q->cols != 4){
565 printf("ERROR: MtxCRS1toCRS0(): input matrix is not 4x4\n");
566 return(NULL);
567 }
568 }
569
570 for(r=1;r<=4;r++){
571 for(c=1;c<=4;c++){
572 if(r==c || c==4) Q->rptr[r][c] = 1.0;
573 else Q->rptr[r][c] = 0.0;
574 }
575 }
576
577 return(Q);
578 }
579
580
581 /*-------------------------------------------------------------------
582 MRIgetVoxVal() - returns voxel value as a float regardless of
583 the underlying data type.
584 -------------------------------------------------------------------*/
585 float MRIgetVoxVal(MRI *mri, int c, int r, int s, int f)
586 {
587 switch(mri->type){
588 case MRI_UCHAR: return( (float) MRIseq_vox(mri,c,r,s,f)); break;
589 case MRI_SHORT: return( (float) MRISseq_vox(mri,c,r,s,f)); break;
590 case MRI_INT: return( (float) MRIIseq_vox(mri,c,r,s,f)); break;
591 case MRI_LONG: return( (float) MRILseq_vox(mri,c,r,s,f)); break;
592 case MRI_FLOAT: return( (float) MRIFseq_vox(mri,c,r,s,f)); break;
593 }
594 return(-10000000000.9);
595 }
596 /*-------------------------------------------------------------------
597 MRIsetVoxVal() - sets voxel value to that passed as the float
598 voxval, regardless of the underlying data type. If the underlying
599 type is integer-based, then it is rounded to the nearest integer. No
600 attempt is made to prevent overflows.
601 -------------------------------------------------------------------*/
602 int MRIsetVoxVal(MRI *mri, int c, int r, int s, int f, float voxval)
603 {
604 switch(mri->type){
605 case MRI_UCHAR: MRIseq_vox(mri,c,r,s,f) = nint(voxval); break;
606 case MRI_SHORT: MRISseq_vox(mri,c,r,s,f) = nint(voxval); break;
607 case MRI_INT: MRIIseq_vox(mri,c,r,s,f) = nint(voxval); break;
608 case MRI_LONG: MRILseq_vox(mri,c,r,s,f) = nint(voxval); break;
609 case MRI_FLOAT: MRIFseq_vox(mri,c,r,s,f) = voxval; break;
610 default: return(1); break;
611 }
612 return(0);
613 }
614
615 /*------------------------------------------------------------------
616 MRIinterpCode() - returns the numeric interpolation code given the
617 name of the interpolation method.
618 -----------------------------------------------------------------*/
619 int MRIinterpCode(char *InterpString)
620 {
621 if(!strncasecmp(InterpString,"nearest",3))
622 return(SAMPLE_NEAREST);
623 if(!strncasecmp(InterpString,"trilinear",3))
624 return(SAMPLE_TRILINEAR);
625 if(!strncasecmp(InterpString,"sinc",3))
626 return(SAMPLE_SINC);
627 if(!strncasecmp(InterpString,"cubic",3))
628 return(SAMPLE_CUBIC);
629
630 return(-1);
631 }
632
633 /*------------------------------------------------------------------
634 MRIinterpString() - returns the the name of the interpolation method
635 given numeric interpolation code
636 -----------------------------------------------------------------*/
637 char * MRIinterpString(int InterpCode)
638 {
639 switch (InterpCode)
640 {
641 case SAMPLE_NEAREST: return("nearest"); break ;
642 case SAMPLE_TRILINEAR: return("trilinear"); break ;
643 case SAMPLE_SINC: return("sinc"); break ;
644 case SAMPLE_CUBIC: return("cubic"); break ;
645 }
646 return(NULL);
647 }
648 /*------------------------------------------------------------------
649 MRIprecisionCode() - returns the numeric code given the
650 name of the precision. This corresponds to the value of the type
651 field in the MRI structure.
652 -----------------------------------------------------------------*/
653 int MRIprecisionCode(char *PrecisionString)
654 {
655 if(!strcasecmp(PrecisionString,"uchar"))
656 return(MRI_UCHAR);
657 if(!strcasecmp(PrecisionString,"short"))
658 return(MRI_SHORT);
659 if(!strcasecmp(PrecisionString,"int"))
660 return(MRI_INT);
661 if(!strcasecmp(PrecisionString,"long"))
662 return(MRI_LONG);
663 if(!strcasecmp(PrecisionString,"float"))
664 return(MRI_FLOAT);
665
666 return(-1);
667 }
668
669 /*------------------------------------------------------------------
670 MRIprecisionString() - returns the the name of the precision given
671 numeric precision code. The code corresponds to the value of the
672 type field in the MRI structure.
673 -----------------------------------------------------------------*/
674 char * MRIprecisionString(int PrecisionCode)
675 {
676 switch (PrecisionCode)
677 {
678 case MRI_UCHAR: return("uchar"); break ;
679 case MRI_SHORT: return("short"); break ;
680 case MRI_INT: return("int"); break ;
681 case MRI_LONG: return("long"); break ;
682 case MRI_FLOAT: return("float"); break ;
683 }
684 return(NULL);
685 }
686
687 /*-----------------------------------------------------
688 ------------------------------------------------------*/
689 int
690 MRImatch(MRI *mri1, MRI *mri2)
691 {
692 return(
693 (mri1->width == mri2->width) &&
694 (mri1->height == mri2->height) &&
695 (mri1->depth == mri2->depth) &&
696 (mri1->type == mri2->type)
697 ) ;
698 }
699 /*-----------------------------------------------------
700 ------------------------------------------------------*/
701 MRI *
702 MRIscalarMul(MRI *mri_src, MRI *mri_dst, float scalar)
703 {
704 int width, height, depth, x, y, z, frame ;
705 BUFTYPE *psrc, *pdst ;
706 float *pfsrc, *pfdst, dval ;
707 short *pssrc, *psdst ;
708
709 width = mri_src->width ;
710 height = mri_src->height ;
711 depth = mri_src->depth ;
712 if (!mri_dst)
713 mri_dst = MRIclone(mri_src, NULL) ;
714
715 for (frame = 0 ; frame < mri_src->nframes ; frame++)
716 {
717 for (z = 0 ; z < depth ; z++)
718 {
719 for (y = 0 ; y < height ; y++)
720 {
721 switch (mri_src->type)
722 {
723 case MRI_UCHAR:
724 psrc = &MRIseq_vox(mri_src, 0, y, z, frame) ;
725 pdst = &MRIseq_vox(mri_dst, 0, y, z, frame) ;
726 for (x = 0 ; x < width ; x++)
727 {
728 dval = *psrc++ * scalar ;
729 if (dval < 0)
730 dval = 0 ;
731 if (dval > 255)
732 dval = 255 ;
733 *pdst++ = dval ;
734 }
735 break ;
736 case MRI_FLOAT:
737 pfsrc = &MRIFseq_vox(mri_src, 0, y, z, frame) ;
738 pfdst = &MRIFseq_vox(mri_dst, 0, y, z, frame) ;
739 for (x = 0 ; x < width ; x++)
740 *pfdst++ = *pfsrc++ * scalar ;
741 break ;
742 case MRI_SHORT:
743 pssrc = &MRISseq_vox(mri_src, 0, y, z, frame) ;
744 psdst = &MRISseq_vox(mri_dst, 0, y, z, frame) ;
745 for (x = 0 ; x < width ; x++)
746 *psdst++ = (short)nint((float)*pssrc++ * scalar) ;
747 break ;
748 default:
749 ErrorReturn
750 (NULL,
751 (ERROR_UNSUPPORTED,
752 "MRIscalarMul: unsupported type %d", mri_src->type)) ;
753 }
754 }
755 }
756 }
757 return(mri_dst) ;
758 }
759 /*-----------------------------------------------------
760 ------------------------------------------------------*/
761 MRI *
762 MRIscalarMulFrame(MRI *mri_src, MRI *mri_dst, float scalar, int frame)
763 {
764 int width, height, depth, x, y, z ;
765 BUFTYPE *psrc, *pdst ;
766 float *pfsrc, *pfdst, dval ;
767 short *pssrc, *psdst ;
768
769 width = mri_src->width ;
770 height = mri_src->height ;
771 depth = mri_src->depth ;
772 if (!mri_dst)
773 mri_dst = MRIclone(mri_src, NULL) ;
774
775 for (z = 0 ; z < depth ; z++)
776 {
777 for (y = 0 ; y < height ; y++)
778 {
779 switch (mri_src->type)
780 {
781 case MRI_UCHAR:
782 psrc = &MRIseq_vox(mri_src, 0, y, z, frame) ;
783 pdst = &MRIseq_vox(mri_dst, 0, y, z, frame) ;
784 for (x = 0 ; x < width ; x++)
785 {
786 dval = *psrc++ * scalar ;
787 if (dval < 0)
788 dval = 0 ;
789 if (dval > 255)
790 dval = 255 ;
791 *pdst++ = dval ;
792 }
793 break ;
794 case MRI_FLOAT:
795 pfsrc = &MRIFseq_vox(mri_src, 0, y, z, frame) ;
796 pfdst = &MRIFseq_vox(mri_dst, 0, y, z, frame) ;
797 for (x = 0 ; x < width ; x++)
798 *pfdst++ = *pfsrc++ * scalar ;
799 break ;
800 case MRI_SHORT:
801 pssrc = &MRISseq_vox(mri_src, 0, y, z, frame) ;
802 psdst = &MRISseq_vox(mri_dst, 0, y, z, frame) ;
803 for (x = 0 ; x < width ; x++)
804 *psdst++ = (short)nint((float)*pssrc++ * scalar) ;
805 break ;
806 default:
807 ErrorReturn
808 (NULL,
809 (ERROR_UNSUPPORTED,
810 "MRIscalarMulFrame: unsupported type %d", mri_src->type)) ;
811 }
812 }
813 }
814 return(mri_dst) ;
815 }
816 /*-----------------------------------------------------
817 ------------------------------------------------------*/
818 int
819 MRIvalRange(MRI *mri, float *pmin, float *pmax)
820 {
821 int width, height, depth, x, y, z, frame ;
822 float fmin, fmax, *pf, val ;
823 BUFTYPE *pb ;
824
825 width = mri->width ;
826 height = mri->height ;
827 depth = mri->depth ;
828
829 fmin = 10000.0f ;
830 fmax = -10000.0f ;
831 switch (mri->type)
832 {
833 case MRI_FLOAT:
834 for (frame = 0 ; frame < mri->nframes ; frame++)
835 {
836 for (z = 0 ; z < depth ; z++)
837 {
838 for (y = 0 ; y < height ; y++)
839 {
840 pf = &MRIFseq_vox(mri, 0, y, z, frame) ;
841 for (x = 0 ; x < width ; x++)
842 {
843 val = *pf++ ;
844 if (val < fmin)
845 fmin = val ;
846 if (val > fmax)
847 fmax = val ;
848 }
849 }
850 }
851 }
852 break ;
853 case MRI_INT:
854 for (frame = 0 ; frame < mri->nframes ; frame++)
855 {
856 for (z = 0 ; z < depth ; z++)
857 {
858 for (y = 0 ; y < height ; y++)
859 {
860 for (x = 0 ; x < width ; x++)
861 {
862 val = (float)MRIIseq_vox(mri, x, y, z, frame) ;
863 if (val < fmin)
864 fmin = val ;
865 if (val > fmax)
866 fmax = val ;
867 }
868 }
869 }
870 }
871 break ;
872 case MRI_SHORT:
873 for (frame = 0 ; frame < mri->nframes ; frame++)
874 {
875 for (z = 0 ; z < depth ; z++)
876 {
877 for (y = 0 ; y < height ; y++)
878 {
879 for (x = 0 ; x < width ; x++)
880 {
881 val = (float)MRISseq_vox(mri, x, y, z, frame) ;
882 if (val < fmin)
883 fmin = val ;
884 if (val > fmax)
885 fmax = val ;
886 }
887 }
888 }
889 }
890 break ;
891 case MRI_UCHAR:
892 for (frame = 0 ; frame < mri->nframes ; frame++)
893 {
894 for (z = 0 ; z < depth ; z++)
895 {
896 for (y = 0 ; y < height ; y++)
897 {
898 pb = &MRIseq_vox(mri, 0, y, z, frame) ;
899 for (x = 0 ; x < width ; x++)
900 {
901 val = (float)*pb++ ;
902 if (val < fmin)
903 fmin = val ;
904 if (val > fmax)
905 fmax = val ;
906 }
907 }
908 }
909 }
910 break ;
911 default:
912 for (frame = 0 ; frame < mri->nframes ; frame++)
913 {
914 for (z = 0 ; z < depth ; z++)
915 {
916 for (y = 0 ; y < height ; y++)
917 {
918 for (x = 0 ; x < width ; x++)
919 {
920 val = (float)MRIgetVoxVal(mri, x, y, z, frame) ;
921 if (val < fmin)
922 fmin = val ;
923 if (val > fmax)
924 fmax = val ;
925 }
926 }
927 }
928 }
929 break ;
930 }
931
932 *pmin = fmin ;
933 *pmax = fmax ;
934 return(NO_ERROR) ;
935 }
936 int
937 MRInonzeroValRange(MRI *mri, float *pmin, float *pmax)
938 {
939 int width, height, depth, x, y, z, frame ;
940 float fmin, fmax, val ;
941
942 width = mri->width ;
943 height = mri->height ;
944 depth = mri->depth ;
945
946 fmin = 10000.0f ;
947 fmax = -10000.0f ;
948 for (frame = 0 ; frame < mri->nframes ; frame++)
949 {
950 for (z = 0 ; z < depth ; z++)
951 {
952 for (y = 0 ; y < height ; y++)
953 {
954 for (x = 0 ; x < width ; x++)
955 {
956 val = MRIgetVoxVal(mri, x, y, z, 0) ;
957 if (FZERO(val))
958 continue ;
959 if (val < fmin)
960 fmin = val ;
961 if (val > fmax)
962 fmax = val ;
963 }
964 }
965 }
966 }
967
968 *pmin = fmin ;
969 *pmax = fmax ;
970 return(NO_ERROR) ;
971 }
972 /*-----------------------------------------------------
973 ------------------------------------------------------*/
974 int
975 MRIvalRangeFrame(MRI *mri, float *pmin, float *pmax, int frame)
976 {
977 int width, height, depth, x, y, z ;
978 float fmin, fmax, *pf, val ;
979 BUFTYPE *pb ;
980
981 width = mri->width ;
982 height = mri->height ;
983 depth = mri->depth ;
984
985 fmin = 10000.0f ;
986 fmax = -10000.0f ;
987 switch (mri->type)
988 {
989 case MRI_FLOAT:
990 for (z = 0 ; z < depth ; z++)
991 {
992 for (y = 0 ; y < height ; y++)
993 {
994 pf = &MRIFseq_vox(mri, 0, y, z, frame) ;
995 for (x = 0 ; x < width ; x++)
996 {
997 val = *pf++ ;
998 if (val < fmin)
999 fmin = val ;
1000 if (val > fmax)
1001 fmax = val ;
1002 }
1003 }
1004 }
1005 break ;
1006 case MRI_INT:
1007 for (z = 0 ; z < depth ; z++)
1008 {
1009 for (y = 0 ; y < height ; y++)
1010 {
1011 for (x = 0 ; x < width ; x++)
1012 {
1013 val = (float)MRIIseq_vox(mri, x, y, z, frame) ;
1014 if (val < fmin)
1015 fmin = val ;
1016 if (val > fmax)
1017 fmax = val ;
1018 }
1019 }
1020 }
1021 break ;
1022 case MRI_SHORT:
1023 for (z = 0 ; z < depth ; z++)
1024 {
1025 for (y = 0 ; y < height ; y++)
1026 {
1027 for (x = 0 ; x < width ; x++)
1028 {
1029 val = (float)MRISseq_vox(mri, x, y, z, frame) ;
1030 if (val < fmin)
1031 fmin = val ;
1032 if (val > fmax)
1033 fmax = val ;
1034 }
1035 }
1036 }
1037 break ;
1038 case MRI_UCHAR:
1039 for (z = 0 ; z < depth ; z++)
1040 {
1041 for (y = 0 ; y < height ; y++)
1042 {
1043 pb = &MRIseq_vox(mri, 0, y, z, frame) ;
1044 for (x = 0 ; x < width ; x++)
1045 {
1046 val = (float)*pb++ ;
1047 if (val < fmin)
1048 fmin = val ;
1049 if (val > fmax)
1050 fmax = val ;
1051 }
1052 }
1053 }
1054 break ;
1055 default:
1056 ErrorReturn(ERROR_UNSUPPORTED,
1057 (ERROR_UNSUPPORTED, "MRIvalRange: unsupported type %d",
1058 mri->type)) ;
1059 }
1060
1061 *pmin = fmin ;
1062 *pmax = fmax ;
1063 return(NO_ERROR) ;
1064 }
1065 /*-----------------------------------------------------
1066 ------------------------------------------------------*/
1067 int
1068 MRIvalRangeRegion(MRI *mri, float *pmin, float *pmax, MRI_REGION *region)
1069 {
1070 int width, height, depth, x, y, z, x0, y0, z0 ;
1071 float fmin, fmax, *pf, val ;
1072 BUFTYPE *pb ;
1073
1074 width = region->x + region->dx ;
1075 if (width > mri->width)
1076 width = mri->width ;
1077 height = region->y + region->dy ;
1078 if (height > mri->height)
1079 height = mri->height ;
1080 depth = region->z + region->dz ;
1081 if (depth > mri->depth)
1082 depth = mri->depth ;
1083 x0 = region->x ;
1084 if (x0 < 0)
1085 x0 = 0 ;
1086 y0 = region->y ;
1087 if (y0 < 0)
1088 y0 = 0 ;
1089 z0 = region->z ;
1090 if (z0 < 0)
1091 z0 = 0 ;
1092
1093 fmin = 10000.0f ;
1094 fmax = -10000.0f ;
1095 switch (mri->type)
1096 {
1097 default:
1098 for (z = z0 ; z < depth ; z++)
1099 {
1100 for (y = y0 ; y < height ; y++)
1101 {
1102 pf = &MRIFvox(mri, x0, y, z) ;
1103 for (x = x0 ; x < width ; x++)
1104 {
1105 val = MRIgetVoxVal(mri, x, y, z, 0) ;
1106 if (val < fmin)
1107 fmin = val ;
1108 if (val > fmax)
1109 fmax = val ;
1110 }
1111 }
1112 }
1113 break ;
1114
1115 case MRI_FLOAT:
1116 for (z = z0 ; z < depth ; z++)
1117 {
1118 for (y = y0 ; y < height ; y++)
1119 {
1120 pf = &MRIFvox(mri, x0, y, z) ;
1121 for (x = x0 ; x < width ; x++)
1122 {
1123 val = *pf++ ;
1124 if (val < fmin)
1125 fmin = val ;
1126 if (val > fmax)
1127 fmax = val ;
1128 }
1129 }
1130 }
1131 break ;
1132 case MRI_UCHAR:
1133 for (z = z0 ; z < depth ; z++)
1134 {
1135 for (y = y0 ; y < height ; y++)
1136 {
1137 pb = &MRIvox(mri, x0, y, z) ;
1138 for (x = x0 ; x < width ; x++)
1139 {
1140 val = (float)*pb++ ;
1141 if (val < fmin)
1142 fmin = val ;
1143 if (val > fmax)
1144 fmax = val ;
1145 }
1146 }
1147 }
1148 break ;
1149 }
1150
1151 *pmin = fmin ;
1152 *pmax = fmax ;
1153 return(NO_ERROR) ;
1154 }
1155 /*-----------------------------------------------------
1156 ------------------------------------------------------*/
1157 MRI_REGION *
1158 MRIclipRegion(MRI *mri, MRI_REGION *reg_src, MRI_REGION *reg_clip)
1159 {
1160 int x2, y2, z2 ;
1161
1162 x2 = MIN(mri->width-1, reg_src->x + reg_src->dx - 1) ;
1163 y2 = MIN(mri->height-1, reg_src->y + reg_src->dy - 1) ;
1164 z2 = MIN(mri->depth-1, reg_src->z + reg_src->dz - 1) ;
1165 reg_clip->x = MAX(0, reg_src->x) ;
1166 reg_clip->y = MAX(0, reg_src->y) ;
1167 reg_clip->z = MAX(0, reg_src->z) ;
1168 reg_clip->dx = x2 - reg_clip->x + 1 ;
1169 reg_clip->dy = y2 - reg_clip->y + 1 ;
1170 reg_clip->dz = z2 - reg_clip->z + 1 ;
1171 return(reg_clip) ;
1172 }
1173 /*-----------------------------------------------------
1174 ------------------------------------------------------*/
1175 MRI *
1176 MRIvalScale(MRI *mri_src, MRI *mri_dst, float flo, float fhi)
1177 {
1178 int width, height, depth, x, y, z ;
1179 float fmin, fmax, *pf_src, *pf_dst, val, scale ;
1180 short *ps_src, *ps_dst ;
1181 BUFTYPE *pb_src, *pb_dst ;
1182
1183 if (!mri_dst)
1184 mri_dst = MRIclone(mri_src, NULL) ;
1185
1186 MRIvalRange(mri_src, &fmin, &fmax) ;
1187 scale = (fhi - flo) / (fmax - fmin) ;
1188
1189 width = mri_src->width ;
1190 height = mri_src->height ;
1191 depth = mri_src->depth ;
1192
1193 switch (mri_src->type)
1194 {
1195 case MRI_FLOAT:
1196 for (z = 0 ; z < depth ; z++)
1197 {
1198 for (y = 0 ; y < height ; y++)
1199 {
1200 pf_src = &MRIFvox(mri_src, 0, y, z) ;
1201 pf_dst = &MRIFvox(mri_dst, 0, y, z) ;
1202 for (x = 0 ; x < width ; x++)
1203 {
1204 val = *pf_src++ ;
1205 *pf_dst++ = (val - fmin) * scale + flo ;
1206 }
1207 }
1208 }
1209 break ;
1210 case MRI_SHORT:
1211 for (z = 0 ; z < depth ; z++)
1212 {
1213 for (y = 0 ; y < height ; y++)
1214 {
1215 ps_src = &MRISvox(mri_src, 0, y, z) ;
1216 ps_dst = &MRISvox(mri_dst, 0, y, z) ;
1217 for (x = 0 ; x < width ; x++)
1218 {
1219 val = (float)(*ps_src++) ;
1220 *ps_dst++ = (short)nint((val - fmin) * scale + flo) ;
1221 }
1222 }
1223 }
1224 break ;
1225 case MRI_UCHAR:
1226 for (z = 0 ; z < depth ; z++)
1227 {
1228 for (y = 0 ; y < height ; y++)
1229 {
1230 pb_src = &MRIvox(mri_src, 0, y, z) ;
1231 pb_dst = &MRIvox(mri_dst, 0, y, z) ;
1232 for (x = 0 ; x < width ; x++)
1233 {
1234 val = (float)*pb_src++ ;
1235 *pb_dst++ = (BUFTYPE)nint((val - fmin) * scale + flo) ;
1236 }
1237 }
1238 }
1239 break ;
1240 default:
1241 ErrorReturn(mri_dst,
1242 (ERROR_UNSUPPORTED, "MRIvalScale: unsupported type %d",
1243 mri_src->type)) ;
1244 }
1245
1246 return(mri_dst) ;
1247 }
1248 /*-----------------------------------------------------
1249 ------------------------------------------------------*/
1250 MRI *
1251 MRIconfThresh(MRI *mri_src, MRI *mri_probs, MRI *mri_classes, MRI *mri_dst,
1252 float thresh, int min_target, int max_target)
1253 {
1254 int x, y, z, width, height, depth, class ;
1255 float *pprobs, prob ;
1256 BUFTYPE *pclasses, *pdst, *psrc, src ;
1257
1258 if (!mri_dst)
1259 mri_dst = MRIclone(mri_classes, NULL) ;
1260
1261 width = mri_classes->width ;
1262 height = mri_classes->height ;
1263 depth = mri_classes->depth ;
1264
1265 for (z = 0 ; z < depth ; z++)
1266 {
1267 for (y = 0 ; y < height ; y++)
1268 {
1269 pprobs = &MRIFvox(mri_probs, 0, y, z) ;
1270 pclasses = &MRIvox(mri_classes, 0, y, z) ;
1271 pdst = &MRIvox(mri_dst, 0, y, z) ;
1272 psrc = &MRIvox(mri_src, 0, y, z) ;
1273 for (x = 0 ; x < width ; x++)
1274 {
1275 src = *psrc++ ;
1276 prob = *pprobs++ ;
1277 class = (int)*pclasses++ ;
1278 if (prob >= thresh &&
1279 ((class >= min_target) && (class <= max_target)))
1280 *pdst++ = src ;
1281 else if ((class >= min_target) && (class <= max_target))
1282 *pdst++ = 25 ;
1283 else
1284 *pdst++ = 0 ;
1285 }
1286 }
1287 }
1288 return(mri_dst) ;
1289 }
1290 /*-----------------------------------------------------
1291 ------------------------------------------------------*/
1292 int
1293 MRIboundingBoxNbhd(MRI *mri, int thresh, int wsize,MRI_REGION *box)
1294 {
1295 int width, height, depth, x, y, z, x1, y1, z1, xi, yi, zi, xk, yk, zk,
1296 whalf, in_brain ;
1297 BUFTYPE *psrc ;
1298 float *pfsrc ;
1299 short *pssrc ;
1300
1301 whalf = (wsize-1)/2 ;
1302 box->dx = width = mri->width ;
1303 box->dy = height = mri->height ;
1304 box->dz = depth = mri->depth ;
1305
1306 x1 = y1 = z1 = 0 ;
1307 box->x = width-1 ;
1308 box->y = height-1 ;
1309 box->z = depth-1 ;
1310 switch (mri->type)
1311 {
1312 case MRI_UCHAR:
1313 for (z = 0 ; z < depth ; z++)
1314 {
1315 for (y = 0 ; y < height ; y++)
1316 {
1317 psrc = &MRIvox(mri, 0, y, z) ;
1318 for (x = 0 ; x < width ; x++)
1319 {
1320 if (*psrc++ > thresh)
1321 {
1322 in_brain = 1 ;
1323 for (zk = -whalf ; in_brain && zk <= whalf ; zk++)
1324 {
1325 zi = mri->zi[z+zk] ;
1326 for (yk = -whalf ; in_brain && yk <= whalf ; yk++)
1327 {
1328 yi = mri->yi[y+yk] ;
1329 for (xk = -whalf ;
1330 in_brain && xk <= whalf ;
1331 xk++)
1332 {
1333 xi = mri->xi[x+xk] ;
1334 if (MRIvox(mri, xi, yi, zi) < thresh)
1335 in_brain = 0 ;
1336 }
1337 }
1338 }
1339 if (in_brain)
1340 {
1341 if (x < box->x)
1342 box->x = x ;
1343 if (y < box->y)
1344 box->y = y ;
1345 if (z < box->z)
1346 box->z = z ;
1347 if (x > x1)
1348 x1 = x ;
1349 if (y > y1)
1350 y1 = y ;
1351 if (z > z1)
1352 z1 = z ;
1353 }
1354 }
1355 }
1356 }
1357 }
1358 break ;
1359 case MRI_SHORT:
1360 for (z = 0 ; z < depth ; z++)
1361 {
1362 for (y = 0 ; y < height ; y++)
1363 {
1364 pssrc = &MRISvox(mri, 0, y, z) ;
1365 for (x = 0 ; x < width ; x++)
1366 {
1367 if (*pssrc++ > thresh)
1368 {
1369 in_brain = 1 ;
1370 for (zk = -whalf ; in_brain && zk <= whalf ; zk++)
1371 {
1372 zi = mri->zi[z+zk] ;
1373 for (yk = -whalf ; in_brain && yk <= whalf ; yk++)
1374 {
1375 yi = mri->yi[y+yk] ;
1376 for (xk = -whalf ;
1377 in_brain && xk <= whalf ;
1378 xk++)
1379 {
1380 xi = mri->xi[x+xk] ;
1381 if (MRISvox(mri, xi, yi, zi) < thresh)
1382 in_brain = 0 ;
1383 }
1384 }
1385 }
1386 if (in_brain)
1387 {
1388 if (x < box->x)
1389 box->x = x ;
1390 if (y < box->y)
1391 box->y = y ;
1392 if (z < box->z)
1393 box->z = z ;
1394 if (x > x1)
1395 x1 = x ;
1396 if (y > y1)
1397 y1 = y ;
1398 if (z > z1)
1399 z1 = z ;
1400 }
1401 }
1402 }
1403 }
1404 }
1405 break ;
1406 case MRI_FLOAT:
1407 for (z = 0 ; z < depth ; z++)
1408 {
1409 for (y = 0 ; y < height ; y++)
1410 {
1411 pfsrc = &MRIFvox(mri, 0, y, z) ;
1412 for (x = 0 ; x < width ; x++)
1413 {
1414 if (*pfsrc++ > thresh)
1415 {
1416 in_brain = 1 ;
1417 for (zk = -whalf ; in_brain && zk <= whalf ; zk++)
1418 {
1419 zi = mri->zi[z+zk] ;
1420 for (yk = -whalf ; in_brain && yk <= whalf ; yk++)
1421 {
1422 yi = mri->yi[y+yk] ;
1423 for (xk = -whalf ;
1424 in_brain && xk <= whalf ;
1425 xk++)
1426 {
1427 xi = mri->xi[x+xk] ;
1428 if (MRIFvox(mri, xi, yi, zi) < thresh)
1429 in_brain = 0 ;
1430 }
1431 }
1432 }
1433 if (in_brain)
1434 {
1435 if (x < box->x)
1436 box->x = x ;
1437 if (y < box->y)
1438 box->y = y ;
1439 if (z < box->z)
1440 box->z = z ;
1441 if (x > x1)
1442 x1 = x ;
1443 if (y > y1)
1444 y1 = y ;
1445 if (z > z1)
1446 z1 = z ;
1447 }
1448 }
1449 }
1450 }
1451 }
1452 break ;
1453 default:
1454 ErrorReturn(ERROR_UNSUPPORTED,
1455 (ERROR_UNSUPPORTED, "MRIboundingBoxNbd: unsupported type %d",
1456 mri->type)) ;
1457 break ;
1458 }
1459 box->x -= whalf+1 ; box->y -= whalf+1 ; box->z -= whalf+1 ;
1460 x1 += whalf+1 ; y1 += whalf+1 ; z1 += whalf+1 ;
1461 box->x = MAX(0,box->x) ; box->y = MAX(0,box->y) ; box->z = MAX(0,box->z) ;
1462 x1 = MIN(width-1,x1) ; y1 = MIN(height-1, y1) ; z1 = MIN(depth-1, z1) ;
1463 box->dx = x1 - box->x + 1 ;
1464 box->dy = y1 - box->y + 1 ;
1465 box->dz = z1 - box->z + 1 ;
1466 return(NO_ERROR) ;
1467 }
1468 /*-----------------------------------------------------
1469 ------------------------------------------------------*/
1470 #define MIN_DARK 10
1471
1472 int
1473 MRIfindApproximateSkullBoundingBox(MRI *mri, int thresh,MRI_REGION *box)
1474 {
1475 int width, height, depth, x, y, z, x1, y1, z1;
1476 int ndark, max_dark, start, nlight, max_light ;
1477 double means[3] ;
1478 Real val ;
1479
1480 width = mri->width ; height = mri->height ; depth = mri->depth ;
1481
1482 MRIcenterOfMass(mri, means, thresh) ;
1483
1484
1485 #define MAX_LIGHT 30 /* don't let there by 3 cm of
1486 bright stuff 'outside' of brain */
1487
1488 /* search for left edge */
1489 nlight = ndark = max_dark = 0 ;
1490 y = nint(means[1]) ; z = nint(means[2]) ;
1491 for (start = x1 = x = nint(means[0]) ; x >= 0 ; x--)
1492 {
1493 MRIsampleVolumeType(mri, x, y, z, &val, SAMPLE_NEAREST) ;
1494
1495 if (val < thresh)
1496 {
1497 if (!ndark)
1498 start = x ;
1499 ndark++ ;
1500 nlight = 0 ;
1501 }
1502 else
1503 {
1504 if (++nlight > MAX_LIGHT)
1505 max_dark = 0 ;
1506 if (ndark > max_dark)
1507 {
1508 max_dark = ndark ; x1 = start ;
1509 }
1510 ndark = 0 ;
1511 }
1512 }
1513 if (ndark > max_dark)
1514 {
1515 max_dark = ndark ;
1516 x1 = start ;
1517 }
1518 if (max_dark < MIN_DARK)
1519 x1 = 0 ;
1520 box->x = x1 ;
1521
1522 /* search for right edge */
1523 nlight = ndark = max_dark = 0 ;
1524 y = nint(means[1]) ; z = nint(means[2]) ;
1525 for (start = x1 = x = nint(means[0]) ; x < width ; x++)
1526 {
1527 MRIsampleVolumeType(mri, x, y, z, &val, SAMPLE_NEAREST) ;
1528 if (val < thresh)
1529 {
1530 if (!ndark)
1531 start = x ;
1532 ndark++ ;
1533 nlight = 0 ;
1534 }
1535 else
1536 {
1537 if (++nlight > MAX_LIGHT)
1538 max_dark = 0 ;
1539 if (ndark >= max_dark)
1540 {
1541 max_dark = ndark ; x1 = start ;
1542 }
1543 ndark = 0 ;
1544 }
1545 }
1546 if (ndark > max_dark)
1547 {
1548 max_dark = ndark ;
1549 x1 = start ;
1550 }
1551 if (max_dark < MIN_DARK)
1552 x1 = mri->width-1 ;
1553 box->dx = x1 - box->x + 1 ;
1554
1555 /* search for superior edge */
1556 nlight = ndark = max_dark = max_light = 0 ;
1557 x = MAX(0,nint(means[0])-20) ; // avoid inter-hemispheric fissure
1558 z = nint(means[2]) ;
1559 for (start = y1 = y = nint(means[1]) ; y >= 0 ; y--)
1560 {
1561 MRIsampleVolumeType(mri, x, y, z, &val, SAMPLE_NEAREST) ;
1562 if (val < thresh)
1563 {
1564 if (nlight > max_light)
1565 max_light = nlight ;
1566 if (!ndark)
1567 start = y ;
1568 ndark++ ;
1569 nlight = 0 ;
1570 }
1571 else
1572 {
1573 if (++nlight > MAX_LIGHT)
1574 max_dark = 0 ;
1575 if (ndark >= max_dark)
1576 {
1577 max_dark = ndark ; y1 = start ;
1578 max_light = 0 ; // max_light is max in a row light above dark
1579 }
1580 ndark = 0 ;
1581 }
1582 }
1583
1584 /* if we ended on a string of dark voxels, check two things:
1585 1. the string was longer than the previous longest
1586 2. the strong was longer than 1/2 the previous longest, and there
1587 was an intervening string of light voxels indicated it was still in
1588 brain.
1589 */
1590 if ((ndark > max_dark) || (y < 0 &&
1591 (ndark > max_dark/2) && max_light > MAX_LIGHT/2))
1592 {
1593 max_dark = ndark ;
1594 y1 = start ;
1595 }
1596 if (max_dark < MIN_DARK)
1597 y1 = 0 ;
1598 box->y = y1 ;
1599
1600 /* search for inferior edge */
1601 nlight = ndark = max_dark = 0 ;
1602 x = nint(means[0]) ; z = nint(means[2]) ;
1603 for (start = y = y1 = nint(means[1]) ; y < height ; y++)
1604 {
1605 MRIsampleVolumeType(mri, x, y, z, &val, SAMPLE_NEAREST) ;
1606 if (val < thresh)
1607 {
1608 if (!ndark)
1609 start = y ;
1610 ndark++ ;
1611 nlight = 0 ;
1612 }
1613 else
1614 {
1615 if (++nlight > MAX_LIGHT)
1616 max_dark = 0 ;
1617 if (ndark >= max_dark)
1618 {
1619 max_dark = ndark ; y1 = start ;
1620 }
1621 ndark = 0 ;
1622 }
1623 }
1624 if (ndark > max_dark)
1625 {
1626 max_dark = ndark ;
1627 y1 = start ;
1628 }
1629 if (max_dark < MIN_DARK)
1630 y1 = mri->height-1 ;
1631 box->dy = y1 - box->y + 1 ;
1632
1633 /* search for posterior edge */
1634 nlight = ndark = max_dark = 0 ;
1635 x = nint(means[0]) ; y = nint(means[1]) ;
1636 for (z1 = start = z = nint(means[2]) ; z >= 0 ; z--)
1637 {
1638 MRIsampleVolumeType(mri, x, y, z, &val, SAMPLE_NEAREST) ;
1639 if (val < thresh)
1640 {
1641 if (!ndark)
1642 start = z ;
1643 ndark++ ;
1644 nlight = 0 ;
1645 }
1646 else
1647 {
1648 if (++nlight > MAX_LIGHT)
1649 max_dark = 0 ;
1650 if (ndark >= max_dark)
1651 {
1652 max_dark = ndark ; z1 = start ;
1653 }
1654 ndark = 0 ;
1655 }
1656 }
1657 if (ndark > max_dark)
1658 {
1659 max_dark = ndark ;
1660 z1 = start ;
1661 }
1662 if (max_dark < MIN_DARK)
1663 z1 = 0 ;
1664 box->z = z1 ;
1665
1666 /* search for anterior edge */
1667 nlight = ndark = max_dark = 0 ;
1668 x = nint(means[0]) ; y = nint(means[1]) ;
1669 for (start = z = nint(means[2]) ; z < depth ; z++)
1670 {
1671 MRIsampleVolumeType(mri, x, y, z, &val, SAMPLE_NEAREST) ;
1672 if (val < thresh)
1673 {
1674 if (!ndark)
1675 start = z ;
1676 ndark++ ;
1677 nlight = 0 ;
1678 }
1679 else
1680 {
1681 if (++nlight > MAX_LIGHT)
1682 max_dark = 0 ;
1683 if (ndark >= max_dark)
1684 {
1685 max_dark = ndark ; z1 = start ;
1686 }
1687 ndark = 0 ;
1688 }
1689 }
1690 if (ndark > max_dark)
1691 {
1692 max_dark = ndark ;
1693 z1 = start ;
1694 }
1695 if (max_dark < MIN_DARK)
1696 z1 = mri->depth-1 ;
1697 box->dz = z1 - box->z + 1 ;
1698
1699 return(NO_ERROR) ;
1700 }
1701 /*-----------------------------------------------------
1702 ------------------------------------------------------*/
1703 int
1704 MRIboundingBox(MRI *mri, int thresh, MRI_REGION *box)
1705 {
1706 int width, height, depth, x, y, z, x1, y1, z1 ;
1707 BUFTYPE *psrc ;
1708 float *pfsrc ;
1709 short *pssrc ;
1710
1711 box->dx = width = mri->width ;
1712 box->dy = height = mri->height ;
1713 box->dz = depth = mri->depth ;
1714
1715 x1 = y1 = z1 = 0 ;
1716 box->x = width-1 ;
1717 box->y = height-1 ;
1718 box->z = depth-1 ;
1719 switch (mri->type)
1720 {
1721 case MRI_UCHAR:
1722 for (z = 0 ; z < depth ; z++)
1723 {
1724 for (y = 0 ; y < height ; y++)
1725 {
1726 psrc = &MRIvox(mri, 0, y, z) ;
1727 for (x = 0 ; x < width ; x++)
1728 {
1729 if (*psrc++ > thresh)
1730 {
1731 if (x < box->x)
1732 box->x = x ;
1733 if (y < box->y)
1734 box->y = y ;
1735 if (z < box->z)
1736 box->z = z ;
1737 if (x > x1)
1738 x1 = x ;
1739 if (y > y1)
1740 y1 = y ;
1741 if (z > z1)
1742 z1 = z ;
1743 }
1744 }
1745 }
1746 }
1747 break ;
1748 case MRI_FLOAT:
1749 for (z = 0 ; z < depth ; z++)
1750 {
1751 for (y = 0 ; y < height ; y++)
1752 {
1753 pfsrc = &MRIFvox(mri, 0, y, z) ;
1754 for (x = 0 ; x < width ; x++)
1755 {
1756 if (*pfsrc++ > thresh)
1757 {
1758 if (x < box->x)
1759 box->x = x ;
1760 if (y < box->y)
1761 box->y = y ;
1762 if (z < box->z)
1763 box->z = z ;
1764 if (x > x1)
1765 x1 = x ;
1766 if (y > y1)
1767 y1 = y ;
1768 if (z > z1)
1769 z1 = z ;
1770 }
1771 }
1772 }
1773 }
1774 break ;
1775 case MRI_SHORT:
1776 for (z = 0 ; z < depth ; z++)
1777 {
1778 for (y = 0 ; y < height ; y++)
1779 {
1780 pssrc = &MRISvox(mri, 0, y, z) ;
1781 for (x = 0 ; x < width ; x++)
1782 {
1783 if (*pssrc++ > thresh)
1784 {
1785 if (x < box->x)
1786 box->x = x ;
1787 if (y < box->y)
1788 box->y = y ;
1789 if (z < box->z)
1790 box->z = z ;
1791 if (x > x1)
1792 x1 = x ;
1793 if (y > y1)
1794 y1 = y ;
1795 if (z > z1)
1796 z1 = z ;
1797 }
1798 }
1799 }
1800 }
1801 break ;
1802 default:
1803 ErrorReturn(ERROR_UNSUPPORTED,
1804 (ERROR_UNSUPPORTED, "MRIboundingBox: unsupported type %d",
1805 mri->type)) ;
1806 break ;
1807 }
1808 box->dx = x1 - box->x + 1 ;
1809 box->dy = y1 - box->y + 1 ;
1810 box->dz = z1 - box->z + 1 ;
1811 return(NO_ERROR) ;
1812 }
1813 /*-----------------------------------------------------
1814 ------------------------------------------------------*/
1815 int
1816 MRIcheckSize(MRI *mri_src, MRI *mri_check, int width, int height, int depth)
1817 {
1818 if (!mri_check)
1819 return(0) ;
1820
1821 if (!width)
1822 width = mri_src->width ;
1823 if (!height)
1824 height = mri_src->height ;
1825 if (!depth)
1826 depth = mri_src->depth ;
1827
1828 if (width != mri_check->width ||
1829 height != mri_check->height ||
1830 depth != mri_check->depth)
1831 return(0) ;
1832
1833 return(1) ;
1834 }
1835 /*-----------------------------------------------------
1836 ------------------------------------------------------*/
1837 int
1838 MRItransformRegion(MRI *mri_src, MRI *mri_dst, MRI_REGION *src_region,
1839 MRI_REGION *dst_region)
1840 {
1841 Real xw, yw, zw, xt, yt, zt, xv, yv, zv ;
1842
1843 if (getSliceDirection(mri_src) != getSliceDirection(mri_dst))
1844 ErrorReturn(ERROR_UNSUPPORTED,
1845 (ERROR_UNSUPPORTED,
1846 "MRItransformRegion(%s): slice directions must match",
1847 mri_src->fname)) ;
1848
1849 if (!mri_src->linear_transform)
1850 ErrorReturn(ERROR_UNSUPPORTED,
1851 (ERROR_UNSUPPORTED,
1852 "MRItransformRegion(%s): no transform loaded",
1853 mri_src->fname)) ;
1854 if (!mri_dst->linear_transform)
1855 ErrorReturn(ERROR_UNSUPPORTED,
1856 (ERROR_UNSUPPORTED,
1857 "MRItransformRegion(%s): no transform loaded",
1858 mri_dst->fname)) ;
1859 /*
1860 The convention is that positive xspace coordinates run
1861 from the patient's left side to right side, positive
1862 yspace coordinates run from patient posterior to anterior
1863 and positive zspace coordinates run from inferior to superior.
1864 */
1865 switch (getSliceDirection(mri_src))
1866 {
1867 case MRI_CORONAL:
1868 break ;
1869 default:
1870 ErrorReturn
1871 (ERROR_UNSUPPORTED,
1872 (ERROR_UNSUPPORTED,
1873 "MRIregionToTalairachRegion: unsupported slice direction %d",
1874 getSliceDirection(mri_src))) ;
1875 }
1876
1877 xv = (Real)src_region->x ;
1878 yv = (Real)src_region->y ;
1879 zv = (Real)src_region->z ;
1880 MRIvoxelToWorld(mri_src, xv, yv, zv, &xw, &yw, &zw) ;
1881 transform_point(mri_src->linear_transform, xw, yw, zw, &xt, &yt, &zt) ;
1882 transform_point(mri_dst->inverse_linear_transform, xt, yt, zt, &xw,&yw,&zw);
1883 MRIworldToVoxel(mri_dst, xw, yw, zw, &xv, &yv, &zv) ;
1884 dst_region->x = nint(xv) ;
1885 dst_region->y = nint(yv) ;
1886 dst_region->z = nint(zv) ;
1887
1888 xv = (Real)(src_region->x + src_region->dx - 1) ;
1889 yv = (Real)(src_region->y + src_region->dy - 1) ;
1890 zv = (Real)(src_region->z + src_region->dz - 1) ;
1891 MRIvoxelToWorld(mri_src, xv, yv, zv, &xw, &yw, &zw) ;
1892 transform_point(mri_src->linear_transform, xw, yw, zw, &xt, &yt, &zt) ;
1893 transform_point(mri_dst->inverse_linear_transform, xt, yt, zt, &xw,&yw,&zw);
1894 MRIworldToVoxel(mri_dst, xw, yw, zw, &xv, &yv, &zv) ;
1895 dst_region->dx = nint(xv - (Real)dst_region->x) + 1 ;
1896 dst_region->dy = nint(yv - (Real)dst_region->y) + 1 ;
1897 dst_region->dz = nint(zv - (Real)dst_region->z) + 1 ;
1898
1899 return(NO_ERROR) ;
1900 }
1901 /*-----------------------------------------------------
1902 ------------------------------------------------------*/
1903 int
1904 MRIvoxelToVoxel(MRI *mri_src, MRI *mri_dst, Real xv, Real yv, Real zv,
1905 Real *pxt, Real *pyt, Real *pzt)
1906 {
1907 Real xw, yw, zw, xt, yt, zt ;
1908
1909 #if 0
1910 if (!mri_src->linear_transform)
1911 ErrorReturn(ERROR_UNSUPPORTED,
1912 (ERROR_UNSUPPORTED,
1913 "MRIvoxelToVoxel(%s): no transform loaded", mri_src->fname));
1914 #endif
1915
1916 /*
1917 The convention is that positive xspace coordinates run
1918 from the patient's left side to right side, positive
1919 yspace coordinates run from patient posterior to anterior
1920 and positive zspace coordinates run from inferior to superior.
1921 */
1922 switch (getSliceDirection(mri_src))
1923 {
1924 case MRI_CORONAL:
1925 break ;
1926 default:
1927 ErrorReturn(ERROR_UNSUPPORTED,
1928 (ERROR_UNSUPPORTED,
1929 "MRIvoxelToVoxel: unsupported slice direction %d",
1930 getSliceDirection(mri_src))) ;
1931 }
1932
1933 if (!mri_src->linear_transform || !mri_dst->inverse_linear_transform)
1934 {
1935 /*
1936 if either doesn't have a transform defined, assume they are in
1937 the same coordinate system.
1938 */
1939 *pxt = xv ; *pyt = yv ; *pzt = zv ;
1940 }
1941 else
1942 {
1943 MRIvoxelToWorld(mri_src, xv, yv, zv, &xw, &yw, &zw) ;
1944 if (mri_src->linear_transform)
1945 transform_point(mri_src->linear_transform, xw, yw, zw, &xt, &yt, &zt) ;
1946 else
1947 {
1948 xt = xw ; yt = yw ; zt = zw ;
1949 }
1950 if (mri_dst->inverse_linear_transform)
1951 transform_point
1952 (mri_dst->inverse_linear_transform, xt,yt,zt,&xw,&yw,&zw);
1953 else
1954 {
1955 xw = xt ; yw = yt ; zw = zt ;
1956 }
1957 MRIworldToVoxel(mri_dst, xw, yw, zw, pxt, pyt, pzt) ;
1958 }
1959
1960 return(NO_ERROR) ;
1961 }
1962 /*-----------------------------------------------------
1963 ------------------------------------------------------*/
1964 int
1965 MRIvoxelToTalairachVoxel(MRI *mri, Real xv, Real yv, Real zv,
1966 Real *pxt, Real *pyt, Real *pzt)
1967 {
1968 Real xw, yw, zw, xt, yt, zt ;
1969
1970 #if 0
1971 if (!mri->linear_transform)
1972 ErrorReturn(ERROR_UNSUPPORTED,
1973 (ERROR_UNSUPPORTED,
1974 "MRIvoxelToTalairachVoxel(%s): no transform loaded",
1975 mri->fname)) ;
1976 #endif
1977 /*
1978 The convention is that positive xspace coordinates run
1979 from the patient's left side to right side, positive
1980 yspace coordinates run from patient posterior to anterior
1981 and positive zspace coordinates run from inferior to superior.
1982 */
1983 switch (getSliceDirection(mri))
1984 {
1985 case MRI_CORONAL:
1986 break ;
1987 default:
1988 ErrorReturn(ERROR_UNSUPPORTED,
1989 (ERROR_UNSUPPORTED,
1990 "MRIvoxelToTalairachVoxel: unsupported slice direction %d",
1991 getSliceDirection(mri))) ;
1992 }
1993
1994 MRIvoxelToWorld(mri, xv, yv, zv, &xw, &yw, &zw) ;
1995 if (mri->linear_transform)
1996 transform_point(mri->linear_transform, xw, yw, zw, &xt, &yt, &zt) ;
1997 else
1998 { xt = xw ; yt = yw ; zt = zw ; }
1999 MRIworldToVoxel(mri, xt, yt, zt, pxt, pyt, pzt) ;
2000
2001 return(NO_ERROR) ;
2002 }
2003 /*-----------------------------------------------------
2004 ------------------------------------------------------*/
2005 int
2006 MRIvoxelToTalairach(MRI *mri, Real xv, Real yv, Real zv,
2007 Real *pxt, Real *pyt, Real *pzt)
2008 {
2009 Real xw, yw, zw ;
2010
2011 #if 0
2012 if (!mri->linear_transform)
2013 ErrorReturn(ERROR_UNSUPPORTED,
2014 (ERROR_UNSUPPORTED,
2015 "MRIvoxelToTalairachVoxel(%s): no transform loaded",
2016 mri->fname)) ;
2017 #endif
2018
2019 /*
2020 The convention is that positive xspace coordinates run
2021 from the patient's left side to right side, positive
2022 yspace coordinates run from patient posterior to anterior
2023 and positive zspace coordinates run from inferior to superior.
2024 */
2025 switch (getSliceDirection(mri))
2026 {
2027 case MRI_CORONAL:
2028 break ;
2029 default:
2030 ErrorReturn(ERROR_UNSUPPORTED,
2031 (ERROR_UNSUPPORTED,
2032 "MRIvoxelToTalairachVoxel: unsupported slice direction %d",
2033 getSliceDirection(mri))) ;
2034 }
2035
2036 MRIvoxelToWorld(mri, xv, yv, zv, &xw, &yw, &zw) ;
2037 if (mri->linear_transform)
2038 transform_point(mri->linear_transform, xw, yw, zw, pxt, pyt, pzt) ;
2039 else
2040 { *pxt = xw ; *pyt = yw ; *pzt = zw ; }
2041
2042 return(NO_ERROR) ;
2043 }
2044 /*-----------------------------------------------------
2045 ------------------------------------------------------*/
2046 int
2047 MRItalairachToVoxel(MRI *mri, Real xt, Real yt, Real zt,
2048 Real *pxv, Real *pyv, Real *pzv)
2049 {
2050 Real xw, yw, zw ;
2051
2052 #if 0
2053 if (!mri->inverse_linear_transform)
2054 ErrorReturn(ERROR_UNSUPPORTED,
2055 (ERROR_UNSUPPORTED,
2056 "MRItalairachToVoxel(%s): no transform loaded",
2057 mri->fname)) ;
2058 #endif
2059
2060 /*
2061 The convention is that positive xspace coordinates run
2062 from the patient's left side to right side, positive
2063 yspace coordinates run from patient posterior to anterior
2064 and positive zspace coordinates run from inferior to superior.
2065 */
2066 switch (getSliceDirection(mri))
2067 {
2068 case MRI_CORONAL:
2069 break ;
2070 default:
2071 ErrorReturn(ERROR_UNSUPPORTED,
2072 (ERROR_UNSUPPORTED,
2073 "MRIvoxelToTalairachVoxel: unsupported slice direction %d",
2074 getSliceDirection(mri))) ;
2075 }
2076
2077 if (mri->inverse_linear_transform)
2078 transform_point(mri->inverse_linear_transform, xt, yt, zt, &xw, &yw,&zw);
2079 else
2080 { xw = xt ; yw = yt ; zw = zt ; }
2081 MRIworldToVoxel(mri, xw, yw, zw, pxv, pyv, pzv) ;
2082
2083 return(NO_ERROR) ;
2084 }
2085 /*-----------------------------------------------------
2086 ------------------------------------------------------*/
2087 int
2088 MRItalairachVoxelToVoxel(MRI *mri, Real xtv, Real ytv, Real ztv,
2089 Real *pxv, Real *pyv, Real *pzv)
2090 {
2091 Real xw, yw, zw, xt, yt, zt ;
2092
2093 #if 0
2094 if (!mri->inverse_linear_transform)
2095 ErrorReturn(ERROR_UNSUPPORTED,
2096 (ERROR_UNSUPPORTED,
2097 "MRItalairachVoxelToVoxel(%s): no transform loaded",
2098 mri->fname)) ;
2099 #endif
2100
2101 /*
2102 The convention is that positive xspace coordinates run
2103 from the patient's left side to right side, positive
2104 yspace coordinates run from patient posterior to anterior
2105 and positive zspace coordinates run from inferior to superior.
2106 */
2107 switch (getSliceDirection(mri))
2108 {
2109 case MRI_CORONAL:
2110 break ;
2111 default:
2112 ErrorReturn(ERROR_UNSUPPORTED,
2113 (ERROR_UNSUPPORTED,
2114 "MRIvoxelToTalairachVoxel: unsupported slice direction %d",
2115 getSliceDirection(mri))) ;
2116 }
2117
2118 MRIvoxelToWorld(mri, xtv, ytv, ztv, &xt, &yt, &zt) ;
2119 if (mri->inverse_linear_transform)
2120 transform_point(mri->inverse_linear_transform, xt, yt, zt, &xw, &yw,&zw);
2121 else
2122 { xw = xt ; yw = yt ; zw = zt ; }
2123 MRIworldToVoxel(mri, xw, yw, zw, pxv, pyv, pzv) ;
2124
2125 return(NO_ERROR) ;
2126 }
2127 /*-----------------------------------------------------
2128 ------------------------------------------------------*/
2129 int
2130 MRItalairachVoxelToWorld(MRI *mri, Real xtv, Real ytv, Real ztv,
2131 Real *pxw, Real *pyw, Real *pzw)
2132 {
2133 Real xw, yw, zw, xt, yt, zt ;
2134
2135 #if 0
2136 if (!mri->inverse_linear_transform)
2137 ErrorReturn(ERROR_UNSUPPORTED,
2138 (ERROR_UNSUPPORTED,
2139 "MRItalairachVoxelToVoxel(%s): no transform loaded",
2140 mri->fname)) ;
2141 #endif
2142
2143 /*
2144 The convention is that positive xspace coordinates run
2145 from the patient's left side to right side, positive
2146 yspace coordinates run from patient posterior to anterior
2147 and positive zspace coordinates run from inferior to superior.
2148 */
2149 switch (getSliceDirection(mri))
2150 {
2151 case MRI_CORONAL:
2152 break ;
2153 default:
2154 ErrorReturn(ERROR_UNSUPPORTED,
2155 (ERROR_UNSUPPORTED,
2156 "MRIvoxelToTalairachVoxel: unsupported slice direction %d",
2157 getSliceDirection(mri))) ;
2158 }
2159
2160 MRIvoxelToWorld(mri, xtv, ytv, ztv, &xt, &yt, &zt) ;
2161 if (mri->inverse_linear_transform)
2162 transform_point(mri->inverse_linear_transform, xt, yt, zt, &xw, &yw,&zw);
2163 else
2164 { xw = xt ; yw = yt ; zw = zt ; }
2165 *pxw = xw ; *pyw = yw ; *pzw = zw ;
2166
2167 return(NO_ERROR) ;
2168 }
2169 /*-----------------------------------------------------
2170 ------------------------------------------------------*/
2171 #define V4_LOAD(v, x, y, z, r) (VECTOR_ELT(v,1)=x, VECTOR_ELT(v,2)=y, \
$^
VECTOR_ELT(v,3)=z, VECTOR_ELT(v,4)=r) ;
2172
2173 int
2174 MRIvoxelToWorld(MRI *mri, Real xv, Real yv, Real zv,
2175 Real *pxw, Real *pyw, Real *pzw)
2176 {
2177 VECTOR *vw, *vv;
2178 MATRIX *RfromI;
2179
2180 // if the transform is not cached yet, then
2181 if (!mri->i_to_r__)
2182 mri->i_to_r__ = extract_i_to_r(mri);
2183 if (!mri->r_to_i__)
2184 mri->r_to_i__ = extract_r_to_i(mri);
2185
2186 RfromI = mri->i_to_r__; // extract_i_to_r(mri);
2187
2188 vv = VectorAlloc(4, MATRIX_REAL) ;
2189 V4_LOAD(vv, xv, yv, zv, 1.) ;
2190 vw = MatrixMultiply(RfromI, vv, NULL) ;
2191 *pxw = V3_X(vw);
2192 *pyw = V3_Y(vw);
2193 *pzw = V3_Z(vw);
2194
2195 // MatrixFree(&RfromI);
2196 VectorFree(&vv);
2197 VectorFree(&vw);
2198 return(NO_ERROR) ;
2199 }
2200 /*-----------------------------------------------------
2201 ------------------------------------------------------*/
2202 int
2203 MRIworldToTalairachVoxel(MRI *mri, Real xw, Real yw, Real zw,
2204 Real *pxv, Real *pyv, Real *pzv)
2205 {
2206 Real xt, yt, zt ;
2207
2208 transform_point(mri->linear_transform, xw, yw, zw, &xt, &yt, &zt) ;
2209 MRIworldToVoxel(mri, xt, yt, zt, pxv, pyv, pzv) ;
2210 return(NO_ERROR) ;
2211 }
2212 /*-----------------------------------------------------
2213 ------------------------------------------------------*/
2214 int MRIworldToVoxelIndex(MRI *mri, Real xw, Real yw, Real zw,
2215 int *pxv, int *pyv, int *pzv)
2216 {
2217 Real xv, yv, zv;
2218 MRIworldToVoxel(mri, xw, yw, zw, &xv, &yv, &zv);
2219 *pxv = (int) xv;
2220 *pyv = (int) yv;
2221 *pzv = (int) zv;
2222
2223 /*
2224 switch (getSliceDirection(mri))
2225 {
2226 case MRI_CORONAL:
2227 #if 0
2228 *pxv = ((Real)mri->xend - xw) / mri->xsize ;
2229 *pzv = (yw - (Real)mri->zstart) / mri->zsize ;
2230 *pyv = (-zw - (Real)mri->ystart) / mri->ysize ;
2231 #else
2232 trans_SetBounds ( mri->xstart, mri->xend, mri->ystart, mri->yend,
2233 mri->zstart, mri->zend );
2234 trans_SetResolution ( mri->xsize, mri->ysize, mri->zsize );
2235 trans_RASToVoxelIndex(xw, yw, zw, pxv, pyv, pzv) ;
2236 #endif
2237 break ;
2238 default:
2239 ErrorReturn(ERROR_UNSUPPORTED,
2240 (ERROR_UNSUPPORTED,
2241 "MRIworldToVoxel: unsupported slice direction %d",
2242 getSliceDirection(mri))) ;
2243 break ;
2244 }
2245 */
2246 return(NO_ERROR) ;
2247 }
2248
2249 /*
2250 int MRIvoxelToSurfaceRAS and int MRIsurfaceRASToVoxel
2251
2252 get the surfaceRAS values from original voxel
2253 Note that this is different from MRIvoxelToWorld().
2254
2255 Note that currently MATRIX uses float** to store data.
2256 Going around the circle of transform causes error accumulation quickly.
2257 I noticed that 7 x 10^(-6) is very common.
2258
2259 */
2260
2261 MATRIX *surfaceRASFromVoxel_(MRI *mri)
2262 {
2263 // Derivation (avoid expensive matrix calculation)
2264 //
2265 // orig -----(rasFromVoxel)------> RAS (scanner RAS or physical RAS)
2266 // | |
2267 //(conformedVoxelFromVoxel) (1)
2268 // | |
2269 // V V
2270 //conformed--(RASfromConformed)----->RAS (scanner RAS or physical RAS)
2271 // | |
2272 // (1) (surfaceRASFromRAS)
2273 // | |
2274 // V V
2275 //conformed-(surfaceRASFromConformed)->surfaceRAS
2276 //
2277 //
2278 // where RASFromConformed = [ -1 0 0 s1 ] where s1 = c_r + 128
2279 // [ 0 0 1 s2 ] s2 = c_a - 128
2280 // [ 0 -1 0 s3 ] s3 = c_s + 128
2281 // [ 0 0 0 1 ]
2282 //
2283 // surfaceRASFromConformed= [ -1 0 0 128 ]
2284 // [ 0 0 1 -128 ]
2285 // [ 0 -1 0 128 ]
2286 // [ 0 0 0 1 ]
2287 // Therefore
2288 // surfaceRASFromRAS= [ 1 0 0 -c_r] just a translation matrix
2289 // [ 0 1 0 -c_a]
2290 // [ 0 0 1 -c_s]
2291 // [ 0 0 0 1 ]
2292 //
2293 // surfaceRASFromVoxel = surfaceRASFromRAS (x) rasFromVoxel
2294 //
2295 // i.e. applying translation on RASFromVoxel
2296 //
2297 // This means tha
2298 //
2299 // if RASFromVoxel = ( X | T ), then
2300 // ( 0 | 1 )
2301 //
2302 // surfaceRASFromVoxel = ( 1 | -C) * ( X | T ) = ( X | T - C )
2303 // ( 0 | 1 ) ( 0 | 1 ) ( 0 | 1 )
2304 //
2305 MATRIX *rasFromVoxel;
2306 MATRIX *sRASFromVoxel;
2307 double m14, m24, m34;
2308
2309 // if the transform is not cached yet, then
2310 if (!mri->i_to_r__)
2311 mri->i_to_r__ = extract_i_to_r(mri);
2312 if (!mri->r_to_i__)
2313 mri->r_to_i__ = extract_r_to_i(mri);
2314
2315 rasFromVoxel = mri->i_to_r__; // extract_i_to_r(mri);
2316
2317 sRASFromVoxel = MatrixCopy(rasFromVoxel, NULL);
2318 // MatrixFree(&rasFromVoxel);
2319 // modify
2320 m14 = *MATRIX_RELT(sRASFromVoxel, 1,4);
2321 *MATRIX_RELT(sRASFromVoxel, 1,4) = m14 - mri->c_r;
2322 m24 = *MATRIX_RELT(sRASFromVoxel, 2,4);
2323 *MATRIX_RELT(sRASFromVoxel, 2,4) = m24 - mri->c_a;
2324 m34 = *MATRIX_RELT(sRASFromVoxel, 3,4);
2325 *MATRIX_RELT(sRASFromVoxel, 3,4) = m34 - mri->c_s;
2326
2327 return sRASFromVoxel;
2328 }
2329
2330 MATRIX *surfaceRASFromRAS_(MRI *mri)
2331 {
2332 MATRIX *sRASFromRAS;
2333 sRASFromRAS = MatrixAlloc(4, 4, MATRIX_REAL);
2334 MatrixIdentity(4, sRASFromRAS);
2335 *MATRIX_RELT(sRASFromRAS, 1,4) = - mri->c_r;
2336 *MATRIX_RELT(sRASFromRAS, 2,4) = - mri->c_a;
2337 *MATRIX_RELT(sRASFromRAS, 3,4) = - mri->c_s;
2338 return sRASFromRAS;
2339 }
2340
2341 MATRIX *RASFromSurfaceRAS_(MRI *mri)
2342 {
2343 MATRIX *RASFromSRAS;
2344 RASFromSRAS = MatrixAlloc(4, 4, MATRIX_REAL);
2345 MatrixIdentity(4, RASFromSRAS);
2346 *MATRIX_RELT(RASFromSRAS, 1,4) = mri->c_r;
2347 *MATRIX_RELT(RASFromSRAS, 2,4) = mri->c_a;
2348 *MATRIX_RELT(RASFromSRAS, 3,4) = mri->c_s;
2349 return RASFromSRAS;
2350 }
2351
2352 int MRIRASToSurfaceRAS(MRI *mri, Real xr, Real yr, Real zr,
2353 Real *xsr, Real *ysr, Real *zsr)
2354 {
2355 MATRIX *surfaceRASFromRAS=0;
2356 VECTOR *v, *sr;
2357 v = VectorAlloc(4, MATRIX_REAL);
2358 V4_LOAD(v, xr, yr, zr, 1.);
2359 surfaceRASFromRAS = surfaceRASFromRAS_(mri);
2360 sr = MatrixMultiply(surfaceRASFromRAS, v, NULL);
2361 *xsr = V3_X(sr);
2362 *ysr = V3_Y(sr);
2363 *zsr = V3_Z(sr);
2364 MatrixFree(&surfaceRASFromRAS);
2365 VectorFree(&v);
2366 VectorFree(&sr);
2367 return (NO_ERROR);
2368 }
2369
2370 int MRIsurfaceRASToRAS(MRI *mri, Real xsr, Real ysr, Real zsr,
2371 Real *xr, Real *yr, Real *zr)
2372 {
2373 MATRIX *RASFromSurfaceRAS=0;
2374 VECTOR *v, *r;
2375 v = VectorAlloc(4, MATRIX_REAL);
2376 V4_LOAD(v, xsr, ysr, zsr, 1.);
2377 RASFromSurfaceRAS = RASFromSurfaceRAS_(mri);
2378 r = MatrixMultiply(RASFromSurfaceRAS, v, NULL);
2379 *xr = V3_X(r);
2380 *yr = V3_Y(r);
2381 *zr = V3_Z(r);
2382 MatrixFree(&RASFromSurfaceRAS);
2383 VectorFree(&v);
2384 VectorFree(&r);
2385 return (NO_ERROR);
2386 }
2387
2388
2389 int MRIvoxelToSurfaceRAS(MRI *mri, Real xv, Real yv, Real zv,
2390 Real *xs, Real *ys, Real *zs)
2391 {
2392 MATRIX *sRASFromVoxel;
2393 VECTOR *vv, *sr;
2394
2395 sRASFromVoxel = surfaceRASFromVoxel_(mri);
2396 // calculate the surface ras value
2397 vv = VectorAlloc(4, MATRIX_REAL);
2398 V4_LOAD(vv, xv, yv, zv, 1.);
2399 sr = MatrixMultiply(sRASFromVoxel, vv, NULL);
2400 *xs = V3_X(sr);
2401 *ys = V3_Y(sr);
2402 *zs = V3_Z(sr);
2403
2404 MatrixFree(&sRASFromVoxel);
2405 VectorFree(&vv);
2406 VectorFree(&sr);
2407
2408 return (NO_ERROR);
2409 }
2410
2411 MATRIX *voxelFromSurfaceRAS_(MRI *mri)
2412 {
2413 MATRIX *voxelFromSRAS =0;
2414 //////////////////////////////////////////////////////////////////
2415 // it turned out that this can be done easily without taking inverse
2416 // Note the surfaceRASFromVoxel_ is given by
2417 //
2418 // ( X | T - C)
2419 // ( 0 | 1 )
2420 // Note, however, that we define C by
2421 //
2422 // ( X | T ) (S/2) = ( C ) where S = (w/2, h/2, d/2)^t
2423 // ( 0 | 1 ) ( 1 ) ( 1 )
2424 // Thus
2425 // X*S/2 + T = C
2426 // or
2427 // T - C = - X*S/2
2428 // or
2429 // surfaceRASFromVoxel = ( X | - X*S/2 )
2430 // ( 0 | 1 )
2431 // whose inverse is given by
2432 //
2433 // voxelFromSurfaceRAS = ( X ^(-1)| S/2 )
2434 // ( 0 | 1 )
2435 //
2436 // since
2437 // ( X^(-1) S/2) ( X -X*S/2) = ( 1 S/2 - S/2) = 1
2438 // ( 0 1 ) ( 0 1 ) ( 0 1 )
2439 //
2440 // thus get r_to_i__ and set translation part to S/2 is the quickest way
2441 /////////////////////////////////////////////////////////////////////
2442 // if the transform is not cached yet, then
2443 if (!mri->i_to_r__)
2444 mri->i_to_r__ = extract_i_to_r(mri);
2445 if (!mri->r_to_i__)
2446 mri->r_to_i__ = extract_r_to_i(mri);
2447
2448 voxelFromSRAS = MatrixCopy(mri->r_to_i__, NULL);
2449 // modify translation part
2450 *MATRIX_RELT(voxelFromSRAS, 1,4) = mri->width/2;
2451 *MATRIX_RELT(voxelFromSRAS, 2,4) = mri->height/2;
2452 *MATRIX_RELT(voxelFromSRAS, 3,4) = mri->depth/2;
2453
2454 #if 0
2455 // no more expensive inverse
2456 MATRIX *sRASFromVoxel = surfaceRASFromVoxel_(mri);
2457 MATRIX *voxelFromSRAS = MatrixInverse(sRASFromVoxel, NULL);
2458 MatrixFree(&sRASFromVoxel) ;
2459 #endif
2460
2461 return voxelFromSRAS;
2462 }
2463
2464 /* extract the RASToVoxel Matrix */
2465 MATRIX *GetSurfaceRASToVoxelMatrix(MRI *mri){
2466 return voxelFromSurfaceRAS_(mri);
2467 }
2468
2469 int MRIsurfaceRASToVoxel(MRI *mri, Real xr, Real yr, Real zr,
2470 Real *xv, Real *yv, Real *zv)
2471 {
2472 MATRIX *voxelFromSRAS;
2473 static VECTOR *sr = NULL, *vv = NULL;
2474
2475 voxelFromSRAS=voxelFromSurfaceRAS_(mri);
2476 if (sr == NULL)
2477 sr = VectorAlloc(4, MATRIX_REAL);
2478 V4_LOAD(sr, xr, yr, zr, 1.);
2479 vv = MatrixMultiply(voxelFromSRAS, sr, vv);
2480 *xv = V3_X(vv);
2481 *yv = V3_Y(vv);
2482 *zv = V3_Z(vv);
2483
2484 MatrixFree(&voxelFromSRAS);
2485 // VectorFree(&sr);
2486 // VectorFree(&vv);
2487
2488 return (NO_ERROR);
2489 }
2490
2491 /*------------------------------------------------------*/
2492 int
2493 MRIworldToVoxel(MRI *mri, Real xw, Real yw, Real zw,
2494 Real *pxv, Real *pyv, Real *pzv)
2495 {
2496 VECTOR *vv, *vw;
2497 MATRIX *IfromR;
2498
2499 // if transform is not cached yet, then
2500 if (!mri->r_to_i__)
2501 mri->r_to_i__ = extract_r_to_i(mri);
2502 if (!mri->i_to_r__)
2503 mri->i_to_r__ = extract_i_to_r(mri);
2504
2505 IfromR = mri->r_to_i__;
2506 vw = VectorAlloc(4, MATRIX_REAL) ;
2507 V4_LOAD(vw, xw, yw, zw, 1.) ;
2508 vv = MatrixMultiply(IfromR, vw, NULL) ;
2509 *pxv = V3_X(vv);
2510 *pyv = V3_Y(vv);
2511 *pzv = V3_Z(vv);
2512
2513 VectorFree(&vv);
2514 VectorFree(&vw);
2515
2516 return(NO_ERROR) ;
2517 }
2518 /*-----------------------------------------------------
2519 ------------------------------------------------------*/
2520 int
2521 MRIinitHeader(MRI *mri)
2522 {
2523 mri->ptype = 2 ;
2524
2525 /* most of these are in mm */
2526 mri->imnr0 = 1 ;
2527 mri->imnr1 = mri->depth ;
2528 mri->fov = mri->width ;
2529 mri->thick = 1.0 ;
2530 mri->xsize = 1.0 ;
2531 mri->ysize = 1.0 ;
2532 mri->zsize = 1.0 ;
2533 mri->ps = 1 ;
2534 mri->xstart = -mri->width/2.0 ;
2535 mri->xend = mri->width/2.0 ;
2536 mri->ystart = -mri->height/2.0 ;
2537 mri->yend = mri->height/2.0 ;
2538 mri->zstart = -mri->depth/2.0 ;
2539 mri->zend = mri->depth/2 ;
2540 // coronal
2541 mri->x_r = -1;
2542 mri->x_a = 0.;
2543 mri->x_s = 0.;
2544 //
2545 mri->y_r = 0.;
2546 mri->y_a = 0.;
2547 mri->y_s = -1;
2548 //
2549 mri->z_r = 0.;
2550 mri->z_a = 1;
2551 mri->z_s = 0.;
2552 //
2553 mri->c_r = mri->c_a = mri->c_s = 0.0;
2554
2555 mri->ras_good_flag = 1;
2556 mri->gdf_image_stem[0] = '\0';
2557 mri->tag_data = NULL;
2558 mri->tag_data_size = 0;
2559
2560 if (!mri->i_to_r__)
2561 mri->i_to_r__ = extract_i_to_r(mri);
2562 if (!mri->r_to_i__)
2563 mri->r_to_i__ = extract_r_to_i(mri);
2564
2565 return(NO_ERROR) ;
2566 }
2567
2568 /**
2569 * MRIreInitCache
2570 *
2571 * @param mri MRI* whose header information was modified
2572 *
2573 * @return NO_ERROR
2574 */
2575 int MRIreInitCache(MRI *mri)
2576 {
2577 if (mri->i_to_r__)
2578 {
2579 MatrixFree(&mri->i_to_r__);
2580 mri->i_to_r__ = 0;
2581 }
2582 if (mri->r_to_i__)
2583 {
2584 MatrixFree(&mri->r_to_i__);
2585 mri->r_to_i__ = 0;
2586 }
2587 mri->i_to_r__ = extract_i_to_r(mri);
2588 mri->r_to_i__ = extract_r_to_i(mri);
2589
2590 return (NO_ERROR);
2591 }
2592
2593 /*-----------------------------------------------------
2594 Parameters:
2595
2596 Returns value:
2597
2598 Description
2599 change the direction of slices
2600 ------------------------------------------------------*/
2601 MRI *
2602 MRIextract(MRI *mri_src, MRI *mri_dst, int x0, int y0, int z0,
2603 int dx, int dy, int dz)
2604 {
2605 return(MRIextractInto(mri_src, mri_dst, x0, y0, z0, dx, dy, dz, 0, 0, 0)) ;
2606 }
2607 /*-----------------------------------------------------
2608 Parameters:
2609
2610 Returns value:
2611
2612 Description
2613 Extract a cubic region of an MR image and return it to the caller
2614 ------------------------------------------------------*/
2615 MRI *
2616 MRIextractRegion(MRI *mri_src, MRI *mri_dst, MRI_REGION *region)
2617 {
2618 return(MRIextractInto(mri_src, mri_dst, region->x, region->y, region->z,
2619 region->dx, region->dy, region->dz, 0, 0, 0)) ;
2620 }
2621 /*-----------------------------------------------------
2622 Parameters:
2623
2624 Returns value:
2625
2626 Description
2627 Extract a cubic region of an MR image and return it to the caller
2628 ------------------------------------------------------*/
2629 MRI *
2630 MRIextractIntoRegion(MRI *mri_src, MRI *mri_dst, int x0, int y0, int z0,
2631 MRI_REGION *region)
2632 {
2633 return(MRIextractInto(mri_src, mri_dst, x0, y0, z0, region->dx, region->dy,
2634 region->dz, region->x, region->y, region->z)) ;
2635 }
2636 /*-----------------------------------------------------
2637 Parameters:
2638
2639 Returns value:
2640
2641 Description
2642 Extract a cubic region of an MR image and return it to the caller
2643 ------------------------------------------------------*/
2644 MRI *
2645 MRIextractInto(MRI *mri_src, MRI *mri_dst, int x0, int y0, int z0,
2646 int dx, int dy, int dz, int x1, int y1, int z1)
2647 {
2648 int width, height, depth, ys, zs, yd, zd, bytes, frame, xsize,ysize,zsize,
2649 dst_alloced = 0 ;
2650 Real c_r, c_a, c_s;
2651
2652 width = mri_src->width ;
2653 depth = mri_src->depth ;
2654 height = mri_src->height ;
2655
2656 if (z0 >= depth || y0 >= height || x0 >= width)
2657 ErrorReturn(NULL,
2658 (ERROR_BADPARM,
2659 "MRIextractInto: bad src location (%d, %d, %d)", x0,y0,z0));
2660 // validation
2661 if (x0 < 0)
2662 x0 = 0 ;
2663 if (y0 < 0)
2664 y0 = 0 ;
2665 if (z0 < 0)
2666 z0 = 0 ;
2667 if (x0+dx > width)
2668 dx = (width - x0) ;
2669 if (y0+dy > height)
2670 dy = (height - y0) ;
2671 if (z0+dz > depth)
2672 dz = (depth - z0) ;
2673 if (x1 < 0)
2674 x1 = 0 ;
2675 if (y1 < 0)
2676 y1 = 0 ;
2677 if (z1 < 0)
2678 z1 = 0 ;
2679
2680 if (!mri_dst)
2681 {
2682 mri_dst = MRIallocSequence(dx, dy, dz, mri_src->type, mri_src->nframes) ;
2683 MRIcopyHeader(mri_src, mri_dst) ;
2684 mri_dst->imnr0 = z0 + mri_src->imnr0 - z1 ;
2685 mri_dst->imnr1 = mri_dst->imnr0 + dz - 1 ;
2686 dst_alloced = 1 ;
2687 }
2688
2689 if (mri_src->type != mri_dst->type)
2690 {
2691 MRIfree(&mri_dst) ;
2692 ErrorReturn(NULL,
2693 (ERROR_BADPARM,
2694 "MRIextractInto: src and dst types must match"));
2695 }
2696
2697 if (x1+dx > mri_dst->width)
2698 dx = (mri_dst->width - x1) ;
2699 if (y1+dy > mri_dst->height)
2700 dy = (mri_dst->height - y1) ;
2701 if (z1+dz > mri_dst->depth)
2702 dz = (mri_dst->depth - z1) ;
2703
2704 xsize = mri_src->xsize ;
2705 ysize = mri_src->ysize ;
2706 zsize = mri_src->zsize ;
2707
2708 if (dst_alloced)
2709 {
2710 mri_dst->xstart += x0*xsize ;
2711 mri_dst->xend = mri_dst->xstart + dx*xsize ;
2712 mri_dst->ystart += y0*ysize ;
2713 mri_dst->yend = mri_dst->ystart + dy*ysize ;
2714 mri_dst->zstart += z0*zsize ;
2715 mri_dst->zend = mri_dst->zstart + dz*zsize ;
2716 }
2717
2718 bytes = dx ;
2719 switch (mri_src->type)
2720 {
2721 case MRI_FLOAT:
2722 bytes *= sizeof(float) ;
2723 break ;
2724 case MRI_LONG:
2725 bytes *= sizeof(long) ;
2726 break ;
2727 case MRI_INT:
2728 bytes *= sizeof(int) ;
2729 break ;
2730 case MRI_SHORT:
2731 bytes *= sizeof(short) ;
2732 break ;
2733 default:
2734 break ;
2735 }
2736
2737 for (frame = 0 ; frame < mri_src->nframes ; frame++)
2738 {
2739 for (zd = z1, zs = z0 ; zs < z0+dz ; zs++, zd++)
2740 {
2741 for (yd = y1, ys = y0 ; ys < y0+dy ; ys++, yd++)
2742 {
2743 switch (mri_src->type)
2744 {
2745 case MRI_UCHAR:
2746 memcpy(&MRIseq_vox(mri_dst, x1, yd, zd,frame),
2747 &MRIseq_vox(mri_src,x0,ys,zs,frame), bytes);
2748 break ;
2749 case MRI_FLOAT:
2750 memcpy(&MRIFseq_vox(mri_dst, x1, yd, zd,frame),
2751 &MRIFseq_vox(mri_src,x0,ys,zs,frame), bytes);
2752 break ;
2753 case MRI_SHORT:
2754 memcpy(&MRISseq_vox(mri_dst, x1, yd, zd,frame),
2755 &MRISseq_vox(mri_src,x0,ys,zs,frame), bytes);
2756 break ;
2757 case MRI_LONG:
2758 memcpy(&MRILseq_vox(mri_dst, x1, yd, zd,frame),
2759 &MRILseq_vox(mri_src,x0,ys,zs,frame), bytes);
2760 break ;
2761 }
2762 }
2763 }
2764 }
2765 // calculate c_ras
2766 MRIcalcCRASforExtractedVolume
2767 (mri_src, mri_dst, x0, y0, z0, x1, y1, z1, &c_r, &c_a, &c_s);
2768 mri_dst->c_r = c_r;
2769 mri_dst->c_a = c_a;
2770 mri_dst->c_s = c_s;
2771 // initialize cached transform
2772 MRIreInitCache(mri_dst);
2773
2774 return(mri_dst) ;
2775 }
2776 /*-----------------------------------------------------
2777 Parameters:
2778
2779 Returns value:
2780
2781 Description
2782 change the direction of slices
2783 ------------------------------------------------------*/
2784 MRI *
2785 MRIreslice(MRI *mri_src, MRI *mri_dst, int slice_direction)
2786 {
2787 int width, height, depth, x1, x2, x3 ;
2788 BUFTYPE *psrc, val, *pdst ;
2789
2790 int src_slice_direction = getSliceDirection(mri_src);
2791 if (slice_direction == src_slice_direction)
2792 {
2793 mri_dst = MRIcopy(mri_src, NULL) ;
2794 return(mri_dst) ;
2795 }
2796
2797 width = mri_src->width ;
2798 height = mri_src->height ;
2799 depth = mri_src->depth ;
2800
2801
2802 if ((src_slice_direction == MRI_SAGITTAL &&
2803 slice_direction == MRI_CORONAL) ||
2804 (src_slice_direction == MRI_CORONAL &&
2805 slice_direction == MRI_SAGITTAL))
2806 {
2807 /*
2808 coronal images are back to front of the head, thus the depth axis
2809 points from the nose to the back of the head, with x from neck to
2810 crown, and y from ear to ear.
2811 */
2812 /* x1 --> x3
2813 x2 --> x2
2814 x3 --> x1
2815 */
2816 if (!mri_dst)
2817 {
2818 mri_dst = MRIalloc(depth, height, width, mri_src->type) ;
2819 MRIcopyHeader(mri_src, mri_dst) ;
2820 }
2821 else if (depth != mri_dst->width || height != mri_dst->height ||
2822 width != mri_dst->depth)
2823 {
2824 ErrorReturn(NULL,
2825 (ERROR_BADPARM,
2826 "MRIreslice: invalid destination size (%d, %d, %d)",
2827 mri_dst->width, mri_dst->height, mri_dst->depth)) ;
2828 }
2829
2830 for (x3 = 0 ; x3 < depth ; x3++)
2831 {
2832 for (x2 = 0 ; x2 < height ; x2++)
2833 {
2834 psrc = &MRIvox(mri_src, 0, x2, x3) ;
2835 for (x1 = 0 ; x1 < width ; x1++)
2836 {
2837 /* swap so in place transformations are possible */
2838 mri_dst->slices[x1][x2][x3] = *psrc++ ;
2839 }
2840 }
2841 }
2842 }
2843 else
2844 if ((src_slice_direction == MRI_HORIZONTAL &&
2845 slice_direction == MRI_CORONAL) ||
2846 (src_slice_direction == MRI_CORONAL &&
2847 slice_direction == MRI_HORIZONTAL))
2848 {
2849 /*
2850 horizontal images are top to bottom of the head, thus the depth axis
2851 points from the top of the head to the neck, with x from ear to ear
2852 and y from nose to back of head.
2853 */
2854 /* x3 --> x2
2855 x2 --> x3
2856 x1 --> x1
2857 */
2858 if (!mri_dst)
2859 {
2860 mri_dst = MRIalloc(width, depth, height, mri_src->type) ;
2861 MRIcopyHeader(mri_src, mri_dst) ;
2862 }
2863 else if (depth != mri_dst->height || height != mri_dst->depth ||
2864 width != mri_dst->width)
2865 ErrorReturn(NULL,
2866 (ERROR_BADPARM,
2867 "MRIreslice: invalid destination size (%d, %d, %d)",
2868 mri_dst->width, mri_dst->height, mri_dst->depth)) ;
2869
2870 for (x3 = 0 ; x3 < depth ; x3++)
2871 {
2872 for (x2 = 0 ; x2 < height ; x2++)
2873 {
2874 psrc = &MRIvox(mri_src, 0, x2, x3) ;
2875 pdst = &MRIvox(mri_dst, 0, x3, x2) ;
2876 for (x1 = 0 ; x1 < width ; x1++)
2877 {
2878 /* swap so in place transformations are possible */
2879 *pdst++ = *psrc++ ;
2880 }
2881 }
2882 }
2883 }
2884 else
2885 if ((src_slice_direction == MRI_SAGITTAL &&
2886 slice_direction == MRI_HORIZONTAL))
2887 {
2888 /*
2889 horizontal images are top to bottom of the head,
2890 thus the depth axis
2891 points from the top of the head to the neck, with x from
2892 ear to ear
2893 and y from nose to back of head.
2894 */
2895 /* x3 --> x2
2896 x1 --> x3
2897 x2 --> x1
2898 */
2899 if (!mri_dst)
2900 {
2901 mri_dst = MRIalloc(width, depth, height, mri_src->type) ;
2902 MRIcopyHeader(mri_src, mri_dst) ;
2903 }
2904 else if (depth != mri_dst->height || height != mri_dst->depth ||
2905 width != mri_dst->width)
2906 ErrorReturn(NULL,
2907 (ERROR_BADPARM,
2908 "MRIreslice: invalid destination size (%d, %d, %d)",
2909 mri_dst->width, mri_dst->height, mri_dst->depth)) ;
2910
2911 for (x3 = 0 ; x3 < depth ; x3++)
2912 {
2913 for (x2 = 0 ; x2 < height ; x2++)
2914 {
2915 psrc = &MRIvox(mri_src, 0, x2, x3) ;
2916 for (x1 = 0 ; x1 < width ; x1++)
2917 {
2918 /* swap so in place transformations are possible */
2919 mri_dst->slices[x2][x1][x3] = *psrc++ ;
2920 }
2921 }
2922 }
2923 }
2924 else
2925 if (src_slice_direction == MRI_HORIZONTAL &&
2926 slice_direction == MRI_SAGITTAL)
2927 {
2928 /*
2929 horizontal images are top to bottom of the head,
2930 thus the depth axis
2931 points from the top of the head to the neck,
2932 with x from ear to ear
2933 and y from nose to back of head.
2934 */
2935 /* x2 --> x3
2936 x3 --> x1
2937 x1 --> x2
2938 */
2939 if (!mri_dst)
2940 {
2941 mri_dst = MRIalloc(width, depth, height, mri_src->type) ;
2942 MRIcopyHeader(mri_src, mri_dst) ;
2943 }
2944 else if (depth != mri_dst->height || height != mri_dst->depth ||
2945 width != mri_dst->width)
2946 ErrorReturn(NULL,
2947 (ERROR_BADPARM,
2948 "MRIreslice: invalid destination size (%d, %d, %d)",
2949 mri_dst->width, mri_dst->height, mri_dst->depth)) ;
2950
2951 for (x3 = 0 ; x3 < depth ; x3++)
2952 {
2953 for (x2 = 0 ; x2 < height ; x2++)
2954 {
2955 psrc = &MRIvox(mri_src, 0, x2, x3) ;
2956 for (x1 = 0 ; x1 < width ; x1++)
2957 {
2958 /* swap so in place transformations are possible */
2959 mri_dst->slices[x1][x3][x2] = *psrc++ ;
2960 }
2961 }
2962 }
2963 }
2964 else
2965 switch (src_slice_direction)
2966 {
2967 default:
2968 MRIfree(&mri_dst) ;
2969 ErrorReturn(NULL,
2970 (ERROR_BADPARM,
2971 "MRIreslice: mri_src unknown slice direction %d",
2972 src_slice_direction)) ;
2973 break ;
2974 case MRI_CORONAL:
2975 /*
2976 coronal images are back to front of the head,
2977 thus the depth axis
2978 points from the nose to the back of the head,
2979 with x from neck to
2980 crown, and y from ear to ear.
2981 */
2982 switch (slice_direction)
2983 {
2984 case MRI_SAGITTAL:
2985 /* x1 --> x3
2986 x2 --> x2
2987 x3 --> x1
2988 */
2989 if (!mri_dst)
2990 {
2991 mri_dst = MRIalloc(depth, height, width, mri_src->type) ;
2992 MRIcopyHeader(mri_src, mri_dst) ;
2993 }
2994 else if (depth != mri_dst->width ||
2995 height != mri_dst->height ||
2996 width != mri_dst->depth)
2997 ErrorReturn
2998 (NULL,
2999 (ERROR_BADPARM,
3000 "MRIreslice: invalid destination size (%d, %d, %d)",
3001 mri_dst->width, mri_dst->height, mri_dst->depth)) ;
3002
3003 for (x3 = 0 ; x3 < depth ; x3++)
3004 {
3005 for (x2 = 0 ; x2 < height ; x2++)
3006 {
3007 psrc = &MRIvox(mri_src, 0, x2, x3) ;
3008 for (x1 = 0 ; x1 < width ; x1++)
3009 {
3010 /* swap so in place transformations
3011 are possible */
3012 val = *psrc++ ;
3013 #if 0
3014 mri_dst->slices[x3][x2][x1] =
3015 mri_src->slices[x1][x2][x3] ;
3016 #endif
3017 mri_dst->slices[x1][x2][x3] = val ;
3018 }
3019 }
3020 }
3021 break ;
3022 case MRI_HORIZONTAL:
3023 break ;
3024 }
3025 break ;
3026 case MRI_SAGITTAL:
3027 /*
3028 sagittal images are slices in
3029 the plane of the nose, with depth going
3030 from ear to ear.
3031 */
3032 break ;
3033 }
3034 setDirectionCosine(mri_dst, slice_direction);
3035 mri_dst->ras_good_flag = 0;
3036 return(mri_dst) ;
3037 }
3038 /*-----------------------------------------------------
3039 Parameters:
3040
3041 Returns value:
3042
3043 Description
3044 Set an MRI intensity values to 0
3045 ------------------------------------------------------*/
3046 int
3047 MRIclear(MRI *mri)
3048 {
3049 int width, depth, height, bytes, y, z, frame, nframes ;
3050
3051 width = mri->width ;
3052 height = mri->height ;
3053 depth = mri->depth ;
3054 nframes = mri->nframes ;
3055 bytes = width ;
3056
3057 switch (mri->type)
3058 {
3059 case MRI_UCHAR:
3060 bytes *= sizeof(unsigned char) ;
3061 break ;
3062 case MRI_BITMAP:
3063 bytes /= 8 ;
3064 break ;
3065 case MRI_FLOAT:
3066 bytes *= sizeof(float) ;
3067 break ;
3068 case MRI_LONG:
3069 bytes *= sizeof(long) ;
3070 break ;
3071 case MRI_INT:
3072 bytes *= sizeof(int) ;
3073 break ;
3074 case MRI_SHORT:
3075 bytes *= sizeof(short) ;
3076 break ;
3077 default:
3078 ErrorReturn(ERROR_UNSUPPORTED,
3079 (ERROR_UNSUPPORTED,
3080 "MRIclear: unsupported input type %d", mri->type)) ;
3081 break ;
3082 }
3083
3084 for (frame = 0 ; frame < nframes ; frame++)
3085 {
3086 for (z = 0 ; z < depth ; z++)
3087 {
3088 for (y = 0 ; y < height ; y++)
3089 memset(mri->slices[z+frame*depth][y], 0, bytes) ;
3090 }
3091 }
3092
3093 return(NO_ERROR) ;
3094 }
3095 /*-----------------------------------------------------
3096 Parameters:
3097
3098 Returns value:
3099
3100 Description
3101 find the principle components of a (binary) MRI. The
3102 eigenvectors are the columns of the matrix mEvectors, the
3103 eigenvalues are returned in the array evalues and the means
3104 in means (these last two must be three elements long.)
3105 ------------------------------------------------------*/
3106 int
3107 MRIcenterOfMass(MRI *mri,double *means, BUFTYPE threshold)
3108 {
3109 int width, height, depth, x, y, z ;
3110 long npoints ;
3111 double mx, my, mz, weight ;
3112 Real val ;
3113
3114 width = mri->width ;
3115 height = mri->height ;
3116 depth = mri->depth ;
3117
3118 mx = my = mz = weight = 0.0f ; npoints = 0L ;
3119
3120 for (z = 0 ; z < depth ; z++)
3121 {
3122 for (y = 0 ; y < height ; y++)
3123 {
3124 for (x = 0 ; x < width ; x++)
3125 {
3126 MRIsampleVolumeType(mri, x, y, z, &val, SAMPLE_NEAREST) ;
3127 if (val > threshold)
3128 {
3129 weight += val ;
3130 mx += (float)x*val ;
3131 my += (float)y*val ;
3132 mz += (float)z*val ;
3133 npoints++ ;
3134 }
3135 }
3136 }
3137 }
3138
3139 if (weight > 0.0)
3140 {
3141 mx /= weight ;
3142 my /= weight ;
3143 mz /= weight ;
3144 means[0] = mx ;
3145 means[1] = my ;
3146 means[2] = mz ;
3147 }
3148 else
3149 means[0] = means[1] = means[2] = 0.0f ;
3150
3151
3152 return(NO_ERROR) ;
3153 }
3154 /*-----------------------------------------------------
3155 Parameters:
3156
3157 Returns value:
3158
3159 Description
3160 find the principle components of a (binary) MRI. The
3161 eigenvectors are the columns of the matrix mEvectors, the
3162 eigenvalues are returned in the array evalues and the means
3163 in means (these last two must be three elements long.)
3164 ------------------------------------------------------*/
3165 int
3166 MRIprincipleComponents(MRI *mri, MATRIX *mEvectors, float *evalues,
3167 double *means, BUFTYPE threshold)
3168 {
3169 int width, height, depth, x, y, z ;
3170 BUFTYPE *psrc, val ;
3171 long npoints ;
3172 MATRIX *mCov, *mX, *mXT, *mTmp ;
3173 double mx, my, mz, weight ;
3174
3175 if (mri->type != MRI_UCHAR)
3176 ErrorReturn(ERROR_UNSUPPORTED,
3177 (ERROR_UNSUPPORTED,
3178 "MRIprincipleComponents: unsupported input type %d",
3179 mri->type)) ;
3180
3181 width = mri->width ;
3182 height = mri->height ;
3183 depth = mri->depth ;
3184
3185 mx = my = mz = weight = 0.0f ; npoints = 0L ;
3186
3187 for (z = 0 ; z < depth ; z++)
3188 {
3189 for (y = 0 ; y < height ; y++)
3190 {
3191 psrc = &MRIvox(mri, 0, y, z) ;
3192 for (x = 0 ; x < width ; x++)
3193 {
3194 val = *psrc++ ;
3195 if (val > threshold)
3196 {
3197 weight += val ;
3198 mx += (float)x*val ;
3199 my += (float)y*val ;
3200 mz += (float)z*val ;
3201 npoints++ ;
3202 }
3203 }
3204 }
3205 }
3206
3207 if (weight > 0.0)
3208 {
3209 mx /= weight ;
3210 my /= weight ;
3211 mz /= weight ;
3212 means[0] = mx ;
3213 means[1] = my ;
3214 means[2] = mz ;
3215 }
3216 else
3217 means[0] = means[1] = means[2] = 0.0f ;
3218
3219 mX = MatrixAlloc(3, 1, MATRIX_REAL) ; /* zero-mean coordinate vector */
3220 mXT = NULL ; /* transpose of above */
3221 mTmp = MatrixAlloc(3, 3, MATRIX_REAL) ; /* tmp matrix for covariance */
3222 mCov = MatrixAlloc(3, 3, MATRIX_REAL) ; /* covariance matrix */
3223
3224 for (z = 0 ; z < depth ; z++)
3225 {
3226 for (y = 0 ; y < height ; y++)
3227 {
3228 psrc = &MRIvox(mri, 0, y, z) ;
3229 for (x = 0 ; x < width ; x++)
3230 {
3231 val = *psrc++ ;
3232 if (val > threshold)
3233 {
3234 mX->rptr[1][1] = (x - (int)mx)*val ;
3235 mX->rptr[2][1] = (y - (int)my)*val ;
3236 mX->rptr[3][1] = (z - (int)mz)*val ;
3237 mXT = MatrixTranspose(mX, mXT) ;
3238 mTmp = MatrixMultiply(mX, mXT, mTmp) ;
3239 mCov = MatrixAdd(mTmp, mCov, mCov) ;
3240 }
3241 }
3242 }
3243 }
3244
3245 if (weight > 0)
3246 MatrixScalarMul(mCov, 1.0f/weight, mCov) ;
3247
3248 MatrixEigenSystem(mCov, evalues, mEvectors) ;
3249
3250 return(NO_ERROR) ;
3251 }
3252 /*-----------------------------------------------------
3253 Parameters:
3254
3255 Returns value:
3256
3257 Description
3258 find the principle components of a (binary) MRI. The
3259 eigenvectors are the columns of the matrix mEvectors, the
3260 eigenvalues are returned in the array evalues and the means
3261 in means (these last two must be three elements long.)
3262 ------------------------------------------------------*/
3263 int
3264 MRIbinaryPrincipleComponents(MRI *mri, MATRIX *mEvectors, float *evalues,
3265 double *means, BUFTYPE threshold)
3266 {
3267 int width, height, depth, x, y, z ;
3268 BUFTYPE *psrc, val ;
3269 long npoints ;
3270 MATRIX *mCov, *mX, *mXT, *mTmp ;
3271 double mx, my, mz, weight ;
3272
3273 if (mri->type != MRI_UCHAR)
3274 ErrorReturn(ERROR_UNSUPPORTED,
3275 (ERROR_UNSUPPORTED,
3276 "MRIprincipleComponents: unsupported input type %d",
3277 mri->type)) ;
3278
3279 width = mri->width ;
3280 height = mri->height ;
3281 depth = mri->depth ;
3282
3283 mx = my = mz = weight = 0.0f ; npoints = 0L ;
3284
3285 for (z = 0 ; z < depth ; z++)
3286 {
3287 for (y = 0 ; y < height ; y++)
3288 {
3289 psrc = &MRIvox(mri, 0, y, z) ;
3290 for (x = 0 ; x < width ; x++)
3291 {
3292 val = *psrc++ ;
3293 if (val > threshold)
3294 {
3295 weight++ ;
3296 mx += (float)x ;
3297 my += (float)y ;
3298 mz += (float)z ;
3299 npoints++ ;
3300 }
3301 }
3302 }
3303 }
3304
3305 if (weight > 0.0)
3306 {
3307 mx /= weight ;
3308 my /= weight ;
3309 mz /= weight ;
3310 means[0] = mx ;
3311 means[1] = my ;
3312 means[2] = mz ;
3313 }
3314 else
3315 means[0] = means[1] = means[2] = 0.0f ;
3316
3317 mX = MatrixAlloc(3, 1, MATRIX_REAL) ; /* zero-mean coordinate vector */
3318 mXT = NULL ; /* transpose of above */
3319 mTmp = MatrixAlloc(3, 3, MATRIX_REAL) ; /* tmp matrix for covariance */
3320 mCov = MatrixAlloc(3, 3, MATRIX_REAL) ; /* covariance matrix */
3321
3322 for (z = 0 ; z < depth ; z++)
3323 {
3324 for (y = 0 ; y < height ; y++)
3325 {
3326 psrc = &MRIvox(mri, 0, y, z) ;
3327 for (x = 0 ; x < width ; x++)
3328 {
3329 val = *psrc++ ;
3330 if (val > threshold)
3331 {
3332 mX->rptr[1][1] = (x - (int)mx) ;
3333 mX->rptr[2][1] = (y - (int)my) ;
3334 mX->rptr[3][1] = (z - (int)mz) ;
3335 mXT = MatrixTranspose(mX, mXT) ;
3336 mTmp = MatrixMultiply(mX, mXT, mTmp) ;
3337 mCov = MatrixAdd(mTmp, mCov, mCov) ;
3338 }
3339 }
3340 }
3341 }
3342
3343 if (weight > 0)
3344 MatrixScalarMul(mCov, 1.0f/weight, mCov) ;
3345
3346 MatrixEigenSystem(mCov, evalues, mEvectors) ;
3347
3348 return(NO_ERROR) ;
3349 }
3350 /*-----------------------------------------------------
3351 Parameters:
3352
3353 Returns value:
3354
3355 Description
3356 threshold an MRI.
3357 ------------------------------------------------------*/
3358 MRI *
3359 MRIthresholdRangeInto(MRI *mri_src,MRI *mri_dst,BUFTYPE low_val,BUFTYPE hi_val)
3360 {
3361 int width, height, depth, x, y, z ;
3362 BUFTYPE *psrc, *pdst, val ;
3363 float *pfsrc, *pfdst, fval ;
3364
3365 if (!mri_dst)
3366 mri_dst = MRIclone(mri_src, NULL) ;
3367
3368 width = mri_src->width ;
3369 height = mri_src->height ;
3370 depth = mri_src->depth ;
3371
3372 switch (mri_src->type)
3373 {
3374 case MRI_UCHAR:
3375 for (z = 0 ; z < depth ; z++)
3376 {
3377 for (y = 0 ; y < height ; y++)
3378 {
3379 psrc = &MRIvox(mri_src, 0, y, z) ;
3380 pdst = &MRIvox(mri_dst, 0, y, z) ;
3381 for (x = 0 ; x < width ; x++, pdst++)
3382 {
3383 val = *psrc++ ;
3384 if (val >= low_val && val <= hi_val)
3385 *pdst = val ;
3386 else
3387 *pdst = 0 ;
3388 }
3389 }
3390 }
3391 break ;
3392 case MRI_FLOAT:
3393 for (z = 0 ; z < depth ; z++)
3394 {
3395 for (y = 0 ; y < height ; y++)
3396 {
3397 pfsrc = &MRIFvox(mri_src, 0, y, z) ;
3398 pfdst = &MRIFvox(mri_dst, 0, y, z) ;
3399 for (x = 0 ; x < width ; x++, pdst++)
3400 {
3401 fval = *pfsrc++ ;
3402 if (fval >= low_val && fval <= hi_val)
3403 *pfdst = fval ;
3404 else
3405 *pfdst = 0 ;
3406 }
3407 }
3408 }
3409 break ;
3410 default:
3411 ErrorReturn(mri_dst,
3412 (ERROR_UNSUPPORTED,
3413 "MRIthresholdRangeInto: unsupported type %d",
3414 mri_src->type)) ;
3415 break ;
3416 }
3417 return(mri_dst) ;
3418 }
3419 /*-----------------------------------------------------
3420 Parameters:
3421
3422 Returns value:
3423
3424 Description
3425 threshold an MRI.
3426 ------------------------------------------------------*/
3427 MRI *
3428 MRIthreshold(MRI *mri_src, MRI *mri_dst, float threshold)
3429 {
3430 int width, height, depth, x, y, z ;
3431 float val ;
3432
3433 if (!mri_dst)
3434 mri_dst = MRIclone(mri_src, NULL) ;
3435
3436 width = mri_src->width ;
3437 height = mri_src->height ;
3438 depth = mri_src->depth ;
3439
3440 for (z = 0 ; z < depth ; z++)
3441 {
3442 for (y = 0 ; y < height ; y++)
3443 {
3444 for (x = 0 ; x < width ; x++)
3445 {
3446 val = MRIgetVoxVal(mri_src, x, y, z, 0) ;
3447 if (val < threshold)
3448 val = 0 ;
3449 MRIsetVoxVal(mri_dst, x, y, z, 0, val) ;
3450 }
3451 }
3452 }
3453
3454 return(mri_dst) ;
3455 }
3456 /*-----------------------------------------------------
3457 Parameters:
3458
3459 Returns value:
3460
3461 Description
3462 threshold an MRI.
3463 ------------------------------------------------------*/
3464 MRI *
3465 MRIinvertContrast(MRI *mri_src, MRI *mri_dst, float threshold)
3466 {
3467 int width, height, depth, x, y, z ;
3468 BUFTYPE *psrc, *pdst, val ;
3469
3470 if (!mri_dst)
3471 mri_dst = MRIclone(mri_src, NULL) ;
3472
3473 width = mri_src->width ;
3474 height = mri_src->height ;
3475 depth = mri_src->depth ;
3476
3477 for (z = 0 ; z < depth ; z++)
3478 {
3479 for (y = 0 ; y < height ; y++)
3480 {
3481 psrc = &MRIvox(mri_src, 0, y, z) ;
3482 pdst = &MRIvox(mri_dst, 0, y, z) ;
3483 for (x = 0 ; x < width ; x++)
3484 {
3485 val = *psrc++ ;
3486 if (val > threshold)
3487 val = 255 - val ;
3488 *pdst++ = val ;
3489 }
3490 }
3491 }
3492
3493 return(mri_dst) ;
3494 }
3495 /*-----------------------------------------------------
3496 Parameters:
3497
3498 Returns value:
3499
3500 Description
3501 threshold an MRI.
3502 ------------------------------------------------------*/
3503 MRI *
3504 MRIbinarize(MRI *mri_src, MRI *mri_dst, BUFTYPE threshold, BUFTYPE low_val,
3505 BUFTYPE hi_val)
3506 {
3507 int width, height, depth, x, y, z, f ;
3508 Real val ;
3509
3510 if (!mri_dst)
3511 mri_dst = MRIclone(mri_src, NULL) ;
3512
3513 width = mri_src->width ;
3514 height = mri_src->height ;
3515 depth = mri_src->depth ;
3516
3517 for (f = 0 ; f < mri_src->nframes ; f++)
3518 {
3519 for (z = 0 ; z < depth ; z++)
3520 {
3521 for (y = 0 ; y < height ; y++)
3522 {
3523 for (x = 0 ; x < width ; x++)
3524 {
3525 MRIsampleVolumeFrameType
3526 (mri_src, x, y, z, f, SAMPLE_NEAREST, &val) ;
3527 if (val < threshold)
3528 val = low_val ;
3529 else
3530 val = hi_val ;
3531 MRIsetVoxVal(mri_dst, x, y, z, f, val) ;
3532 }
3533 }
3534 }
3535 }
3536
3537 return(mri_dst) ;
3538 }
3539
3540 /*-----------------------------------------------------*/
3541 MRI *MRIsubtract(MRI *mri1, MRI *mri2, MRI *mri_dst)
3542 {
3543 int nframes, width, height, depth, x, y, z, f, s ;
3544 float v1, v2, v=0.0;
3545 BUFTYPE *p1=NULL, *p2=NULL, *pdst=NULL ;
3546 short *ps1=NULL, *ps2=NULL, *psdst=NULL ;
3547 int *pi1=NULL, *pi2=NULL, *pidst=NULL ;
3548 long *pl1=NULL, *pl2=NULL, *pldst=NULL ;
3549 float *pf1=NULL, *pf2=NULL, *pfdst=NULL ;
3550
3551 width = mri1->width ;
3552 height = mri1->height ;
3553 depth = mri1->depth ;
3554 nframes = mri1->nframes ;
3555 if(nframes == 0) nframes = 1;
3556
3557 if (!mri_dst){
3558 mri_dst = MRIallocSequence(width, height, depth, mri1->type,nframes) ;
3559 MRIcopyHeader(mri1, mri_dst) ;
3560 }
3561
3562 if(mri1->type != mri2->type){
3563 /* Generic but slow */
3564 for (f = 0 ; f < nframes ; f++){
3565 for (z = 0 ; z < depth ; z++){
3566 for (y = 0 ; y < height ; y++){
3567 for (x = 0 ; x < width ; x++){
3568 v1 = MRIgetVoxVal(mri1,x,y,z,f);
3569 v2 = MRIgetVoxVal(mri2,x,y,z,f);
3570 v = v1-v2;
3571 MRIsetVoxVal(mri_dst,x,y,z,f,v);
3572 }
3573 }
3574 }
3575 }
3576 return(mri_dst) ;
3577 }
3578
3579
3580 s = 0;
3581 for (f = 0 ; f < nframes ; f++){
3582 for (z = 0 ; z < depth ; z++){
3583 for (y = 0 ; y < height ; y++){
3584
3585 switch(mri_dst->type){
3586 case MRI_UCHAR: pdst = mri_dst->slices[s][y] ; break;
3587 case MRI_SHORT: psdst = (short *) mri_dst->slices[s][y] ; break;
3588 case MRI_INT: pidst = (int *) mri_dst->slices[s][y] ; break;
3589 case MRI_LONG: pldst = (long *) mri_dst->slices[s][y] ; break;
3590 case MRI_FLOAT: pfdst = (float *) mri_dst->slices[s][y] ; break;
3591 }
3592 switch(mri1->type){
3593 case MRI_UCHAR:
3594 p1 = mri1->slices[s][y] ;
3595 p2 = mri2->slices[s][y] ;
3596 break;
3597 case MRI_SHORT:
3598 ps1 = (short *) mri1->slices[s][y] ;
3599 ps2 = (short *) mri2->slices[s][y] ;
3600 break;
3601 case MRI_INT:
3602 pi1 = (int *) mri1->slices[s][y] ;
3603 pi2 = (int *) mri2->slices[s][y] ;
3604 break;
3605 case MRI_LONG:
3606 pl1 = (long *) mri1->slices[s][y] ;
3607 pl2 = (long *) mri2->slices[s][y] ;
3608 break;
3609 case MRI_FLOAT:
3610 pf1 = (float *) mri1->slices[s][y] ;
3611 pf2 = (float *) mri2->slices[s][y] ;
3612 break;
3613 }
3614
3615 for (x = 0 ; x < width ; x++){
3616
3617 switch(mri1->type){
3618 case MRI_UCHAR: v = (float)(*p1++) - (float)(*p2++); break;
3619 case MRI_SHORT: v = (float)(*ps1++) - (float)(*ps2++); break;
3620 case MRI_INT: v = (float)(*pi1++) - (float)(*pi2++); break;
3621 case MRI_LONG: v = (float)(*pl1++) - (float)(*pl2++); break;
3622 case MRI_FLOAT: v = (float)(*pf1++) - (float)(*pf2++); break;
3623 }
3624
3625 switch(mri_dst->type){
3626 case MRI_UCHAR: (*pdst++) = (BUFTYPE) v; break;
3627 case MRI_SHORT: (*psdst++) = (short) v; break;
3628 case MRI_INT: (*pidst++) = (int) v; break;
3629 case MRI_LONG: (*pldst++) = (long) v; break;
3630 case MRI_FLOAT: (*pfdst++) = (float) v; break;
3631 }
3632
3633 }
3634 }
3635 s++;
3636 }
3637 }
3638
3639 return(mri_dst) ;
3640 }
3641 #if 0
3642 /*------------------------------------------------------
3643 MRIsubtract(mri1,mri2,mridiff) - computes mri1-mri2.
3644 ------------------------------------------------------*/
3645 MRI *MRIsubtract(MRI *mri1, MRI *mri2, MRI *mri_dst)
3646 {
3647 int nframes, width, height, depth, x, y, z, f ;
3648 float v1, v2, vdiff;
3649
3650 width = mri1->width ;
3651 height = mri1->height ;
3652 depth = mri1->depth ;
3653 nframes = mri1->nframes ;
3654 if(nframes == 0) nframes = 1;
3655
3656 if (!mri_dst){
3657 mri_dst = MRIallocSequence(width, height, depth, mri1->type,nframes) ;
3658 MRIcopyHeader(mri1, mri_dst) ;
3659 }
3660
3661 for (z = 0 ; z < depth ; z++){
3662 for (y = 0 ; y < height ; y++){
3663 for (x = 0 ; x < width ; x++){
3664 for (f = 0 ; f < nframes ; f++){
3665 v1 = MRIgetVoxVal(mri1,x,y,z,f);
3666 v2 = MRIgetVoxVal(mri2,x,y,z,f);
3667 vdiff = v1-v2;
3668 MRIsetVoxVal(mri_dst,x,y,z,f,vdiff);
3669 }
3670 }
3671 }
3672 }
3673 return(mri_dst) ;
3674 }
3675 #endif
3676 /*-----------------------------------------------------
3677 ------------------------------------------------------*/
3678 MRI *
3679 MRIabsdiff(MRI *mri1, MRI *mri2, MRI *mri_dst)
3680 {
3681 int width, height, depth, x, y, z ;
3682 BUFTYPE *p1, *p2, *pdst, v1, v2 ;
3683 float f1, f2 ;
3684
3685 width = mri1->width ;
3686 height = mri1->height ;
3687 depth = mri1->depth ;
3688
3689 if (!mri_dst)
3690 {
3691 mri_dst = MRIalloc(width, height, depth, mri1->type) ;
3692 MRIcopyHeader(mri1, mri_dst) ;
3693 }
3694
3695 if (mri1->type == MRI_UCHAR && mri2->type == MRI_UCHAR)
3696 {
3697 for (z = 0 ; z < depth ; z++)
3698 {
3699 for (y = 0 ; y < height ; y++)
3700 {
3701 p1 = mri1->slices[z][y] ;
3702 p2 = mri2->slices[z][y] ;
3703 pdst = mri_dst->slices[z][y] ;
3704 for (x = 0 ; x < width ; x++)
3705 {
3706 v1 = *p1++ ;
3707 v2 = *p2++ ;
3708 if (v1 > v2)
3709 *pdst++ = v1 - v2 ;
3710 else
3711 *pdst++ = v2 - v1 ;
3712 }
3713 }
3714 }
3715 }
3716 else
3717 {
3718 for (z = 0 ; z < depth ; z++)
3719 {
3720 for (y = 0 ; y < height ; y++)
3721 {
3722 for (x = 0 ; x < width ; x++)
3723 {
3724 f1 = MRIgetVoxVal(mri1, x, y, z, 0) ;
3725 f2 = MRIgetVoxVal(mri2, x, y, z, 0) ;
3726 MRIsetVoxVal(mri_dst, x, y, z, 0, fabs(f1 - f2)) ;
3727 }
3728 }
3729 }
3730 }
3731 return(mri_dst) ;
3732 }
3733 /*-----------------------------------------------------
3734 ------------------------------------------------------*/
3735 MRI *MRIabs(MRI *mri_src, MRI *mri_dst)
3736 {
3737 int width, height, depth, nframes, x, y, z,f ;
3738 float val;
3739
3740 width = mri_src->width ;
3741 height = mri_src->height ;
3742 depth = mri_src->depth ;
3743 nframes = mri_src->nframes;
3744
3745 if (!mri_dst){
3746 mri_dst = MRIallocSequence(width, height, depth, mri_src->type, nframes) ;
3747 MRIcopyHeader(mri_src, mri_dst) ;
3748 }
3749
3750 for (z = 0 ; z < depth ; z++){
3751 for (y = 0 ; y < height ; y++){
3752 for (x = 0 ; x < width ; x++){
3753 for (f = 0 ; f < nframes ; f++){
3754 val = fabs(MRIgetVoxVal(mri_src,x,y,z,f));
3755 MRIsetVoxVal(mri_src,x,y,z,f,val);
3756 }
3757 }
3758 }
3759 }
3760 return(mri_dst) ;
3761 }
3762 /*-----------------------------------------------------*/
3763 MRI * MRIadd(MRI *mri1, MRI *mri2, MRI *mri_dst)
3764 {
3765 int nframes, width, height, depth, x, y, z, f, s ;
3766 float v1, v2, v=0.0;
3767 BUFTYPE *p1=NULL, *p2=NULL, *pdst=NULL ;
3768 short *ps1=NULL, *ps2=NULL, *psdst=NULL ;
3769 int *pi1=NULL, *pi2=NULL, *pidst=NULL ;
3770 long *pl1=NULL, *pl2=NULL, *pldst=NULL ;
3771 float *pf1=NULL, *pf2=NULL, *pfdst=NULL ;
3772
3773 width = mri1->width ;
3774 height = mri1->height ;
3775 depth = mri1->depth ;
3776 nframes = mri1->nframes ;
3777 if(nframes == 0) nframes = 1;
3778
3779 if (!mri_dst){
3780 mri_dst = MRIallocSequence(width, height, depth, mri1->type,nframes) ;
3781 MRIcopyHeader(mri1, mri_dst) ;
3782 }
3783
3784 if(mri1->type == MRI_UCHAR || (mri1->type != mri2->type)){
3785 /* Generic but slow */
3786 for (f = 0 ; f < nframes ; f++){
3787 for (z = 0 ; z < depth ; z++){
3788 for (y = 0 ; y < height ; y++){
3789 for (x = 0 ; x < width ; x++){
3790 v1 = MRIgetVoxVal(mri1,x,y,z,f);
3791 v2 = MRIgetVoxVal(mri2,x,y,z,f);
3792 v = v1+v2;
3793 if (mri_dst->type == MRI_UCHAR && v > 255)
3794 v = 255 ;
3795 MRIsetVoxVal(mri_dst,x,y,z,f,v);
3796 }
3797 }
3798 }
3799 }
3800 return(mri_dst) ;
3801 }
3802
3803
3804 s = 0;
3805 for (f = 0 ; f < nframes ; f++){
3806 for (z = 0 ; z < depth ; z++){
3807 for (y = 0 ; y < height ; y++){
3808
3809 switch(mri_dst->type){
3810 case MRI_UCHAR: pdst = mri_dst->slices[s][y] ; break;
3811 case MRI_SHORT: psdst = (short *) mri_dst->slices[s][y] ; break;
3812 case MRI_INT: pidst = (int *) mri_dst->slices[s][y] ; break;
3813 case MRI_LONG: pldst = (long *) mri_dst->slices[s][y] ; break;
3814 case MRI_FLOAT: pfdst = (float *) mri_dst->slices[s][y] ; break;
3815 }
3816
3817 switch(mri1->type){
3818 case MRI_UCHAR:
3819 p1 = mri1->slices[s][y] ;
3820 p2 = mri2->slices[s][y] ;
3821 break;
3822 case MRI_SHORT:
3823 ps1 = (short *) mri1->slices[s][y] ;
3824 ps2 = (short *) mri2->slices[s][y] ;
3825 break;
3826 case MRI_INT:
3827 pi1 = (int *) mri1->slices[s][y] ;
3828 pi2 = (int *) mri2->slices[s][y] ;
3829 break;
3830 case MRI_LONG:
3831 pl1 = (long *) mri1->slices[s][y] ;
3832 pl2 = (long *) mri2->slices[s][y] ;
3833 break;
3834 case MRI_FLOAT:
3835 pf1 = (float *) mri1->slices[s][y] ;
3836 pf2 = (float *) mri2->slices[s][y] ;
3837 break;
3838 }
3839
3840 for (x = 0 ; x < width ; x++){
3841
3842 switch(mri_dst->type){
3843 case MRI_UCHAR:
3844 switch(mri1->type){
3845 case MRI_UCHAR: (*pdst++) = (BUFTYPE) ((*p1++)+(*p2++)); break;
3846 case MRI_SHORT: (*pdst++) = (BUFTYPE) ((*ps1++)+(*ps2++)); break;
3847 case MRI_INT: (*pdst++) = (BUFTYPE) ((*pi1++)+(*pi2++)); break;
3848 case MRI_LONG: (*pdst++) = (BUFTYPE) ((*pl1++)+(*pl2++)); break;
3849 case MRI_FLOAT: (*pdst++) = (BUFTYPE) ((*pf1++)+(*pf2++)); break;
3850 }
3851 break;
3852 case MRI_SHORT:
3853 switch(mri1->type){
3854 case MRI_UCHAR: (*psdst++) = ((short)(*p1++)+(*p2++)); break;
3855 case MRI_SHORT: (*psdst++) = (short) ((*ps1++)+(*ps2++)); break;
3856 case MRI_INT: (*psdst++) = (short) ((*pi1++)+(*pi2++)); break;
3857 case MRI_LONG: (*psdst++) = (short) ((*pl1++)+(*pl2++)); break;
3858 case MRI_FLOAT: (*psdst++) = (short) ((*pf1++)+(*pf2++)); break;
3859 }
3860 break;
3861 case MRI_INT:
3862 switch(mri1->type){
3863 case MRI_UCHAR: (*pidst++) = ((int)(*p1++)+(*p2++)); break;
3864 case MRI_SHORT: (*pidst++) = ((int)(*ps1++)+(*ps2++)); break;
3865 case MRI_INT: (*pidst++) = (int) ((*pi1++)+(*pi2++)); break;
3866 case MRI_LONG: (*pidst++) = (int) ((*pl1++)+(*pl2++)); break;
3867 case MRI_FLOAT: (*pidst++) = (int) ((*pf1++)+(*pf2++)); break;
3868 }
3869 break;
3870 case MRI_LONG:
3871 switch(mri1->type){
3872 case MRI_UCHAR: (*pldst++) = ((long)(*p1++)+(*p2++)); break;
3873 case MRI_SHORT: (*pldst++) = ((long)(*ps1++)+(*ps2++)); break;
3874 case MRI_INT: (*pldst++) = ((long)(*pi1++)+(*pi2++)); break;
3875 case MRI_LONG: (*pldst++) = (long) ((*pl1++)+(*pl2++)); break;
3876 case MRI_FLOAT: (*pldst++) = (long) ((*pf1++)+(*pf2++)); break;
3877 }
3878 break;
3879 case MRI_FLOAT:
3880 switch(mri1->type){
3881 case MRI_UCHAR: (*pfdst++) = ((float)(*p1++)+(*p2++)); break;
3882 case MRI_SHORT: (*pfdst++) = ((float)(*ps1++)+(*ps2++)); break;
3883 case MRI_INT: (*pfdst++) = ((float)(*pi1++)+(*pi2++)); break;
3884 case MRI_LONG: (*pfdst++) = ((float)(*pl1++)+(*pl2++)); break;
3885 case MRI_FLOAT: (*pfdst++) = (*pf1++)+(*pf2++); break;
3886 }
3887 break;
3888 }
3889 }
3890 }
3891 s++;
3892 }
3893 }
3894
3895 return(mri_dst) ;
3896 }
3897 /*-----------------------------------------------------------
3898 MRIaverage() - computes average of source and destination.
3899 ------------------------------------------------------*/
3900 MRI *
3901 MRIaverage(MRI *mri_src, int dof, MRI *mri_dst)
3902 {
3903 int width, height, depth, x, y, z, f ;
3904 Real src, dst ;
3905
3906 width = mri_src->width ;
3907 height = mri_src->height ;
3908 depth = mri_src->depth ;
3909
3910 if (!mri_dst)
3911 {
3912 mri_dst = MRIalloc(width, height, depth, mri_src->type) ;
3913 MRIcopyHeader(mri_src, mri_dst) ;
3914 }
3915
3916 if (!MRIcheckSize(mri_src, mri_dst,0,0,0))
3917 ErrorReturn(NULL,
3918 (ERROR_BADPARM,"MRIaverage: incompatible volume dimensions"));
3919 #if 0
3920 if ((mri_src->type != MRI_UCHAR) || (mri_dst->type != MRI_UCHAR))
3921 ErrorReturn(NULL,
3922 (ERROR_UNSUPPORTED,
3923 "MRISaverage: unsupported voxel format %d",mri_src->type));
3924 #endif
3925
3926 for (f = 0 ; f < mri_src->nframes ; f++)
3927 {
3928 for (z = 0 ; z < depth ; z++)
3929 {
3930 for (y = 0 ; y < height ; y++)
3931 {
3932 for (x = 0 ; x < width ; x++)
3933 {
3934 MRIsampleVolumeFrameType
3935 (mri_src, x, y, z, f, SAMPLE_NEAREST, &src) ;
3936 MRIsampleVolumeFrameType
3937 (mri_dst, x, y, z, f, SAMPLE_NEAREST, &dst) ;
3938 MRIsetVoxVal
3939 (mri_dst, x, y, z, f, (dst*dof+src)/(Real)(dof+1)) ;
3940 }
3941 }
3942 }
3943 }
3944 return(mri_dst) ;
3945 }
3946 /*-----------------------------------------------------
3947 Parameters:
3948
3949 Returns value:
3950
3951 Description
3952
3953 ------------------------------------------------------*/
3954 MRI *
3955 MRImultiply(MRI *mri1, MRI *mri2, MRI *mri_dst)
3956 {
3957 int width, height, depth, x, y, z ;
3958 float f1, f2 ;
3959
3960 width = mri1->width ;
3961 height = mri1->height ;
3962 depth = mri1->depth ;
3963
3964 if (!mri_dst)
3965 {
3966 mri_dst = MRIalloc(width, height, depth, mri1->type) ;
3967 MRIcopyHeader(mri1, mri_dst) ;
3968 }
3969
3970 for (z = 0 ; z < depth ; z++)
3971 {
3972 for (y = 0 ; y < height ; y++)
3973 {
3974 for (x = 0 ; x < width ; x++)
3975 {
3976 f1 = MRIgetVoxVal(mri1, x, y, z, 0) ;
3977 f2 = MRIgetVoxVal(mri2, x, y, z, 0) ;
3978 MRIsetVoxVal(mri_dst, x, y, z, 0, f1*f2) ;
3979 }
3980 }
3981 }
3982 return(mri_dst) ;
3983 }
3984 /*-----------------------------------------------------
3985 Parameters:
3986
3987 Returns value:
3988
3989 Description
3990
3991 ------------------------------------------------------*/
3992 MRI *
3993 MRIscaleAndMultiply(MRI *mri1, float scale, MRI *mri2, MRI *mri_dst)
3994 {
3995 int width, height, depth, x, y, z ;
3996 BUFTYPE *p1, *p2, *pdst ;
3997 float out_val ;
3998
3999 width = mri1->width ;
4000 height = mri1->height ;
4001 depth = mri1->depth ;
4002
4003 if (!mri_dst)
4004 {
4005 mri_dst = MRIalloc(width, height, depth, mri1->type) ;
4006 MRIcopyHeader(mri1, mri_dst) ;
4007 }
4008
4009 for (z = 0 ; z < depth ; z++)
4010 {
4011 for (y = 0 ; y < height ; y++)
4012 {
4013 p1 = mri1->slices[z][y] ;
4014 p2 = mri2->slices[z][y] ;
4015 pdst = mri_dst->slices[z][y] ;
4016 for (x = 0 ; x < width ; x++)
4017 {
4018 out_val = *p1++ * (*p2++/scale) ;
4019 if (out_val > 255)
4020 out_val = 255 ;
4021 else if (out_val < 0)
4022 out_val = 0 ;
4023 *pdst++ = (BUFTYPE)nint(out_val) ;
4024 }
4025 }
4026 }
4027 return(mri_dst) ;
4028 }
4029 /*-----------------------------------------------------
4030 Parameters:
4031
4032 Returns value:
4033
4034 Description
4035
4036 ------------------------------------------------------*/
4037 MRI *
4038 MRIdivide(MRI *mri1, MRI *mri2, MRI *mri_dst)
4039 {
4040 int width, height, depth, x, y, z ;
4041 BUFTYPE *p1, *p2, *pdst ;
4042
4043 width = mri1->width ;
4044 height = mri1->height ;
4045 depth = mri1->depth ;
4046
4047 if (!mri_dst)
4048 {
4049 mri_dst = MRIalloc(width, height, depth, mri1->type) ;
4050 MRIcopyHeader(mri1, mri_dst) ;
4051 }
4052
4053 if (mri1->type != MRI_UCHAR || mri2->type != MRI_UCHAR)
4054 {
4055 Real val1, val2, dst ;
4056
4057 for (z = 0 ; z < depth ; z++)
4058 {
4059 for (y = 0 ; y < height ; y++)
4060 {
4061 pdst = mri_dst->slices[z][y] ;
4062 for (x = 0 ; x < width ; x++)
4063 {
4064 if (x == Gx && y == Gy && z==Gz)
4065 DiagBreak() ;
4066 val1 = MRIgetVoxVal(mri1, x, y, z, 0) ;
4067 val2 = MRIgetVoxVal(mri2, x, y, z, 0) ;
4068 if (FZERO(val2))
4069 {
4070 dst = FZERO(val1) ? 0 : 255 ;
4071 }
4072 else
4073 dst = val1 / val2 ;
4074 if (abs(dst) > 1000)
4075 DiagBreak() ;
4076 MRIsetVoxVal(mri_dst, x, y, z, 0, dst) ;
4077 }
4078 }
4079 }
4080 }
4081 else /* both UCHAR volumes */
4082 {
4083 for (z = 0 ; z < depth ; z++)
4084 {
4085 for (y = 0 ; y < height ; y++)
4086 {
4087 p1 = mri1->slices[z][y] ;
4088 p2 = mri2->slices[z][y] ;
4089 pdst = mri_dst->slices[z][y] ;
4090 for (x = 0 ; x < width ; x++)
4091 {
4092 if (!*p2)
4093 {
4094 *pdst = FZERO(*p1) ? 0 : 255 ;
4095 p2++ ;
4096 }
4097 else
4098 *pdst++ = *p1++ / *p2++ ;
4099 }
4100 }
4101 }
4102 }
4103 return(mri_dst) ;
4104 }
4105 /*-----------------------------------------------------
4106 MRIclone() - create a copy of an mri struct. Copies
4107 header info and allocs the pixel space (but does not
4108 copy pixel data).
4109 ------------------------------------------------------*/
4110 MRI *MRIclone(MRI *mri_src, MRI *mri_dst)
4111 {
4112 if (!mri_dst)
4113 mri_dst =
4114 MRIallocSequence(mri_src->width, mri_src->height,mri_src->depth,
4115 mri_src->type, mri_src->nframes);
4116
4117 MRIcopyHeader(mri_src, mri_dst) ;
4118 return(mri_dst) ;
4119 }
4120 /*---------------------------------------------------------------------
4121 MRIcloneSpace() - create a copy of an mri struct but allows user to
4122 set nframes (ie, all the spatial stuff is copied). Copies header
4123 info and allocs the pixel space (but does not copy pixel data).
4124 -------------------------------------------------------------------*/
4125 MRI *MRIcloneBySpace(MRI *mri_src, int nframes)
4126 {
4127 MRI *mri_dst;
4128 mri_dst = MRIallocSequence(mri_src->width, mri_src->height,mri_src->depth,
4129 mri_src->type, nframes);
4130 MRIcopyHeader(mri_src, mri_dst) ;
4131 mri_dst->nframes = nframes;
4132 return(mri_dst) ;
4133 }
4134 /*-----------------------------------------------------
4135 Description
4136 Copy one MRI into another (including header info)
4137 ------------------------------------------------------*/
4138 MRI *
4139 MRIcloneRoi(MRI *mri_src, MRI *mri_dst)
4140 {
4141 int w, h, d ;
4142
4143 w = mri_src->width - mri_src->roi.x ;
4144 h = mri_src->height - mri_src->roi.y ;
4145 d = mri_src->depth - mri_src->roi.z ;
4146 mri_dst = MRIallocSequence(w, h, d, MRI_FLOAT, mri_src->nframes) ;
4147 MRIcopyHeader(mri_src, mri_dst) ;
4148 mri_dst->xstart = mri_src->xstart + mri_src->roi.x * mri_src->xsize ;
4149 mri_dst->ystart = mri_src->ystart + mri_src->roi.y * mri_src->ysize ;
4150 mri_dst->zstart = mri_src->zstart + mri_src->roi.z * mri_src->zsize ;
4151 mri_dst->xend = mri_src->xstart + w * mri_src->xsize ;
4152 mri_dst->yend = mri_src->ystart + h * mri_src->ysize ;
4153 mri_dst->zend = mri_src->zstart + d * mri_src->zsize ;
4154 return(mri_dst) ;
4155 }
4156 /*-----------------------------------------------------
4157 Parameters:
4158
4159 Returns value:
4160
4161 Description
4162 Copy one MRI into another (including header info and data)
4163 ------------------------------------------------------*/
4164 MRI *
4165 MRIcopy(MRI *mri_src, MRI *mri_dst)
4166 {
4167 int width, height, depth, bytes, x, y, z, frame, val ;
4168 float *fdst, *fsrc ;
4169 BUFTYPE *csrc, *cdst ;
4170 int dest_ptype, *isrc;
4171 short *ssrc, *sdst ;
4172
4173 if (mri_src == mri_dst)
4174 return(mri_dst) ;
4175 width = mri_src->width ;
4176 height = mri_src->height ;
4177 depth = mri_src->depth ;
4178
4179 if (!mri_dst)
4180 {
4181 if(mri_src->slices)
4182 mri_dst = MRIallocSequence(width, height, depth, mri_src->type,
4183 mri_src->nframes) ;
4184 else
4185 mri_dst = MRIallocHeader(width, height, depth, mri_src->type);
4186 }
4187 dest_ptype = mri_dst->ptype;
4188 MRIcopyHeader(mri_src, mri_dst) ;
4189 mri_dst->ptype = dest_ptype;
4190
4191 if(!mri_src->slices)
4192 return(mri_dst);
4193
4194 if (mri_src->type == mri_dst->type)
4195 {
4196 bytes = width ;
4197 switch (mri_src->type)
4198 {
4199 case MRI_UCHAR:
4200 bytes *= sizeof(BUFTYPE) ;
4201 break ;
4202 case MRI_SHORT:
4203 bytes *= sizeof(short);
4204 break;
4205 case MRI_FLOAT:
4206 bytes *= sizeof(float) ;
4207 break ;
4208 case MRI_INT:
4209 bytes *= sizeof(int) ;
4210 break ;
4211 case MRI_LONG:
4212 bytes *= sizeof(long) ;
4213 break ;
4214 }
4215
4216 for (frame = 0 ; frame < mri_src->nframes ; frame++)
4217 {
4218 for (z = 0 ; z < depth ; z++)
4219 {
4220 for (y = 0 ; y < height ; y++)
4221 {
4222 memcpy(mri_dst->slices[z+frame*depth][y],
4223 mri_src->slices[z+frame*depth][y], bytes) ;
4224 }
4225 }
4226 }
4227 }
4228 else
4229 {
4230 switch (mri_src->type)
4231 {
4232 case MRI_FLOAT:
4233 switch (mri_dst->type)
4234 {
4235 case MRI_SHORT: /* float --> short */
4236 for (frame = 0 ; frame < mri_src->nframes ; frame++)
4237 {
4238 for (z = 0 ; z < depth ; z++)
4239 {
4240 for (y = 0 ; y < height ; y++)
4241 {
4242 sdst = &MRISseq_vox(mri_dst, 0, y, z, frame) ;
4243 fsrc = &MRIFseq_vox(mri_src, 0, y, z, frame) ;
4244 for (x = 0 ; x < width ; x++)
4245 {
4246 val = nint(*fsrc++) ;
4247 *sdst++ = (short)val ;
4248 }
4249 }
4250 }
4251 }
4252 break ;
4253 case MRI_UCHAR: /* float --> unsigned char */
4254 for (frame = 0 ; frame < mri_src->nframes ; frame++)
4255 {
4256 for (z = 0 ; z < depth ; z++)
4257 {
4258 for (y = 0 ; y < height ; y++)
4259 {
4260 cdst = &MRIseq_vox(mri_dst, 0, y, z, frame) ;
4261 fsrc = &MRIFseq_vox(mri_src, 0, y, z, frame) ;
4262 for (x = 0 ; x < width ; x++)
4263 {
4264 val = nint(*fsrc++) ;
4265 if (val > 255)
4266 val = 255 ;
4267 *cdst++ = (BUFTYPE)val ;
4268 }
4269 }
4270 }
4271 }
4272 break ;
4273 default:
4274 ErrorReturn(NULL,
4275 (ERROR_BADPARM,
4276 "MRIcopy: src type %d & dst type %d unsupported",
4277 mri_src->type, mri_dst->type)) ;
4278 break ;
4279 }
4280 break ;
4281 case MRI_UCHAR:
4282 switch (mri_dst->type)
4283 {
4284 case MRI_FLOAT: /* unsigned char --> float */
4285 for (frame = 0 ; frame < mri_src->nframes ; frame++)
4286 {
4287 for (z = 0 ; z < depth ; z++)
4288 {
4289 for (y = 0 ; y < height ; y++)
4290 {
4291 fdst = &MRIFseq_vox(mri_dst, 0, y, z, frame) ;
4292 csrc = &MRIseq_vox(mri_src, 0, y, z, frame) ;
4293 for (x = 0 ; x < width ; x++)
4294 *fdst++ = (float)*csrc++ ;
4295 }
4296 }
4297 }
4298 break ;
4299 default:
4300 ErrorReturn(NULL,
4301 (ERROR_BADPARM,
4302 "MRIcopy: src type %d & dst type %d unsupported",
4303 mri_src->type, mri_dst->type)) ;
4304 break ;
4305 }
4306 break ;
4307 case MRI_SHORT:
4308 switch (mri_dst->type)
4309 {
4310 case MRI_FLOAT: /* short --> float */
4311 for (frame = 0 ; frame < mri_src->nframes ; frame++)
4312 {
4313 for (z = 0 ; z < depth ; z++)
4314 {
4315 for (y = 0 ; y < height ; y++)
4316 {
4317 fdst = &MRIFseq_vox(mri_dst, 0, y, z, frame) ;
4318 ssrc = &MRISseq_vox(mri_src, 0, y, z, frame) ;
4319 for (x = 0 ; x < width ; x++)
4320 {
4321 if (z == 113 && y == 143 && x == 161)
4322 DiagBreak() ;
4323 *fdst++ = (float)*ssrc++ ;
4324 }
4325 }
4326 }
4327 }
4328 break ;
4329 case MRI_UCHAR:
4330 for (frame = 0 ; frame < mri_src->nframes ; frame++)
4331 {
4332 for (z = 0 ; z < depth ; z++)
4333 {
4334 for (y = 0 ; y < height ; y++)
4335 {
4336 cdst = &MRIseq_vox(mri_dst, 0, y, z, frame) ;
4337 ssrc = &MRISseq_vox(mri_src, 0, y, z, frame) ;
4338 for (x = 0 ; x < width ; x++)
4339 {
4340 *cdst++ = (float)*ssrc++ ;
4341 }
4342 }
4343 }
4344 }
4345 break ;
4346 default:
4347 ErrorReturn(NULL,
4348 (ERROR_BADPARM,
4349 "MRIcopy: src type %d & dst type %d unsupported",
4350 mri_src->type, mri_dst->type)) ;
4351 break ;
4352 }
4353 break ;
4354 case MRI_INT:
4355 switch (mri_dst->type)
4356 {
4357 case MRI_FLOAT: /* unsigned char --> float */
4358 for (frame = 0 ; frame < mri_src->nframes ; frame++)
4359 {
4360 for (z = 0 ; z < depth ; z++)
4361 {
4362 for (y = 0 ; y < height ; y++)
4363 {
4364 fdst = &MRIFseq_vox(mri_dst, 0, y, z, frame) ;
4365 isrc = &MRIIseq_vox(mri_src, 0, y, z, frame) ;
4366 for (x = 0 ; x < width ; x++)
4367 *fdst++ = (float)*isrc++ ;
4368 }
4369 }
4370 }
4371 break ;
4372 default:
4373 ErrorReturn(NULL,
4374 (ERROR_BADPARM,
4375 "MRIcopy: src type %d & dst type %d unsupported",
4376 mri_src->type, mri_dst->type)) ;
4377 break ;
4378 }
4379 break ;
4380 default:
4381 ErrorReturn(NULL,
4382 (ERROR_BADPARM,
4383 "MRIcopy: src type %d & dst type %d unsupported",
4384 mri_src->type, mri_dst->type)) ;
4385 break ; /* in case someone removes the errorreturn */
4386 }
4387 }
4388 return(mri_dst) ;
4389 }
4390 /*
4391 make MAX_INDEX way larger than it has to be. This will give
4392 some headroom for bad (e.g. poorly registered) images without
4393 sacrificing too much space.
4394 */
4395 #define MAX_INDEX 500
4396 /*-----------------------------------------------------
4397 Parameters:
4398
4399 Returns value:
4400
4401 Description
4402 allocate a lookup table that allows indices which
4403 are outside the image region.
4404 ------------------------------------------------------*/
4405 int
4406 MRIallocIndices(MRI *mri)
4407 {
4408 int width, height, depth, i ;
4409
4410 width = mri->width ;
4411 height = mri->height ;
4412 depth = mri->depth ;
4413 mri->xi = (int *)calloc(width+2*MAX_INDEX, sizeof(int)) ;
4414 if (!mri->xi)
4415 ErrorExit(ERROR_NO_MEMORY,
4416 "MRIallocIndices: could not allocate %d elt index array",
4417 width+2*MAX_INDEX) ;
4418 mri->yi = (int *)calloc(height+2*MAX_INDEX, sizeof(int)) ;
4419 if (!mri->yi)
4420 ErrorExit(ERROR_NO_MEMORY,
4421 "MRIallocIndices: could not allocate %d elt index array",
4422 height+2*MAX_INDEX) ;
4423 mri->zi = (int *)calloc(depth+2*MAX_INDEX, sizeof(int)) ;
4424 if (!mri->zi)
4425 ErrorExit(ERROR_NO_MEMORY,
4426 "MRIallocIndices: could not allocate %d elt index array",
4427 depth+2*MAX_INDEX) ;
4428
4429 /*
4430 indexing into these arrays returns valid pixel indices from
4431 -MAX_INDEX to width+MAX_INDEX
4432 */
4433 mri->xi += MAX_INDEX ;
4434 mri->yi += MAX_INDEX ;
4435 mri->zi += MAX_INDEX ;
4436 for (i = -MAX_INDEX ; i < width+MAX_INDEX ; i++)
4437 {
4438 if (i <= 0)
4439 mri->xi[i] = 0 ;
4440 else if (i >= width)
4441 mri->xi[i] = width-1 ;
4442 else
4443 mri->xi[i] = i ;
4444 }
4445 for (i = -MAX_INDEX ; i < height+MAX_INDEX ; i++)
4446 {
4447 if (i <= 0)
4448 mri->yi[i] = 0 ;
4449 else if (i >= height)
4450 mri->yi[i] = height-1 ;
4451 else
4452 mri->yi[i] = i ;
4453 }
4454 for (i = -MAX_INDEX ; i < depth+MAX_INDEX ; i++)
4455 {
4456 if (i <= 0)
4457 mri->zi[i] = 0 ;
4458 else if (i >= depth)
4459 mri->zi[i] = depth-1 ;
4460 else
4461 mri->zi[i] = i ;
4462 }
4463
4464 return(NO_ERROR) ;
4465 }
4466 /*-----------------------------------------------------
4467 Parameters:
4468
4469 Returns value:
4470
4471 Description
4472 allocate an MRI data structure as well as space for
4473 the image data
4474 ------------------------------------------------------*/
4475 MRI *
4476 MRIallocSequence(int width, int height, int depth, int type, int nframes)
4477 {
4478 MRI *mri ;
4479 int slice, row, bpp ;
4480 BUFTYPE *buf ;
4481
4482 mris_alloced++ ;
4483
4484 if ((width <= 0) || (height <= 0) || (depth <= 0))
4485 ErrorReturn(NULL,
4486 (ERROR_BADPARM, "MRIalloc(%d, %d, %d): bad parm",
4487 width, height, depth)) ;
4488 #if 1
4489 mri = MRIallocHeader(width, height, depth, type) ;
4490 MRIinitHeader(mri) ;
4491 #else
4492 mri = (MRI *)calloc(1, sizeof(MRI)) ;
4493 if (!mri)
4494 ErrorExit(ERROR_NO_MEMORY, "MRIalloc: could not allocate MRI\n") ;
4495
4496 mri->scale = 1 ;
4497 mri->height = height ;
4498 mri->width = width ;
4499 mri->yinvert = 1 ;
4500 mri->depth = depth ;
4501 mri->type = type ;
4502 #endif
4503 mri->nframes = nframes ;
4504 MRIallocIndices(mri) ;
4505 mri->slices = (BUFTYPE ***)calloc(depth*nframes, sizeof(BUFTYPE **)) ;
4506 if (!mri->slices)
4507 ErrorExit(ERROR_NO_MEMORY,
4508 "MRIalloc: could not allocate %d slices\n", mri->depth) ;
4509
4510 for (slice = 0 ; slice < depth*nframes ; slice++)
4511 {
4512 /* allocate pointer to array of rows */
4513 mri->slices[slice] = (BUFTYPE **)calloc(mri->height, sizeof(BUFTYPE *)) ;
4514 if (!mri->slices[slice])
4515 ErrorExit
4516 (ERROR_NO_MEMORY,
4517 "MRIalloc(%d, %d, %d): could not allocate "
4518 "%d bytes for %dth slice\n",
4519 height, width, depth, mri->height*sizeof(BUFTYPE *), slice) ;
4520
4521 #if USE_ELECTRIC_FENCE
4522 switch (mri->type)
4523 {
4524 case MRI_BITMAP:
4525 bpp = 1 ;
4526 break ;
4527 case MRI_UCHAR:
4528 bpp = 8 ;
4529 break ;
4530 case MRI_TENSOR:
4531 case MRI_FLOAT:
4532 bpp = sizeof(float) * 8 ;
4533 break ;
4534 case MRI_INT:
4535 bpp = sizeof(int) * 8 ;
4536 break ;
4537 case MRI_SHORT:
4538 bpp = sizeof(short) * 8 ;
4539 break ;
4540 case MRI_LONG:
4541 bpp = sizeof(long) * 8 ;
4542 break ;
4543 default:
4544 ErrorReturn(NULL,
4545 (ERROR_BADPARM,
4546 "MRIalloc(%d, %d, %d, %d): unknown type",
4547 width, height, depth, mri->type)) ;
4548 break ;
4549 }
4550 bpp /= 8 ;
4551 buf = (BUFTYPE *)calloc((mri->width*mri->height*bpp), 1) ;
4552 if (buf == NULL)
4553 ErrorExit
4554 (ERROR_NO_MEMORY,
4555 "MRIalloc(%d, %d, %d): could not allocate "
4556 "%d bytes for %dth slice\n",
4557 height, width, depth, (mri->width*mri->height*bpp), slice) ;
4558 for (row = 0 ; row < mri->height ; row++)
4559 {
4560 mri->slices[slice][row] = buf+(row*mri->width*bpp) ;
4561 }
4562 #else
4563 /* allocate each row */
4564 for (row = 0 ; row < mri->height ; row++)
4565 {
4566 switch (mri->type)
4567 {
4568 case MRI_BITMAP:
4569 mri->slices[slice][row] =
4570 (BUFTYPE*)calloc(mri->width/8,sizeof(BUFTYPE));
4571 break ;
4572 case MRI_UCHAR:
4573 mri->slices[slice][row] =
4574 (BUFTYPE*)calloc(mri->width,sizeof(BUFTYPE));
4575 break ;
4576 case MRI_TENSOR:
4577 case MRI_FLOAT:
4578 mri->slices[slice][row] =
4579 (BUFTYPE *)calloc(mri->width, sizeof(float));
4580 break ;
4581 case MRI_INT:
4582 mri->slices[slice][row] =
4583 (BUFTYPE *)calloc(mri->width, sizeof(int)) ;
4584 break ;
4585 case MRI_SHORT:
4586 mri->slices[slice][row] =
4587 (BUFTYPE *)calloc(mri->width, sizeof(short));
4588 break ;
4589 case MRI_LONG:
4590 mri->slices[slice][row] =
4591 (BUFTYPE *)calloc(mri->width, sizeof(long)) ;
4592 break ;
4593 default:
4594 ErrorReturn(NULL,
4595 (ERROR_BADPARM,
4596 "MRIalloc(%d, %d, %d, %d): unknown type",
4597 width, height, depth, mri->type)) ;
4598 break ;
4599 }
4600
4601 if (!mri->slices[slice][row])
4602 ErrorExit
4603 (ERROR_NO_MEMORY,
4604 "MRIalloc(%d,%d,%d): could not allocate "
4605 "%dth row in %dth slice\n",
4606 width,height,depth, slice, row) ;
4607 }
4608 #endif
4609 }
4610
4611 return(mri) ;
4612 }
4613 /*-----------------------------------------------------
4614 Parameters:
4615
4616 Returns value:
4617
4618 Description
4619 allocate an MRI data structure but not space for
4620 the image data
4621 ------------------------------------------------------*/
4622 MRI *
4623 MRIallocHeader(int width, int height, int depth, int type)
4624 {
4625 MRI *mri ;
4626
4627 mri = (MRI *)calloc(1, sizeof(MRI)) ;
4628 if (!mri)
4629 ErrorExit(ERROR_NO_MEMORY, "MRIalloc: could not allocate MRI\n") ;
4630
4631 mri->imnr0 = 1 ;
4632 mri->imnr1 = depth;
4633 mri->fov = width ;
4634 mri->thick = 1.0 ;
4635 mri->scale = 1 ;
4636 mri->roi.dx = mri->width = width ;
4637 mri->roi.dy = mri->height = height ;
4638 mri->roi.dz = mri->depth = depth ;
4639 mri->yinvert = 1 ;
4640 mri->xsize = mri->ysize = mri->zsize = 1 ;
4641 mri->type = type ;
4642 mri->nframes = 1 ;
4643 mri->xi = mri->yi = mri->zi = NULL ;
4644 mri->slices = NULL ;
4645 mri->ps = 1 ;
4646 mri->xstart = -mri->width/2.0 ;
4647 mri->xend = mri->width/2.0 ;
4648 mri->ystart = -mri->height/2.0 ;
4649 mri->yend = mri->height/2.0 ;
4650 mri->zstart = -mri->depth/2.0 ;
4651 mri->zend = mri->depth/2 ;
4652 //
4653 mri->x_r = -1;
4654 mri->x_a = 0.;
4655 mri->x_s = 0.;
4656 //
4657 mri->y_r = 0.;
4658 mri->y_a = 0.;
4659 mri->y_s = -1;
4660 //
4661 mri->z_r = 0.;
4662 mri->z_a = 1.;
4663 mri->z_s = 0.;
4664 //
4665 mri->c_r = mri->c_a = mri->c_s = 0.0;
4666 mri->ras_good_flag = 0;
4667 mri->brightness = 1;
4668 mri->register_mat = NULL;
4669 mri->subject_name[0] = '\0';
4670 mri->path_to_t1[0] = '\0';
4671 mri->fname_format[0] = '\0';
4672 mri->gdf_image_stem[0] = '\0';
4673 mri->tag_data = NULL;
4674 mri->tag_data_size = 0;
4675
4676 mri->i_to_r__ = extract_i_to_r(mri);
4677 mri->r_to_i__ = extract_r_to_i(mri);
4678
4679 return(mri) ;
4680 }
4681 /*-----------------------------------------------------
4682 Parameters:
4683
4684 Returns value:
4685
4686 Description
4687 allocate an MRI data structure as well as space for
4688 the image data
4689 ------------------------------------------------------*/
4690 MRI *
4691 MRIalloc(int width, int height, int depth, int type)
4692 {
4693 return(MRIallocSequence(width, height, depth, type, 1)) ;
4694 }
4695 /*-----------------------------------------------------
4696 Parameters:
4697
4698 Returns value:
4699
4700 Description
4701 Free and MRI data structure and all its attached memory
4702 ------------------------------------------------------*/
4703 int
4704 MRIfree(MRI **pmri)
4705 {
4706 MRI *mri ;
4707 int slice, i ;
4708 #if !USE_ELECTRIC_FENCE
4709 int row ;
4710 #endif
4711
4712 mris_alloced-- ;
4713 mri = *pmri ;
4714 if (!mri)
4715 ErrorReturn(ERROR_BADPARM, (ERROR_BADPARM, "MRIfree: null pointer\n")) ;
4716
4717 if (mri->xi)
4718 free(mri->xi-MAX_INDEX) ;
4719 if (mri->yi)
4720 free(mri->yi-MAX_INDEX) ;
4721 if (mri->zi)
4722 free(mri->zi-MAX_INDEX) ;
4723
4724 if (mri->slices)
4725 {
4726 for (slice = 0 ; slice < mri->depth*mri->nframes ; slice++)
4727 {
4728 if (mri->slices[slice])
4729 {
4730 #if USE_ELECTRIC_FENCE
4731 free(mri->slices[slice][0]) ;
4732 #else
4733 for (row = 0 ; row < mri->height ; row++)
4734 free(mri->slices[slice][row]) ;
4735 #endif
4736 free(mri->slices[slice]) ;
4737 }
4738 }
4739 free(mri->slices) ;
4740 }
4741
4742 if (mri->free_transform)
4743 delete_general_transform(&mri->transform) ;
4744
4745 if(mri->register_mat != NULL)
4746 MatrixFree(&(mri->register_mat));
4747
4748 if (mri->i_to_r__)
4749 MatrixFree(&mri->i_to_r__);
4750 if (mri->r_to_i__)
4751 MatrixFree(&mri->r_to_i__);
4752
4753 for (i = 0 ; i < mri->ncmds ; i++)
4754 free(mri->cmdlines[i]) ;
4755
4756 free(mri) ;
4757 *pmri = NULL ;
4758
4759 return(NO_ERROR) ;
4760 }
4761 /*-----------------------------------------------------
4762 Parameters:
4763
4764 Returns value:
4765
4766 Description
4767 Free and MRI data structure and all its attached memory
4768 ------------------------------------------------------*/
4769 int
4770 MRIfreeFrames(MRI *mri, int start_frame)
4771 {
4772 int slice, row, end_frame ;
4773
4774 end_frame = mri->nframes-1 ;
4775 if (!mri)
4776 ErrorReturn(ERROR_BADPARM, (ERROR_BADPARM, "MRIfree: null pointer\n")) ;
4777
4778 if (mri->slices)
4779 {
4780 for (slice = start_frame*mri->depth ;
4781 slice < mri->depth*end_frame ; slice++)
4782 {
4783 if (mri->slices[slice])
4784 {
4785 for (row = 0 ; row < mri->height ; row++)
4786 free(mri->slices[slice][row]) ;
4787 free(mri->slices[slice]) ;
4788 }
4789 }
4790 }
4791
4792 mri->nframes -= (end_frame-start_frame+1) ;
4793 return(NO_ERROR) ;
4794 }
4795 /*-----------------------------------------------------
4796 Parameters:
4797
4798 Returns value:
4799
4800 Description
4801 Dump the MRI header to a file
4802 ------------------------------------------------------*/
4803 int
4804 MRIdump(MRI *mri, FILE *fp)
4805 {
4806 fprintf(fp, "%6.6s = %s\n", "fname", mri->fname);
4807 fprintf(fp, "%6.6s = %d\n", "height", mri->height);
4808 fprintf(fp, "%6.6s = %d\n", "width", mri->width);
4809 fprintf(fp, "%6.6s = %d\n", "depth", mri->depth);
4810 fprintf(fp, "%6.6s = %d\n", "nframes", mri->nframes);
4811 fprintf(fp, "%6.6s = %d\n", "imnr0", mri->imnr0);
4812 fprintf(fp, "%6.6s = %d\n", "imnr1", mri->imnr1);
4813 fprintf(fp, "%6.6s = %d\n", "xnum", mri->width);
4814 fprintf(fp, "%6.6s = %d\n", "ynum", mri->height);
4815 fprintf(fp, "%6.6s = %f\n", "fov", mri->fov);
4816 fprintf(fp, "%6.6s = %f\n", "thick", mri->thick);
4817 fprintf(fp, "%6.6s = %f\n", "xstart", mri->xstart); /* strtx */
4818 fprintf(fp, "%6.6s = %f\n", "xend", mri->xend); /* endx */
4819 fprintf(fp, "%6.6s = %f\n", "ystart", mri->ystart); /* strty */
4820 fprintf(fp, "%6.6s = %f\n", "yend", mri->yend); /* endy */
4821 fprintf(fp, "%6.6s = %f\n", "zstart", mri->zstart); /* strtz */
4822 fprintf(fp, "%6.6s = %f\n", "zend", mri->zend); /* endz */
4823 fprintf(fp, "%6.6s = %d\n", "type", mri->type);
4824 fprintf(fp, "%6.6s = %f\n", "xsize", mri->xsize);
4825 fprintf(fp, "%6.6s = %f\n", "ysize", mri->ysize);
4826 fprintf(fp, "%6.6s = %f\n", "zsize", mri->zsize);
4827 fprintf(fp, "%6.6s = %f %f %f\n", "x ras", mri->x_r, mri->x_a, mri->x_s);
4828 fprintf(fp, "%6.6s = %f %f %f\n", "y ras", mri->y_r, mri->y_a, mri->y_s);
4829 fprintf(fp, "%6.6s = %f %f %f\n", "z ras", mri->z_r, mri->z_a, mri->z_s);
4830 fprintf(fp, "%6.6s = %f %f %f\n", "c ras", mri->c_r, mri->c_a, mri->c_s);
4831 fprintf(fp, "%s = %f\n", "det(xyz_ras)", MRIvolumeDeterminant(mri));
4832 fprintf(fp, "%s = %d\n", "ras_good_flag", mri->ras_good_flag);
4833 fprintf(fp, "%s = %d\n", "brightness", mri->brightness);
4834 fprintf(fp, "%s = %s\n", "subject_name", mri->subject_name);
4835 fprintf(fp, "%s = %s\n", "path_to_t1", mri->path_to_t1);
4836 fprintf(fp, "%s = %s\n", "fname_format", mri->fname_format);
4837 if(mri->register_mat != NULL)
4838 {
4839 fprintf(fp, "%s = \n", "register_mat");
4840 MatrixPrint(fp, mri->register_mat);
4841 }
4842 return(NO_ERROR) ;
4843 }
4844 /*-----------------------------------------------------
4845 Parameters:
4846
4847 Returns value:
4848
4849 Description
4850 Dump the non-zero elements of an MRI buffer to a file
4851 ------------------------------------------------------*/
4852 int
4853 MRIdumpBuffer(MRI *mri, FILE *fp)
4854 {
4855 int x, y, z ;
4856
4857 for (z = 0 ; z < mri->depth ; z++)
4858 {
4859 for (y = 0 ; y < mri->height ; y++)
4860 {
4861 for (x = 0 ; x < mri->width ; x++)
4862 {
4863 switch (mri->type)
4864 {
4865 case MRI_UCHAR:
4866 if (!FZERO(mri->slices[z][y][x]))
4867 fprintf
4868 (fp,
4869 "[%d][%d][%d]: %d\n",
4870 x,y,z,(int)mri->slices[z][y][x]);
4871 break ;
4872 case MRI_FLOAT:
4873 /* if (!FZERO(MRIFvox(mri,x,y,z)))*/
4874 fprintf
4875 (fp,
4876 "[%d][%d][%d]: %2.3f\n",
4877 x,y,z, MRIFvox(mri,x,y,z));
4878 break ;
4879 }
4880 }
4881 }
4882 }
4883 return(NO_ERROR) ;
4884 }
4885 /*-----------------------------------------------------
4886 Parameters:
4887
4888 Returns value:
4889
4890 Description
4891 Find the peak intensity in an MRI image
4892 ------------------------------------------------------*/
4893 int
4894 MRIpeak(MRI *mri, int *px, int *py, int *pz)
4895 {
4896 int max_row, max_col, max_slice, row, col, slice, width, height, depth ;
4897 BUFTYPE val, max_val, *im ;
4898 long lval, lmax_val, *lim ;
4899 int ival, imax_val, *iim ;
4900 float fval, fmax_val, *fim ;
4901
4902 max_val = 0 ;
4903 lmax_val = 0L ;
4904 imax_val = 0 ;
4905 fmax_val = 0.0f ;
4906 max_row = max_col = max_slice = -1 ; /* to prevent compiler warning */
4907 width = mri->width ;
4908 height = mri->height ;
4909 depth = mri->depth ;
4910 for (slice = 0 ; slice < depth ; slice++)
4911 {
4912 for (row = 0 ; row < height ; row++)
4913 {
4914 switch (mri->type)
4915 {
4916 case MRI_UCHAR:
4917 im = mri->slices[slice][row] ;
4918 for (col = 0 ; col < width ; col++)
4919 {
4920 val = *im++ ;
4921 if (val > max_val)
4922 {
4923 max_val = val ;
4924 max_row = row ;
4925 max_col = col ;
4926 max_slice = slice ;
4927 }
4928 }
4929 break ;
4930 case MRI_LONG:
4931 lim = (long *)mri->slices[slice][row] ;
4932 for (col = 0 ; col < width ; col++)
4933 {
4934 lval = *lim++ ;
4935 if (lval > lmax_val)
4936 {
4937 lmax_val = lval ;
4938 max_row = row ;
4939 max_col = col ;
4940 max_slice = slice ;
4941 }
4942 }
4943 break ;
4944 case MRI_FLOAT:
4945 fim = (float *)mri->slices[slice][row] ;
4946 for (col = 0 ; col < width ; col++)
4947 {
4948 fval = *fim++ ;
4949 if (fval > fmax_val)
4950 {
4951 fmax_val = fval ;
4952 max_row = row ;
4953 max_col = col ;
4954 max_slice = slice ;
4955 }
4956 }
4957 break ;
4958 case MRI_INT:
4959 iim = (int *)mri->slices[slice][row] ;
4960 for (col = 0 ; col < width ; col++)
4961 {
4962 ival = *iim++ ;
4963 if (ival > imax_val)
4964 {
4965 imax_val = ival ;
4966 max_row = row ;
4967 max_col = col ;
4968 max_slice = slice ;
4969 }
4970 }
4971 break ;
4972 }
4973 }
4974 }
4975
4976 *px = max_col ;
4977 *py = max_row ;
4978 *pz = max_slice ;
4979 return(NO_ERROR) ;
4980 }
4981 /*--------------------------------------------------------------
4982 Description: Copy the header information from one MRI into another.
4983 Does not copy the dimension lengths, only the geometry, pulse seq,
4984 etc.
4985 ------------------------------------------------------*/
4986 int MRIcopyHeader(MRI *mri_src, MRI *mri_dst)
4987 {
4988 int i ;
4989
4990 mri_dst->dof = mri_src->dof ;
4991 mri_dst->mean = mri_src->mean ;
4992 mri_dst->xsize = mri_src->xsize ;
4993 mri_dst->ysize = mri_src->ysize ;
4994 mri_dst->zsize = mri_src->zsize ;
4995 if (mri_src->linear_transform)
4996 {
4997 copy_general_transform(&mri_src->transform, &mri_dst->transform) ;
4998 mri_dst->linear_transform = mri_src->linear_transform ;
4999 mri_dst->inverse_linear_transform = mri_src->inverse_linear_transform ;
5000 mri_dst->linear_transform =
5001 get_linear_transform_ptr(&mri_dst->transform) ;
5002 mri_dst->inverse_linear_transform =
5003 get_inverse_linear_transform_ptr(&mri_dst->transform) ;
5004 mri_dst->free_transform = 1 ;
5005 }
5006 strcpy(mri_dst->transform_fname, mri_src->transform_fname) ;
5007 if (mri_dst->depth == mri_src->depth)
5008 {
5009 mri_dst->imnr0 = mri_src->imnr0 ;
5010 mri_dst->imnr1 = mri_src->imnr1 ;
5011 }
5012 mri_dst->ptype = mri_src->ptype ;
5013 mri_dst->fov = mri_src->fov ;
5014 mri_dst->thick = mri_src->thick ;
5015 mri_dst->ps = mri_src->ps ;
5016 mri_dst->location = mri_src->location ;
5017 mri_dst->xstart = mri_src->xstart ;
5018 mri_dst->xend = mri_src->xend ;
5019 mri_dst->ystart = mri_src->ystart ;
5020 mri_dst->yend = mri_src->yend ;
5021 mri_dst->zstart = mri_src->zstart ;
5022 mri_dst->zend = mri_src->zend ;
5023 mri_dst->flip_angle = mri_src->flip_angle ;
5024 mri_dst->tr = mri_src->tr ;
5025 mri_dst->te = mri_src->te ;
5026 mri_dst->ti = mri_src->ti ;
5027 strcpy(mri_dst->fname, mri_src->fname) ;
5028 mri_dst->x_r = mri_src->x_r;
5029 mri_dst->x_a = mri_src->x_a;
5030 mri_dst->x_s = mri_src->x_s;
5031 mri_dst->y_r = mri_src->y_r;
5032 mri_dst->y_a = mri_src->y_a;
5033 mri_dst->y_s = mri_src->y_s;
5034 mri_dst->z_r = mri_src->z_r;
5035 mri_dst->z_a = mri_src->z_a;
5036 mri_dst->z_s = mri_src->z_s;
5037 mri_dst->c_r = mri_src->c_r;
5038 mri_dst->c_a = mri_src->c_a;
5039 mri_dst->c_s = mri_src->c_s;
5040 mri_dst->ras_good_flag = mri_src->ras_good_flag;
5041
5042 mri_dst->brightness = mri_src->brightness;
5043 if(mri_src->register_mat != NULL)
5044 MatrixCopy(mri_src->register_mat, mri_dst->register_mat);
5045 else
5046 mri_dst->register_mat = NULL;
5047 strcpy(mri_dst->subject_name, mri_src->subject_name);
5048 strcpy(mri_dst->path_to_t1, mri_src->path_to_t1);
5049 strcpy(mri_dst->fname_format, mri_src->fname_format);
5050
5051 strcpy(mri_dst->gdf_image_stem, mri_src->gdf_image_stem);
5052
5053 mri_dst->i_to_r__ = MatrixCopy(mri_src->i_to_r__, mri_dst->i_to_r__);
5054 mri_dst->r_to_i__ = MatrixCopy(mri_src->r_to_i__, mri_dst->r_to_i__);
5055
5056 for (i = 0 ; i < mri_src->ncmds ; i++)
5057 {
5058 mri_dst->cmdlines[i] =
5059 (char *)calloc(strlen(mri_src->cmdlines[i])+1, sizeof(char)) ;
5060 strcpy(mri_dst->cmdlines[i], mri_src->cmdlines[i]) ;
5061 }
5062 mri_dst->ncmds = mri_src->ncmds ;
5063 return(NO_ERROR) ;
5064 }
5065 /*-----------------------------------------------------
5066 Parameters:
5067
5068 Returns value:
5069
5070 Description
5071 Translate the MRI image mri_src by the vector
5072 dx, dy, dz and store the result in mri_dst.
5073 ------------------------------------------------------*/
5074 MRI *
5075 MRItranslate(MRI *mri_src, MRI *mri_dst, double dx, double dy, double dz)
5076 {
5077 int y1, y2, y3, width, height, depth ;
5078 BUFTYPE *pdst ;
5079 Real x1, x2, x3, val ;
5080
5081 width = mri_src->width ;
5082 height = mri_src->height ;
5083 depth = mri_src->depth ;
5084 if (!mri_dst)
5085 mri_dst = MRIclone(mri_src, NULL) ;
5086 else
5087 MRIclear(mri_dst) ;
5088
5089 for (y3 = 0 ; y3 < depth ; y3++)
5090 {
5091 x3 = (Real)y3 - dz ;
5092 if (x3 < 0 || x3 >= depth)
5093 continue ;
5094
5095 for (y2 = 0 ; y2 < height ; y2++)
5096 {
5097 x2 = (Real)y2 - dy ;
5098 if (x2 < 0 || x2 >= height)
5099 continue ;
5100
5101 pdst = &MRIvox(mri_dst, 0, y2, y3) ;
5102 for (y1 = 0 ; y1 < width ; y1++, pdst++)
5103 {
5104 x1 = (Real)y1 - dx ;
5105 if (x1 >= 0 && x1 < width)
5106 {
5107 MRIsampleVolume(mri_src, x1, x2, x3, &val) ;
5108 *pdst = (BUFTYPE)nint(val) ;
5109 }
5110 }
5111 }
5112 }
5113
5114 mri_dst->ras_good_flag = 0;
5115
5116 return(mri_dst) ;
5117 }
5118 /*-----------------------------------------------------
5119 Parameters:
5120
5121 Returns value:
5122
5123 Description
5124 Rotate mri_src around the Y axis and return the
5125 result in mri_dst
5126 ------------------------------------------------------*/
5127 MRI *
5128 MRIrotateX(MRI *mri_src, MRI *mri_dst, float x_angle)
5129 {
5130 int width, height, depth ;
5131 MATRIX *m, *mO ;
5132
5133 width = mri_src->width ;
5134 height = mri_src->height ;
5135 depth = mri_src->depth ;
5136 if (!mri_dst)
5137 mri_dst = MRIclone(mri_src, NULL) ;
5138 else
5139 MRIclear(mri_dst) ;
5140
5141 m = MatrixAllocRotation(3, x_angle, X_ROTATION) ;
5142
5143 mO = MatrixAlloc(3, 1, MATRIX_REAL) ;
5144 mO->rptr[1][1] = mri_src->width / 2 ;
5145 mO->rptr[2][1] = mri_src->height / 2 ;
5146 mO->rptr[3][1] = mri_src->depth / 2 ;
5147
5148 /* build rotation matrix */
5149 mri_dst = MRIrotate(mri_src, NULL, m, mO) ;
5150 MatrixFree(&m) ;
5151 MatrixFree(&mO) ;
5152
5153 mri_dst->ras_good_flag = 0;
5154
5155 return(mri_dst) ;
5156 }
5157 /*-----------------------------------------------------
5158 Parameters:
5159
5160 Returns value:
5161
5162 Description
5163 Rotate mri_src around the Y axis and return the
5164 result in mri_dst
5165 ------------------------------------------------------*/
5166 MRI *
5167 MRIrotateY(MRI *mri_src, MRI *mri_dst, float y_angle)
5168 {
5169 int width, height, depth ;
5170 MATRIX *m, *mO ;
5171
5172 width = mri_src->width ;
5173 height = mri_src->height ;
5174 depth = mri_src->depth ;
5175 if (!mri_dst)
5176 mri_dst = MRIclone(mri_src, NULL) ;
5177 else
5178 MRIclear(mri_dst) ;
5179
5180 /* origin of coordinate system */
5181 mO = MatrixAlloc(3, 1, MATRIX_REAL) ;
5182 mO->rptr[1][1] = mri_src->width / 2 ;
5183 mO->rptr[2][1] = mri_src->height / 2 ;
5184 mO->rptr[3][1] = mri_src->depth / 2 ;
5185
5186 m = MatrixAllocRotation(3, y_angle, Y_ROTATION) ;
5187
5188 /* build rotation matrix */
5189 mri_dst = MRIrotate(mri_src, NULL, m, mO) ;
5190 MatrixFree(&m) ;
5191 MatrixFree(&mO) ;
5192
5193 mri_dst->ras_good_flag = 0;
5194
5195 return(mri_dst) ;
5196 }
5197 /*-----------------------------------------------------
5198 Parameters:
5199
5200 Returns value:
5201
5202 Description
5203 Rotate mri_src around the Z axis and return the
5204 result in mri_dst
5205 ------------------------------------------------------*/
5206 MRI *
5207 MRIrotateZ(MRI *mri_src, MRI *mri_dst, float z_angle)
5208 {
5209 int width, height, depth ;
5210 MATRIX *m, *mO ;
5211
5212 width = mri_src->width ;
5213 height = mri_src->height ;
5214 depth = mri_src->depth ;
5215 if (!mri_dst)
5216 mri_dst = MRIclone(mri_src, NULL) ;
5217 else
5218 MRIclear(mri_dst) ;
5219
5220 m = MatrixAllocRotation(3, z_angle, Z_ROTATION) ;
5221 mO = MatrixAlloc(3, 1, MATRIX_REAL) ;
5222 mO->rptr[1][1] = mri_src->width / 2 ;
5223 mO->rptr[2][1] = mri_src->height / 2 ;
5224 mO->rptr[3][1] = mri_src->depth / 2 ;
5225
5226 mri_dst = MRIrotate(mri_src, NULL, m, mO) ;
5227 MatrixFree(&m) ;
5228 MatrixFree(&mO) ;
5229
5230 mri_dst->ras_good_flag = 0;
5231
5232 return(mri_dst) ;
5233 }
5234 /*-----------------------------------------------------
5235 Parameters:
5236
5237 Returns value:
5238
5239 Description
5240 Rotate mri_src around the Y axis and return the
5241 result in mri_dst
5242 ------------------------------------------------------*/
5243 MRI *
5244 MRIrotateX_I(MRI *mri_src, MRI *mri_dst, float x_angle)
5245 {
5246 int width, height, depth ;
5247 MATRIX *m ;
5248
5249 width = mri_src->width ;
5250 height = mri_src->height ;
5251 depth = mri_src->depth ;
5252 if (!mri_dst)
5253 mri_dst = MRIclone(mri_src, NULL) ;
5254 else
5255 MRIclear(mri_dst) ;
5256
5257 m = MatrixAllocRotation(3, x_angle, X_ROTATION) ;
5258
5259 /* build rotation matrix */
5260 mri_dst = MRIrotate_I(mri_src, NULL, m, NULL) ;
5261 MatrixFree(&m) ;
5262
5263 mri_dst->ras_good_flag = 0;
5264
5265 return(mri_dst) ;
5266 }
5267 /*-----------------------------------------------------
5268 Parameters:
5269
5270 Returns value:
5271
5272 Description
5273 Rotate mri_src around the Y axis and return the
5274 result in mri_dst
5275 ------------------------------------------------------*/
5276 MRI *
5277 MRIrotateY_I(MRI *mri_src, MRI *mri_dst, float y_angle)
5278 {
5279 int width, height, depth ;
5280 MATRIX *m ;
5281
5282 width = mri_src->width ;
5283 height = mri_src->height ;
5284 depth = mri_src->depth ;
5285 if (!mri_dst)
5286 mri_dst = MRIclone(mri_src, NULL) ;
5287 else
5288 MRIclear(mri_dst) ;
5289
5290 m = MatrixAllocRotation(3, y_angle, Y_ROTATION) ;
5291
5292 /* build rotation matrix */
5293 mri_dst = MRIrotate_I(mri_src, NULL, m, NULL) ;
5294 MatrixFree(&m) ;
5295
5296 mri_dst->ras_good_flag = 0;
5297
5298 return(mri_dst) ;
5299 }
5300 /*-----------------------------------------------------
5301 Parameters:
5302
5303 Returns value:
5304
5305 Description
5306 Rotate mri_src around the Z axis and return the
5307 result in mri_dst
5308 ------------------------------------------------------*/
5309 MRI *
5310 MRIrotateZ_I(MRI *mri_src, MRI *mri_dst, float z_angle)
5311 {
5312 int width, height, depth ;
5313 MATRIX *m ;
5314
5315 width = mri_src->width ;
5316 height = mri_src->height ;
5317 depth = mri_src->depth ;
5318 if (!mri_dst)
5319 mri_dst = MRIclone(mri_src, NULL) ;
5320 else
5321 MRIclear(mri_dst) ;
5322
5323 m = MatrixAllocRotation(3, z_angle, Z_ROTATION) ;
5324 mri_dst = MRIrotate_I(mri_src, NULL, m, NULL) ;
5325 MatrixFree(&m) ;
5326
5327 mri_dst->ras_good_flag = 0;
5328
5329 return(mri_dst) ;
5330 }
5331 /*-----------------------------------------------------
5332 Parameters:
5333
5334 Returns value:
5335
5336 Description
5337 Scale the MRI image mri_src by sx,sy,sz in the
5338 x, y, and z directions respectively.
5339 ------------------------------------------------------*/
5340 MRI *
5341 MRIscale(MRI *mri_src, MRI *mri_dst, float sx, float sy, float sz)
5342 {
5343 int width, height, depth ;
5344 MATRIX *m ;
5345
5346 width = mri_src->width ;
5347 height = mri_src->height ;
5348 depth = mri_src->depth ;
5349 if (!mri_dst)
5350 {
5351 mri_dst = MRIalloc(width, height, depth, mri_src->type) ;
5352 MRIcopyHeader(mri_src, mri_dst) ;
5353 }
5354
5355 m = MatrixAlloc(4, 4, MATRIX_REAL) ;
5356
5357 /* build rotation matrix */
5358 m->rptr[1][1] = sx ;
5359 m->rptr[2][2] = sy ;
5360 m->rptr[3][3] = sz ;
5361 m->rptr[4][4] = 1.0 ;
5362 mri_dst = MRIlinearTransform(mri_src, NULL, m) ;
5363 MatrixFree(&m) ;
5364
5365 mri_dst->ras_good_flag = 0;
5366
5367 return(mri_dst) ;
5368 }
5369 /*-----------------------------------------------------
5370 Parameters:
5371
5372 Returns value:
5373
5374 Description
5375 Rotate about the point mO
5376 ------------------------------------------------------*/
5377 MRI *
5378 MRIrotate(MRI *mri_src, MRI *mri_dst, MATRIX *mR, MATRIX *mO)
5379 {
5380 int x1, x2, x3, y1, y2, y3, width, height, depth, y1o, y2o, y3o, freeit ;
5381 MATRIX *mX, *mY ; /* original and transformed coordinate systems */
5382 MATRIX *mRinv ; /* inverse of R */
5383
5384 mRinv = MatrixInverse(mR, NULL) ;
5385 if (!mRinv)
5386 ErrorReturn(NULL,(ERROR_BADPARM,"MRIrotate: rotation matrix is singular"));
5387
5388 width = mri_src->width ;
5389 height = mri_src->height ;
5390 depth = mri_src->depth ;
5391 if (!mri_dst)
5392 mri_dst = MRIclone(mri_src, NULL) ;
5393 else
5394 MRIclear(mri_dst) ;
5395
5396 if (!mO)
5397 {
5398 mO = MatrixAlloc(3, 1, MATRIX_REAL) ;
5399 mO->rptr[1][1] = mri_src->width / 2 ;
5400 mO->rptr[2][1] = mri_src->height / 2 ;
5401 mO->rptr[3][1] = mri_src->depth / 2 ;
5402 freeit = 1 ;
5403 }
5404 else
5405 freeit = 0 ;
5406
5407 mX = MatrixAlloc(3, 1, MATRIX_REAL) ; /* input coordinates */
5408 mY = MatrixAlloc(3, 1, MATRIX_REAL) ; /* transformed coordinates */
5409
5410
5411 y1o = mO->rptr[1][1] ;
5412 y2o = mO->rptr[2][1] ;
5413 y3o = mO->rptr[3][1] ;
5414 for (y3 = 0 ; y3 < depth ; y3++)
5415 {
5416 mY->rptr[3][1] = y3 - y3o ;
5417 for (y2 = 0 ; y2 < height ; y2++)
5418 {
5419 mY->rptr[2][1] = y2 - y2o ;
5420 for (y1 = 0 ; y1 < width ; y1++)
5421 {
5422 mY->rptr[1][1] = y1 - y1o ;
5423 MatrixMultiply(mRinv, mY, mX) ;
5424 MatrixAdd(mX, mO, mX) ;
5425
5426 /* should do bilinear interpolation here */
5427 x1 = nint(mX->rptr[1][1]) ;
5428 x2 = nint(mX->rptr[2][1]) ;
5429 x3 = nint(mX->rptr[3][1]) ;
5430 if (x1 >= 0 && x1 < width &&
5431 x2 >= 0 && x2 < height &&
5432 x3 >= 0 && x3 < depth)
5433 mri_dst->slices[y3][y2][y1] = mri_src->slices[x3][x2][x1] ;
5434 }
5435 }
5436 }
5437
5438 MatrixFree(&mX) ;
5439 MatrixFree(&mRinv) ;
5440 MatrixFree(&mY) ;
5441 if (freeit)
5442 MatrixFree(&mO) ;
5443
5444 mri_dst->ras_good_flag = 0;
5445
5446 return(mri_dst) ;
5447 }
5448 /*-----------------------------------------------------
5449 Parameters:
5450
5451 Returns value:
5452
5453 Description
5454 Rotate about the point mO using trilinear interpolation
5455 ------------------------------------------------------*/
5456 MRI *
5457 MRIrotate_I(MRI *mri_src, MRI *mri_dst, MATRIX *mR, MATRIX *mO)
5458 {
5459 int y1, y2, y3, width, height, depth, y1o, y2o, y3o, freeit ;
5460 MATRIX *mX, *mY ; /* original and transformed coordinate systems */
5461 MATRIX *mRinv ; /* inverse of R */
5462 float x1, x2, x3 ;
5463 Real val ;
5464
5465 mRinv = MatrixInverse(mR, NULL) ;
5466 if (!mRinv)
5467 ErrorReturn(NULL,(ERROR_BADPARM,
5468 "MRIrotate_I: rotation matrix is singular"));
5469
5470 width = mri_src->width ;
5471 height = mri_src->height ;
5472 depth = mri_src->depth ;
5473 if (!mri_dst)
5474 mri_dst = MRIclone(mri_src, NULL) ;
5475 else
5476 MRIclear(mri_dst) ;
5477
5478 if (!mO)
5479 {
5480 mO = MatrixAlloc(3, 1, MATRIX_REAL) ;
5481 mO->rptr[1][1] = mri_src->width / 2 ;
5482 mO->rptr[2][1] = mri_src->height / 2 ;
5483 mO->rptr[3][1] = mri_src->depth / 2 ;
5484 freeit = 1 ;
5485 }
5486 else
5487 freeit = 0 ;
5488
5489 mX = MatrixAlloc(3, 1, MATRIX_REAL) ; /* input coordinates */
5490 mY = MatrixAlloc(3, 1, MATRIX_REAL) ; /* transformed coordinates */
5491
5492
5493 y1o = mO->rptr[1][1] ;
5494 y2o = mO->rptr[2][1] ;
5495 y3o = mO->rptr[3][1] ;
5496 if (Gdiag == 99)
5497 MatrixPrint(stdout, mRinv) ;
5498 if (Gdiag == 99)
5499 MatrixPrint(stdout, mO) ;
5500 for (y3 = 0 ; y3 < depth ; y3++)
5501 {
5502 mY->rptr[3][1] = y3 - y3o ;
5503 for (y2 = 0 ; y2 < height ; y2++)
5504 {
5505 mY->rptr[2][1] = y2 - y2o ;
5506 for (y1 = 0 ; y1 < width ; y1++)
5507 {
5508 mY->rptr[1][1] = y1 - y1o ;
5509 MatrixMultiply(mRinv, mY, mX) ;
5510 MatrixAdd(mX, mO, mX) ;
5511
5512 /* do trilinear interpolation here */
5513 x1 = mX->rptr[1][1] ;
5514 x2 = mX->rptr[2][1] ;
5515 x3 = mX->rptr[3][1] ;
5516
5517 MRIsampleVolume(mri_src, x1, x2, x3, &val) ;
5518 mri_dst->slices[y3][y2][y1] = (BUFTYPE)nint(val) ;
5519 }
5520 }
5521 }
5522
5523 MatrixFree(&mX) ;
5524 MatrixFree(&mRinv) ;
5525 MatrixFree(&mY) ;
5526 if (freeit)
5527 MatrixFree(&mO) ;
5528
5529 mri_dst->ras_good_flag = 0;
5530
5531 return(mri_dst) ;
5532 }
5533 /*-----------------------------------------------------
5534 Parameters:
5535
5536 Returns value:
5537
5538 Description
5539 Perform an affine coordinate transformation x' = Ax + B on
5540 the MRI image mri_src into mri_dst
5541 ------------------------------------------------------*/
5542 MRI *
5543 MRIaffine(MRI *mri_src, MRI *mri_dst, MATRIX *mA, MATRIX *mB)
5544 {
5545 int x1, x2, x3, y1, y2, y3, width, height, depth ;
5546 MATRIX *mX, *mY ; /* original and transformed coordinate systems */
5547
5548 width = mri_src->width ;
5549 height = mri_src->height ;
5550 depth = mri_src->depth ;
5551 if (!mri_dst)
5552 {
5553 mri_dst = MRIalloc(width, height, depth, mri_src->type) ;
5554 MRIcopyHeader(mri_src, mri_dst) ;
5555 }
5556
5557 mX = MatrixAlloc(3, 1, MATRIX_REAL) ; /* input coordinates */
5558 mY = MatrixAlloc(3, 1, MATRIX_REAL) ; /* transformed coordinates */
5559
5560 for (x3 = 0 ; x3 < depth ; x3++)
5561 {
5562 mX->rptr[3][1] = x3 ;
5563 for (x2 = 0 ; x2 < height ; x2++)
5564 {
5565 mX->rptr[2][1] = x2 ;
5566 for (x1 = 0 ; x1 < width ; x1++)
5567 {
5568 mX->rptr[1][1] = x1 ;
5569 if (mA)
5570 MatrixMultiply(mA, mX, mY) ;
5571 else
5572 MatrixCopy(mX, mY) ;
5573 if (mB)
5574 MatrixAdd(mY, mB, mY) ;
5575 y1 = nint(mY->rptr[1][1]) ;
5576 y2 = nint(mY->rptr[2][1]) ;
5577 y3 = nint(mY->rptr[3][1]) ;
5578 if (y1 >= 0 && y1 < width &&
5579 y2 >= 0 && y2 < height &&
5580 y3 >= 0 && y3 < depth)
5581 mri_dst->slices[y3][y2][y1] = mri_src->slices[x3][x2][x1] ;
5582 }
5583 }
5584 }
5585
5586
5587 MatrixFree(&mX) ;
5588 MatrixFree(&mY) ;
5589
5590 mri_dst->ras_good_flag = 0;
5591
5592 return(mri_dst) ;
5593 }
5594 /*-----------------------------------------------------
5595 Parameters:
5596
5597 Returns value:
5598
5599 Description
5600 Convert a slice of an MRI data structure into a HIPS image.
5601 ------------------------------------------------------*/
5602 IMAGE *
5603 MRItoImageView(MRI *mri, IMAGE *I, int slice, int view, int frame)
5604 {
5605 int width, height, depth, x, y, yp, w, h, d,
5606 xm, ym, zm, format ;
5607 float fmin, fmax ;
5608 Real val ;
5609 int src_slice_direction;
5610 int xsign, ysign;
5611
5612 xsign=ysign=1; // let compiler be satisfied
5613
5614 src_slice_direction = getSliceDirection(mri);
5615 // only strict slice direction is supported
5616 if (src_slice_direction == MRI_UNDEFINED)
5617 ErrorReturn(NULL,
5618 (ERROR_UNSUPPORTED,
5619 "MRItoImageView(%d, %d): unsupported view/slice direction %d",
5620 slice, view, src_slice_direction)) ;
5621
5622 // generic routines to get the right axes
5623 //
5624 // should be able to do this in generic terms.
5625 // don't have time to do that
5626 //
5627 // Define the view to be the following:
5628 // coronal = (-R, -S)
5629 // sagittal = ( A, -S)
5630 // horizontal = (-R, A)
5631 //
5632 // translate these direction into (x,y)
5633 d = w = h = xm = ym = zm = 0 ; /* silly compiler warnings */
5634 width = mri->width ;
5635 height = mri->height ;
5636 depth = mri->depth ;
5637
5638 switch(src_slice_direction)
5639 {
5640 case MRI_CORONAL: // x direction can be -R or R,
5641 // y direction can be -S or S, z direction can be -A or A
5642 // +/-1 0 0
5643 // 0 0 +/-1
5644 // 0 +/-1 0
5645 switch(view)
5646 {
5647 case MRI_CORONAL:
5648 w = width; h = height; d = depth;
5649 xsign = (mri->x_r > 0) ? -1 : 1; ysign = (mri->y_s > 0) ? -1 : 1;
5650 break;
5651 case MRI_SAGITTAL:
5652 w = depth; h = height; d = width;
5653 xsign = (mri->z_a > 0) ? 1 : -1; ysign = (mri->y_s > 0) ? -1 : 1;
5654 break;
5655 case MRI_HORIZONTAL:
5656 w = width; h = depth; d = height;
5657 xsign = (mri->x_r > 0) ? -1 : 1; ysign = (mri->z_a > 0) ? 1 : -1;
5658 break;
5659 }
5660 break;
5661 case MRI_SAGITTAL: // x direction can be -A or A,
5662 // y direction can be -S or S, z direction can be -R or R
5663 // 0 0 +/-1
5664 // +/-1 0 0
5665 // 0 +/-1 0
5666 switch(view)
5667 {
5668 case MRI_CORONAL:
5669 w = depth; h = height; d = width;
5670 xsign =
5671 (mri->z_r > 0) ? -1 : 1; ysign = (mri->y_s > 0) ? -1 : 1;
5672 break;
5673 case MRI_SAGITTAL:
5674 w = width; h = height; d = depth;
5675 xsign = (mri->x_a > 0) ? 1 : -1; ysign = (mri->y_s > 0) ? -1 : 1;
5676 break;
5677 case MRI_HORIZONTAL:
5678 w = depth; h = width; d = height;
5679 xsign = (mri->z_r > 0) ? -1 : 1; ysign = (mri->x_a > 0) ? 1 : -1;
5680 break;
5681 }
5682 break;
5683 case MRI_HORIZONTAL: // x direction can be -R or R,
5684 // y direction can be -A or A, z direction can be -S or S
5685 // +/-1 0 0
5686 // 0 +/-1 0
5687 // 0 0 +/-1
5688 switch(view)
5689 {
5690 case MRI_CORONAL:
5691 w = width; h = depth; d = height;
5692 xsign = (mri->x_r > 0) ? -1 : 1; ysign = (mri->z_s > 0) ? -1 : 1;
5693 break;
5694 case MRI_SAGITTAL:
5695 w = height; h = depth; d = width;
5696 xsign = (mri->y_a > 0) ? 1 : -1; ysign = (mri->z_s > 0) ? -1 : 1;
5697 break;
5698 case MRI_HORIZONTAL:
5699 w = width; h = height; d = depth;
5700 xsign = (mri->x_r > 0) ? -1 : 1; ysign = (mri->y_a > 0) ? 1 : -1;
5701 break;
5702 }
5703 break;
5704 default:
5705 ErrorReturn
5706 (NULL,
5707 (ERROR_UNSUPPORTED,
5708 "MRItoImageView(%d, %d): unsupported view/slice direction %d",
5709 slice, view, src_slice_direction)) ;
5710 }
5711 if (slice < 0 || slice >= d)
5712 ErrorReturn(NULL, (ERROR_BADPARM, "MRItoImageView: bad slice %d\n",slice));
5713
5714 #if 0
5715 format = (mri->type == MRI_UCHAR) ? PFBYTE :
5716 mri->type == MRI_INT ? PFINT :
5717 mri->type == MRI_FLOAT ? PFFLOAT :
5718 mri->type == MRI_SHORT ? PFFLOAT : PFBYTE ;
5719 #else
5720 format = PFBYTE ;
5721 #endif
5722
5723 if (I && ((I->rows != h) || (I->cols != w) || (I->pixel_format != format)))
5724 {
5725 ImageFree(&I);
5726 I = NULL ; /* must allocate a new one */
5727 }
5728 if (!I)
5729 I = ImageAlloc(h, w, format, 1) ;
5730
5731 fmin = 10000000 ; fmax = -fmin ;
5732
5733 // Image values assigned from MRI
5734 // we need to gert min and max in IMAGE
5735 for (y = 0 ; y < h ; y++)
5736 {
5737 for (x = 0 ; x < w ; x++)
5738 {
5739 switch(src_slice_direction)
5740 {
5741 case MRI_CORONAL:
5742 switch (view) /* calculate coordinates in MR structure */
5743 {
5744 case MRI_CORONAL:
5745 xm = (xsign> 0) ? x : (w - 1 -x);
5746 ym = (ysign> 0) ? y : (h - 1 -y);
5747 zm = slice ;
5748 break ;
5749 case MRI_SAGITTAL:
5750 xm = slice ;
5751 ym = (ysign>0) ? y : (h - 1 - y);
5752 zm = (xsign>0) ? x : (w - 1 - x);
5753 break ;
5754 case MRI_HORIZONTAL:
5755 xm = (xsign>0) ? x : (w - 1 - x);
5756 ym = slice ;
5757 zm = (ysign>0) ? y : (h - 1 - y);
5758 break ;
5759 }
5760 break;
5761 case MRI_SAGITTAL:
5762 switch (view) /* calculate coordinates in MR structure */
5763 {
5764 case MRI_CORONAL:
5765 xm = slice;
5766 ym = (ysign>0) ? y : (h - 1 - y);
5767 zm = (xsign>0) ? x : (w - 1 - x);
5768 break ;
5769 case MRI_SAGITTAL:
5770 xm = (xsign>0) ? x : (w - 1 - x);
5771 ym = (ysign>0) ? y : (h - 1 - y);
5772 zm = slice ;
5773 break ;
5774 case MRI_HORIZONTAL:
5775 xm = (ysign>0) ? y : (h - 1 - y);
5776 ym = slice;
5777 zm = (xsign>0) ? x : (w - 1 - x);
5778 break ;
5779 }
5780 break;
5781 case MRI_HORIZONTAL:
5782 switch (view) /* calculate coordinates in MR structure */
5783 {
5784 case MRI_CORONAL:
5785 xm = (xsign>0) ? x : (w - 1 - x);
5786 ym = slice ;
5787 zm = (ysign>0) ? y : (h - 1 - y);
5788 break ;
5789 case MRI_SAGITTAL:
5790 xm = slice ;
5791 ym = (xsign>0) ? x : (w - 1 - x);
5792 zm = (ysign>0) ? y : (h - 1 - y);
5793 break ;
5794 case MRI_HORIZONTAL:
5795 xm = (xsign>0) ? x : (w - 1 - x);
5796 ym = (ysign>0) ? y : (h - 1 - y);
5797 zm = slice ;
5798 break ;
5799 }
5800 break;
5801 }
5802 MRIsampleVolumeFrame(mri, xm, ym, zm, frame, &val) ;
5803 // check min max
5804 if (val > fmax)
5805 fmax = val ;
5806 if (val < fmin)
5807 fmin = val ;
5808 }
5809 }
5810 if (FZERO(fmax-fmin))
5811 ErrorReturn(I, (ERROR_BADPARM, "MRItoImageView: constant image")) ;
5812
5813 // after all these calculation, we are going to do it again?
5814 for (y = 0 ; y < h ; y++)
5815 {
5816
5817 for (x = 0 ; x < w ; x++)
5818 {
5819 switch(src_slice_direction)
5820 {
5821 case MRI_CORONAL:
5822 switch (view) /* calculate coordinates in MR structure */
5823 {
5824 case MRI_CORONAL:
5825 xm = (xsign> 0) ? x : (w - 1 -x);
5826 ym = (ysign> 0) ? y : (h - 1 -y);
5827 zm = slice ;
5828 break ;
5829 case MRI_SAGITTAL:
5830 xm = slice ;
5831 ym = (ysign>0) ? y : (h - 1 - y);
5832 zm = (xsign>0) ? x : (w - 1 - x);
5833 break ;
5834 case MRI_HORIZONTAL:
5835 xm = (xsign>0) ? x : (w - 1 - x);
5836 ym = slice ;
5837 zm = (ysign>0) ? y : (h - 1 - y);
5838 break ;
5839 }
5840 break;
5841 case MRI_SAGITTAL:
5842 switch (view) /* calculate coordinates in MR structure */
5843 {
5844 case MRI_CORONAL:
5845 xm = slice;
5846 ym = (ysign>0) ? y : (h - 1 - y);
5847 zm = (xsign>0) ? x : (w - 1 - x);
5848 break ;
5849 case MRI_SAGITTAL:
5850 xm = (xsign>0) ? x : (w - 1 - x);
5851 ym = (ysign>0) ? y : (h - 1 - y);
5852 zm = slice ;
5853 break ;
5854 case MRI_HORIZONTAL:
5855 xm = (ysign>0) ? y : (h - 1 - y);
5856 ym = slice;
5857 zm = (xsign>0) ? x : (w - 1 - x);
5858 break ;
5859 }
5860 break;
5861 case MRI_HORIZONTAL:
5862 switch (view) /* calculate coordinates in MR structure */
5863 {
5864 case MRI_CORONAL:
5865 xm = (xsign>0) ? x : (w - 1 - x);
5866 ym = slice ;
5867 zm = (ysign>0) ? y : (h - 1 - y);
5868 break ;
5869 case MRI_SAGITTAL:
5870 xm = slice ;
5871 ym = (xsign>0) ? x : (w - 1 - x);
5872 zm = (ysign>0) ? y : (h - 1 - y);
5873 break ;
5874 case MRI_HORIZONTAL:
5875 xm = (xsign>0) ? x : (w - 1 - x);
5876 ym = (ysign>0) ? y : (h - 1 - y);
5877 zm = slice ;
5878 break ;
5879 }
5880 break;
5881 }
5882 MRIsampleVolumeFrame(mri, xm, ym, zm, frame, &val) ;
5883 yp = h - (y+1) ; /* hips coordinate system is inverted */
5884 *IMAGEpix(I, x, yp) = (byte)(255.0 * (val - fmin) / (fmax - fmin)) ;
5885 }
5886 }
5887
5888 return(I) ;
5889 }
5890 /*-----------------------------------------------------
5891 Parameters:
5892
5893 Returns value:
5894
5895 Description
5896 Convert a slice of an MRI data structure into a HIPS image.
5897 ------------------------------------------------------*/
5898 IMAGE *
5899 MRItoImage(MRI *mri, IMAGE *I, int slice)
5900 {
5901 int width, height, y, yp ;
5902
5903 width = mri->width ;
5904 height = mri->height ;
5905 if (slice < 0 || slice >= mri->depth)
5906 ErrorReturn(NULL, (ERROR_BADPARM, "MRItoImage: bad slice %d\n", slice)) ;
5907
5908 if (!I)
5909 {
5910 I = ImageAlloc(height, width,
5911 mri->type == MRI_UCHAR ? PFBYTE :
5912 mri->type == MRI_INT ? PFINT :
5913 mri->type == MRI_FLOAT ? PFFLOAT : PFBYTE, 1) ;
5914 }
5915
5916 for (y = 0 ; y < height ; y++)
5917 {
5918 yp = height - (y+1) ;
5919
5920 #if 0
5921 if (mri->type == MRI_UCHAR)
5922 image_to_buffer(I->image, mri, slice) ;
5923 else
5924 #endif
5925 switch (mri->type)
5926 {
5927 case MRI_INT:
5928 memcpy
5929 (IMAGEIpix(I, 0, yp),mri->slices[slice][y],width*sizeof(int)) ;
5930 break ;
5931 case MRI_FLOAT:
5932 memcpy
5933 (IMAGEFpix(I, 0, yp),mri->slices[slice][y],width*sizeof(float));
5934 break ;
5935 case MRI_UCHAR:
5936 memcpy(IMAGEpix(I, 0, yp), mri->slices[slice][y],
5937 width*sizeof(unsigned char)) ;
5938 break ;
5939 default:
5940 case MRI_LONG:
5941 ImageFree(&I) ;
5942 ErrorReturn
5943 (NULL,
5944 (ERROR_UNSUPPORTED,
5945 "MRItoImage: unsupported type %d",
5946 mri->type)) ;
5947 break ;
5948 }
5949 }
5950
5951 return(I) ;
5952 }
5953
5954 MRI *
5955 ImageToMRI(IMAGE *I)
5956 {
5957 MRI *mri;
5958 int width, height, depth, type, nframes, y, yp, x ;
5959 int frames;
5960
5961 type = MRI_UCHAR; // to make compiler happy
5962 width = I->ocols;
5963 height = I->orows;
5964 depth = 1;
5965 nframes = I->num_frame;
5966
5967 switch(I->pixel_format)
5968 {
5969 case PFBYTE:
5970 type = MRI_UCHAR;
5971 break;
5972 case PFSHORT:
5973 type = MRI_SHORT;
5974 break;
5975 case PFINT:
5976 type = MRI_INT;
5977 break;
5978 case PFFLOAT:
5979 type = MRI_FLOAT;
5980 break;
5981 case PFDOUBLE:
5982 case PFCOMPLEX:
5983 default:
5984 ErrorExit
5985 (ERROR_BADPARM, "IMAGE type = %d not supported\n", I->pixel_format);
5986 break;
5987 }
5988 // allocate memory
5989 if (nframes <= 1)
5990 mri = MRIalloc(width, height, depth, type);
5991 else
5992 mri = MRIallocSequence(width, height, depth, type, nframes);
5993
5994 // just fake the size
5995 mri->nframes = nframes;
5996 mri->imnr0 = 1;
5997 mri->imnr1 = 1;
5998 mri->thick = mri->ps = 1.0;
5999 mri->xsize = mri->ysize = mri->zsize = 1.0;
6000 mri->xend = mri->width * mri->xsize / 2.0;
6001 mri->xstart = -mri->xend;
6002 mri->yend = mri->height * mri->ysize / 2.0;
6003 mri->ystart = -mri->yend;
6004 mri->zend = mri->depth * mri->zsize / 2.0;
6005 mri->zstart = -mri->zend;
6006 mri->fov = ((mri->xend - mri->xstart) > (mri->yend - mri->ystart) ?
6007 (mri->xend - mri->xstart) : (mri->yend - mri->ystart));
6008 // set orientation to be coronal
6009 mri->x_r = -1; mri->y_r = 0; mri->z_r = 0; mri->c_r = 0;
6010 mri->x_a = 0; mri->y_a = 0; mri->z_a = 1; mri->c_a = 0;
6011 mri->x_s = 0; mri->y_s = -1; mri->z_s = 0; mri->c_s = 0;
6012
6013 // hips coordinate system is inverted
6014 for (frames = 0; frames < nframes; ++frames)
6015 {
6016
6017 for (y = 0 ; y < height ; y++)
6018 {
6019 yp = height - (y+1) ;
6020
6021 for (x = 0; x < width; ++x)
6022 {
6023 switch (mri->type)
6024 {
6025 case MRI_UCHAR:
6026 MRIseq_vox(mri, x, y, 0, frames) = *IMAGEpix(I, x, yp);
6027 break ;
6028 case MRI_SHORT:
6029 MRISseq_vox(mri, x, y, 0, frames) = *IMAGESpix(I, x, yp);
6030 break;
6031 case MRI_INT:
6032 MRIIseq_vox(mri, x, y, 0, frames) = *IMAGEIpix(I, x, yp);
6033 break ;
6034 case MRI_FLOAT:
6035 MRIFseq_vox(mri, x, y, 0, frames) = *IMAGEFpix(I, x, yp);
6036 break ;
6037 default:
6038 ErrorReturn
6039 (NULL,
6040 (ERROR_UNSUPPORTED,
6041 "MRItoImage: unsupported type %d",
6042 mri->type)) ;
6043 break ;
6044 }
6045 }
6046 }
6047 } // frames
6048 return(mri) ;
6049 }
6050
6051 /*-----------------------------------------------------
6052 Parameters:
6053
6054 Returns value:
6055
6056 Description
6057 Build an MRI from all values s.t. min_val <= val <= max_val
6058 ------------------------------------------------------*/
6059 MRI *
6060 MRIextractValues(MRI *mri_src, MRI *mri_dst, float min_val, float max_val)
6061 {
6062 BUFTYPE *psrc, *pdst, val ;
6063 float *pfsrc, *pfdst, fval ;
6064 int frame, x, y, z, width, height, depth ;
6065
6066 width = mri_src->width ;
6067 height = mri_src->height ;
6068 depth = mri_src->depth ;
6069 if (!mri_dst)
6070 mri_dst = MRIclone(mri_src, NULL) ;
6071
6072 for (frame = 0 ; frame < mri_src->nframes ; frame++)
6073 {
6074 for (z = 0 ; z < depth ; z++)
6075 {
6076 for (y = 0 ; y < height ; y++)
6077 {
6078 switch (mri_src->type)
6079 {
6080 case MRI_UCHAR:
6081 psrc = &MRIseq_vox(mri_src, 0, y, z, frame) ;
6082 pdst = &MRIseq_vox(mri_dst, 0, y, z, frame) ;
6083 for (x = 0 ; x < width ; x++)
6084 {
6085 val = *psrc++ ;
6086 if ((val < min_val) || (val > max_val))
6087 val = 0 ;
6088 *pdst++ = val ;
6089 }
6090 break ;
6091 case MRI_FLOAT:
6092 pfsrc = &MRIFseq_vox(mri_src, 0, y, z, frame) ;
6093 pfdst = &MRIFseq_vox(mri_dst, 0, y, z, frame) ;
6094 for (x = 0 ; x < width ; x++)
6095 {
6096 fval = *pfsrc++ ;
6097 if ((fval < min_val) || (fval > max_val))
6098 fval = 0.0f ;
6099 *pfdst++ = fval ;
6100 }
6101 break ;
6102 default:
6103 ErrorReturn
6104 (NULL,
6105 (ERROR_UNSUPPORTED,
6106 "MRIextractValues: unsupported type %d",mri_src->type));
6107 }
6108 }
6109 }
6110 }
6111
6112 return(mri_dst) ;
6113 }
6114 /*-----------------------------------------------------
6115 Parameters:
6116
6117 Returns value:
6118
6119 Description
6120 ------------------------------------------------------*/
6121 MRI *
6122 MRIupsample2(MRI *mri_src, MRI *mri_dst)
6123 {
6124 int width, depth, height, x, y, z ;
6125 BUFTYPE *pdst ;
6126 short *psdst ;
6127 float *pfdst ;
6128
6129 if (mri_dst && mri_src->type != mri_dst->type)
6130 ErrorReturn
6131 (NULL,
6132 (ERROR_UNSUPPORTED, "MRIupsample2: source and dst must be same type"));
6133
6134 width = 2*mri_src->width ;
6135 height = 2*mri_src->height ;
6136 depth = 2*mri_src->depth ;
6137
6138 if (!mri_dst)
6139 {
6140 mri_dst = MRIalloc(width, height, depth, mri_src->type) ;
6141 MRIcopyHeader(mri_src, mri_dst) ;
6142 }
6143
6144 for (z = 0 ; z < depth ; z++)
6145 {
6146 for (y = 0 ; y < height ; y++)
6147 {
6148 switch (mri_src->type)
6149 {
6150 case MRI_UCHAR:
6151 pdst = &MRIvox(mri_dst, 0, y, z) ;
6152 for (x = 0 ; x < width ; x++)
6153 *pdst++ = MRIvox(mri_src, x/2, y/2, z/2) ;
6154 break ;
6155 case MRI_SHORT:
6156 psdst = &MRISvox(mri_dst, 0, y, z) ;
6157 for (x = 0 ; x < width ; x++)
6158 *psdst++ = MRISvox(mri_src, x/2, y/2, z/2) ;
6159 break ;
6160 case MRI_FLOAT:
6161 pfdst = &MRIFvox(mri_dst, 0, y, z) ;
6162 for (x = 0 ; x < width ; x++)
6163 *pfdst++ = MRIFvox(mri_src, x/2, y/2, z/2) ;
6164 break ;
6165 default:
6166 ErrorReturn
6167 (NULL,
6168 (ERROR_UNSUPPORTED,
6169 "MRIupsample2: unsupported src type %d", mri_src->type)) ;
6170 }
6171
6172 }
6173 }
6174
6175 mri_dst->imnr0 = mri_src->imnr0 ;
6176 mri_dst->imnr1 = mri_src->imnr0 + mri_dst->depth - 1 ;
6177
6178 mri_dst->xsize = mri_src->xsize/2 ;
6179 mri_dst->ysize = mri_src->ysize/2 ;
6180 mri_dst->zsize = mri_src->zsize/2 ;
6181
6182 mri_dst->ras_good_flag = 0;
6183
6184 return(mri_dst) ;
6185 }
6186 MRI *
6187 MRIdownsample2LabeledVolume(MRI *mri_src, MRI *mri_dst)
6188 {
6189 int width, depth, height, x, y, z, x1, y1, z1, counts[256], label,
6190 max_count, out_label ;
6191 BUFTYPE *psrc ;
6192
6193 if (mri_src->type != MRI_UCHAR)
6194 ErrorReturn(NULL,
6195 (ERROR_UNSUPPORTED,
6196 "MRIdownsample2LabeledVolume: source must be UCHAR"));
6197
6198 width = mri_src->width/2 ;
6199 height = mri_src->height/2 ;
6200 depth = mri_src->depth/2 ;
6201
6202 if (!mri_dst)
6203 {
6204 mri_dst = MRIalloc(width, height, depth, mri_src->type) ;
6205 MRIcopyHeader(mri_src, mri_dst) ;
6206 }
6207
6208 MRIclear(mri_dst) ;
6209 for (z = 0 ; z < depth ; z++)
6210 {
6211 for (y = 0 ; y < height ; y++)
6212 {
6213 for (x = 0 ; x < width ; x++)
6214 {
6215 memset(counts, 0, sizeof(counts)) ;
6216 if (x == 96 && y == 66 && z == 56)
6217 DiagBreak() ;
6218 for (z1 = 2*z ; z1 <= 2*z+1 ; z1++)
6219 {
6220 for (y1 = 2*y ; y1 <= 2*y+1 ; y1++)
6221 {
6222 psrc = &MRIvox(mri_src, 2*x, y1, z1) ;
6223 for (x1 = 2*x ; x1 <= 2*x+1 ; x1++)
6224 {
6225 label = *psrc++ ;
6226 counts[label]++ ;
6227 }
6228 }
6229 }
6230 for (out_label = label = 0, max_count = counts[0] ;
6231 label <= 255 ;
6232 label++)
6233 {
6234 if (counts[label] > max_count)
6235 {
6236 out_label = label ;
6237 max_count = counts[label] ;
6238 }
6239 }
6240 MRIvox(mri_dst, x, y, z) = out_label ;
6241 }
6242 }
6243 }
6244
6245 mri_dst->imnr0 = mri_src->imnr0 ;
6246 mri_dst->imnr1 = mri_src->imnr0 + mri_dst->depth - 1 ;
6247 mri_dst->xsize = mri_src->xsize*2 ;
6248 mri_dst->ysize = mri_src->ysize*2 ;
6249 mri_dst->zsize = mri_src->zsize*2 ;
6250
6251 mri_dst->ras_good_flag = 0;
6252
6253 return(mri_dst) ;
6254 }
6255 /*-----------------------------------------------------
6256 Parameters:
6257
6258 Returns value:
6259
6260 Description
6261 ------------------------------------------------------*/
6262 MRI *
6263 MRIdownsample2(MRI *mri_src, MRI *mri_dst)
6264 {
6265 int width, depth, height, x, y, z, x1, y1, z1 ;
6266 BUFTYPE *psrc ;
6267 short *pssrc ;
6268 float val ;
6269
6270 if (mri_dst && mri_src->type != mri_dst->type)
6271 ErrorReturn
6272 (NULL,
6273 (ERROR_UNSUPPORTED,
6274 "MRIdownsample2: source and dst must be same type"));
6275
6276 width = mri_src->width/2 ;
6277 height = mri_src->height/2 ;
6278 depth = mri_src->depth/2 ;
6279
6280 if (!mri_dst)
6281 {
6282 mri_dst = MRIalloc(width, height, depth, mri_src->type) ;
6283 MRIcopyHeader(mri_src, mri_dst) ;
6284 }
6285
6286 MRIclear(mri_dst) ;
6287 for (z = 0 ; z < depth ; z++)
6288 {
6289 for (y = 0 ; y < height ; y++)
6290 {
6291 for (x = 0 ; x < width ; x++)
6292 {
6293 for (val = 0.0f, z1 = 2*z ; z1 <= 2*z+1 ; z1++)
6294 {
6295 for (y1 = 2*y ; y1 <= 2*y+1 ; y1++)
6296 {
6297 switch (mri_src->type)
6298 {
6299 case MRI_UCHAR:
6300 psrc = &MRIvox(mri_src, 2*x, y1, z1) ;
6301 for (x1 = 2*x ; x1 <= 2*x+1 ; x1++)
6302 val += *psrc++ ;
6303 break ;
6304 case MRI_SHORT:
6305 pssrc = &MRISvox(mri_src, 2*x, y1, z1) ;
6306 for (x1 = 2*x ; x1 <= 2*x+1 ; x1++)
6307 val += *pssrc++ ;
6308 break ;
6309 default:
6310 ErrorReturn
6311 (NULL,
6312 (ERROR_UNSUPPORTED,
6313 "MRIdownsample2: unsupported input type %d",
6314 mri_src->type));
6315 }
6316 }
6317 }
6318 switch (mri_src->type)
6319 {
6320 case MRI_UCHAR:
6321 MRIvox(mri_dst, x, y, z) = (BUFTYPE)nint(val/8.0f) ;
6322 break ;
6323 case MRI_SHORT:
6324 MRISvox(mri_dst, x, y, z) = (short)nint(val/8.0f) ;
6325 break ;
6326 }
6327 }
6328 }
6329 }
6330
6331 mri_dst->imnr0 = mri_src->imnr0 ;
6332 mri_dst->imnr1 = mri_src->imnr0 + mri_dst->depth - 1 ;
6333 mri_dst->xsize = mri_src->xsize*2 ;
6334 mri_dst->ysize = mri_src->ysize*2 ;
6335 mri_dst->zsize = mri_src->zsize*2 ;
6336
6337 mri_dst->ras_good_flag = 0;
6338
6339 return(mri_dst) ;
6340 }
6341 /*-------------------------------------------------------------
6342 MRI MRIvalueFill(MRI *mri, float value) -- fills an mri volume
6343 with the given value. Type of mri can be anything.
6344 -------------------------------------------------------------*/
6345 int MRIvalueFill(MRI *mri, float value)
6346 {
6347 int c,r,s,f;
6348
6349 for(c=0; c < mri->width; c++){
6350 for(r=0; r < mri->height; r++){
6351 for(s=0; s < mri->depth; s++){
6352 for(f=0; f < mri->nframes; f++){
6353 switch(mri->type){
6354 case MRI_UCHAR:
6355 MRIseq_vox(mri,c,r,s,f) = (unsigned char) (nint(value));
6356 break;
6357 case MRI_SHORT:
6358 MRISseq_vox(mri,c,r,s,f) = (short) (nint(value));
6359 break;
6360 case MRI_INT:
6361 MRIIseq_vox(mri,c,r,s,f) = (int) (nint(value));
6362 break;
6363 case MRI_FLOAT:
6364 MRIFseq_vox(mri,c,r,s,f) = value;
6365 break;
6366 }
6367 }
6368 }
6369 }
6370 }
6371
6372 return(0);
6373 }
6374 /*-----------------------------------------------------
6375 Parameters:
6376
6377 Returns value:
6378
6379 Description
6380 Iteratively set all voxels in mri_dst that neighbor
6381 a voxel that has already been filled (starting with the seed),
6382 and for which the corresponding voxel in mri_src is
6383 below threshold.
6384 ------------------------------------------------------*/
6385 MRI *
6386 MRIfill(MRI *mri_src, MRI *mri_dst, int seed_x, int seed_y,
6387 int seed_z, int threshold, int fill_val, int max_count)
6388 {
6389 int width, height, depth, x, y, z, nfilled, xmin, xmax, ymin, ymax,
6390 zmin, zmax, on, x0, x1, y0, y1, z0, z1 ;
6391 BUFTYPE *psrc, *pdst, val ;
6392
6393 width = mri_src->width ;
6394 height = mri_src->height ;
6395 depth = mri_src->depth ;
6396 if (!mri_dst)
6397 mri_dst = MRIclone(mri_src, NULL) ;
6398
6399 if (seed_x < 0)
6400 seed_x = 0 ;
6401 else if (seed_x >= width)
6402 seed_x = width-1 ;
6403 if (seed_y < 0)
6404 seed_y = 0 ;
6405 else if (seed_y >= height)
6406 seed_y = height-1 ;
6407 if (seed_z < 0)
6408 seed_z = 0 ;
6409 else if (seed_z >= depth)
6410 seed_z = depth-1 ;
6411
6412 xmin = MAX(seed_x-1,0) ; xmax = MIN(seed_x+1, width-1) ;
6413 ymin = MAX(seed_y-1,0) ; ymax = MIN(seed_y+1, height-1) ;
6414 zmin = MAX(seed_z-1,0) ; zmax = MIN(seed_z+1, depth-1) ;
6415
6416 /* replace all occurrences of fill_val with fill_val-1 */
6417 for (z = 0 ; z < depth ; z++)
6418 {
6419 for (y = 0 ; y < height ; y++)
6420 {
6421 pdst = &MRIvox(mri_dst, 0, y, z) ;
6422 for (x = 0 ; x < width ; x++, pdst++)
6423 {
6424 val = *pdst ;
6425 if (val == fill_val)
6426 *pdst = val-1 ;
6427 }
6428 }
6429 }
6430
6431 MRIvox(mri_dst, seed_x, seed_y, seed_z) = fill_val ;
6432 do
6433 {
6434 z0 = zmin ; z1 = zmax ; y0 = ymin ; y1 = ymax ; x0 = xmin ; x1 = xmax ;
6435 nfilled = 0 ;
6436 for (z = zmin ; z <= zmax ; z++)
6437 {
6438 for (y = ymin ; y <= ymax ; y++)
6439 {
6440 psrc = &MRIvox(mri_src, xmin, y, z) ;
6441 pdst = &MRIvox(mri_dst, xmin, y, z) ;
6442 for (x = xmin ; x <= xmax ; x++, psrc++, pdst++)
6443 {
6444 val = *psrc ;
6445 if ((val > threshold) || (*pdst == fill_val))
6446 continue ;
6447
6448 on = 0 ;
6449 if (x > 0)
6450 on = (MRIvox(mri_dst, x-1, y, z) == fill_val) ;
6451 if (!on && (x < width-1))
6452 on = (MRIvox(mri_dst, x+1, y, z) == fill_val) ;
6453 if (!on && (y > 0))
6454 on = (MRIvox(mri_dst, x, y-1, z) == fill_val) ;
6455 if (!on && (y < height-1))
6456 on = (MRIvox(mri_dst, x, y+1, z) == fill_val) ;
6457 if (!on && (z > 0))
6458 on = (MRIvox(mri_dst, x, y, z-1) == fill_val) ;
6459 if (!on && (z < depth-1))
6460 on = (MRIvox(mri_dst, x, y, z+1) == fill_val) ;
6461 if (on)
6462 {
6463 if (x <= x0)
6464 x0 = MAX(x-1,0) ;
6465 if (x >= x1)
6466 x1 = MIN(x+1,width-1) ;
6467 if (y <= y0)
6468 y0 = MAX(y-1,0) ;
6469 if (y >= y1)
6470 y1 = MIN(y+1,height-1) ;
6471 if (z <= z0)
6472 z0 = MAX(z-1,0) ;
6473 if (z >= z1)
6474 z1 = MIN(z+1,depth-1) ;
6475 nfilled++ ;
6476 *pdst = fill_val ;
6477 }
6478 }
6479 }
6480 }
6481 zmin = z0 ; zmax = z1 ; ymin = y0 ; ymax = y1 ; xmin = x0 ; xmax = x1 ;
6482 /* fprintf(stderr, "# filled = %d\n", nfilled) ;*/
6483 if ((max_count > 0) && (nfilled > max_count))
6484 break ;
6485 } while (nfilled > 0) ;
6486
6487 return(mri_dst) ;
6488 }
6489 /*-----------------------------------------------------
6490 Parameters:
6491
6492 Returns value:
6493
6494 Description
6495 ------------------------------------------------------*/
6496 MRI *
6497 MRIfillFG(MRI *mri_src, MRI *mri_dst, int seed_x, int seed_y,
6498 int seed_z, int threshold, int fill_val, int *npix)
6499 {
6500 int width, height, depth, x, y, z, nfilled, xmin, xmax, ymin, ymax,
6501 zmin, zmax, on, x0, x1, y0, y1, z0, z1, total_pix ;
6502 BUFTYPE *psrc, *pdst, val ;
6503
6504 width = mri_src->width ;
6505 height = mri_src->height ;
6506 depth = mri_src->depth ;
6507 if (!mri_dst)
6508 mri_dst = MRIclone(mri_src, NULL) ;
6509
6510 if (seed_x < 0)
6511 seed_x = 0 ;
6512 else if (seed_x >= width)
6513 seed_x = width-1 ;
6514 if (seed_y < 0)
6515 seed_y = 0 ;
6516 else if (seed_y >= height)
6517 seed_y = width-1 ;
6518 if (seed_z < 0)
6519 seed_z = 0 ;
6520 else if (seed_z >= depth)
6521 seed_z = width-1 ;
6522
6523 xmin = MAX(seed_x-1,0) ; xmax = MIN(seed_x+1, width-1) ;
6524 ymin = MAX(seed_y-1,0) ; ymax = MIN(seed_y+1, height-1) ;
6525 zmin = MAX(seed_z-1,0) ; zmax = MIN(seed_z+1, depth-1) ;
6526
6527 /* replace all occurrences of fill_val with fill_val-1 */
6528 for (z = 0 ; z < depth ; z++)
6529 {
6530 for (y = 0 ; y < height ; y++)
6531 {
6532 pdst = &MRIvox(mri_dst, 0, y, z) ;
6533 for (x = 0 ; x < width ; x++, pdst++)
6534 {
6535 val = *pdst ;
6536 if (val == fill_val)
6537 *pdst = val-1 ;
6538 }
6539 }
6540 }
6541
6542 MRIvox(mri_dst, seed_x, seed_y, seed_z) = fill_val ;
6543 total_pix = 1 ; /* include the seed point */
6544 do
6545 {
6546 z0 = zmin ; z1 = zmax ; y0 = ymin ; y1 = ymax ; x0 = xmin ; x1 = xmax ;
6547 nfilled = 0 ;
6548 for (z = zmin ; z <= zmax ; z++)
6549 {
6550 for (y = ymin ; y <= ymax ; y++)
6551 {
6552 psrc = &MRIvox(mri_src, xmin, y, z) ;
6553 pdst = &MRIvox(mri_dst, xmin, y, z) ;
6554 for (x = xmin ; x <= xmax ; x++, psrc++, pdst++)
6555 {
6556 val = *psrc ;
6557 if ((val < threshold) || (*pdst == fill_val))
6558 continue ;
6559
6560 on = 0 ;
6561 if (x > 0)
6562 on = (MRIvox(mri_dst, x-1, y, z) == fill_val) ;
6563 if (!on && (x < width-1))
6564 on = (MRIvox(mri_dst, x+1, y, z) == fill_val) ;
6565 if (!on && (y > 0))
6566 on = (MRIvox(mri_dst, x, y-1, z) == fill_val) ;
6567 if (!on && (y < height-1))
6568 on = (MRIvox(mri_dst, x, y+1, z) == fill_val) ;
6569 if (!on && (z > 0))
6570 on = (MRIvox(mri_dst, x, y, z-1) == fill_val) ;
6571 if (!on && (z < depth-1))
6572 on = (MRIvox(mri_dst, x, y, z+1) == fill_val) ;
6573 if (on)
6574 {
6575 if (x <= x0)
6576 x0 = MAX(x-1,0) ;
6577 if (x >= x1)
6578 x1 = MIN(x+1,width-1) ;
6579 if (y <= y0)
6580 y0 = MAX(y-1,0) ;
6581 if (y >= y1)
6582 y1 = MIN(y+1,height-1) ;
6583 if (z <= z0)
6584 z0 = MAX(z-1,0) ;
6585 if (z >= z1)
6586 z1 = MIN(z+1,depth-1) ;
6587 nfilled++ ;
6588 *pdst = fill_val ;
6589 }
6590 }
6591 }
6592 }
6593 zmin = z0 ; zmax = z1 ; ymin = y0 ; ymax = y1 ; xmin = x0 ; xmax = x1 ;
6594 total_pix += nfilled ;
6595 /* fprintf(stderr, "# filled = %d\n", nfilled) ;*/
6596 } while (nfilled > 0) ;
6597
6598 if (npix)
6599 *npix = total_pix ;
6600 return(mri_dst) ;
6601 }
6602 /*-----------------------------------------------------
6603 Parameters:
6604
6605 Returns value:
6606
6607 Description
6608 ------------------------------------------------------*/
6609 MRI *
6610 MRIfillBG(MRI *mri_src, MRI *mri_dst, int seed_x, int seed_y,
6611 int seed_z, int threshold, int fill_val, int *npix)
6612 {
6613 int width, height, depth, x, y, z, nfilled, xmin, xmax, ymin, ymax,
6614 zmin, zmax, on, x0, x1, y0, y1, z0, z1, total_pix ;
6615 BUFTYPE *psrc, *pdst, val ;
6616
6617 width = mri_src->width ;
6618 height = mri_src->height ;
6619 depth = mri_src->depth ;
6620 if (!mri_dst)
6621 mri_dst = MRIclone(mri_src, NULL) ;
6622
6623 if (seed_x < 0)
6624 seed_x = 0 ;
6625 else if (seed_x >= width)
6626 seed_x = width-1 ;
6627 if (seed_y < 0)
6628 seed_y = 0 ;
6629 else if (seed_y >= height)
6630 seed_y = width-1 ;
6631 if (seed_z < 0)
6632 seed_z = 0 ;
6633 else if (seed_z >= depth)
6634 seed_z = width-1 ;
6635
6636 xmin = MAX(seed_x-1,0) ; xmax = MIN(seed_x+1, width-1) ;
6637 ymin = MAX(seed_y-1,0) ; ymax = MIN(seed_y+1, height-1) ;
6638 zmin = MAX(seed_z-1,0) ; zmax = MIN(seed_z+1, depth-1) ;
6639
6640 /* replace all occurrences of fill_val with fill_val-1 */
6641 for (z = 0 ; z < depth ; z++)
6642 {
6643 for (y = 0 ; y < height ; y++)
6644 {
6645 pdst = &MRIvox(mri_dst, 0, y, z) ;
6646 for (x = 0 ; x < width ; x++, pdst++)
6647 {
6648 val = *pdst ;
6649 if (val == fill_val)
6650 *pdst = val-1 ;
6651 }
6652 }
6653 }
6654
6655 MRIvox(mri_dst, seed_x, seed_y, seed_z) = fill_val ;
6656 total_pix = 0 ;
6657 do
6658 {
6659 z0 = zmin ; z1 = zmax ; y0 = ymin ; y1 = ymax ; x0 = xmin ; x1 = xmax ;
6660 nfilled = 0 ;
6661 for (z = zmin ; z <= zmax ; z++)
6662 {
6663 for (y = ymin ; y <= ymax ; y++)
6664 {
6665 psrc = &MRIvox(mri_src, xmin, y, z) ;
6666 pdst = &MRIvox(mri_dst, xmin, y, z) ;
6667 for (x = xmin ; x <= xmax ; x++, psrc++, pdst++)
6668 {
6669 if (z == 130 && (y == 145 || y == 146) && x == 142)
6670 DiagBreak() ;
6671 val = *psrc ;
6672 if ((val > threshold) || (*pdst == fill_val))
6673 continue ;
6674
6675 on = 0 ;
6676 if (x > 0)
6677 on = (MRIvox(mri_dst, x-1, y, z) == fill_val) ;
6678 if (!on && (x < width-1))
6679 on = (MRIvox(mri_dst, x+1, y, z) == fill_val) ;
6680 if (!on && (y > 0))
6681 on = (MRIvox(mri_dst, x, y-1, z) == fill_val) ;
6682 if (!on && (y < height-1))
6683 on = (MRIvox(mri_dst, x, y+1, z) == fill_val) ;
6684 if (!on && (z > 0))
6685 on = (MRIvox(mri_dst, x, y, z-1) == fill_val) ;
6686 if (!on && (z < depth-1))
6687 on = (MRIvox(mri_dst, x, y, z+1) == fill_val) ;
6688 if (on)
6689 {
6690 if (z == 130 && (y == 145 || y == 146) && x == 142)
6691 DiagBreak() ;
6692 if (x <= x0)
6693 x0 = MAX(x-1,0) ;
6694 if (x >= x1)
6695 x1 = MIN(x+1,width-1) ;
6696 if (y <= y0)
6697 y0 = MAX(y-1,0) ;
6698 if (y >= y1)
6699 y1 = MIN(y+1,height-1) ;
6700 if (z <= z0)
6701 z0 = MAX(z-1,0) ;
6702 if (z >= z1)
6703 z1 = MIN(z+1,depth-1) ;
6704 nfilled++ ;
6705 *pdst = fill_val ;
6706 }
6707 }
6708 }
6709 }
6710 zmin = z0 ; zmax = z1 ; ymin = y0 ; ymax = y1 ; xmin = x0 ; xmax = x1 ;
6711 total_pix += nfilled ;
6712 /* fprintf(stderr, "# filled = %d\n", nfilled) ;*/
6713 } while (nfilled > 0) ;
6714
6715 if (npix)
6716 *npix = total_pix ;
6717 return(mri_dst) ;
6718 }
6719 /*-----------------------------------------------------
6720 Parameters:
6721
6722 Returns value:
6723
6724 Description
6725 ------------------------------------------------------*/
6726 int
6727 MRIsetResolution(MRI *mri, float xres, float yres, float zres)
6728 {
6729 mri->ps = (xres+yres+zres) / 3.0f ;
6730 mri->xsize = xres ;
6731 mri->ysize = yres ;
6732 mri->zsize = zres ;
6733 mri->xstart *= xres ; mri->xend *= xres ;
6734 mri->ystart *= yres ; mri->yend *= yres ;
6735 mri->zstart *= zres ; mri->zend *= zres ;
6736 mri->thick = MAX(MAX(xres,yres),zres) ;
6737 #if 0
6738 mri->x_r = mri->x_r * xres ;
6739 mri->x_a = mri->x_a * xres ;
6740 mri->x_s = mri->x_s * xres ;
6741 mri->y_r = mri->y_r * yres ;
6742 mri->y_a = mri->y_a * yres ;
6743 mri->y_s = mri->y_s * yres ;
6744 mri->z_r = mri->z_r * zres ;
6745 mri->z_a = mri->z_a * zres ;
6746 mri->z_s = mri->z_s * zres ;
6747 #endif
6748 return(NO_ERROR) ;
6749 }
6750 /*-----------------------------------------------------
6751 Parameters:
6752
6753 Returns value:
6754
6755 Description
6756 ------------------------------------------------------*/
6757 int
6758 MRIsetTransform(MRI *mri, General_transform *transform)
6759 {
6760 mri->transform = *transform ;
6761 mri->linear_transform = get_linear_transform_ptr(transform) ;
6762 mri->inverse_linear_transform = get_inverse_linear_transform_ptr(transform) ;
6763
6764 return(NO_ERROR) ;
6765 }
6766 /*-----------------------------------------------------
6767 Parameters:
6768
6769 Returns value:
6770
6771 Description
6772 ------------------------------------------------------*/
6773 MRI *
6774 MRIextractTalairachPlane(MRI *mri_src, MRI *mri_dst, int orientation,
6775 int x, int y, int z, int wsize)
6776 {
6777 Real e1_x, e1_y, e1_z, e2_x, e2_y, e2_z, xbase, ybase, zbase ;
6778 int whalf, xk, yk, xi, yi, zi ;
6779 Real ex, ey, ez, len, x0, y0, z0 ;
6780
6781 whalf = (wsize-1)/2 ;
6782
6783 if (!mri_dst)
6784 {
6785 mri_dst = MRIalloc(wsize, wsize, 1, MRI_UCHAR) ;
6786 MRIcopyHeader(mri_src, mri_dst) ;
6787 mri_dst->xstart = x-whalf*mri_dst->xsize ;
6788 mri_dst->ystart = y-whalf*mri_dst->ysize ;
6789 mri_dst->zstart = z-whalf*mri_dst->zsize ;
6790 mri_dst->xend = mri_dst->xstart + wsize*mri_dst->xsize ;
6791 mri_dst->yend = mri_dst->ystart + wsize*mri_dst->ysize ;
6792 mri_dst->zend = mri_dst->zstart + wsize*mri_dst->zsize ;
6793 mri_dst->imnr0 = z + mri_src->imnr0 ;
6794 mri_dst->imnr1 = mri_dst->imnr0 ;
6795 }
6796
6797 MRIvoxelToTalairachVoxel(mri_src, x, y, z, &x0, &y0, &z0) ;
6798 switch (orientation)
6799 {
6800 default:
6801 case MRI_CORONAL: /* basis vectors in x-y plane */
6802 /* the 'x' basis vector */
6803 ex = (Real)x0+1 ; ey = (Real)y0 ; ez = (Real)z0 ;
6804 MRItalairachVoxelToVoxel(mri_src, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
6805 e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
6806
6807 /* the 'y' basis vector */
6808 ex = (Real)x0 ; ey = (Real)y0+1 ; ez = (Real)z0 ;
6809 MRItalairachVoxelToVoxel(mri_src, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
6810 e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
6811 break ;
6812 case MRI_HORIZONTAL: /* basis vectors in x-z plane */
6813 /* the 'x' basis vector */
6814 ex = (Real)x0+1 ; ey = (Real)y0 ; ez = (Real)z0 ;
6815 MRItalairachVoxelToVoxel(mri_src, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
6816 e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
6817
6818 /* the 'y' basis vector */
6819 ex = (Real)x0 ; ey = (Real)y0 ; ez = (Real)z0+1 ;
6820 MRItalairachVoxelToVoxel(mri_src, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
6821 e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
6822 break ;
6823 case MRI_SAGITTAL: /* basis vectors in y-z plane */
6824 /* the 'x' basis vector */
6825 ex = (Real)x0 ; ey = (Real)y0 ; ez = (Real)z0+1.0 ;
6826 MRItalairachVoxelToVoxel(mri_src, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
6827 e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
6828
6829 /* the 'y' basis vector */
6830 ex = (Real)x0 ; ey = (Real)y0+1.0 ; ez = (Real)z0 ;
6831 MRItalairachVoxelToVoxel(mri_src, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
6832 e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
6833 break ;
6834 }
6835
6836 len = sqrt(e1_x*e1_x + e1_y*e1_y + e1_z*e1_z) ;
6837 /* e1_x /= len ; e1_y /= len ; e1_z /= len ;*/
6838 len = sqrt(e2_x*e2_x + e2_y*e2_y + e2_z*e2_z) ;
6839 /* e2_x /= len ; e2_y /= len ; e2_z /= len ;*/
6840
6841 for (yk = -whalf ; yk <= whalf ; yk++)
6842 {
6843 xbase = (float)x + (float)yk * e2_x ;
6844 ybase = (float)y + (float)yk * e2_y ;
6845 zbase = (float)z + (float)yk * e2_z ;
6846 for (xk = -whalf ; xk <= whalf ; xk++)
6847 {
6848 /* in-plane vect. is linear combination of scaled basis vects */
6849 xi = mri_src->xi[nint(xbase + xk*e1_x)] ;
6850 yi = mri_src->yi[nint(ybase + xk*e1_y)] ;
6851 zi = mri_src->zi[nint(zbase + xk*e1_z)] ;
6852 MRIvox(mri_dst, xk+whalf,yk+whalf,0) = MRIvox(mri_src, xi, yi, zi) ;
6853 }
6854 }
6855
6856 return(mri_dst) ;
6857 }
6858 /*-----------------------------------------------------
6859 Parameters:
6860
6861 Returns value:
6862
6863 Description
6864 ------------------------------------------------------*/
6865 MRI *
6866 MRIextractArbitraryPlane(MRI *mri_src, MRI *mri_dst,
6867 Real e1_x, Real e1_y, Real e1_z,
6868 Real e2_x, Real e2_y, Real e2_z,
6869 int x, int y, int z, int wsize)
6870 {
6871 Real xbase, ybase, zbase ;
6872 int whalf, xk, yk, xi, yi, zi ;
6873
6874 whalf = (wsize-1)/2 ;
6875
6876 if (!mri_dst)
6877 {
6878 mri_dst = MRIalloc(wsize, wsize, 1, MRI_UCHAR) ;
6879 MRIcopyHeader(mri_src, mri_dst) ;
6880 mri_dst->xstart = x-whalf*mri_dst->xsize ;
6881 mri_dst->ystart = y-whalf*mri_dst->ysize ;
6882 mri_dst->zstart = z-whalf*mri_dst->zsize ;
6883 mri_dst->xend = mri_dst->xstart + wsize*mri_dst->xsize ;
6884 mri_dst->yend = mri_dst->ystart + wsize*mri_dst->ysize ;
6885 mri_dst->zend = mri_dst->zstart + wsize*mri_dst->zsize ;
6886 mri_dst->imnr0 = z + mri_src->imnr0 ;
6887 mri_dst->imnr1 = mri_dst->imnr0 ;
6888 }
6889
6890
6891
6892 for (yk = -whalf ; yk <= whalf ; yk++)
6893 {
6894 xbase = (float)x + (float)yk * e2_x ;
6895 ybase = (float)y + (float)yk * e2_y ;
6896 zbase = (float)z + (float)yk * e2_z ;
6897 for (xk = -whalf ; xk <= whalf ; xk++)
6898 {
6899 /* in-plane vect. is linear combination of scaled basis vects */
6900 xi = mri_src->xi[nint(xbase + xk*e1_x)] ;
6901 yi = mri_src->yi[nint(ybase + xk*e1_y)] ;
6902 zi = mri_src->zi[nint(zbase + xk*e1_z)] ;
6903 MRIvox(mri_dst, xk+whalf,yk+whalf,0) = MRIvox(mri_src, xi, yi, zi) ;
6904 }
6905 }
6906
6907 return(mri_dst) ;
6908 }
6909 /*-----------------------------------------------------
6910 Parameters:
6911
6912 Returns value:
6913
6914 Description
6915 ------------------------------------------------------*/
6916 int
6917 MRIeraseTalairachPlaneNew(MRI *mri, MRI *mri_mask, int orientation, int x,
6918 int y, int z, int wsize, int fill_val)
6919 {
6920 Real e1_x, e1_y, e1_z, e2_x, e2_y, e2_z, xbase, ybase, zbase ;
6921 int whalf, xk, yk, xi, yi, zi, xki, yki, x0, y0 ;
6922 Real ex, ey, ez, len, xt0, yt0, zt0 ;
6923
6924 whalf = (wsize-1)/2 ;
6925
6926 x0 = mri_mask->width/2 ; y0 = mri_mask->height/2 ;
6927 MRIvoxelToTalairachVoxel(mri, x, y, z, &xt0, &yt0, &zt0) ;
6928 switch (orientation)
6929 {
6930 default:
6931 case MRI_CORONAL: /* basis vectors in x-y plane */
6932 /* the 'x' basis vector */
6933 ex = (Real)xt0+1 ; ey = (Real)yt0 ; ez = (Real)zt0 ;
6934 MRItalairachVoxelToVoxel(mri, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
6935 e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
6936
6937 /* the 'y' basis vector */
6938 ex = (Real)xt0 ; ey = (Real)yt0+1 ; ez = (Real)zt0 ;
6939 MRItalairachVoxelToVoxel(mri, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
6940 e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
6941 break ;
6942 case MRI_HORIZONTAL: /* basis vectors in x-z plane */
6943 /* the 'x' basis vector */
6944 ex = (Real)xt0+1 ; ey = (Real)yt0 ; ez = (Real)zt0 ;
6945 MRItalairachVoxelToVoxel(mri, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
6946 e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
6947
6948 /* the 'y' basis vector */
6949 ex = (Real)xt0 ; ey = (Real)yt0 ; ez = (Real)zt0+1 ;
6950 MRItalairachVoxelToVoxel(mri, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
6951 e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
6952 break ;
6953 case MRI_SAGITTAL: /* basis vectors in y-z plane */
6954 /* the 'x' basis vector */
6955 ex = (Real)xt0 ; ey = (Real)yt0 ; ez = (Real)zt0+1.0 ;
6956 MRItalairachVoxelToVoxel(mri, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
6957 e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
6958
6959 /* the 'y' basis vector */
6960 ex = (Real)xt0 ; ey = (Real)yt0+1.0 ; ez = (Real)zt0 ;
6961 MRItalairachVoxelToVoxel(mri, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
6962 e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
6963 break ;
6964 }
6965
6966 /*
6967 don't want to normalize basis - they are orthonormal in magnet space,
6968 not necessarily Talairach space.
6969 */
6970 len = sqrt(e1_x*e1_x + e1_y*e1_y + e1_z*e1_z) ;
6971 /* e1_x /= len ; e1_y /= len ; e1_z /= len ;*/
6972 len = sqrt(e2_x*e2_x + e2_y*e2_y + e2_z*e2_z) ;
6973 /* e2_x /= len ; e2_y /= len ; e2_z /= len ;*/
6974
6975 for (yk = -whalf ; yk <= whalf ; yk++)
6976 {
6977 xbase = (float)x + (float)yk * e2_x ;
6978 ybase = (float)y + (float)yk * e2_y ;
6979 zbase = (float)z + (float)yk * e2_z ;
6980 for (xk = -whalf ; xk <= whalf ; xk++)
6981 {
6982 /* in-plane vect. is linear combination of scaled basis vects */
6983 xi = mri->xi[nint(xbase + xk*e1_x)] ;
6984 yi = mri->yi[nint(ybase + xk*e1_y)] ;
6985 zi = mri->zi[nint(zbase + xk*e1_z)] ;
6986 xki = mri_mask->xi[xk+x0] ; yki = mri_mask->yi[yk+y0] ;
6987 if (MRIvox(mri_mask, xki, yki,0))
6988 MRIvox(mri, xi, yi, zi) = fill_val ;
6989 }
6990 }
6991
6992 return(NO_ERROR) ;
6993 }
6994 /*-----------------------------------------------------
6995 Parameters:
6996
6997 Returns value:
6998
6999 Description
7000 ------------------------------------------------------*/
7001 int
7002 MRIeraseTalairachPlane(MRI *mri, MRI *mri_mask, int orientation, int x, int y,
7003 int z, int wsize, int fill_val)
7004 {
7005 Real e1_x, e1_y, e1_z, e2_x, e2_y, e2_z, xbase, ybase, zbase ;
7006 int whalf, xk, yk, xi, yi, zi ;
7007 Real ex, ey, ez, len ;
7008
7009 whalf = (wsize-1)/2 ;
7010
7011 switch (orientation)
7012 {
7013 default:
7014 case MRI_CORONAL: /* basis vectors in x-y plane */
7015 /* the 'x' basis vector */
7016 ex = (Real)x+1 ; ey = (Real)y ; ez = (Real)z ;
7017 MRIvoxelToTalairachVoxel(mri, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
7018 e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
7019
7020 /* the 'y' basis vector */
7021 ex = (Real)x ; ey = (Real)y+1 ; ez = (Real)z ;
7022 MRIvoxelToTalairachVoxel(mri, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
7023 e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
7024 break ;
7025 case MRI_HORIZONTAL: /* basis vectors in x-z plane */
7026 /* the 'x' basis vector */
7027 ex = (Real)x+1 ; ey = (Real)y ; ez = (Real)z ;
7028 MRIvoxelToTalairachVoxel(mri, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
7029 e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
7030
7031 /* the 'y' basis vector */
7032 ex = (Real)x ; ey = (Real)y ; ez = (Real)z+1 ;
7033 MRIvoxelToTalairachVoxel(mri, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
7034 e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
7035 break ;
7036 case MRI_SAGITTAL: /* basis vectors in y-z plane */
7037 /* the 'x' basis vector */
7038 ex = (Real)x ; ey = (Real)y ; ez = (Real)z+1.0 ;
7039 MRIvoxelToTalairachVoxel(mri, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
7040 e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
7041
7042 /* the 'y' basis vector */
7043 ex = (Real)x ; ey = (Real)y+1.0 ; ez = (Real)z ;
7044 MRIvoxelToTalairachVoxel(mri, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
7045 e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
7046 break ;
7047 }
7048
7049 /*
7050 don't want to normalize basis - they are orthonormal in magnet space,
7051 not necessarily Talairach space.
7052 */
7053 len = sqrt(e1_x*e1_x + e1_y*e1_y + e1_z*e1_z) ;
7054 /* e1_x /= len ; e1_y /= len ; e1_z /= len ;*/
7055 len = sqrt(e2_x*e2_x + e2_y*e2_y + e2_z*e2_z) ;
7056 /* e2_x /= len ; e2_y /= len ; e2_z /= len ;*/
7057
7058 for (yk = -whalf ; yk <= whalf ; yk++)
7059 {
7060 xbase = (float)x + (float)yk * e2_x ;
7061 ybase = (float)y + (float)yk * e2_y ;
7062 zbase = (float)z + (float)yk * e2_z ;
7063 for (xk = -whalf ; xk <= whalf ; xk++)
7064 {
7065 /* in-plane vect. is linear combination of scaled basis vects */
7066 xi = mri->xi[nint(xbase + xk*e1_x)] ;
7067 yi = mri->yi[nint(ybase + xk*e1_y)] ;
7068 zi = mri->zi[nint(zbase + xk*e1_z)] ;
7069 if (MRIvox(mri_mask, xk+whalf,yk+whalf,0))
7070 MRIvox(mri, xi, yi, zi) = fill_val ;
7071 }
7072 }
7073
7074 return(NO_ERROR) ;
7075 }
7076 /*-----------------------------------------------------
7077 Parameters:
7078
7079 Returns value:
7080
7081 Description
7082 ------------------------------------------------------*/
7083 MRI *
7084 MRIextractPlane(MRI *mri_src, MRI *mri_dst, int orientation, int where)
7085 {
7086 int x, y, z, width, height ;
7087
7088 switch (orientation)
7089 {
7090 default:
7091 case MRI_CORONAL: /* basis vectors in x-y plane */
7092 width = mri_src->width ; height = mri_src->height ;
7093 break ;
7094 case MRI_HORIZONTAL: /* basis vectors in x-z plane */
7095 width = mri_src->width ; height = mri_src->depth ;
7096 break ;
7097 case MRI_SAGITTAL: /* basis vectors in y-z plane */
7098 width = mri_src->depth ; height = mri_src->height ;
7099 break ;
7100 }
7101
7102 if (!mri_dst)
7103 {
7104 mri_dst = MRIalloc(width, height, 1, MRI_UCHAR) ;
7105 MRIcopyHeader(mri_src, mri_dst) ;
7106 mri_dst->zstart = where ; mri_dst->zend = where+1 ;
7107 mri_dst->imnr0 = 0 ; mri_dst->imnr1 = 1 ;
7108 }
7109 switch (orientation)
7110 {
7111 default:
7112 case MRI_CORONAL: /* basis vectors in x-y plane */
7113 for (x = 0 ; x < mri_src->width ; x++)
7114 {
7115 for (y = 0 ; y < mri_src->height ; y++)
7116 MRIvox(mri_dst, x, y, 0) = MRIvox(mri_src, x, y, where) ;
7117 }
7118 break ;
7119 case MRI_HORIZONTAL: /* basis vectors in x-z plane */
7120 for (x = 0 ; x < mri_src->width ; x++)
7121 {
7122 for (z = 0 ; z < mri_src->depth ; z++)
7123 MRIvox(mri_dst, x, z, 0) = MRIvox(mri_src, x, where, z) ;
7124 }
7125 break ;
7126 case MRI_SAGITTAL: /* basis vectors in y-z plane */
7127 for (z = 0 ; z < mri_src->depth ; z++)
7128 {
7129 for (y = 0 ; y < mri_src->height ; y++)
7130 MRIvox(mri_dst, z, y, 0) = MRIvox(mri_src, where, y, z) ;
7131 }
7132 break ;
7133 }
7134
7135 return(mri_dst) ;
7136 }
7137 /*-----------------------------------------------------
7138 Parameters:
7139
7140 Returns value:
7141
7142 Description
7143 ------------------------------------------------------*/
7144 MRI *
7145 MRIfillPlane
7146 (MRI *mri_mask, MRI *mri_dst, int orientation, int where, int fillval)
7147 {
7148 int x, y, z, width, height ;
7149
7150 switch (orientation)
7151 {
7152 default:
7153 case MRI_CORONAL: /* basis vectors in x-y plane */
7154 width = mri_mask->width ; height = mri_mask->height ;
7155 break ;
7156 case MRI_HORIZONTAL: /* basis vectors in x-z plane */
7157 width = mri_mask->width ; height = mri_mask->depth ;
7158 break ;
7159 case MRI_SAGITTAL: /* basis vectors in y-z plane */
7160 width = mri_mask->depth ; height = mri_mask->height ;
7161 break ;
7162 }
7163
7164 switch (orientation)
7165 {
7166 default:
7167 case MRI_CORONAL: /* basis vectors in x-y plane */
7168 for (x = 0 ; x < mri_dst->width ; x++)
7169 {
7170 for (y = 0 ; y < mri_dst->height ; y++)
7171 if (MRIvox(mri_mask, x, y, 0))
7172 MRIvox(mri_dst, x, y, where) = fillval ;
7173 }
7174 break ;
7175 case MRI_HORIZONTAL: /* basis vectors in x-z plane */
7176 for (x = 0 ; x < mri_dst->width ; x++)
7177 {
7178 for (z = 0 ; z < mri_dst->depth ; z++)
7179 {
7180 if (MRIvox(mri_mask, x, z, 0))
7181 MRIvox(mri_dst, x, where, z) = fillval ;
7182 }
7183 }
7184 break ;
7185 case MRI_SAGITTAL: /* basis vectors in y-z plane */
7186 for (z = 0 ; z < mri_dst->depth ; z++)
7187 {
7188 for (y = 0 ; y < mri_dst->height ; y++)
7189 if (MRIvox(mri_mask, z, y, 0))
7190 MRIvox(mri_dst, where, y, z) = fillval ;
7191 }
7192 break ;
7193 }
7194
7195 return(mri_dst) ;
7196 }
7197 /*-----------------------------------------------------
7198 Parameters:
7199
7200 Returns value:
7201
7202 Description
7203 ------------------------------------------------------*/
7204 int
7205 MRIerasePlane(MRI *mri, float x0, float y0, float z0,
7206 float dx, float dy, float dz, int fill_val)
7207 {
7208 int *pxi, *pyi, *pzi, xi, yi, zi, x, y, z ;
7209 float e1_x, e1_y, e1_z, e2_x, e2_y, e2_z, maxlen, l1, l2 ;
7210
7211 maxlen = MAX(mri->width, mri->height) ; maxlen = MAX(maxlen, mri->depth) ;
7212
7213 /* don't care about sign (right-hand rule) */
7214 e1_x = dz*dz - dx*dy ;
7215 e1_y = dx*dx - dy*dz ;
7216 e1_z = dy*dy - dz*dx ;
7217 l1 = sqrt(e1_x*e1_x + e1_y*e1_y + e1_z*e1_z) ;
7218 e1_x /= l1 ; e1_y /= l1 ; e1_z /= l1 ;
7219
7220 e2_x = e1_y*dz - e1_z*dy ;
7221 e2_y = e1_x*dz - e1_z*dx ;
7222 e2_z = e1_y*dx - e1_x*dy ;
7223 l2 = sqrt(e2_x*e2_x + e2_y*e2_y + e2_z*e2_z) ;
7224 e2_x /= l2 ; e2_y /= l2 ; e2_z /= l2 ;
7225
7226 pxi = mri->xi ; pyi = mri->yi ; pzi = mri->zi ;
7227 maxlen *= 1.5 ; /* make sure to get entire extent */
7228 for (l1 = -maxlen/2 ; l1 <= maxlen/2 ; l1 += 0.5f)
7229 {
7230 for (l2 = -maxlen/2 ; l2 <= maxlen/2 ; l2 += 0.5f)
7231 {
7232 x = nint(x0 + l1 * e1_x + l2 * e2_x) ; xi = pxi[x] ;
7233 y = nint(y0 + l1 * e1_y + l2 * e2_y) ; yi = pyi[y] ;
7234 z = nint(z0 + l1 * e1_z + l2 * e2_z) ; zi = pzi[z] ;
7235 MRIvox(mri, xi, yi, zi) = fill_val ;
7236 }
7237 }
7238
7239 return(NO_ERROR) ;
7240 }
7241 /*-----------------------------------------------------
7242 Parameters:
7243
7244 Returns value:
7245
7246 Description
7247 Interpolate the volume to cubic voxels.
7248 ------------------------------------------------------*/
7249 MRI *
7250 MRIinterpolate(MRI *mri_src, MRI *mri_dst)
7251 {
7252 int xs, ys, zs, xd, yd, zd, max_dim, xorig, yorig, zorig, dorig ;
7253 float sx, sy, sz, psize ;
7254 int width, height, depth, i ;
7255 float xsmd, ysmd, zsmd, xspd, yspd, zspd, weights[8], fout ;
7256 int xsp, xsm, ysp, ysm, zsp, zsm ; /* surrounding coordinates */
7257 float vals[8], outval ;
7258
7259 width = mri_src->width ; height = mri_src->height ; depth = mri_src->depth;
7260 if (width > height)
7261 {
7262 max_dim = width > depth ? width : depth ;
7263 psize = width > depth ? mri_src->xsize : mri_src->zsize ;
7264 }
7265 else
7266 {
7267 max_dim = height > depth ? height : depth ;
7268 psize = height > depth ? mri_src->ysize : mri_src->zsize ;
7269 }
7270
7271 if (!mri_dst)
7272 {
7273 mri_dst = MRIalloc(max_dim, max_dim, max_dim, mri_src->type) ;
7274 MRIcopyHeader(mri_src, mri_dst) ;
7275 }
7276
7277 mri_dst->xsize = mri_dst->ysize = mri_dst->zsize = psize ;
7278 sx = (float)width / (float)max_dim ;
7279 sy = (float)height / (float)max_dim ;
7280 sz = (float)depth / (float)max_dim ;
7281
7282 mri_dst->imnr0 = 1;
7283 mri_dst->imnr1 = mri_dst->depth;
7284 mri_dst->xstart = -mri_dst->xsize * mri_dst->width / 2;
7285 mri_dst->xend = -mri_dst->xstart;
7286 mri_dst->ystart = -mri_dst->ysize * mri_dst->height / 2;
7287 mri_dst->yend = -mri_dst->ystart;
7288 mri_dst->zstart = -mri_dst->zsize * mri_dst->depth / 2;
7289 mri_dst->zend = -mri_dst->zstart;
7290
7291 xorig = (width-1)/2 ; yorig = (height-1)/2 ; zorig = (depth-1)/2 ;
7292 dorig = (max_dim-1)/2 ;
7293
7294 /*
7295 for each output voxel, find the 8 nearest input voxels and interpolate
7296 the output voxel from them.
7297 */
7298 for (zd = 0 ; zd < max_dim ; zd++)
7299 {
7300 printf("interpolate: %d/%d\n",zd+1,max_dim);
7301 for (yd = 0 ; yd < max_dim ; yd++)
7302 {
7303 for (xd = 0 ; xd < max_dim ; xd++)
7304 {
7305 /* do trilinear interpolation here */
7306 xs = sx*(xd-dorig) + xorig ;
7307 ys = sy*(yd-dorig) + yorig ;
7308 zs = sz*(zd-dorig) + zorig ;
7309
7310 /*
7311 these boundary conditions will cause
7312 reflection across the border
7313 for the 1st negative pixel.
7314 */
7315 if (xs > -1 && xs < width &&
7316 ys > -1 && ys < height &&
7317 zs > -1 && zs < depth)
7318 {
7319 xsm = (int)xs ;
7320 xsp = MIN(width-1, xsm+1) ;
7321 ysm = (int)ys ;
7322 ysp = MIN(height-1, ysm+1) ;
7323 zsm = (int)zs ;
7324 zsp = MIN(depth-1, zsm+1) ;
7325 xsmd = xs - (float)xsm ;
7326 ysmd = ys - (float)ysm ;
7327 zsmd = zs - (float)zsm ;
7328 xspd = (1.0f - xsmd) ;
7329 yspd = (1.0f - ysmd) ;
7330 zspd = (1.0f - zsmd) ;
7331
7332 /* vals[0] = mri_src->slices[zsm][ysm][xsm] ;
7333 vals[1] = mri_src->slices[zsm][ysm][xsp] ;
7334 vals[2] = mri_src->slices[zsm][ysp][xsm] ;
7335 vals[3] = mri_src->slices[zsm][ysp][xsp] ;
7336 vals[4] = mri_src->slices[zsp][ysm][xsm] ;
7337 vals[5] = mri_src->slices[zsp][ysm][xsp] ;
7338 vals[6] = mri_src->slices[zsp][ysp][xsm] ;
7339 vals[7] = mri_src->slices[zsp][ysp][xsp] ;
7340 */
7341 /* different vox types... */
7342 vals[0] = MRIFvox(mri_src, xsm, ysm, zsm);
7343 vals[1] = MRIFvox(mri_src, xsp, ysm, zsm);
7344 vals[2] = MRIFvox(mri_src, xsm, ysp, zsm);
7345 vals[3] = MRIFvox(mri_src, xsp, ysp, zsm);
7346 vals[4] = MRIFvox(mri_src, xsm, ysm, zsp);
7347 vals[5] = MRIFvox(mri_src, xsp, ysm, zsp);
7348 vals[6] = MRIFvox(mri_src, xsm, ysp, zsp);
7349 vals[7] = MRIFvox(mri_src, xsp, ysp, zsp);
7350
7351 weights[0] = zsmd * ysmd * xsmd ;
7352 weights[1] = zsmd * ysmd * xspd ;
7353 weights[2] = zsmd * yspd * xsmd ;
7354 weights[3] = zsmd * yspd * xspd ;
7355 weights[4] = zspd * ysmd * xsmd ;
7356 weights[5] = zspd * ysmd * xspd ;
7357 weights[6] = zspd * yspd * xsmd ;
7358 weights[7] = zspd * yspd * xspd ;
7359 /*
7360 for(i = 0;i < 8;i++)
7361 printf("%d, %f, %f\n",i,vals[i], weights[i]);
7362 */
7363 for (fout = 0.0f, i = 0 ; i < 8 ; i++)
7364 fout += (float)vals[i] * weights[i] ;
7365 outval = (float)nint(fout) ;
7366 MRIvox(mri_dst, xd, yd, zd) = (BUFTYPE)nint(fout) ;
7367
7368 }
7369 }
7370 }
7371 }
7372
7373 mri_dst->ras_good_flag = 0;
7374
7375 return(mri_dst) ;
7376 }
7377 /*-----------------------------------------------------
7378 Parameters:
7379
7380 Returns value:
7381
7382 Description
7383 ------------------------------------------------------*/
7384 int
7385 MRIsampleVolumeFrame(MRI *mri,Real x,Real y,Real z,int frame,Real *pval)
7386 {
7387 int OutOfBounds;
7388 int xm, xp, ym, yp, zm, zp, width, height, depth ;
7389 Real val, xmd, ymd, zmd, xpd, ypd, zpd ; /* d's are distances */
7390
7391 if (FEQUAL((int)x,x) && FEQUAL((int)y,y) && FEQUAL((int)z, z))
7392 return(MRIsampleVolumeFrameType
7393 (mri, x, y, z, frame, SAMPLE_NEAREST, pval)) ;
7394
7395 if (frame >= mri->nframes)
7396 {
7397 *pval = 1.0 ;
7398 return(NO_ERROR) ;
7399 }
7400
7401 OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
7402 if(OutOfBounds == 1){
7403 /* unambiguoulsy out of bounds */
7404 *pval = 0.0;
7405 return(NO_ERROR) ;
7406 }
7407
7408 width = mri->width ; height = mri->height ; depth = mri->depth ;
7409 if (x >= width)
7410 x = width - 1.0 ;
7411 if (y >= height)
7412 y = height - 1.0 ;
7413 if (z >= depth)
7414 z = depth - 1.0 ;
7415 if (x < 0.0)
7416 x = 0.0 ;
7417 if (y < 0.0)
7418 y = 0.0 ;
7419 if (z < 0.0)
7420 z = 0.0 ;
7421
7422 xm = MAX((int)x, 0) ;
7423 xp = MIN(width-1, xm+1) ;
7424 ym = MAX((int)y, 0) ;
7425 yp = MIN(height-1, ym+1) ;
7426 zm = MAX((int)z, 0) ;
7427 zp = MIN(depth-1, zm+1) ;
7428
7429 xmd = x - (float)xm ;
7430 ymd = y - (float)ym ;
7431 zmd = z - (float)zm ;
7432 xpd = (1.0f - xmd) ;
7433 ypd = (1.0f - ymd) ;
7434 zpd = (1.0f - zmd) ;
7435
7436 switch (mri->type)
7437 {
7438 case MRI_UCHAR:
7439 *pval = val =
7440 xpd * ypd * zpd * (Real)MRIseq_vox(mri, xm, ym, zm, frame) +
7441 xpd * ypd * zmd * (Real)MRIseq_vox(mri, xm, ym, zp, frame) +
7442 xpd * ymd * zpd * (Real)MRIseq_vox(mri, xm, yp, zm, frame) +
7443 xpd * ymd * zmd * (Real)MRIseq_vox(mri, xm, yp, zp, frame) +
7444 xmd * ypd * zpd * (Real)MRIseq_vox(mri, xp, ym, zm, frame) +
7445 xmd * ypd * zmd * (Real)MRIseq_vox(mri, xp, ym, zp, frame) +
7446 xmd * ymd * zpd * (Real)MRIseq_vox(mri, xp, yp, zm, frame) +
7447 xmd * ymd * zmd * (Real)MRIseq_vox(mri, xp, yp, zp, frame) ;
7448 break ;
7449 case MRI_FLOAT:
7450 *pval = val =
7451 xpd * ypd * zpd * (Real)MRIFseq_vox(mri, xm, ym, zm, frame) +
7452 xpd * ypd * zmd * (Real)MRIFseq_vox(mri, xm, ym, zp, frame) +
7453 xpd * ymd * zpd * (Real)MRIFseq_vox(mri, xm, yp, zm, frame) +
7454 xpd * ymd * zmd * (Real)MRIFseq_vox(mri, xm, yp, zp, frame) +
7455 xmd * ypd * zpd * (Real)MRIFseq_vox(mri, xp, ym, zm, frame) +
7456 xmd * ypd * zmd * (Real)MRIFseq_vox(mri, xp, ym, zp, frame) +
7457 xmd * ymd * zpd * (Real)MRIFseq_vox(mri, xp, yp, zm, frame) +
7458 xmd * ymd * zmd * (Real)MRIFseq_vox(mri, xp, yp, zp, frame) ;
7459 break ;
7460 case MRI_SHORT:
7461 *pval = val =
7462 xpd * ypd * zpd * (Real)MRISseq_vox(mri, xm, ym, zm, frame) +
7463 xpd * ypd * zmd * (Real)MRISseq_vox(mri, xm, ym, zp, frame) +
7464 xpd * ymd * zpd * (Real)MRISseq_vox(mri, xm, yp, zm, frame) +
7465 xpd * ymd * zmd * (Real)MRISseq_vox(mri, xm, yp, zp, frame) +
7466 xmd * ypd * zpd * (Real)MRISseq_vox(mri, xp, ym, zm, frame) +
7467 xmd * ypd * zmd * (Real)MRISseq_vox(mri, xp, ym, zp, frame) +
7468 xmd * ymd * zpd * (Real)MRISseq_vox(mri, xp, yp, zm, frame) +
7469 xmd * ymd * zmd * (Real)MRISseq_vox(mri, xp, yp, zp, frame) ;
7470 break ;
7471 case MRI_INT:
7472 *pval = val =
7473 xpd * ypd * zpd * (Real)MRIIseq_vox(mri, xm, ym, zm, frame) +
7474 xpd * ypd * zmd * (Real)MRIIseq_vox(mri, xm, ym, zp, frame) +
7475 xpd * ymd * zpd * (Real)MRIIseq_vox(mri, xm, yp, zm, frame) +
7476 xpd * ymd * zmd * (Real)MRIIseq_vox(mri, xm, yp, zp, frame) +
7477 xmd * ypd * zpd * (Real)MRIIseq_vox(mri, xp, ym, zm, frame) +
7478 xmd * ypd * zmd * (Real)MRIIseq_vox(mri, xp, ym, zp, frame) +
7479 xmd * ymd * zpd * (Real)MRIIseq_vox(mri, xp, yp, zm, frame) +
7480 xmd * ymd * zmd * (Real)MRIIseq_vox(mri, xp, yp, zp, frame) ;
7481 break ;
7482 case MRI_LONG:
7483 *pval = val =
7484 xpd * ypd * zpd * (Real)MRILseq_vox(mri, xm, ym, zm, frame) +
7485 xpd * ypd * zmd * (Real)MRILseq_vox(mri, xm, ym, zp, frame) +
7486 xpd * ymd * zpd * (Real)MRILseq_vox(mri, xm, yp, zm, frame) +
7487 xpd * ymd * zmd * (Real)MRILseq_vox(mri, xm, yp, zp, frame) +
7488 xmd * ypd * zpd * (Real)MRILseq_vox(mri, xp, ym, zm, frame) +
7489 xmd * ypd * zmd * (Real)MRILseq_vox(mri, xp, ym, zp, frame) +
7490 xmd * ymd * zpd * (Real)MRILseq_vox(mri, xp, yp, zm, frame) +
7491 xmd * ymd * zmd * (Real)MRILseq_vox(mri, xp, yp, zp, frame) ;
7492 break ;
7493 default:
7494 ErrorReturn(ERROR_UNSUPPORTED,
7495 (ERROR_UNSUPPORTED,
7496 "MRIsampleVolumeFrame: unsupported type %d", mri->type)) ;
7497 break ;
7498 }
7499 return(NO_ERROR) ;
7500 }
7501
7502
7503
7504 /*---------------------------------------------------------------------------
7505 Purpose: to return the approximate fraction of a voxel centered
7506 at the given point
7507 is labeled with a given label by the labeled volume: mri
7508
7509 Input: mri is the labeled volume. Ea voxel contains the uchar label index
7510 x,y,z is the floating point location of the center of a voxel
7511 whose labeling is to be determined. The voxel is examined to see
7512 how much of it is labeled with the label, ucharLabel
7513
7514 Output: pval is the fraction which the given voxel location is labeled
7515 by ucharLabel
7516 returns NO_ERROR or ERROR_UNSUPPORTED if an unsupported
7517 (non-uchar) mri labeled volume is passed in
7518 AAM: 7/26/00
7519 --------------------------------------------------------------------------*/
7520
7521 #ifndef uchar
7522 #define uchar unsigned char
7523 #endif
7524 int
7525 MRIsampleLabeledVolume
7526 (MRI *mri, Real x, Real y, Real z, Real *pval, unsigned char ucharLabel)
7527 {
7528 /* m's are the mri grid locations less than x (or y or z)
7529 (i.e. floor(x), p's are essentially rounding up to the next
7530 grid location greater than x */
7531 int xm, xp, ym, yp, zm, zp;
7532 int width, height, depth ;
7533 Real xmd, ymd, zmd, xpd, ypd, zpd ; /* d's are distances */
7534 uchar ucharDmmm;
7535 uchar ucharDmmp;
7536 uchar ucharDmpm;
7537 uchar ucharDmpp;
7538 uchar ucharDpmm;
7539 uchar ucharDpmp;
7540 uchar ucharDppm;
7541 uchar ucharDppp;
7542
7543
7544 *pval=0.0;
7545
7546
7547
7548 width = mri->width ;
7549 height = mri->height ;
7550 depth = mri->depth ;
7551 /* if (x >= width)
7552 x = width - 1.0 ;
7553 if (y >= height)
7554 y = height - 1.0 ;
7555 if (z >= depth)
7556 z = depth - 1.0 ;
7557 if (x < 0.0)
7558 x = 0.0 ;
7559 if (y < 0.0)
7560 y = 0.0 ;
7561 if (z < 0.0)
7562 z = 0.0 ;
7563 */
7564
7565 /* if the x,y,z point is out of range
7566 then return that none of the given voxel was labeled by ucharLabel */
7567 if (x >= width) return(NO_ERROR) ;
7568 if (y >= height) return(NO_ERROR) ;
7569 if (z >= depth) return(NO_ERROR) ;
7570 if (x < 0.0) return(NO_ERROR) ;
7571 if (y < 0.0) return(NO_ERROR) ;
7572 if (z < 0.0) return(NO_ERROR) ;
7573
7574 xm = MAX((int)x, 0) ;
7575 xp = MIN(width-1, xm+1) ;
7576 ym = MAX((int)y, 0) ;
7577 yp = MIN(height-1, ym+1) ;
7578 zm = MAX((int)z, 0) ;
7579 zp = MIN(depth-1, zm+1) ;
7580
7581 ucharDmmm = MRIvox(mri, xm, ym, zm) == ucharLabel ? 1 : 0;
7582 ucharDmmp = MRIvox(mri, xm, ym, zp) == ucharLabel ? 1 : 0;
7583 ucharDmpm = MRIvox(mri, xm, yp, zm) == ucharLabel ? 1 : 0;
7584 ucharDmpp = MRIvox(mri, xm, yp, zp) == ucharLabel ? 1 : 0;
7585 ucharDpmm = MRIvox(mri, xp, ym, zm) == ucharLabel ? 1 : 0;
7586 ucharDpmp = MRIvox(mri, xp, ym, zp) == ucharLabel ? 1 : 0;
7587 ucharDppm = MRIvox(mri, xp, yp, zm) == ucharLabel ? 1 : 0;
7588 ucharDppp = MRIvox(mri, xp, yp, zp) == ucharLabel ? 1 : 0;
7589
7590 xmd = x - (float)xm ;
7591 ymd = y - (float)ym ;
7592 zmd = z - (float)zm ;
7593 xpd = (1.0f - xmd) ;
7594 ypd = (1.0f - ymd) ;
7595 zpd = (1.0f - zmd) ;
7596
7597
7598
7599 switch (mri->type)
7600 {
7601 case MRI_UCHAR:
7602 *pval =
7603 xpd * ypd * zpd * (Real)ucharDmmm +
7604 xpd * ypd * zmd * (Real)ucharDmmp +
7605 xpd * ymd * zpd * (Real)ucharDmpm +
7606 xpd * ymd * zmd * (Real)ucharDmpp +
7607 xmd * ypd * zpd * (Real)ucharDpmm +
7608 xmd * ypd * zmd * (Real)ucharDpmp +
7609 xmd * ymd * zpd * (Real)ucharDppm +
7610 xmd * ymd * zmd * (Real)ucharDppp ;
7611 break ;
7612 default:
7613 ErrorReturn(ERROR_UNSUPPORTED,
7614 (ERROR_UNSUPPORTED,
7615 "MRIsampleVolume: unsupported type %d", mri->type)) ;
7616 break ;
7617 }
7618 return(NO_ERROR) ;
7619 }
7620 /*-----------------------------------------------------
7621 Parameters:
7622
7623 Returns value:
7624
7625 Description
7626 ------------------------------------------------------*/
7627 int
7628 MRIsampleVolumeType(MRI *mri, Real x, Real y, Real z, Real *pval, int type)
7629 {
7630 int xv, yv, zv ;
7631 int OutOfBounds;
7632
7633 switch (type)
7634 {
7635 default:
7636 case SAMPLE_NEAREST:
7637 break ;
7638 case SAMPLE_TRILINEAR:
7639 return(MRIsampleVolume(mri, x, y, z, pval)) ;
7640 case SAMPLE_CUBIC:
7641 return(MRIcubicSampleVolume(mri, x, y, z, pval)) ;
7642 case SAMPLE_SINC:
7643 return(MRIsincSampleVolume(mri, x, y, z, 5, pval)) ;
7644 }
7645
7646 OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
7647 if(OutOfBounds == 1){
7648 /* unambiguously out of bounds */
7649 *pval = 0.0;
7650 return(NO_ERROR) ;
7651 }
7652
7653 xv = nint(x) ; yv = nint(y) ; zv = nint(z) ;
7654 if (xv < 0)
7655 xv = 0 ;
7656 if (xv >= mri->width)
7657 xv = mri->width-1 ;
7658 if (yv < 0)
7659 yv = 0 ;
7660 if (yv >= mri->height)
7661 yv = mri->height-1 ;
7662 if (zv < 0)
7663 zv = 0 ;
7664 if (zv >= mri->depth)
7665 zv = mri->depth-1 ;
7666
7667 switch (mri->type)
7668 {
7669 case MRI_UCHAR:
7670 *pval = (float)MRIvox(mri, xv, yv, zv) ;
7671 break ;
7672 case MRI_SHORT:
7673 *pval = (float)MRISvox(mri, xv, yv, zv) ;
7674 break ;
7675 case MRI_INT:
7676 *pval = (float)MRIIvox(mri, xv, yv, zv) ;
7677 break ;
7678 case MRI_FLOAT:
7679 *pval = MRIFvox(mri, xv, yv, zv) ;
7680 break ;
7681 default:
7682 *pval = 0 ;
7683 ErrorReturn
7684 (ERROR_UNSUPPORTED,
7685 (ERROR_UNSUPPORTED,
7686 "MRIsampleVolumeType: unsupported volume type %d",
7687 mri->type)) ;
7688 }
7689 return(NO_ERROR) ;
7690 }
7691 /*-----------------------------------------------------
7692 Parameters:
7693
7694 Returns value:
7695
7696 Description
7697 ------------------------------------------------------*/
7698 int
7699 MRIsampleVolumeFrameType
7700 (MRI *mri, Real x, Real y, Real z, int frame, int type, Real *pval)
7701 {
7702 int xv, yv, zv ;
7703 int OutOfBounds;
7704
7705 if (FEQUAL((int)x,x) && FEQUAL((int)y,y) && FEQUAL((int)z, z))
7706 type = SAMPLE_NEAREST ;
7707
7708 switch (type)
7709 {
7710 case SAMPLE_NEAREST:
7711 break ;
7712 case SAMPLE_TRILINEAR:
7713 return(MRIsampleVolumeFrame(mri, x, y, z, frame, pval)) ;
7714 default:
7715 /*E* add SAMPLE_CUBIC here? */
7716 case SAMPLE_SINC:
7717 ErrorReturn
7718 (ERROR_UNSUPPORTED,
7719 (ERROR_UNSUPPORTED,
7720 "MRIsampleVolumeFrameType(%d): unsupported interpolation type",
7721 type));
7722 /* return(MRIsincSampleVolume(mri, x, y, z, 5, pval)) ;*/
7723 }
7724
7725 OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
7726 if(OutOfBounds == 1){
7727 /* unambiguously out of bounds */
7728 *pval = 0.0;
7729 return(NO_ERROR) ;
7730 }
7731
7732 xv = nint(x) ; yv = nint(y) ; zv = nint(z) ;
7733 if (xv < 0)
7734 xv = 0 ;
7735 if (xv >= mri->width)
7736 xv = mri->width-1 ;
7737 if (yv < 0)
7738 yv = 0 ;
7739 if (yv >= mri->height)
7740 yv = mri->height-1 ;
7741 if (zv < 0)
7742 zv = 0 ;
7743 if (zv >= mri->depth)
7744 zv = mri->depth-1 ;
7745
7746 switch (mri->type)
7747 {
7748 case MRI_UCHAR:
7749 *pval = (float)MRIseq_vox(mri, xv, yv, zv, frame) ;
7750 break ;
7751 case MRI_SHORT:
7752 *pval = (float)MRISseq_vox(mri, xv, yv, zv, frame) ;
7753 break ;
7754 case MRI_INT:
7755 *pval = (float)MRIIseq_vox(mri, xv, yv, zv, frame) ;
7756 break ;
7757 case MRI_FLOAT:
7758 *pval = MRIFseq_vox(mri, xv, yv, zv, frame) ;
7759 break ;
7760 default:
7761 *pval = 0 ;
7762 ErrorReturn
7763 (ERROR_UNSUPPORTED,
7764 (ERROR_UNSUPPORTED,
7765 "MRIsampleVolumeFrameType: unsupported volume type %d",
7766 mri->type)) ;
7767 }
7768 return(NO_ERROR) ;
7769 }
7770
7771
7772 int
7773 MRIinterpolateIntoVolume(MRI *mri, Real x, Real y, Real z, Real val)
7774 {
7775 int OutOfBounds;
7776 int xm, xp, ym, yp, zm, zp, width, height, depth ;
7777 Real xmd, ymd, zmd, xpd, ypd, zpd ; /* d's are distances */
7778
7779 OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
7780 if(OutOfBounds == 1){
7781 /* unambiguously out of bounds */
7782 return(NO_ERROR) ;
7783 }
7784
7785 width = mri->width ; height = mri->height ; depth = mri->depth ;
7786
7787 if (x >= width) x = width - 1.0 ;
7788 if (y >= height) y = height - 1.0 ;
7789 if (z >= depth) z = depth - 1.0 ;
7790 if (x < 0.0) x = 0.0 ;
7791 if (y < 0.0) y = 0.0 ;
7792 if (z < 0.0) z = 0.0 ;
7793
7794 xm = MAX((int)x, 0) ;
7795 xp = MIN(width-1, xm+1) ;
7796 ym = MAX((int)y, 0) ;
7797 yp = MIN(height-1, ym+1) ;
7798 zm = MAX((int)z, 0) ;
7799 zp = MIN(depth-1, zm+1) ;
7800
7801 xmd = x - (float)xm ;
7802 ymd = y - (float)ym ;
7803 zmd = z - (float)zm ;
7804 xpd = (1.0f - xmd) ;
7805 ypd = (1.0f - ymd) ;
7806 zpd = (1.0f - zmd) ;
7807
7808 switch (mri->type)
7809 {
7810 case MRI_UCHAR:
7811 MRIvox(mri, xm, ym, zm) += nint(xpd * ypd * zpd * val) ;
7812 MRIvox(mri, xm, ym, zp) += nint(xpd * ypd * zmd * val) ;
7813 MRIvox(mri, xm, yp, zm) += nint(xpd * ymd * zpd * val) ;
7814 MRIvox(mri, xm, yp, zp) += nint(xpd * ymd * zmd * val) ;
7815 MRIvox(mri, xp, ym, zm) += nint(xmd * ypd * zpd * val) ;
7816 MRIvox(mri, xp, ym, zp) += nint(xmd * ypd * zmd * val) ;
7817 MRIvox(mri, xp, yp, zm) += nint(xmd * ymd * zpd * val) ;
7818 MRIvox(mri, xp, yp, zp) += nint(xmd * ymd * zmd * val) ;
7819 break ;
7820 case MRI_FLOAT:
7821 MRIFvox(mri, xm, ym, zm) += (xpd * ypd * zpd * val) ;
7822 MRIFvox(mri, xm, ym, zp) += (xpd * ypd * zmd * val) ;
7823 MRIFvox(mri, xm, yp, zm) += (xpd * ymd * zpd * val) ;
7824 MRIFvox(mri, xm, yp, zp) += (xpd * ymd * zmd * val) ;
7825 MRIFvox(mri, xp, ym, zm) += (xmd * ypd * zpd * val) ;
7826 MRIFvox(mri, xp, ym, zp) += (xmd * ypd * zmd * val) ;
7827 MRIFvox(mri, xp, yp, zm) += (xmd * ymd * zpd * val) ;
7828 MRIFvox(mri, xp, yp, zp) += (xmd * ymd * zmd * val) ;
7829 break ;
7830 case MRI_SHORT:
7831 MRISvox(mri, xm, ym, zm) += nint(xpd * ypd * zpd * val) ;
7832 MRISvox(mri, xm, ym, zp) += nint(xpd * ypd * zmd * val) ;
7833 MRISvox(mri, xm, yp, zm) += nint(xpd * ymd * zpd * val) ;
7834 MRISvox(mri, xm, yp, zp) += nint(xpd * ymd * zmd * val) ;
7835 MRISvox(mri, xp, ym, zm) += nint(xmd * ypd * zpd * val) ;
7836 MRISvox(mri, xp, ym, zp) += nint(xmd * ypd * zmd * val) ;
7837 MRISvox(mri, xp, yp, zm) += nint(xmd * ymd * zpd * val) ;
7838 MRISvox(mri, xp, yp, zp) += nint(xmd * ymd * zmd * val) ;
7839 break ;
7840 case MRI_INT:
7841 MRIIvox(mri, xm, ym, zm) += nint(xpd * ypd * zpd * val) ;
7842 MRIIvox(mri, xm, ym, zp) += nint(xpd * ypd * zmd * val) ;
7843 MRIIvox(mri, xm, yp, zm) += nint(xpd * ymd * zpd * val) ;
7844 MRIIvox(mri, xm, yp, zp) += nint(xpd * ymd * zmd * val) ;
7845 MRIIvox(mri, xp, ym, zm) += nint(xmd * ypd * zpd * val) ;
7846 MRIIvox(mri, xp, ym, zp) += nint(xmd * ypd * zmd * val) ;
7847 MRIIvox(mri, xp, yp, zm) += nint(xmd * ymd * zpd * val) ;
7848 MRIIvox(mri, xp, yp, zp) += nint(xmd * ymd * zmd * val) ;
7849 break ;
7850 case MRI_LONG:
7851 MRILvox(mri, xm, ym, zm) += nint(xpd * ypd * zpd * val) ;
7852 MRILvox(mri, xm, ym, zp) += nint(xpd * ypd * zmd * val) ;
7853 MRILvox(mri, xm, yp, zm) += nint(xpd * ymd * zpd * val) ;
7854 MRILvox(mri, xm, yp, zp) += nint(xpd * ymd * zmd * val) ;
7855 MRILvox(mri, xp, ym, zm) += nint(xmd * ypd * zpd * val) ;
7856 MRILvox(mri, xp, ym, zp) += nint(xmd * ypd * zmd * val) ;
7857 MRILvox(mri, xp, yp, zm) += nint(xmd * ymd * zpd * val) ;
7858 MRILvox(mri, xp, yp, zp) += nint(xmd * ymd * zmd * val) ;
7859 break ;
7860 default:
7861 ErrorReturn(ERROR_UNSUPPORTED,
7862 (ERROR_UNSUPPORTED,
7863 "MRIsampleVolume: unsupported type %d", mri->type)) ;
7864 break ;
7865 }
7866 return(NO_ERROR) ;
7867 }
7868
7869 /*-------------------------------------------------------------------
7870 MRIsampleVolume() - performs trilinear interpolation on a
7871 single-frame volume. See MRIsampleSeqVolume() for sampling
7872 multi-frame.
7873 -------------------------------------------------------------------*/
7874 int
7875 MRIsampleVolume(MRI *mri, Real x, Real y, Real z, Real *pval)
7876 {
7877 int OutOfBounds;
7878 int xm, xp, ym, yp, zm, zp, width, height, depth ;
7879 Real val, xmd, ymd, zmd, xpd, ypd, zpd ; /* d's are distances */
7880
7881 if (FEQUAL((int)x,x) && FEQUAL((int)y,y) && FEQUAL((int)z, z))
7882 return(MRIsampleVolumeType(mri, x, y, z, pval, SAMPLE_NEAREST)) ;
7883
7884 OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
7885 if(OutOfBounds == 1){
7886 /* unambiguously out of bounds */
7887 *pval = 0.0;
7888 return(NO_ERROR) ;
7889 }
7890
7891 width = mri->width ; height = mri->height ; depth = mri->depth ;
7892
7893 if (x >= width) x = width - 1.0 ;
7894 if (y >= height) y = height - 1.0 ;
7895 if (z >= depth) z = depth - 1.0 ;
7896 if (x < 0.0) x = 0.0 ;
7897 if (y < 0.0) y = 0.0 ;
7898 if (z < 0.0) z = 0.0 ;
7899
7900 xm = MAX((int)x, 0) ;
7901 xp = MIN(width-1, xm+1) ;
7902 ym = MAX((int)y, 0) ;
7903 yp = MIN(height-1, ym+1) ;
7904 zm = MAX((int)z, 0) ;
7905 zp = MIN(depth-1, zm+1) ;
7906
7907 xmd = x - (float)xm ;
7908 ymd = y - (float)ym ;
7909 zmd = z - (float)zm ;
7910 xpd = (1.0f - xmd) ;
7911 ypd = (1.0f - ymd) ;
7912 zpd = (1.0f - zmd) ;
7913
7914 switch (mri->type)
7915 {
7916 case MRI_UCHAR:
7917 *pval = val =
7918 xpd * ypd * zpd * (Real)MRIvox(mri, xm, ym, zm) +
7919 xpd * ypd * zmd * (Real)MRIvox(mri, xm, ym, zp) +
7920 xpd * ymd * zpd * (Real)MRIvox(mri, xm, yp, zm) +
7921 xpd * ymd * zmd * (Real)MRIvox(mri, xm, yp, zp) +
7922 xmd * ypd * zpd * (Real)MRIvox(mri, xp, ym, zm) +
7923 xmd * ypd * zmd * (Real)MRIvox(mri, xp, ym, zp) +
7924 xmd * ymd * zpd * (Real)MRIvox(mri, xp, yp, zm) +
7925 xmd * ymd * zmd * (Real)MRIvox(mri, xp, yp, zp) ;
7926 break ;
7927 case MRI_FLOAT:
7928 *pval = val =
7929 xpd * ypd * zpd * (Real)MRIFvox(mri, xm, ym, zm) +
7930 xpd * ypd * zmd * (Real)MRIFvox(mri, xm, ym, zp) +
7931 xpd * ymd * zpd * (Real)MRIFvox(mri, xm, yp, zm) +
7932 xpd * ymd * zmd * (Real)MRIFvox(mri, xm, yp, zp) +
7933 xmd * ypd * zpd * (Real)MRIFvox(mri, xp, ym, zm) +
7934 xmd * ypd * zmd * (Real)MRIFvox(mri, xp, ym, zp) +
7935 xmd * ymd * zpd * (Real)MRIFvox(mri, xp, yp, zm) +
7936 xmd * ymd * zmd * (Real)MRIFvox(mri, xp, yp, zp) ;
7937 break ;
7938 case MRI_SHORT:
7939 *pval = val =
7940 xpd * ypd * zpd * (Real)MRISvox(mri, xm, ym, zm) +
7941 xpd * ypd * zmd * (Real)MRISvox(mri, xm, ym, zp) +
7942 xpd * ymd * zpd * (Real)MRISvox(mri, xm, yp, zm) +
7943 xpd * ymd * zmd * (Real)MRISvox(mri, xm, yp, zp) +
7944 xmd * ypd * zpd * (Real)MRISvox(mri, xp, ym, zm) +
7945 xmd * ypd * zmd * (Real)MRISvox(mri, xp, ym, zp) +
7946 xmd * ymd * zpd * (Real)MRISvox(mri, xp, yp, zm) +
7947 xmd * ymd * zmd * (Real)MRISvox(mri, xp, yp, zp) ;
7948 break ;
7949 case MRI_INT:
7950 *pval = val =
7951 xpd * ypd * zpd * (Real)MRIIvox(mri, xm, ym, zm) +
7952 xpd * ypd * zmd * (Real)MRIIvox(mri, xm, ym, zp) +
7953 xpd * ymd * zpd * (Real)MRIIvox(mri, xm, yp, zm) +
7954 xpd * ymd * zmd * (Real)MRIIvox(mri, xm, yp, zp) +
7955 xmd * ypd * zpd * (Real)MRIIvox(mri, xp, ym, zm) +
7956 xmd * ypd * zmd * (Real)MRIIvox(mri, xp, ym, zp) +
7957 xmd * ymd * zpd * (Real)MRIIvox(mri, xp, yp, zm) +
7958 xmd * ymd * zmd * (Real)MRIIvox(mri, xp, yp, zp) ;
7959 break ;
7960 case MRI_LONG:
7961 *pval = val =
7962 xpd * ypd * zpd * (Real)MRILvox(mri, xm, ym, zm) +
7963 xpd * ypd * zmd * (Real)MRILvox(mri, xm, ym, zp) +
7964 xpd * ymd * zpd * (Real)MRILvox(mri, xm, yp, zm) +
7965 xpd * ymd * zmd * (Real)MRILvox(mri, xm, yp, zp) +
7966 xmd * ypd * zpd * (Real)MRILvox(mri, xp, ym, zm) +
7967 xmd * ypd * zmd * (Real)MRILvox(mri, xp, ym, zp) +
7968 xmd * ymd * zpd * (Real)MRILvox(mri, xp, yp, zm) +
7969 xmd * ymd * zmd * (Real)MRILvox(mri, xp, yp, zp) ;
7970 break ;
7971 default:
7972 ErrorReturn(ERROR_UNSUPPORTED,
7973 (ERROR_UNSUPPORTED,
7974 "MRIsampleVolume: unsupported type %d", mri->type)) ;
7975 break ;
7976 }
7977 return(NO_ERROR) ;
7978 }
7979
7980 /*------------------------------------------------------------------
7981 MRIsampleSeqVolume() - performs trilinear interpolation on a
7982 multi-frame volume. valvect is a vector of length nframes. No error
7983 checking for first and last frame. The caller is able to specify
7984 first frame and last frame so that all frames do not have to be
7985 sampled at the same time (this can be important in time-sensative
7986 applications).
7987 -------------------------------------------------------------------*/
7988 int MRIsampleSeqVolume(MRI *mri, Real x, Real y, Real z, float *valvect,
7989 int firstframe, int lastframe)
7990 {
7991 int OutOfBounds;
7992 int f,xm, xp, ym, yp, zm, zp, width, height, depth ;
7993 Real xmd, ymd, zmd, xpd, ypd, zpd ; /* d's are distances */
7994
7995 OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
7996 if(OutOfBounds == 1){
7997 /* unambiguously out of bounds */
7998 for(f=firstframe; f <= lastframe; f++) valvect[f] = 0.0;
7999 return(NO_ERROR) ;
8000 }
8001
8002 width = mri->width ; height = mri->height ; depth = mri->depth ;
8003
8004 if (x >= width) x = width - 1.0 ;
8005 if (y >= height) y = height - 1.0 ;
8006 if (z >= depth) z = depth - 1.0 ;
8007 if (x < 0.0) x = 0.0 ;
8008 if (y < 0.0) y = 0.0 ;
8009 if (z < 0.0) z = 0.0 ;
8010
8011 xm = MAX((int)x, 0) ;
8012 xp = MIN(width-1, xm+1) ;
8013 ym = MAX((int)y, 0) ;
8014 yp = MIN(height-1, ym+1) ;
8015 zm = MAX((int)z, 0) ;
8016 zp = MIN(depth-1, zm+1) ;
8017
8018 xmd = x - (float)xm ;
8019 ymd = y - (float)ym ;
8020 zmd = z - (float)zm ;
8021 xpd = (1.0f - xmd) ;
8022 ypd = (1.0f - ymd) ;
8023 zpd = (1.0f - zmd) ;
8024
8025 for(f = firstframe; f <= lastframe; f++){
8026 switch (mri->type) {
8027 case MRI_UCHAR:
8028 valvect[f] =
8029 xpd * ypd * zpd * (Real)MRIseq_vox(mri, xm, ym, zm, f) +
8030 xpd * ypd * zmd * (Real)MRIseq_vox(mri, xm, ym, zp, f) +
8031 xpd * ymd * zpd * (Real)MRIseq_vox(mri, xm, yp, zm, f) +
8032 xpd * ymd * zmd * (Real)MRIseq_vox(mri, xm, yp, zp, f) +
8033 xmd * ypd * zpd * (Real)MRIseq_vox(mri, xp, ym, zm, f) +
8034 xmd * ypd * zmd * (Real)MRIseq_vox(mri, xp, ym, zp, f) +
8035 xmd * ymd * zpd * (Real)MRIseq_vox(mri, xp, yp, zm, f) +
8036 xmd * ymd * zmd * (Real)MRIseq_vox(mri, xp, yp, zp, f) ;
8037 break ;
8038 case MRI_FLOAT:
8039 valvect[f] =
8040 xpd * ypd * zpd * (Real)MRIFseq_vox(mri, xm, ym, zm, f) +
8041 xpd * ypd * zmd * (Real)MRIFseq_vox(mri, xm, ym, zp, f) +
8042 xpd * ymd * zpd * (Real)MRIFseq_vox(mri, xm, yp, zm, f) +
8043 xpd * ymd * zmd * (Real)MRIFseq_vox(mri, xm, yp, zp, f) +
8044 xmd * ypd * zpd * (Real)MRIFseq_vox(mri, xp, ym, zm, f) +
8045 xmd * ypd * zmd * (Real)MRIFseq_vox(mri, xp, ym, zp, f) +
8046 xmd * ymd * zpd * (Real)MRIFseq_vox(mri, xp, yp, zm, f) +
8047 xmd * ymd * zmd * (Real)MRIFseq_vox(mri, xp, yp, zp, f) ;
8048 break ;
8049 case MRI_SHORT:
8050 valvect[f] =
8051 xpd * ypd * zpd * (Real)MRISseq_vox(mri, xm, ym, zm, f) +
8052 xpd * ypd * zmd * (Real)MRISseq_vox(mri, xm, ym, zp, f) +
8053 xpd * ymd * zpd * (Real)MRISseq_vox(mri, xm, yp, zm, f) +
8054 xpd * ymd * zmd * (Real)MRISseq_vox(mri, xm, yp, zp, f) +
8055 xmd * ypd * zpd * (Real)MRISseq_vox(mri, xp, ym, zm, f) +
8056 xmd * ypd * zmd * (Real)MRISseq_vox(mri, xp, ym, zp, f) +
8057 xmd * ymd * zpd * (Real)MRISseq_vox(mri, xp, yp, zm, f) +
8058 xmd * ymd * zmd * (Real)MRISseq_vox(mri, xp, yp, zp, f) ;
8059 break ;
8060 case MRI_INT:
8061 valvect[f] =
8062 xpd * ypd * zpd * (Real)MRIIseq_vox(mri, xm, ym, zm, f) +
8063 xpd * ypd * zmd * (Real)MRIIseq_vox(mri, xm, ym, zp, f) +
8064 xpd * ymd * zpd * (Real)MRIIseq_vox(mri, xm, yp, zm, f) +
8065 xpd * ymd * zmd * (Real)MRIIseq_vox(mri, xm, yp, zp, f) +
8066 xmd * ypd * zpd * (Real)MRIIseq_vox(mri, xp, ym, zm, f) +
8067 xmd * ypd * zmd * (Real)MRIIseq_vox(mri, xp, ym, zp, f) +
8068 xmd * ymd * zpd * (Real)MRIIseq_vox(mri, xp, yp, zm, f) +
8069 xmd * ymd * zmd * (Real)MRIIseq_vox(mri, xp, yp, zp, f) ;
8070 break ;
8071 case MRI_LONG:
8072 valvect[f] =
8073 xpd * ypd * zpd * (Real)MRILseq_vox(mri, xm, ym, zm, f) +
8074 xpd * ypd * zmd * (Real)MRILseq_vox(mri, xm, ym, zp, f) +
8075 xpd * ymd * zpd * (Real)MRILseq_vox(mri, xm, yp, zm, f) +
8076 xpd * ymd * zmd * (Real)MRILseq_vox(mri, xm, yp, zp, f) +
8077 xmd * ypd * zpd * (Real)MRILseq_vox(mri, xp, ym, zm, f) +
8078 xmd * ypd * zmd * (Real)MRILseq_vox(mri, xp, ym, zp, f) +
8079 xmd * ymd * zpd * (Real)MRILseq_vox(mri, xp, yp, zm, f) +
8080 xmd * ymd * zmd * (Real)MRILseq_vox(mri, xp, yp, zp, f) ;
8081 break ;
8082 default:
8083 ErrorReturn(ERROR_UNSUPPORTED,
8084 (ERROR_UNSUPPORTED,
8085 "MRIsampleSeqVolume: unsupported type %d", mri->type)) ;
8086 break ;
8087 }
8088 }/* end loop over frames */
8089
8090 return(NO_ERROR) ;
8091 }
8092
8093 /*-----------------------------------------------------
8094 used by MRIcubicSampleVolume
8095 ------------------------------------------------------*/
8096
8097 double
8098 localeval(Real x, int iter)
8099 {
8100 double p;
8101 switch (iter)
8102 {
8103 case 0:
8104 p = ((2-x)*x-1)*x; break;
8105 case 1:
8106 p = (3*x-5)*x*x+2; break;
8107 case 2:
8108 p = ((4-3*x)*x+1)*x; break;
8109 case 3:
8110 p = (x-1)*x*x; break;
8111 default:
8112 ErrorReturn(ERROR_UNSUPPORTED,
8113 (ERROR_UNSUPPORTED,
8114 "localeval: called wrong by MRIcubicSampleVolume!")) ;
8115 }
8116 return(p);
8117 }
8118
8119 /*-----------------------------------------------------
8120 Parameters:
8121
8122 Returns value:
8123
8124 Description
8125
8126 by analogy with
8127 /usr/pubsw/common/matlab/6.5/toolbox/matlab/polyfun/interp3.m
8128
8129 uses localeval above
8130
8131 ------------------------------------------------------*/
8132 int
8133 MRIcubicSampleVolume(MRI *mri, Real x, Real y, Real z, Real *pval)
8134 {
8135 int OutOfBounds;
8136 int width, height, depth ;
8137 int ix_low,iy_low,iz_low,ix,iy,iz;
8138 double val,xx,yy,zz,fx,fy,fz,vv[4][4][4];
8139
8140 if (FEQUAL((int)x,x) && FEQUAL((int)y,y) && FEQUAL((int)z, z))
8141 return(MRIsampleVolumeType(mri, x, y, z, pval, SAMPLE_NEAREST)) ;
8142
8143 OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
8144 if(OutOfBounds == 1){
8145 /* unambiguously out of bounds */
8146 *pval = val = 0.0;
8147 return(NO_ERROR) ;
8148 }
8149 width = mri->width ; height = mri->height ; depth = mri->depth ;
8150
8151 /*E* I suppose these are for "ambiguously out of bounds" - within .5vox */
8152
8153 /*E* I think this needs an edit - x is Real, whatever that is, not
8154 int, so any x>= width-1 should be set to width-1.
8155 if (x >= width) x = width - 1.0 ;
8156 if (y >= height) y = height - 1.0 ;
8157 if (z >= depth) z = depth - 1.0 ;
8158 */
8159
8160 if (x > width-1.0) x = width - 1.0 ;
8161 if (y > height-1.0) y = height - 1.0 ;
8162 if (z > depth-1.0) z = depth - 1.0 ;
8163 if (x < 0.0) x = 0.0 ;
8164 if (y < 0.0) y = 0.0 ;
8165 if (z < 0.0) z = 0.0 ;
8166
8167 ix_low = floor((double)x);
8168 if ((ix_low = floor((double)x)) < width-1)
8169 xx = x - ix_low;
8170 else
8171 {
8172 ix_low--;
8173 xx = 1;
8174 }
8175 iy_low = floor((double)y);
8176 if ((iy_low = floor((double)y)) < height-1)
8177 yy = y - iy_low;
8178 else
8179 {
8180 iy_low--;
8181 yy = 1;
8182 }
8183 iz_low = floor((double)z);
8184 if ((iz_low = floor((double)z)) < depth-1)
8185 zz = z - iz_low;
8186 else
8187 {
8188 iz_low--;
8189 zz = 1;
8190 }
8191
8192 /*E* build a little box of the local points plus boundary stuff -
8193 for this rev accept zeroes for the border expansion */
8194
8195 for(iz= MAX(0,1-iz_low); iz<MIN(4,depth+1-iz_low); iz++)
8196 {
8197 for(iy= MAX(0,1-iy_low); iy<MIN(4,height+1-iy_low); iy++)
8198 {
8199 for(ix= MAX(0,1-ix_low); ix<MIN(4,width+1-ix_low); ix++)
8200 {
8201 switch (mri->type)
8202 {
8203 case MRI_UCHAR:
8204 vv[ix][iy][iz] =
8205 (double)MRIvox(mri,ix_low-1+ix,iy_low-1+iy,iz_low-1+iz);
8206 break;
8207 case MRI_FLOAT:
8208 vv[ix][iy][iz] =
8209 (double)MRIFvox(mri,ix_low-1+ix,iy_low-1+iy,iz_low-1+iz);
8210 break;
8211 case MRI_SHORT:
8212 vv[ix][iy][iz] =
8213 (double)MRISvox(mri,ix_low-1+ix,iy_low-1+iy,iz_low-1+iz);
8214 break;
8215 case MRI_INT:
8216 vv[ix][iy][iz] =
8217 (double)MRIIvox(mri,ix_low-1+ix,iy_low-1+iy,iz_low-1+iz);
8218 break;
8219 case MRI_LONG:
8220 vv[ix][iy][iz] =
8221 (double)MRILvox(mri,ix_low-1+ix,iy_low-1+iy,iz_low-1+iz);
8222 break;
8223 default:
8224 ErrorReturn(ERROR_UNSUPPORTED,
8225 (ERROR_UNSUPPORTED,
8226 "MRIcubicSampleVolume: unsupported type %d",
8227 mri->type)) ;
8228 break ;
8229 }
8230 }
8231 }
8232 }
8233
8234 val = 0;
8235
8236 for(iz=0; iz<=3; iz++)
8237 {
8238 fz = localeval(zz,iz);
8239 for(iy=0; iy<=3; iy++)
8240 {
8241 fy = localeval(yy,iy);
8242 for(ix=0; ix<=3; ix++)
8243 {
8244 fx = localeval(xx,ix);
8245 val += (Real)(vv[ix][iy][iz]*fx*fy*fz);
8246 }
8247 }
8248 }
8249
8250 *pval = val/8.;
8251
8252 return(NO_ERROR);
8253 }
8254
8255 /*-----------------------------------------------------
8256 Parameters:
8257
8258 Returns value:
8259
8260 Description
8261 ------------------------------------------------------*/
8262 #define IMIN(a,b) (a < b ? a : b)
8263 #define IMAX(a,b) (a > b ? a : b)
8264 double ham_sinc(double x,double fullwidth)
8265 {
8266 double ham;
8267 if( fabs(x) < 1.0e-5)
8268 ham = 1.0;
8269 else {
8270 ham = sin(PI*x)/(PI*x);
8271 ham *= 0.54 + 0.46 * cos(2.0*PI*x/fullwidth);
8272 }
8273 return ham;
8274 }
8275
8276 /*-------------------------------------------------------------------------*/
8277 int
8278 MRIsincSampleVolume(MRI *mri, Real x, Real y, Real z, int hw, Real *pval)
8279 {
8280
8281 int OutOfBounds;
8282 int width, height, depth ;
8283 int nwidth;
8284 int ix_low,ix_high,iy_low,iy_high,iz_low,iz_high;
8285 int jx1,jy1,jz1,jx_rel,jy_rel,jz_rel;
8286 double coeff_x[128],coeff_y[128],coeff_z[128];
8287 double coeff_x_sum,coeff_y_sum,coeff_z_sum;
8288 double sum_x,sum_y,sum_z;
8289 double xsize,ysize,zsize;
8290
8291 OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
8292 if(OutOfBounds == 1){
8293 /* unambiguously out of bounds */
8294 *pval = 0.0;
8295 return(NO_ERROR) ;
8296 }
8297
8298 xsize = mri->xsize; ysize=mri->ysize; zsize=mri->zsize;
8299 width = mri->width ; height = mri->height ; depth = mri->depth ;
8300 if (x >= width) x = width - 1.0 ;
8301 if (y >= height) y = height - 1.0 ;
8302 if (z >= depth) z = depth - 1.0 ;
8303 if (x < 0.0) x = 0.0 ;
8304 if (y < 0.0) y = 0.0 ;
8305 if (z < 0.0) z = 0.0 ;
8306
8307 nwidth = hw;
8308 ix_low = floor((double)x);
8309 ix_high = ceil((double)x);
8310 iy_low = floor((double)y);
8311 iy_high = ceil((double)y);
8312 iz_low = floor((double)z);
8313 iz_high = ceil((double)z);
8314
8315 coeff_x_sum = coeff_y_sum = coeff_z_sum = 0;
8316 if(iz_low>=0 && iz_high < depth)
8317 {
8318 for (jx1=IMAX(ix_high-nwidth,0), jx_rel=0;
8319 jx1<IMIN(ix_low+nwidth,width-1);
8320 jx1++,jx_rel++)
8321 {
8322 coeff_x[jx_rel] = ham_sinc((double)(x-jx1),2*nwidth);
8323 coeff_x_sum += coeff_x[jx_rel];
8324 }
8325 for (jy1=IMAX(iy_high-nwidth,0), jy_rel=0;
8326 jy1<IMIN(iy_low+nwidth,height-1);
8327 jy1++,jy_rel++)
8328 {
8329 coeff_y[jy_rel] = ham_sinc((double)(y-jy1),2*nwidth);
8330 coeff_y_sum += coeff_y[jy_rel];
8331 }
8332 for (jz1=IMAX(iz_high-nwidth,0), jz_rel=0;
8333 jz1<IMIN(iz_low+nwidth,depth-1);
8334 jz1++,jz_rel++)
8335 {
8336 coeff_z[jz_rel] = ham_sinc((double)(z-jz1),2*nwidth);
8337 coeff_z_sum += coeff_z[jz_rel];
8338 }
8339
8340 for(sum_z=0., jz1=IMAX(iz_high-nwidth,0), jz_rel = 0;
8341 jz1 < IMIN(iz_low+nwidth,depth-1);
8342 jz1++, jz_rel++)
8343 {
8344
8345 for(sum_y=0., jy1=IMAX(iy_high-nwidth,0), jy_rel = 0;
8346 jy1 < IMIN(iy_low+nwidth,height-1);
8347 jy1++, jy_rel++)
8348 {
8349 for(sum_x=0., jx1=IMAX(ix_high-nwidth,0), jx_rel = 0;
8350 jx1 < IMIN(ix_low+nwidth,width-1);
8351 jx1++, jx_rel++)
8352 {
8353
8354 switch(mri->type)
8355 {
8356 case MRI_UCHAR:
8357 sum_x += (coeff_x[jx_rel]/coeff_x_sum)
8358 * (double)MRIvox(mri,jx1,jy1,jz1);
8359 break;
8360 case MRI_SHORT:
8361 sum_x += (coeff_x[jx_rel]/coeff_x_sum)
8362 * (double)MRISvox(mri,jx1,jy1,jz1);
8363 break;
8364 case MRI_INT:
8365 sum_x += (coeff_x[jx_rel]/coeff_x_sum)
8366 * (double)MRIIvox(mri,jx1,jy1,jz1);
8367 break;
8368 case MRI_LONG:
8369 sum_x += (coeff_x[jx_rel]/coeff_x_sum)
8370 * (double)MRILvox(mri,jx1,jy1,jz1);
8371 break;
8372 case MRI_FLOAT:
8373 sum_x += (coeff_x[jx_rel]/coeff_x_sum)
8374 * (double)MRIFvox(mri,jx1,jy1,jz1);
8375 break;
8376 default:
8377 ErrorReturn(ERROR_UNSUPPORTED,
8378 (ERROR_UNSUPPORTED,
8379 "MRIsincSampleVolume: unsupported type %d",
8380 mri->type)) ;
8381 break;
8382 }
8383 }
8384 sum_y += sum_x * (coeff_y[jy_rel]/coeff_y_sum);
8385 }
8386 sum_z += sum_y * (coeff_z[jz_rel]/coeff_z_sum);
8387 }
8388 if((mri->type == MRI_UCHAR || mri->type == MRI_SHORT) && sum_z<0.0)
8389 *pval = 0.0;
8390 else if(mri->type == MRI_UCHAR && sum_z >255.0)
8391 *pval = 255.0;
8392 else if(mri->type == MRI_SHORT && sum_z > 65535.0)
8393 *pval = 65535.0;
8394 else
8395 *pval = sum_z;
8396 }
8397 else
8398 *pval = 0.0;
8399
8400 return(NO_ERROR);
8401 }
8402 /*-----------------------------------------------------------------
8403 MRIindexNotInVolume() - determines whether a col, row, slice point is
8404 in the mri volume. If it is unambiguously in the volume, then 0
8405 is returned. If it is within 0.5 of the edge of the volume, -1
8406 is returned. Otherwise 1 is returned. Flagging the case where
8407 the point is within 0.5 of the edge can be used for assigning
8408 a nearest neighbor when the point is outside but close to the
8409 volume. In this case the index of the nearest neighbor can safely
8410 be computed as the nearest integer to col, row, and slice.
8411 -----------------------------------------------------------------*/
8412 int MRIindexNotInVolume(MRI *mri, Real col, Real row, Real slice)
8413 {
8414 float nicol, nirow, nislice;
8415
8416 /* unambiguously in the volume */
8417 if(col >= 0 && col <= mri->width-1 &&
8418 row >= 0 && row <= mri->height-1 &&
8419 slice >= 0 && slice <= mri->depth-1 )
8420 return(0);
8421
8422 /* within 0.5 of the edge of the volume */
8423 nicol = rint(col);
8424 nirow = rint(row);
8425 nislice = rint(slice);
8426 if(nicol >= 0 && nicol < mri->width &&
8427 nirow >= 0 && nirow < mri->height &&
8428 nislice >= 0 && nislice < mri->depth )
8429 return(-1);
8430
8431 /* unambiguously NOT in the volume */
8432 return(1);
8433
8434 }
8435 /*-----------------------------------------------------
8436 Parameters:
8437
8438 Returns value:
8439
8440 Description
8441 Interpolate the volume directional derivative using
8442 trilinear interpolation.
8443 ------------------------------------------------------*/
8444 float
8445 MRIsampleCardinalDerivative(MRI *mri, int x, int y, int z,
8446 int xk, int yk, int zk)
8447 {
8448 float d ;
8449
8450 if (xk)
8451 d = MRIsampleXDerivative(mri, x, y, z, xk) ;
8452 else if (yk)
8453 d = MRIsampleYDerivative(mri, x, y, z, yk) ;
8454 else
8455 d = MRIsampleZDerivative(mri, x, y, z, zk) ;
8456 return(d) ;
8457 }
8458 /*-----------------------------------------------------
8459 Parameters:
8460
8461 Returns value:
8462
8463 Description
8464 Interpolate the volume directional derivative using
8465 trilinear interpolation.
8466 ------------------------------------------------------*/
8467 float
8468 MRIsampleXDerivative(MRI *mri, int x, int y, int z, int dir)
8469 {
8470 float dx ;
8471 int yk, zk, xi, yi, zi, nvox ;
8472
8473 dx = 0.0 ;
8474
8475 xi = mri->xi[x+dir] ;
8476 for (nvox = 0, zk = -1 ; zk <= 1 ; zk++)
8477 {
8478 zi = mri->zi[z+zk] ;
8479 for (yk = -1 ; yk <= 1 ; yk++)
8480 {
8481 yi = mri->yi[y+yk] ;
8482 dx += dir*MRIvox(mri, xi, yi, zi) ; /* x+dir */
8483 dx -= dir*MRIvox(mri, x, yi, zi) ; /* - x */
8484 nvox += 2 ;
8485 }
8486 }
8487 dx /= ((float)nvox*mri->xsize) ;
8488 return(dx) ;
8489 }
8490 /*-----------------------------------------------------
8491 Parameters:
8492
8493 Returns value:
8494
8495 Description
8496 Interpolate the volume directional derivative using
8497 trilinear interpolation.
8498 ------------------------------------------------------*/
8499 float
8500 MRIsampleYDerivative(MRI *mri, int x, int y, int z, int dir)
8501 {
8502 float dy ;
8503 int xk, zk, xi, yi, zi, nvox ;
8504
8505 dy = 0.0 ;
8506
8507 yi = mri->yi[y+dir] ;
8508 for (nvox = 0, zk = -1 ; zk <= 1 ; zk++)
8509 {
8510 zi = mri->zi[z+zk] ;
8511 for (xk = -1 ; xk <= 1 ; xk++)
8512 {
8513 xi = mri->xi[x+xk] ;
8514 dy += dir*MRIvox(mri, xi, yi, zi) ; /* x+dir */
8515 dy -= dir*MRIvox(mri, x, yi, zi) ; /* - x */
8516 nvox += 2 ;
8517 }
8518 }
8519 dy /= ((float)nvox*mri->ysize) ;
8520 return(dy) ;
8521 }
8522 /*-----------------------------------------------------
8523 Parameters:
8524
8525 Returns value:
8526
8527 Description
8528 Interpolate the volume directional derivative using
8529 trilinear interpolation.
8530 ------------------------------------------------------*/
8531 float
8532 MRIsampleZDerivative(MRI *mri, int x, int y, int z, int dir)
8533 {
8534 float dz ;
8535 int xk, yk, xi, yi, zi, nvox ;
8536
8537 dz = 0.0 ;
8538
8539 zi = mri->zi[z+dir] ;
8540 for (nvox = 0, xk = -1 ; xk <= 1 ; xk++)
8541 {
8542 xi = mri->xi[x+xk] ;
8543 for (yk = -1 ; yk <= 1 ; yk++)
8544 {
8545 yi = mri->yi[y+yk] ;
8546 dz += dir*MRIvox(mri, xi, yi, zi) ; /* x+dir */
8547 dz -= dir*MRIvox(mri, x, yi, zi) ; /* - x */
8548 nvox += 2 ;
8549 }
8550 }
8551 dz /= ((float)nvox*mri->zsize) ;
8552 return(dz) ;
8553 }
8554 int
8555 MRIsampleVolumeDirectionScale(MRI *mri, Real x, Real y, Real z,
8556 Real dx, Real dy, Real dz, Real *pmag,
8557 double sigma)
8558 {
8559 int width, height, depth ;
8560 Real xp1, xm1, yp1, ym1, zp1, zm1, len ;
8561 Real dist, val, k, ktotal, step_size, total_val ;
8562 int n ;
8563
8564 width = mri->width ; height = mri->height ; depth = mri->depth ;
8565 if (x >= width)
8566 x = width - 1.0 ;
8567 if (y >= height)
8568 y = height - 1.0 ;
8569 if (z >= depth)
8570 z = depth - 1.0 ;
8571 if (x < 0.0)
8572 x = 0.0 ;
8573 if (y < 0.0)
8574 y = 0.0 ;
8575 if (z < 0.0)
8576 z = 0.0 ;
8577
8578 step_size = MAX(.5,sigma/2) ;
8579 for (total_val = ktotal = 0.0,n = 0, len = 0.0, dist = step_size ;
8580 dist <= MAX(2*sigma,step_size);
8581 dist += step_size, n++)
8582 {
8583 if (FZERO(sigma))
8584 k = 1.0 ;
8585 else
8586 k = exp(-dist*dist/(2*sigma*sigma)) ;
8587 ktotal += k ;
8588 len += dist ;
8589 xp1 = x + dist*dx ; yp1 = y + dist*dy ; zp1 = z + dist*dz ;
8590 MRIsampleVolume(mri, xp1, yp1, zp1, &val) ;
8591 total_val += k*val ;
8592
8593 xm1 = x - dist*dx ; ym1 = y - dist*dy ; zm1 = z - dist*dz ;
8594 MRIsampleVolume(mri, xm1, ym1, zm1, &val) ;
8595 total_val += k*val ;
8596 if (FZERO(step_size))
8597 break ;
8598 }
8599 total_val /= (double)2.0*ktotal ;
8600
8601 *pmag = total_val ;
8602 return(NO_ERROR) ;
8603 }
8604
8605 int
8606 MRIsampleVolumeDerivativeScale(MRI *mri, Real x, Real y, Real z, Real dx,
8607 Real dy, Real dz, Real *pmag, double sigma)
8608 {
8609 int width, height, depth ;
8610 Real xp1, xm1, yp1, ym1, zp1, zm1, vp1, vm1, len ;
8611 Real dist, val, k, ktotal, step_size ;
8612 int n ;
8613
8614 width = mri->width ; height = mri->height ; depth = mri->depth ;
8615 if (x >= width)
8616 x = width - 1.0 ;
8617 if (y >= height)
8618 y = height - 1.0 ;
8619 if (z >= depth)
8620 z = depth - 1.0 ;
8621 if (x < 0.0)
8622 x = 0.0 ;
8623 if (y < 0.0)
8624 y = 0.0 ;
8625 if (z < 0.0)
8626 z = 0.0 ;
8627
8628 step_size = MAX(.5,sigma/2) ;
8629 for (ktotal = 0.0,n = 0, len = vp1 = vm1 = 0.0, dist = step_size ;
8630 dist <= MAX(2*sigma,step_size);
8631 dist += step_size, n++)
8632 {
8633 if (FZERO(sigma))
8634 k = 1.0 ;
8635 else
8636 k = exp(-dist*dist/(2*sigma*sigma)) ;
8637 ktotal += k ;
8638 len += dist ;
8639 xp1 = x + dist*dx ; yp1 = y + dist*dy ; zp1 = z + dist*dz ;
8640 MRIsampleVolume(mri, xp1, yp1, zp1, &val) ;
8641 vp1 += k*val ;
8642
8643 xm1 = x - dist*dx ; ym1 = y - dist*dy ; zm1 = z - dist*dz ;
8644 MRIsampleVolume(mri, xm1, ym1, zm1, &val) ;
8645 vm1 += k*val ;
8646 if (FZERO(step_size))
8647 break ;
8648 }
8649 vm1 /= (double)ktotal ; vp1 /= (double)ktotal ; len /= (double)ktotal ;
8650
8651 *pmag = (vp1-vm1) / (2.0*len) ;
8652 return(NO_ERROR) ;
8653 }
8654 /*-----------------------------------------------------
8655 Parameters:
8656
8657 Returns value:
8658
8659 Description
8660 Interpolate the volume directional derivative using
8661 trilinear interpolation.
8662 ------------------------------------------------------*/
8663 int
8664 MRIsampleVolumeDerivative(MRI *mri, Real x, Real y, Real z,
8665 Real dx, Real dy, Real dz, Real *pmag)
8666 {
8667 int width, height, depth ;
8668 Real xp1, xm1, yp1, ym1, zp1, zm1, vp1, vm1, len ;
8669
8670 width = mri->width ; height = mri->height ; depth = mri->depth ;
8671 if (x >= width)
8672 x = width - 1.0 ;
8673 if (y >= height)
8674 y = height - 1.0 ;
8675 if (z >= depth)
8676 z = depth - 1.0 ;
8677 if (x < 0.0)
8678 x = 0.0 ;
8679 if (y < 0.0)
8680 y = 0.0 ;
8681 if (z < 0.0)
8682 z = 0.0 ;
8683 #if 1
8684 {
8685 Real dist, val ;
8686 int n ;
8687
8688 for (n = 0, len = vp1 = vm1 = 0.0, dist = .5 ; dist <= 2 ;
8689 dist += 0.5, n++)
8690 {
8691 len += dist ;
8692 xp1 = x + dist*dx ; yp1 = y + dist*dy ; zp1 = z + dist*dz ;
8693 MRIsampleVolume(mri, xp1, yp1, zp1, &val) ;
8694 vp1 += val ;
8695
8696 xm1 = x - dist*dx ; ym1 = y - dist*dy ; zm1 = z - dist*dz ;
8697 MRIsampleVolume(mri, xm1, ym1, zm1, &val) ;
8698 vm1 += val ;
8699 }
8700 vm1 /= (double)n ; vp1 /= (double)n ; len /= (double)n ;
8701 }
8702 #else
8703 xp1 = x + dx ; xm1 = x - dx ;
8704 yp1 = y + dy ; ym1 = y - dy ;
8705 zp1 = z + dz ; zm1 = z - dz ;
8706 len = sqrt(dx*dx+dy*dy+dz*dz) ;
8707 MRIsampleVolume(mri, xp1, yp1, zp1, &vp1) ;
8708 MRIsampleVolume(mri, xm1, ym1, zm1, &vm1) ;
8709 #endif
8710
8711 *pmag = (vp1-vm1) / (2.0*len) ;
8712 return(NO_ERROR) ;
8713 }
8714 /*-----------------------------------------------------
8715 Parameters:
8716
8717 Returns value:
8718
8719 Description
8720 Interpolate the volume gradient to cubic voxels.
8721 ------------------------------------------------------*/
8722 int
8723 MRIsampleVolumeGradient(MRI *mri, Real x, Real y, Real z,
8724 Real *pdx, Real *pdy, Real *pdz)
8725 {
8726 int width, height, depth ;
8727 Real xp1, xm1, yp1, ym1, zp1, zm1 ;
8728
8729 width = mri->width ; height = mri->height ; depth = mri->depth ;
8730 if (x >= width)
8731 x = width - 1.0 ;
8732 if (y >= height)
8733 y = height - 1.0 ;
8734 if (z >= depth)
8735 z = depth - 1.0 ;
8736 if (x < 0.0)
8737 x = 0.0 ;
8738 if (y < 0.0)
8739 y = 0.0 ;
8740 if (z < 0.0)
8741 z = 0.0 ;
8742 MRIsampleVolume(mri, x+1.0, y, z, &xp1) ;
8743 MRIsampleVolume(mri, x-1.0, y, z, &xm1) ;
8744
8745 MRIsampleVolume(mri, x, y+1.0, z, &yp1) ;
8746 MRIsampleVolume(mri, x, y-1.0, z, &ym1) ;
8747
8748 MRIsampleVolume(mri, x, y, z+1.0, &zp1) ;
8749 MRIsampleVolume(mri, x, y, z-1.0, &zm1) ;
8750
8751 *pdx = (xp1-xm1)/(2.0*mri->xsize) ;
8752 *pdy = (yp1-ym1)/(2.0*mri->ysize) ;
8753 *pdz = (zp1-zm1)/(2.0*mri->zsize) ;
8754 return(NO_ERROR) ;
8755 }
8756 /*-----------------------------------------------------
8757 Parameters:
8758
8759 Returns value:
8760
8761 Description
8762 Interpolate the volume gradient to cubic voxels.
8763 ------------------------------------------------------*/
8764 int
8765 MRIsampleVolumeGradientFrame(MRI *mri, Real x, Real y, Real z,
8766 Real *pdx, Real *pdy, Real *pdz, int frame)
8767 {
8768 int width, height, depth ;
8769 Real xp1, xm1, yp1, ym1, zp1, zm1 ;
8770
8771 width = mri->width ; height = mri->height ; depth = mri->depth ;
8772 if (x >= width)
8773 x = width - 1.0 ;
8774 if (y >= height)
8775 y = height - 1.0 ;
8776 if (z >= depth)
8777 z = depth - 1.0 ;
8778 if (x < 0.0)
8779 x = 0.0 ;
8780 if (y < 0.0)
8781 y = 0.0 ;
8782 if (z < 0.0)
8783 z = 0.0 ;
8784 if (frame >= mri->nframes)
8785 frame = mri->nframes-1 ;
8786 if (frame < 0)
8787 frame = 0 ;
8788
8789 MRIsampleVolumeFrame(mri, x+1.0, y, z, frame, &xp1) ;
8790 MRIsampleVolumeFrame(mri, x-1.0, y, z, frame, &xm1) ;
8791
8792 MRIsampleVolumeFrame(mri, x, y+1.0, z, frame, &yp1) ;
8793 MRIsampleVolumeFrame(mri, x, y-1.0, z, frame, &ym1) ;
8794
8795 MRIsampleVolumeFrame(mri, x, y, z+1.0, frame, &zp1) ;
8796 MRIsampleVolumeFrame(mri, x, y, z-1.0, frame, &zm1) ;
8797
8798 *pdx = (xp1-xm1)/(2.0*mri->xsize) ;
8799 *pdy = (yp1-ym1)/(2.0*mri->ysize) ;
8800 *pdz = (zp1-zm1)/(2.0*mri->zsize) ;
8801 return(NO_ERROR) ;
8802 }
8803 /*-----------------------------------------------------
8804 Parameters:
8805
8806 Returns value:
8807
8808 Description
8809 ------------------------------------------------------*/
8810 int
8811 MRIneighborsOn(MRI *mri, int x0, int y0, int z0, int min_val)
8812 {
8813 int nbrs = 0 ;
8814
8815 if (MRIvox(mri,mri->xi[x0-1],y0,z0) >= min_val)
8816 nbrs++ ;
8817 if (MRIvox(mri,mri->xi[x0+1],y0,z0) >= min_val)
8818 nbrs++ ;
8819 if (MRIvox(mri,x0,mri->yi[y0+1],z0) >= min_val)
8820 nbrs++ ;
8821 if (MRIvox(mri,x0,mri->yi[y0-1],z0) >= min_val)
8822 nbrs++ ;
8823 if (MRIvox(mri,x0,y0,mri->zi[z0+1]) >= min_val)
8824 nbrs++ ;
8825 if (MRIvox(mri,x0,y0,mri->zi[z0-1]) >= min_val)
8826 nbrs++ ;
8827 return(nbrs) ;
8828 }
8829 /*-----------------------------------------------------
8830 Parameters:
8831
8832 Returns value:
8833
8834 Description
8835 ------------------------------------------------------*/
8836 int
8837 MRIneighborsOn3x3(MRI *mri, int x, int y, int z, int min_val)
8838 {
8839 int xk, yk, zk, xi, yi, zi, nbrs ;
8840
8841 for (nbrs = 0, zk = -1 ; zk <= 1 ; zk++)
8842 {
8843 zi = mri->zi[z+zk] ;
8844 for (yk = -1 ; yk <= 1 ; yk++)
8845 {
8846 yi = mri->yi[y+yk] ;
8847 for (xk = -1 ; xk <= 1 ; xk++)
8848 {
8849 xi = mri->xi[x+xk] ;
8850 if (!zk && !yk && !xk)
8851 continue ;
8852 if (MRIvox(mri, xi, yi, zi) > min_val)
8853 nbrs++ ;
8854 }
8855 }
8856 }
8857 return(nbrs) ;
8858 }
8859 /*-----------------------------------------------------
8860 Parameters:
8861
8862 Returns value:
8863
8864 Description
8865 ------------------------------------------------------*/
8866 int
8867 MRIneighborsInWindow(MRI *mri, int x, int y, int z, int wsize, int val)
8868 {
8869 int xk, yk, zk, xi, yi, zi, nbrs, whalf ;
8870
8871 whalf = (wsize-1)/2 ;
8872
8873 for (nbrs = 0, zk = -whalf ; zk <= whalf ; zk++)
8874 {
8875 zi = mri->zi[z+zk] ;
8876 for (yk = -whalf ; yk <= whalf ; yk++)
8877 {
8878 yi = mri->yi[y+yk] ;
8879 for (xk = -whalf ; xk <= whalf ; xk++)
8880 {
8881 xi = mri->xi[x+xk] ;
8882 if (!zk && !yk && !xk)
8883 continue ;
8884 if (MRIvox(mri, xi, yi, zi) == val)
8885 nbrs++ ;
8886 }
8887 }
8888 }
8889 return(nbrs) ;
8890 }
8891 /*-----------------------------------------------------
8892 Parameters:
8893
8894 Returns value:
8895
8896 Description
8897 ------------------------------------------------------*/
8898 int
8899 MRIneighbors(MRI *mri, int x0, int y0, int z0, int val)
8900 {
8901 int nbrs = 0 ;
8902
8903 if (nint(MRIgetVoxVal(mri,mri->xi[x0-1],y0,z0,0)) == val)
8904 nbrs++ ;
8905 if (nint(MRIgetVoxVal(mri,mri->xi[x0+1],y0,z0,0)) == val)
8906 nbrs++ ;
8907 if (nint(MRIgetVoxVal(mri,x0,mri->yi[y0+1],z0,0)) == val)
8908 nbrs++ ;
8909 if (nint(MRIgetVoxVal(mri,x0,mri->yi[y0-1],z0,0)) == val)
8910 nbrs++ ;
8911 if (nint(MRIgetVoxVal(mri,x0,y0,mri->zi[z0+1],0)) == val)
8912 nbrs++ ;
8913 if (nint(MRIgetVoxVal(mri,x0,y0,mri->zi[z0-1],0)) == val)
8914 nbrs++ ;
8915 return(nbrs) ;
8916 }
8917 /*-----------------------------------------------------
8918 Parameters:
8919
8920 Returns value:
8921
8922 Description
8923 ------------------------------------------------------*/
8924 int
8925 MRIneighbors3x3(MRI *mri, int x, int y, int z, int val)
8926 {
8927 int xk, yk, zk, xi, yi, zi, nbrs ;
8928
8929 for (nbrs = 0, zk = -1 ; zk <= 1 ; zk++)
8930 {
8931 zi = mri->zi[z+zk] ;
8932 for (yk = -1 ; yk <= 1 ; yk++)
8933 {
8934 yi = mri->yi[y+yk] ;
8935 for (xk = -1 ; xk <= 1 ; xk++)
8936 {
8937 xi = mri->xi[x+xk] ;
8938 if (!zk && !yk && !xk)
8939 continue ;
8940 if (MRIvox(mri, xi, yi, zi) == val)
8941 nbrs++ ;
8942 }
8943 }
8944 }
8945 return(nbrs) ;
8946 }
8947 /*-----------------------------------------------------
8948 ------------------------------------------------------*/
8949 int
8950 MRIneighborsOff(MRI *mri, int x0, int y0, int z0, int min_val)
8951 {
8952 int nbrs = 0 ;
8953
8954 if (MRIvox(mri,x0-1,y0,z0) < min_val)
8955 nbrs++ ;
8956 if (MRIvox(mri,x0+1,y0,z0) < min_val)
8957 nbrs++ ;
8958 if (MRIvox(mri,x0,y0+1,z0) < min_val)
8959 nbrs++ ;
8960 if (MRIvox(mri,x0,y0-1,z0) < min_val)
8961 nbrs++ ;
8962 if (MRIvox(mri,x0,y0,z0+1) < min_val)
8963 nbrs++ ;
8964 if (MRIvox(mri,x0,y0,z0-1) < min_val)
8965 nbrs++ ;
8966 return(nbrs) ;
8967 }
8968 /*-----------------------------------------------------
8969 ------------------------------------------------------*/
8970 int
8971 MRIneighborsOff3x3(MRI *mri, int x, int y, int z, int min_val)
8972 {
8973 int xk, yk, zk, xi, yi, zi, nbrs ;
8974
8975 for (nbrs = 0, zk = -1 ; zk <= 1 ; zk++)
8976 {
8977 zi = mri->zi[z+zk] ;
8978 for (yk = -1 ; yk <= 1 ; yk++)
8979 {
8980 yi = mri->yi[y+yk] ;
8981 for (xk = -1 ; xk <= 1 ; xk++)
8982 {
8983 xi = mri->xi[x+xk] ;
8984 if (!zk && !yk && !xk)
8985 continue ;
8986 if (MRIvox(mri, xi, yi, zi) < min_val)
8987 nbrs++ ;
8988 }
8989 }
8990 }
8991 return(nbrs) ;
8992 }
8993 /*-----------------------------------------------------
8994 Perform an linear coordinate transformation x' = Ax on
8995 the MRI image mri_src into mri_dst
8996 ------------------------------------------------------*/
8997 MRI *
8998 MRIinverseLinearTransform(MRI *mri_src, MRI *mri_dst, MATRIX *mA)
8999 {
9000 MATRIX *m_inv ;
9001
9002 m_inv = MatrixInverse(mA, NULL) ;
9003 if (!m_inv)
9004 ErrorReturn
9005 (NULL,
9006 (ERROR_BADPARM,
9007 "MRIinverseLinearTransform: xform is singular!")) ;
9008 fprintf
9009 (stderr,
9010 "applying the vox-to-vox linear transform (calculated inverse)\n");
9011 MatrixPrint(stderr, m_inv);
9012 mri_dst = MRIlinearTransform(mri_src, mri_dst, m_inv) ;
9013 MatrixFree(&m_inv) ;
9014 return(mri_dst) ;
9015 }
9016 /*-----------------------------------------------------
9017 Convert a transform from RAS to voxel coordinates, then apply
9018 it to an MRI.
9019 ------------------------------------------------------*/
9020 MRI *
9021 MRIapplyRASlinearTransform(MRI *mri_src, MRI *mri_dst, MATRIX *m_ras_xform)
9022 {
9023 MATRIX *m_voxel_xform ;
9024
9025 m_voxel_xform = MRIrasXformToVoxelXform(mri_src, mri_dst, m_ras_xform, NULL);
9026 fprintf(stderr, "applying the vox to vox linear transform\n");
9027 MatrixPrint(stderr, m_voxel_xform);
9028 mri_dst = MRIlinearTransform(mri_src, mri_dst, m_voxel_xform) ;
9029 MatrixFree(&m_voxel_xform) ;
9030 return(mri_dst) ;
9031 }
9032 /*-----------------------------------------------------
9033 Convert a transform from RAS to voxel coordinates, then apply
9034 it to an MRI.
9035 ------------------------------------------------------*/
9036 MRI *
9037 MRIapplyRASlinearTransformInterp
9038 (MRI *mri_src, MRI *mri_dst, MATRIX *m_ras_xform, int interp)
9039 {
9040 MATRIX *m_voxel_xform ;
9041
9042 m_voxel_xform = MRIrasXformToVoxelXform(mri_src, mri_dst, m_ras_xform, NULL);
9043 fprintf(stderr, "applying the vox to vox linear transform\n");
9044 MatrixPrint(stderr, m_voxel_xform);
9045 mri_dst = MRIlinearTransformInterp(mri_src, mri_dst, m_voxel_xform, interp) ;
9046 MatrixFree(&m_voxel_xform) ;
9047 return(mri_dst) ;
9048 }
9049 /*-----------------------------------------------------
9050 Convert a transform from RAS to voxel coordinates, then apply
9051 it to an MRI.
9052 ------------------------------------------------------*/
9053 MRI *
9054 MRIapplyRASinverseLinearTransform(MRI *mri_src, MRI *mri_dst,
9055 MATRIX *m_ras_xform)
9056 {
9057 MATRIX *m_voxel_xform ;
9058
9059 m_voxel_xform = MRIrasXformToVoxelXform(mri_src, mri_dst, m_ras_xform, NULL);
9060 mri_dst = MRIinverseLinearTransform(mri_src, mri_dst, m_voxel_xform) ;
9061 MatrixFree(&m_voxel_xform) ;
9062 return(mri_dst) ;
9063 }
9064
9065 /*-----------------------------------------------------
9066 Perform an linear coordinate transformation x' = Ax on
9067 the MRI image mri_src into mri_dst using sinc interp.
9068 ------------------------------------------------------*/
9069 MRI *
9070 MRIsincTransform(MRI *mri_src, MRI *mri_dst, MATRIX *mA, int hw)
9071 {
9072 int y1, y2, y3, width, height, depth ;
9073 VECTOR *v_X, *v_Y ; /* original and transformed coordinate systems */
9074 MATRIX *mAinv ; /* inverse of mA */
9075 Real val, x1, x2, x3 ;
9076
9077 mAinv = MatrixInverse(mA, NULL) ; /* will sample from dst back to src */
9078 if (!mAinv)
9079 ErrorReturn(NULL, (ERROR_BADPARM,
9080 "MRIsincTransform: xform is singular")) ;
9081
9082 width = mri_src->width ; height = mri_src->height ; depth = mri_src->depth ;
9083 if (!mri_dst)
9084 mri_dst = MRIclone(mri_src, NULL) ;
9085 else
9086 MRIclear(mri_dst) ;
9087
9088 v_X = VectorAlloc(4, MATRIX_REAL) ; /* input (src) coordinates */
9089 v_Y = VectorAlloc(4, MATRIX_REAL) ; /* transformed (dst) coordinates */
9090
9091 v_Y->rptr[4][1] = 1.0f ;
9092 for (y3 = 0 ; y3 < depth ; y3++)
9093 {
9094 V3_Z(v_Y) = y3 ;
9095 for (y2 = 0 ; y2 < height ; y2++)
9096 {
9097 V3_Y(v_Y) = y2 ;
9098 for (y1 = 0 ; y1 < width ; y1++)
9099 {
9100 V3_X(v_Y) = y1 ;
9101 MatrixMultiply(mAinv, v_Y, v_X) ;
9102
9103 x1 = V3_X(v_X) ; x2 = V3_Y(v_X) ; x3 = V3_Z(v_X) ;
9104
9105 if (nint(y1) == 13 && nint(y2) == 10 && nint(y3) == 7)
9106 DiagBreak() ;
9107 if (nint(x1) == 13 && nint(x2) == 10 && nint(x3) == 7)
9108 {
9109 #if 0
9110 fprintf
9111 (stderr,
9112 "(%2.1f, %2.1f, %2.1f) --> (%2.1f, %2.1f, %2.1f)\n",
9113 (float)x1, (float)x2, (float)x3,
9114 (float)y1, (float)y2, (float)y3) ;
9115 #endif
9116 DiagBreak() ;
9117 }
9118
9119 if (x1 > -1 && x1 < width &&
9120 x2 > -1 && x2 < height &&
9121 x3 > -1 && x3 < depth)
9122 {
9123 MRIsincSampleVolume(mri_src, x1, x2, x3, hw, &val);
9124 MRIvox(mri_dst,y1,y2,y3) = (BUFTYPE)nint(val) ;
9125 }
9126 }
9127 }
9128 }
9129
9130 MatrixFree(&v_X) ;
9131 MatrixFree(&mAinv) ;
9132 MatrixFree(&v_Y) ;
9133
9134 mri_dst->ras_good_flag = 0;
9135
9136 return(mri_dst) ;
9137 }
9138 /*-----------------------------------------------------------------
9139 MRIlinearTransform() - for historical reasons, this uses trilinear
9140 interpolation. This the operations under this function name can
9141 now (2/20/02) be found under MRIlinearTransformInterp().
9142 -----------------------------------------------------------------*/
9143 MRI *
9144 MRIlinearTransform(MRI *mri_src, MRI *mri_dst, MATRIX *mA)
9145 {
9146 mri_dst = MRIlinearTransformInterp(mri_src, mri_dst, mA, SAMPLE_TRILINEAR);
9147 return(mri_dst);
9148 }
9149 /*-------------------------------------------------------------------
9150 MRIlinearTransformInterp() Perform linear coordinate transformation
9151 x' = Ax on the MRI image mri_src into mri_dst using the specified
9152 interpolation method. A is a voxel-to-voxel transform.
9153 ------------------------------------------------------------------*/
9154 MRI *
9155 MRIlinearTransformInterp(MRI *mri_src, MRI *mri_dst, MATRIX *mA,
9156 int InterpMethod)
9157 {
9158 int y1, y2, y3, width, height, depth ;
9159 VECTOR *v_X, *v_Y ; /* original and transformed coordinate systems */
9160 MATRIX *mAinv ; /* inverse of mA */
9161 Real val, x1, x2, x3 ;
9162
9163 if(InterpMethod != SAMPLE_NEAREST &&
9164 InterpMethod != SAMPLE_TRILINEAR &&
9165 InterpMethod != SAMPLE_CUBIC &&
9166 InterpMethod != SAMPLE_SINC ){
9167 printf("ERROR: MRIlinearTransformInterp: unrecoginzed interpolation "
9168 "method %d\n",InterpMethod);
9169 }
9170
9171 mAinv = MatrixInverse(mA, NULL) ; /* will sample from dst back to src */
9172 if (!mAinv)
9173 ErrorReturn(NULL, (ERROR_BADPARM,
9174 "MRIlinearTransform: xform is singular")) ;
9175
9176 if (!mri_dst)
9177 mri_dst = MRIclone(mri_src, NULL) ;
9178 else
9179 MRIclear(mri_dst) ;
9180
9181 width = mri_dst->width ; height = mri_dst->height ; depth = mri_dst->depth ;
9182 v_X = VectorAlloc(4, MATRIX_REAL) ; /* input (src) coordinates */
9183 v_Y = VectorAlloc(4, MATRIX_REAL) ; /* transformed (dst) coordinates */
9184
9185 if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
9186 printf("MRIlinearTransformInterp: Applying transform\n");
9187
9188 v_Y->rptr[4][1] = 1.0f ;
9189 for (y3 = 0 ; y3 < depth ; y3++)
9190 {
9191 V3_Z(v_Y) = y3 ;
9192 for (y2 = 0 ; y2 < height ; y2++)
9193 {
9194 V3_Y(v_Y) = y2 ;
9195 for (y1 = 0 ; y1 < width ; y1++)
9196 {
9197 V3_X(v_Y) = y1 ;
9198 MatrixMultiply(mAinv, v_Y, v_X) ;
9199
9200 x1 = V3_X(v_X) ; x2 = V3_Y(v_X) ; x3 = V3_Z(v_X) ;
9201
9202 if (nint(y1) == 13 && nint(y2) == 10 && nint(y3) == 7)
9203 DiagBreak() ;
9204 if (nint(x1) == Gx && nint(x2) == Gy && nint(x3) == Gz)
9205 {
9206 #if 0
9207 fprintf
9208 (stderr,
9209 "(%2.1f, %2.1f, %2.1f) --> (%2.1f, %2.1f, %2.1f)\n",
9210 (float)x1, (float)x2, (float)x3,
9211 (float)y1, (float)y2, (float)y3) ;
9212 #endif
9213 DiagBreak() ;
9214 }
9215
9216 //MRIsampleVolume(mri_src, x1, x2, x3, &val);
9217 MRIsampleVolumeType(mri_src, x1, x2, x3, &val, InterpMethod);
9218 switch (mri_dst->type)
9219 {
9220 case MRI_UCHAR:
9221 MRIvox(mri_dst,y1,y2,y3) = (BUFTYPE)nint(val) ;
9222 break ;
9223 case MRI_SHORT:
9224 MRISvox(mri_dst,y1,y2,y3) = (short)nint(val) ;
9225 break ;
9226 case MRI_FLOAT:
9227 MRIFvox(mri_dst,y1,y2,y3) = (float)(val) ;
9228 break ;
9229 case MRI_INT:
9230 MRIIvox(mri_dst,y1,y2,y3) = nint(val) ;
9231 break ;
9232 default:
9233 ErrorReturn(NULL,
9234 (ERROR_UNSUPPORTED,
9235 "MRIlinearTransform: unsupported dst type %d",
9236 mri_dst->type)) ;
9237 break ;
9238 }
9239 }
9240 }
9241 }
9242
9243 MatrixFree(&v_X) ;
9244 MatrixFree(&mAinv) ;
9245 MatrixFree(&v_Y) ;
9246
9247 mri_dst->ras_good_flag = 1;
9248
9249 if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
9250 {
9251 printf("MRIlinearTransform: done\n");
9252 printf("mri_dst:\n");
9253 printf(" vox res: %g %g %g\n",
9254 mri_dst->xsize,mri_dst->ysize,mri_dst->zsize);
9255 printf(" vox dim: %d %d %d\n",
9256 mri_dst->width,mri_dst->height,mri_dst->depth);
9257 }
9258
9259 return(mri_dst) ;
9260 }
9261 MRI *
9262 MRIconcatenateFrames(MRI *mri_frame1, MRI *mri_frame2, MRI *mri_dst)
9263 {
9264 int width, height, depth, x, y, z ;
9265 BUFTYPE *pf1, *pf2, *pdst1, *pdst2 ;
9266
9267 if (mri_frame1->type != MRI_UCHAR || mri_frame1->type != MRI_UCHAR)
9268 ErrorReturn(NULL,
9269 (ERROR_UNSUPPORTED,"MRIconcatenateFrames: src must be UCHAR"));
9270
9271 width = mri_frame1->width ;
9272 height = mri_frame1->height ;
9273 depth = mri_frame1->depth ;
9274 if (mri_dst == NULL)
9275 {
9276 mri_dst = MRIallocSequence(width, height, depth, mri_frame1->type, 2) ;
9277 MRIcopyHeader(mri_frame1, mri_dst) ;
9278 }
9279 if (!mri_dst)
9280 ErrorExit(ERROR_NOMEMORY, "MRIconcatenateFrames: could not alloc dst") ;
9281
9282
9283 for (z = 0 ; z < depth ; z++)
9284 {
9285 for (y = 0 ; y < height ; y++)
9286 {
9287 pdst1 = &MRIvox(mri_dst, 0, y, z) ;
9288 pdst2 = &MRIseq_vox(mri_dst, 0, y, z, 1) ;
9289 pf1 = &MRIvox(mri_frame1, 0, y, z) ;
9290 pf2 = &MRIvox(mri_frame2, 0, y, z) ;
9291 for (x = 0 ; x < width ; x++)
9292 {
9293 *pdst1++ = *pf1++ ;
9294 *pdst2++ = *pf2++ ;
9295 }
9296 }
9297 }
9298 return(mri_dst) ;
9299 }
9300 /*-----------------------------------------------------
9301 ------------------------------------------------------*/
9302 MRI *
9303 MRIcopyFrame(MRI *mri_src, MRI *mri_dst, int src_frame, int dst_frame)
9304 {
9305 int width, height, depth, y, z, bytes ;
9306 BUFTYPE *psrc, *pdst ;
9307
9308 width = mri_src->width ;
9309 height = mri_src->height ;
9310 depth = mri_src->depth ;
9311
9312 if (!mri_dst)
9313 mri_dst =
9314 MRIallocSequence(width, height, depth, mri_src->type, dst_frame+1) ;
9315 if (!mri_dst)
9316 ErrorExit(ERROR_NOMEMORY, "MRIcopyFrame: could not alloc dst") ;
9317
9318 if (mri_src->type != mri_dst->type)
9319 ErrorReturn(NULL,(ERROR_UNSUPPORTED,
9320 "MRIcopyFrame: src and dst must be same type"));
9321 if (dst_frame >= mri_dst->nframes)
9322 ErrorReturn
9323 (NULL,
9324 (ERROR_BADPARM,
9325 "MRIcopyFrame: dst frame #%d out of range (nframes=%d)\n",
9326 dst_frame, mri_dst->nframes)) ;
9327 MRIcopyHeader(mri_src, mri_dst) ;
9328
9329 switch (mri_src->type)
9330 {
9331 case MRI_UCHAR:
9332 bytes = sizeof(unsigned char) ;
9333 break ;
9334 case MRI_SHORT:
9335 bytes = sizeof(short) ;
9336 break ;
9337 case MRI_INT:
9338 bytes = sizeof(int) ;
9339 break ;
9340 case MRI_FLOAT:
9341 bytes = sizeof(float) ;
9342 break ;
9343 default:
9344 ErrorReturn(NULL, (ERROR_BADPARM,
9345 "MRIcopyFrame: unsupported src format %d",
9346 mri_src->type));
9347 break ;
9348 }
9349 bytes *= width ;
9350 for (z = 0 ; z < depth ; z++)
9351 {
9352 for (y = 0 ; y < height ; y++)
9353 {
9354 switch (mri_src->type)
9355 {
9356 default: /* already handled above */
9357 case MRI_UCHAR:
9358 psrc = &MRIseq_vox(mri_src, 0, y, z, src_frame) ;
9359 pdst = &MRIseq_vox(mri_dst, 0, y, z, dst_frame) ;
9360 break ;
9361 case MRI_SHORT:
9362 psrc = (BUFTYPE *)&MRISseq_vox(mri_src, 0, y, z, src_frame) ;
9363 pdst = (BUFTYPE *)&MRISseq_vox(mri_dst, 0, y, z, dst_frame) ;
9364 break ;
9365 case MRI_INT:
9366 psrc = (BUFTYPE *)&MRIIseq_vox(mri_src, 0, y, z, src_frame) ;
9367 pdst = (BUFTYPE *)&MRIIseq_vox(mri_dst, 0, y, z, dst_frame) ;
9368 break ;
9369 case MRI_FLOAT:
9370 psrc = (BUFTYPE *)&MRIFseq_vox(mri_src, 0, y, z, src_frame) ;
9371 pdst = (BUFTYPE *)&MRIFseq_vox(mri_dst, 0, y, z, dst_frame) ;
9372 break ;
9373 }
9374 memmove(pdst, psrc, bytes) ;
9375 }
9376 }
9377 return(mri_dst) ;
9378 }
9379 /*-----------------------------------------------------
9380 Parameters:
9381
9382 Returns value:
9383
9384 Description
9385 ------------------------------------------------------*/
9386 double
9387 MRImeanFrame(MRI *mri, int frame)
9388 {
9389 int width, height, depth, x, y, z ;
9390 double mean ;
9391 Real val ;
9392
9393 width = mri->width ;
9394 height = mri->height ;
9395 depth = mri->depth ;
9396 if (mri->nframes <= frame)
9397 ErrorReturn(0.0,(ERROR_BADPARM,
9398 "MRImeanFrame: frame %d out of bounds (%d)",
9399 frame, mri->nframes));
9400
9401 for (mean = 0.0, z = 0 ; z < depth ; z++)
9402 {
9403 for (y = 0 ; y < height ; y++)
9404 {
9405 for (x = 0 ; x < width ; x++)
9406 {
9407 MRIsampleVolumeType(mri, x, y, z, &val, SAMPLE_NEAREST) ;
9408 mean += (double)val ;
9409 }
9410 }
9411 }
9412 mean /= (double)(width*height*depth) ;
9413 return(mean) ;
9414 }
9415
9416 #ifndef UCHAR_MIN
9417 #define UCHAR_MIN 0.0
9418 #endif
9419 #ifndef UCHAR_MAX
9420 #define UCHAR_MAX 255.0
9421 #endif
9422 #ifndef SHORT_MIN
9423 #define SHORT_MIN -32768.0
9424 #endif
9425 #ifndef SHORT_MAX
9426 #define SHORT_MAX 32767.0
9427 #endif
9428 #ifndef INT_MIN
9429 #define INT_MIN -2147483648.0
9430 #endif
9431 #ifndef INT_MAX
9432 #define INT_MAX 2147483647.0
9433 #endif
9434 #ifndef LONG_MIN
9435 #define LONG_MIN -2147483648.0
9436 #endif
9437 #ifndef LONG_MAX
9438 #define LONG_MAX 2147483647.0
9439 #endif
9440
9441 #define N_HIST_BINS 1000
9442
9443 /*--------------------------------------------------------------
9444 MRISeqchangeType() - changes the data type for a 3D or 4D volume.
9445 This simply changes the volume dimensions so that it appears to be a
9446 3D volume, then calls MRIchangeType(), and then resets the
9447 dimensions to their original values. The values of the volume can be
9448 rescaled between f_low and f_high.
9449 ------------------------------------------------------------*/
9450 MRI *MRISeqchangeType(MRI *vol, int dest_type, float f_low,
9451 float f_high, int no_scale_option_flag)
9452 {
9453 int nslices, nframes;
9454 MRI *mri;
9455
9456 /* Change vol dimensions to make it look like a single frame */
9457 nslices = vol->depth;
9458 nframes = vol->nframes;
9459 vol->depth = nslices*nframes;
9460 vol->nframes = 1;
9461
9462 /* Change the type */
9463 mri = MRIchangeType(vol,dest_type,f_low,f_high,no_scale_option_flag);
9464
9465 /* Change vol dimensions back to original */
9466 vol->depth = nslices;
9467 vol->nframes = nframes;
9468
9469 /* Check for error */
9470 if(mri == NULL) {
9471 fprintf(stderr,"ERROR: MRISeqchangeType: MRIchangeType\n");
9472 return(NULL);
9473 }
9474
9475 /* Change mri dimensions back to original */
9476 mri->depth = nslices;
9477 mri->nframes = nframes;
9478
9479 return(mri);
9480 }
9481 /*-----------------------------------------------------------
9482 MRIchangeType() - changes the data type of a 3D MRI volume,
9483 with optional rescaling. Use MRISeqchangeType() for 3D or
9484 4D volumes.
9485 ---------------------------------------------------------*/
9486 MRI *MRIchangeType(MRI *src, int dest_type, float f_low,
9487 float f_high, int no_scale_option_flag)
9488 {
9489
9490 MRI *dest = NULL;
9491 int i, j, k;
9492 float val;
9493 int no_scale_flag = FALSE;
9494 float scale, dest_min, dest_max; /* new = scale * (val - min) */
9495 float src_min, src_max;
9496 int hist_bins[N_HIST_BINS];
9497 float bin_size;
9498 int bin;
9499 int nth, n_passed;
9500
9501 /* ----- shut the compiler up ----- */
9502 val = 0.0;
9503 dest_min = dest_max = 0.0;
9504
9505 if(src->type == dest_type)
9506 {
9507 dest = MRIcopy(src, NULL);
9508 return(dest);
9509 }
9510
9511 if(src->type == MRI_UCHAR &&
9512 (dest_type == MRI_SHORT ||
9513 dest_type == MRI_INT ||
9514 dest_type == MRI_LONG ||
9515 dest_type == MRI_FLOAT))
9516 no_scale_flag = TRUE;
9517 else if(src->type == MRI_SHORT &&
9518 (dest_type == MRI_INT ||
9519 dest_type == MRI_LONG ||
9520 dest_type == MRI_FLOAT))
9521 no_scale_flag = TRUE;
9522 else if(src->type == MRI_LONG &&
9523 (dest_type == MRI_INT ||
9524 dest_type == MRI_FLOAT))
9525 no_scale_flag = TRUE;
9526 else if(src->type == MRI_INT &&
9527 (dest_type == MRI_LONG ||
9528 dest_type == MRI_FLOAT))
9529 no_scale_flag = TRUE;
9530 else
9531 {
9532 MRIlimits(src, &src_min, &src_max);
9533
9534 if(no_scale_option_flag)
9535 {
9536 if(dest_type == MRI_UCHAR &&
9537 src_min >= UCHAR_MIN &&
9538 src_max <= UCHAR_MAX)
9539 no_scale_flag = TRUE;
9540 if(dest_type == MRI_SHORT &&
9541 src_min >= SHORT_MIN &&
9542 src_max <= SHORT_MAX)
9543 no_scale_flag = TRUE;
9544 if(dest_type == MRI_INT &&
9545 src_min >= INT_MIN &&
9546 src_max <= INT_MAX)
9547 no_scale_flag = TRUE;
9548 if(dest_type == MRI_LONG &&
9549 src_min >= LONG_MIN &&
9550 src_max <= LONG_MAX)
9551 no_scale_flag = TRUE;
9552 }
9553 }
9554
9555 if(no_scale_flag)
9556 {
9557
9558 dest = MRIalloc(src->width, src->height, src->depth, dest_type);
9559 MRIcopyHeader(src, dest);
9560 dest->type = dest_type;
9561
9562 for(k = 0;k < src->depth;k++)
9563 for(j = 0;j < src->height;j++)
9564 for(i = 0;i < src->width;i++)
9565 {
9566
9567 if(src->type == MRI_UCHAR)
9568 val = (float)MRIvox(src, i, j, k);
9569 if(src->type == MRI_SHORT)
9570 val = (float)MRISvox(src, i, j, k);
9571 if(src->type == MRI_INT)
9572 val = (float)MRIIvox(src, i, j, k);
9573 if(src->type == MRI_LONG)
9574 val = (float)MRILvox(src, i, j, k);
9575 if(src->type == MRI_FLOAT)
9576 val = (float)MRIFvox(src, i, j, k);
9577
9578 if(dest_type == MRI_UCHAR)
9579 MRIvox(dest, i, j, k) = (unsigned char)val;
9580 if(dest_type == MRI_SHORT)
9581 MRISvox(dest, i, j, k) = (short)val;
9582 if(dest_type == MRI_INT)
9583 MRIIvox(dest, i, j, k) = (int)val;
9584 if(dest_type == MRI_LONG)
9585 MRILvox(dest, i, j, k) = (long)val;
9586 if(dest_type == MRI_FLOAT)
9587 MRIFvox(dest, i, j, k) = (float)val;
9588 }
9589 }
9590 else
9591 {
9592 long nonzero = 0 ;
9593
9594 /* ----- build a histogram ----- */
9595 printf("MRIchangeType: Building histogram \n");
9596 bin_size = (src_max - src_min) / (float)N_HIST_BINS;
9597
9598 for(i = 0;i < N_HIST_BINS;i++)
9599 hist_bins[i] = 0;
9600
9601 for(i = 0;i < src->width;i++)
9602 for(j = 0;j < src->height;j++)
9603 for(k = 0;k < src->depth;k++)
9604 {
9605
9606 if(src->type == MRI_UCHAR)
9607 val = (float)MRIvox(src, i, j, k);
9608 if(src->type == MRI_SHORT)
9609 val = (float)MRISvox(src, i, j, k);
9610 if(src->type == MRI_INT)
9611 val = (float)MRIIvox(src, i, j, k);
9612 if(src->type == MRI_LONG)
9613 val = (float)MRILvox(src, i, j, k);
9614 if(src->type == MRI_FLOAT)
9615 val = (float)MRIFvox(src, i, j, k);
9616
9617 if (!DZERO(val))
9618 nonzero++ ;
9619 bin = (int)((val - src_min) / bin_size);
9620
9621 if(bin < 0)
9622 bin = 0;
9623 if(bin >= N_HIST_BINS)
9624 bin = N_HIST_BINS-1;
9625
9626 hist_bins[bin]++;
9627
9628 }
9629
9630 nth = (int)(f_low * src->width * src->height * src->depth);
9631 for(n_passed = 0,bin = 0;n_passed < nth && bin < N_HIST_BINS;bin++)
9632 n_passed += hist_bins[bin];
9633 src_min = (float)bin * bin_size + src_min;
9634
9635 #if 1 // handle mostly empty volumes
9636 nth = (int)((1.0-f_high) * nonzero);
9637 #else
9638 nth = (int)((1.0-f_high) * src->width * src->height * src->depth);
9639 #endif
9640 for(n_passed = 0,bin = N_HIST_BINS-1;n_passed < nth && bin > 0;bin--)
9641 n_passed += hist_bins[bin];
9642 src_max = (float)bin * bin_size + src_min;
9643
9644 if(src_min >= src_max)
9645 {
9646 ErrorReturn
9647 (NULL,
9648 (ERROR_BADPARM,
9649 "MRIchangeType(): after hist: src_min = %g, "
9650 "src_max = %g (f_low = %g, f_high = %g)",
9651 src_min, src_max, f_low, f_high));
9652 }
9653
9654 /* ----- continue ----- */
9655
9656 if(dest_type == MRI_UCHAR)
9657 {
9658 dest_min = UCHAR_MIN;
9659 dest_max = UCHAR_MAX;
9660 }
9661 if(dest_type == MRI_SHORT)
9662 {
9663 dest_min = SHORT_MIN;
9664 dest_max = SHORT_MAX;
9665 }
9666 if(dest_type == MRI_INT)
9667 {
9668 dest_min = INT_MIN;
9669 dest_max = INT_MAX;
9670 }
9671 if(dest_type == MRI_LONG)
9672 {
9673 dest_min = LONG_MIN;
9674 dest_max = LONG_MAX;
9675 }
9676
9677 scale = (dest_max - dest_min) / (src_max - src_min);
9678
9679 dest = MRIalloc(src->width, src->height, src->depth, dest_type);
9680 MRIcopyHeader(src, dest);
9681 dest->type = dest_type;
9682
9683 for(i = 0;i < src->width;i++)
9684 for(j = 0;j < src->height;j++)
9685 for(k = 0;k < src->depth;k++)
9686 {
9687
9688 if(src->type == MRI_SHORT)
9689 val = MRISvox(src, i, j, k);
9690 if(src->type == MRI_INT)
9691 val = MRIIvox(src, i, j, k);
9692 if(src->type == MRI_LONG)
9693 val = MRILvox(src, i, j, k);
9694 if(src->type == MRI_FLOAT)
9695 val = MRIFvox(src, i, j, k);
9696
9697 val = dest_min + scale * (val - src_min);
9698
9699 if(dest->type == MRI_UCHAR)
9700 {
9701 if(val < UCHAR_MIN)
9702 val = UCHAR_MIN;
9703 if(val > UCHAR_MAX)
9704 val = UCHAR_MAX;
9705 MRIvox(dest, i, j, k) = (unsigned char)val;
9706 }
9707 if(dest->type == MRI_SHORT)
9708 {
9709 if(val < SHORT_MIN)
9710 val = SHORT_MIN;
9711 if(val > SHORT_MAX)
9712 val = SHORT_MAX;
9713 MRISvox(dest, i, j, k) = (short)val;
9714 }
9715 if(dest->type == MRI_INT)
9716 {
9717 if(val < INT_MIN)
9718 val = INT_MIN;
9719 if(val > INT_MAX)
9720 val = INT_MAX;
9721 MRIIvox(dest, i, j, k) = (int)val;
9722 }
9723 if(dest->type == MRI_LONG)
9724 {
9725 if(val < LONG_MIN)
9726 val = LONG_MIN;
9727 if(val > LONG_MAX)
9728 val = LONG_MAX;
9729 MRILvox(dest, i, j, k) = (long)val;
9730 }
9731
9732 }
9733
9734 }
9735
9736 return(dest);
9737
9738 } /* end MRIchangeType() */
9739
9740 /*-----------------------------------------------------*/
9741 MATRIX *MRIgetResampleMatrix(MRI *src, MRI *template_vol)
9742 {
9743
9744 MATRIX *src_mat, *dest_mat; /* from i to ras */
9745 float src_det, dest_det;
9746 MATRIX *src_inv, *m;
9747
9748 /* ----- fake the ras values if ras_good_flag is not set ----- */
9749 int src_slice_direction = getSliceDirection(src);
9750 if(!src->ras_good_flag
9751 && (src_slice_direction != MRI_CORONAL)
9752 && (src_slice_direction != MRI_SAGITTAL)
9753 && (src_slice_direction != MRI_HORIZONTAL))
9754 {
9755 ErrorReturn
9756 (NULL,
9757 (ERROR_BADPARM,
9758 "MRIresample(): source volume orientation is unknown"));
9759 }
9760
9761 /*
9762
9763 : solve each row of src_mat * [midx;midy;midz;1] = centerr, centera, centers
9764 and for dest
9765
9766 S = M * s_v
9767
9768 where M = [(x_r y_r z_r)(xsize 0 0 ) s14]
9769 s_v = (center_x) S = (c_r) etc.
9770 [(x_a y_a z_a)( 0 ysize 0 ) s24] (center_y) (c_a)
9771 [(x_s y_s z_s)( 0 0 zsize) s34] (center_z) (c_s)
9772 [ 0 0 0 1 ] ( 1 ) ( 1 )
9773
9774 Write M = [ m s], s_v = (c_v), S = (c_R), then c_R = m * c_v + s or
9775 [ 0 0 0 1] ( 1 ) ( 1 )
9776
9777 The translation s is given by s = c_R - m*c_v
9778
9779 Note the convention c_(r,a,s) being defined in
9780 terms of c_v = (width/2., height/2, depth/2.),
9781 not ((width-1)/2, (height-1)/2, (depth-1)/2).
9782
9783 */
9784
9785 src_mat = extract_i_to_r(src); // error when allocation fails
9786 if(src_mat == NULL)
9787 return NULL; // did ErrorPrintf in extract_i_to_r()
9788
9789 dest_mat = extract_i_to_r(template_vol); // error when allocation fails
9790 if(dest_mat == NULL)
9791 {
9792 MatrixFree(&src_mat);
9793 return NULL; // did ErrorPrintf in extract_i_to_r()
9794 }
9795
9796 // error check
9797 src_det = MatrixDeterminant(src_mat);
9798 dest_det = MatrixDeterminant(dest_mat);
9799
9800 if(src_det == 0.0)
9801 {
9802 errno = 0;
9803 ErrorPrintf
9804 (ERROR_BADPARM,
9805 "MRIresample(): source matrix has zero determinant; matrix is:");
9806 MatrixPrint(stderr, src_mat);
9807 MatrixFree(&src_mat);
9808 MatrixFree(&dest_mat);
9809 return(NULL);
9810 }
9811
9812 if(dest_det == 0.0)
9813 {
9814 errno = 0;
9815 ErrorPrintf
9816 (ERROR_BADPARM,
9817 "MRIresample(): destination matrix has zero determinant; matrix is:");
9818 MatrixPrint(stderr, dest_mat);
9819 MatrixFree(&src_mat);
9820 MatrixFree(&dest_mat);
9821 return(NULL);
9822 }
9823
9824 src_inv = MatrixInverse(src_mat, NULL);
9825
9826 if(src_inv == NULL)
9827 {
9828 errno = 0;
9829 ErrorPrintf
9830 (ERROR_BADPARM,
9831 "MRIresample(): error inverting matrix; determinant is "
9832 "%g, matrix is:", src_det);
9833 MatrixPrint(stderr, src_mat);
9834 MatrixFree(&src_mat);
9835 MatrixFree(&dest_mat);
9836 return(NULL);
9837 }
9838
9839 m = MatrixMultiply(src_inv, dest_mat, NULL);
9840 if(m == NULL)
9841 return(NULL);
9842
9843 MatrixFree(&src_inv);
9844 MatrixFree(&src_mat);
9845 MatrixFree(&dest_mat);
9846
9847 if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
9848 {
9849 printf("MRIresample() matrix is:\n");
9850 MatrixPrint(stdout, m);
9851 }
9852 return(m) ;
9853
9854 } /* end MRIreslice() */
9855
9856
9857 MRI *
9858 MRIresample(MRI *src, MRI *template_vol, int resample_type)
9859 {
9860 return(MRIresampleFill(src, template_vol, resample_type, 0)) ;
9861 } /* end MRIresample() */
9862
9863
9864 MRI *MRIresampleFill
9865 (MRI *src, MRI *template_vol, int resample_type, float fill_val)
9866 {
9867
9868 MRI *dest = NULL;
9869 MATRIX *m;
9870 int di, dj, dk;
9871 int si, sj, sk;
9872 float si_f, sj_f, sk_f;
9873 float si_ff, sj_ff, sk_ff;
9874 MATRIX *sp, *dp;
9875 float val, val000, val001, val010, val011, val100, val101, val110, val111;
9876 float w000, w001, w010, w011, w100, w101, w110, w111;
9877 float si_f2, sj_f2, sk_f2;
9878 float ii2, ij2, ik2, isi_f2, isj_f2, isk_f2;
9879 float w[8];
9880 int wi[8];
9881 int mwi;
9882 Real pval;
9883 int i_good_flag, i1_good_flag;
9884 int j_good_flag, j1_good_flag;
9885 int k_good_flag, k1_good_flag;
9886
9887 /* ----- keep the compiler quiet ----- */
9888 val = 0.0;
9889 val000 = val001 = val010 = val011 = val100 = val101 = val110 = val111 = 0.0;
9890
9891 #if 0
9892 if(src->type != template_vol->type)
9893 {
9894 ErrorReturn
9895 (NULL,
9896 (ERROR_UNSUPPORTED,
9897 "MRIresample(): source and destination types must be identical"));
9898 }
9899 #endif
9900
9901 /* ----- fake the ras values if ras_good_flag is not set ----- */
9902 if(!src->ras_good_flag)
9903 printf
9904 ("MRIresample(): WARNING: ras_good_flag "
9905 "is not set, changing orientation\n"
9906 "to default.\n");
9907
9908 // get dst voxel -> src voxel transform
9909 m = MRIgetResampleMatrix(src, template_vol);
9910 if(m == NULL)
9911 return(NULL);
9912
9913 if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
9914 {
9915 printf("MRIresample() matrix is:\n");
9916 MatrixPrint(stdout, m);
9917 }
9918
9919 dest = MRIalloc(template_vol->width,
9920 template_vol->height,
9921 template_vol->depth,
9922 src->type);
9923 if(dest == NULL)
9924 return(NULL);
9925 MRIreplaceValues(dest, dest, 0.0f, fill_val) ;
9926
9927 MRIcopyHeader(template_vol, dest);
9928 MRIcopyPulseParameters(src, dest) ;
9929
9930 sp = MatrixAlloc(4, 1, MATRIX_REAL);
9931 dp = MatrixAlloc(4, 1, MATRIX_REAL);
9932
9933 *MATRIX_RELT(dp, 4, 1) = 1.0;
9934
9935 for(di = 0;di < template_vol->width;di++)
9936 {
9937 for(dj = 0;dj < template_vol->height;dj++)
9938 {
9939 for(dk = 0;dk < template_vol->depth;dk++)
9940 {
9941
9942 *MATRIX_RELT(dp, 1, 1) = (float)di;
9943 *MATRIX_RELT(dp, 2, 1) = (float)dj;
9944 *MATRIX_RELT(dp, 3, 1) = (float)dk;
9945
9946 MatrixMultiply(m, dp, sp);
9947
9948 si_ff = *MATRIX_RELT(sp, 1, 1);
9949 sj_ff = *MATRIX_RELT(sp, 2, 1);
9950 sk_ff = *MATRIX_RELT(sp, 3, 1);
9951
9952 si = (int)floor(si_ff);
9953 sj = (int)floor(sj_ff);
9954 sk = (int)floor(sk_ff);
9955
9956 if (si == 147 && sj == 91 && sk == 86)
9957 DiagBreak() ;
9958 if (di == 129 && dj == 164 && dk == 147)
9959 DiagBreak() ;
9960 si_f = si_ff - si;
9961 sj_f = sj_ff - sj;
9962 sk_f = sk_ff - sk;
9963
9964 #if 0
9965 if(di % 20 == 0 && dj == di && dk == dj)
9966 {
9967 printf("MRIresample() sample point: %3d %3d %3d: "
9968 "%f (%3d + %f) %f (%3d + %f) %f (%3d + %f)\n",
9969 di, dj, dk,
9970 si_ff, si, si_f,
9971 sj_ff, sj, sj_f,
9972 sk_ff, sk, sk_f);
9973 }
9974 #endif
9975
9976 if(resample_type == SAMPLE_SINC)
9977 {
9978 MRIsincSampleVolume(src, si_ff, sj_ff, sk_ff, 5, &pval);
9979 val = (float)pval;
9980 }
9981 else if(resample_type == SAMPLE_CUBIC)
9982 {
9983 MRIcubicSampleVolume(src, si_ff, sj_ff, sk_ff, &pval);
9984 val = (float)pval;
9985 }
9986 else
9987 {
9988 i_good_flag = (si >= 0 && si < src->width);
9989 i1_good_flag = (si+1 >= 0 && si+1 < src->width);
9990 j_good_flag = (sj >= 0 && sj < src->height);
9991 j1_good_flag = (sj+1 >= 0 && sj+1 < src->height);
9992 k_good_flag = (sk >= 0 && sk < src->depth);
9993 k1_good_flag = (sk+1 >= 0 && sk+1 < src->depth);
9994
9995 if(src->type == MRI_UCHAR)
9996 {
9997 val000 = ( !i_good_flag ||
9998 !j_good_flag ||
9999 !k_good_flag ? 0.0 :
10000 (float)MRIvox(src, si , sj , sk ));
10001 val001 = ( !i_good_flag ||
10002 !j_good_flag ||
10003 !k1_good_flag ? 0.0 :
10004 (float)MRIvox(src, si , sj , sk + 1));
10005 val010 = ( !i_good_flag ||
10006 !j1_good_flag ||
10007 !k_good_flag ? 0.0 :
10008 (float)MRIvox(src, si , sj + 1, sk ));
10009 val011 = ( !i_good_flag ||
10010 !j1_good_flag ||
10011 !k1_good_flag ? 0.0 :
10012 (float)MRIvox(src, si , sj + 1, sk + 1));
10013 val100 = (!i1_good_flag ||
10014 !j_good_flag ||
10015 !k_good_flag ? 0.0 :
10016 (float)MRIvox(src, si + 1, sj , sk ));
10017 val101 = (!i1_good_flag ||
10018 !j_good_flag ||
10019 !k1_good_flag ? 0.0 :
10020 (float)MRIvox(src, si + 1, sj , sk + 1));
10021 val110 = (!i1_good_flag ||
10022 !j1_good_flag ||
10023 !k_good_flag ? 0.0 :
10024 (float)MRIvox(src, si + 1, sj + 1, sk ));
10025 val111 = (!i1_good_flag ||
10026 !j1_good_flag ||
10027 !k1_good_flag ? 0.0 :
10028 (float)MRIvox(src, si + 1, sj + 1, sk + 1));
10029 }
10030
10031 if (si == 154 && sj == 134 && sk == 136)
10032 DiagBreak() ;
10033
10034 if(src->type == MRI_SHORT)
10035 {
10036 val000 = ( !i_good_flag ||
10037 !j_good_flag ||
10038 !k_good_flag ? 0.0 :
10039 (float)MRISvox(src, si , sj , sk ));
10040 val001 = ( !i_good_flag ||
10041 !j_good_flag ||
10042 !k1_good_flag ? 0.0 :
10043 (float)MRISvox(src, si , sj , sk + 1));
10044 val010 = ( !i_good_flag ||
10045 !j1_good_flag ||
10046 !k_good_flag ? 0.0 :
10047 (float)MRISvox(src, si , sj + 1, sk ));
10048 val011 = ( !i_good_flag ||
10049 !j1_good_flag ||
10050 !k1_good_flag ? 0.0 :
10051 (float)MRISvox(src, si , sj + 1, sk + 1));
10052 val100 = (!i1_good_flag ||
10053 !j_good_flag ||
10054 !k_good_flag ? 0.0 :
10055 (float)MRISvox(src, si + 1, sj , sk ));
10056 val101 = (!i1_good_flag ||
10057 !j_good_flag ||
10058 !k1_good_flag ? 0.0 :
10059 (float)MRISvox(src, si + 1, sj , sk + 1));
10060 val110 = (!i1_good_flag ||
10061 !j1_good_flag ||
10062 !k_good_flag ? 0.0 :
10063 (float)MRISvox(src, si + 1, sj + 1, sk ));
10064 val111 = (!i1_good_flag ||
10065 !j1_good_flag ||
10066 !k1_good_flag ? 0.0 :
10067 (float)MRISvox(src, si + 1, sj + 1, sk + 1));
10068 }
10069
10070 if(src->type == MRI_INT)
10071 {
10072 val000 = ( !i_good_flag ||
10073 !j_good_flag ||
10074 !k_good_flag ? 0.0 :
10075 (float)MRIIvox(src, si , sj , sk ));
10076 val001 = ( !i_good_flag ||
10077 !j_good_flag ||
10078 !k1_good_flag ? 0.0 :
10079 (float)MRIIvox(src, si , sj , sk + 1));
10080 val010 = ( !i_good_flag ||
10081 !j1_good_flag ||
10082 !k_good_flag ? 0.0 :
10083 (float)MRIIvox(src, si , sj + 1, sk ));
10084 val011 = ( !i_good_flag ||
10085 !j1_good_flag ||
10086 !k1_good_flag ? 0.0 :
10087 (float)MRIIvox(src, si , sj + 1, sk + 1));
10088 val100 = (!i1_good_flag ||
10089 !j_good_flag ||
10090 !k_good_flag ? 0.0 :
10091 (float)MRIIvox(src, si + 1, sj , sk ));
10092 val101 = (!i1_good_flag ||
10093 !j_good_flag ||
10094 !k1_good_flag ? 0.0 :
10095 (float)MRIIvox(src, si + 1, sj , sk + 1));
10096 val110 = (!i1_good_flag ||
10097 !j1_good_flag ||
10098 !k_good_flag ? 0.0 :
10099 (float)MRIIvox(src, si + 1, sj + 1, sk ));
10100 val111 = (!i1_good_flag ||
10101 !j1_good_flag ||
10102 !k1_good_flag ? 0.0 :
10103 (float)MRIIvox(src, si + 1, sj + 1, sk + 1));
10104 }
10105
10106 if(src->type == MRI_LONG)
10107 {
10108 val000 = ( !i_good_flag ||
10109 !j_good_flag ||
10110 !k_good_flag ? 0.0 :
10111 (float)MRILvox(src, si , sj , sk ));
10112 val001 = ( !i_good_flag ||
10113 !j_good_flag ||
10114 !k1_good_flag ? 0.0 :
10115 (float)MRILvox(src, si , sj , sk + 1));
10116 val010 = ( !i_good_flag ||
10117 !j1_good_flag ||
10118 !k_good_flag ? 0.0 :
10119 (float)MRILvox(src, si , sj + 1, sk ));
10120 val011 = ( !i_good_flag ||
10121 !j1_good_flag ||
10122 !k1_good_flag ? 0.0 :
10123 (float)MRILvox(src, si , sj + 1, sk + 1));
10124 val100 = (!i1_good_flag ||
10125 !j_good_flag ||
10126 !k_good_flag ? 0.0 :
10127 (float)MRILvox(src, si + 1, sj , sk ));
10128 val101 = (!i1_good_flag ||
10129 !j_good_flag ||
10130 !k1_good_flag ? 0.0 :
10131 (float)MRILvox(src, si + 1, sj , sk + 1));
10132 val110 = (!i1_good_flag ||
10133 !j1_good_flag ||
10134 !k_good_flag ? 0.0 :
10135 (float)MRILvox(src, si + 1, sj + 1, sk ));
10136 val111 = (!i1_good_flag ||
10137 !j1_good_flag ||
10138 !k1_good_flag ? 0.0 :
10139 (float)MRILvox(src, si + 1, sj + 1, sk + 1));
10140 }
10141
10142 if(src->type == MRI_FLOAT)
10143 {
10144 val000 = ( !i_good_flag ||
10145 !j_good_flag ||
10146 !k_good_flag ? 0.0 :
10147 (float)MRIFvox(src, si , sj , sk ));
10148 val001 = ( !i_good_flag ||
10149 !j_good_flag ||
10150 !k1_good_flag ? 0.0 :
10151 (float)MRIFvox(src, si , sj , sk + 1));
10152 val010 = ( !i_good_flag ||
10153 !j1_good_flag ||
10154 !k_good_flag ? 0.0 :
10155 (float)MRIFvox(src, si , sj + 1, sk ));
10156 val011 = ( !i_good_flag ||
10157 !j1_good_flag ||
10158 !k1_good_flag ? 0.0 :
10159 (float)MRIFvox(src, si , sj + 1, sk + 1));
10160 val100 = (!i1_good_flag ||
10161 !j_good_flag ||
10162 !k_good_flag ? 0.0 :
10163 (float)MRIFvox(src, si + 1, sj , sk ));
10164 val101 = (!i1_good_flag ||
10165 !j_good_flag ||
10166 !k1_good_flag ? 0.0 :
10167 (float)MRIFvox(src, si + 1, sj , sk + 1));
10168 val110 = (!i1_good_flag ||
10169 !j1_good_flag ||
10170 !k_good_flag ? 0.0 :
10171 (float)MRIFvox(src, si + 1, sj + 1, sk ));
10172 val111 = (!i1_good_flag ||
10173 !j1_good_flag ||
10174 !k1_good_flag ? 0.0 :
10175 (float)MRIFvox(src, si + 1, sj + 1, sk + 1));
10176 }
10177
10178 if(resample_type == SAMPLE_TRILINEAR)
10179 {
10180 val = (1.0-si_f) * (1.0-sj_f) * (1.0-sk_f) * val000 +
10181 (1.0-si_f) * (1.0-sj_f) * ( sk_f) * val001 +
10182 (1.0-si_f) * ( sj_f) * (1.0-sk_f) * val010 +
10183 (1.0-si_f) * ( sj_f) * ( sk_f) * val011 +
10184 ( si_f) * (1.0-sj_f) * (1.0-sk_f) * val100 +
10185 ( si_f) * (1.0-sj_f) * ( sk_f) * val101 +
10186 ( si_f) * ( sj_f) * (1.0-sk_f) * val110 +
10187 ( si_f) * ( sj_f) * ( sk_f) * val111;
10188 }
10189
10190 if(resample_type == SAMPLE_NEAREST)
10191 {
10192 if(si_f < 0.5)
10193 {
10194 if(sj_f < 0.5)
10195 {
10196 if(sk_f < 0.5)
10197 val = val000;
10198 else
10199 val = val001;
10200 }
10201 else
10202 {
10203 if(sk_f < 0.5)
10204 val = val010;
10205 else
10206 val = val011;
10207 }
10208 }
10209 else
10210 {
10211 if(sj_f < 0.5)
10212 {
10213 if(sk_f < 0.5)
10214 val = val100;
10215 else
10216 val = val101;
10217 }
10218 else
10219 {
10220 if(sk_f < 0.5)
10221 val = val110;
10222 else
10223 val = val111;
10224 }
10225 }
10226 }
10227
10228 if(resample_type == SAMPLE_WEIGHTED)
10229 {
10230 /* unfinished */
10231 si_f2 = si_f * si_f;
10232 sj_f2 = sj_f * sj_f;
10233 sk_f2 = sk_f * sk_f;
10234
10235 ii2 = 1. / (1 - 2*si_f + si_f2);
10236 ij2 = 1. / (1 - 2*sj_f + sj_f2);
10237 ik2 = 1. / (1 - 2*sk_f + sk_f2);
10238
10239 isi_f2 = 1 / si_f2;
10240 isj_f2 = 1 / sj_f2;
10241 isk_f2 = 1 / sk_f2;
10242
10243 w000 = ii2 + ij2 + ik2;
10244 w001 = ii2 + ij2 + isk_f2;
10245 w010 = ii2 + isj_f2 + ik2;
10246 w011 = ii2 + isj_f2 + isk_f2;
10247 w100 = isi_f2 + ij2 + ik2;
10248 w101 = isi_f2 + ij2 + isk_f2;
10249 w110 = isi_f2 + isj_f2 + ik2;
10250 w111 = isi_f2 + isj_f2 + isk_f2;
10251
10252 w[0] = w[1] = w[2] = w[3] =
10253 w[4] = w[5] = w[6] = w[7] = 0.0;
10254
10255 wi[0] = 0;
10256 wi[1] = 1;
10257 wi[2] = 2;
10258 wi[3] = 3;
10259 wi[4] = 4;
10260 wi[5] = 5;
10261 wi[6] = 6;
10262 wi[7] = 7;
10263
10264 if(val001 == val000)
10265 wi[1] = 0;
10266
10267 if(val010 == val001)
10268 wi[2] = 1;
10269 if(val010 == val000)
10270 wi[2] = 0;
10271
10272 if(val011 == val010)
10273 wi[3] = 2;
10274 if(val011 == val001)
10275 wi[3] = 1;
10276 if(val011 == val000)
10277 wi[3] = 0;
10278
10279 if(val100 == val011)
10280 wi[4] = 3;
10281 if(val100 == val010)
10282 wi[4] = 2;
10283 if(val100 == val001)
10284 wi[4] = 1;
10285 if(val100 == val000)
10286 wi[4] = 0;
10287
10288 if(val101 == val100)
10289 wi[5] = 4;
10290 if(val101 == val011)
10291 wi[5] = 3;
10292 if(val101 == val010)
10293 wi[5] = 2;
10294 if(val101 == val001)
10295 wi[5] = 1;
10296 if(val101 == val000)
10297 wi[5] = 0;
10298
10299 if(val110 == val101)
10300 wi[6] = 5;
10301 if(val110 == val100)
10302 wi[6] = 4;
10303 if(val110 == val011)
10304 wi[6] = 3;
10305 if(val110 == val010)
10306 wi[6] = 2;
10307 if(val110 == val001)
10308 wi[6] = 1;
10309 if(val110 == val000)
10310 wi[6] = 0;
10311
10312 if(val111 == val110)
10313 wi[7] = 6;
10314 if(val111 == val101)
10315 wi[7] = 5;
10316 if(val111 == val100)
10317 wi[7] = 4;
10318 if(val111 == val011)
10319 wi[7] = 3;
10320 if(val111 == val010)
10321 wi[7] = 2;
10322 if(val111 == val001)
10323 wi[7] = 1;
10324 if(val111 == val000)
10325 wi[7] = 0;
10326
10327 w[wi[0]] += w000;
10328 w[wi[1]] += w001;
10329 w[wi[2]] += w010;
10330 w[wi[3]] += w011;
10331 w[wi[4]] += w100;
10332 w[wi[5]] += w101;
10333 w[wi[6]] += w110;
10334 w[wi[7]] += w111;
10335
10336 mwi = 0;
10337
10338 if(w[1] > w[mwi])
10339 mwi = 1;
10340 if(w[2] > w[mwi])
10341 mwi = 2;
10342 if(w[3] > w[mwi])
10343 mwi = 3;
10344 if(w[4] > w[mwi])
10345 mwi = 4;
10346 if(w[5] > w[mwi])
10347 mwi = 5;
10348 if(w[6] > w[mwi])
10349 mwi = 6;
10350 if(w[7] > w[mwi])
10351 mwi = 7;
10352
10353 if(mwi == 0)
10354 val = val000;
10355 if(mwi == 1)
10356 val = val001;
10357 if(mwi == 2)
10358 val = val010;
10359 if(mwi == 3)
10360 val = val011;
10361 if(mwi == 4)
10362 val = val100;
10363 if(mwi == 5)
10364 val = val101;
10365 if(mwi == 6)
10366 val = val110;
10367 if(mwi == 7)
10368 val = val111;
10369
10370 }
10371
10372 }
10373
10374 if(dest->type == MRI_UCHAR)
10375 MRIvox(dest, di, dj, dk) = (unsigned char)val;
10376 if(dest->type == MRI_SHORT)
10377 MRISvox(dest, di, dj, dk) = (short)val;
10378 if(dest->type == MRI_INT)
10379 MRIIvox(dest, di, dj, dk) = (int)val;
10380 if(dest->type == MRI_LONG)
10381 MRILvox(dest, di, dj, dk) = (long)val;
10382 if(dest->type == MRI_FLOAT)
10383 MRIFvox(dest, di, dj, dk) = (float)val;
10384
10385 }
10386 }
10387 }
10388
10389 {
10390 MATRIX *m_old_voxel_to_ras, *m_voxel_to_ras,
10391 *m_old_ras_to_voxel, *v_ras, *v_vox, *m_new_ras_to_voxel, *v_vox2 ;
10392
10393 m_old_voxel_to_ras = MRIgetVoxelToRasXform(src) ;
10394
10395 m_voxel_to_ras = MatrixMultiply(m_old_voxel_to_ras, m, NULL) ;
10396
10397 dest->x_r = *MATRIX_RELT(m_voxel_to_ras,1,1)/dest->xsize;
10398 dest->x_a = *MATRIX_RELT(m_voxel_to_ras,2,1)/dest->xsize;
10399 dest->x_s = *MATRIX_RELT(m_voxel_to_ras,3,1)/dest->xsize;
10400
10401 dest->y_r = *MATRIX_RELT(m_voxel_to_ras,1,2)/dest->ysize;
10402 dest->y_a = *MATRIX_RELT(m_voxel_to_ras,2,2)/dest->ysize;
10403 dest->y_s = *MATRIX_RELT(m_voxel_to_ras,3,2)/dest->ysize;
10404
10405 dest->z_r = *MATRIX_RELT(m_voxel_to_ras,1,3)/dest->zsize;
10406 dest->z_a = *MATRIX_RELT(m_voxel_to_ras,2,3)/dest->zsize;
10407 dest->z_s = *MATRIX_RELT(m_voxel_to_ras,3,3)/dest->zsize;
10408
10409 /* compute the RAS coordinates of the center of the dest. image
10410 and put them in c_r, c_a, and c_s.
10411
10412 C = M * c_v
10413 */
10414 v_vox = VectorAlloc(4, MATRIX_REAL) ;
10415
10416 /* voxel coords of center of dest image */
10417 VECTOR_ELT(v_vox,4) = 1.0 ;
10418 VECTOR_ELT(v_vox,1) = (dest->width)/2.0 ;
10419 VECTOR_ELT(v_vox,2) = (dest->height)/2.0 ;
10420 VECTOR_ELT(v_vox,3) = (dest->depth)/2.0 ;
10421
10422 v_vox2 =
10423 MatrixMultiply(m, v_vox, NULL) ; /* voxel coords in source image */
10424 v_ras =
10425 MatrixMultiply(m_old_voxel_to_ras, v_vox2, NULL) ; /* ras cntr of dest */
10426
10427 dest->c_r = VECTOR_ELT(v_ras, 1);
10428 dest->c_a = VECTOR_ELT(v_ras, 2);
10429 dest->c_s = VECTOR_ELT(v_ras, 3);
10430 dest->ras_good_flag = 1 ;
10431
10432 if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
10433 {
10434 m_new_ras_to_voxel = MRIgetRasToVoxelXform(dest) ;
10435 m_old_ras_to_voxel = MRIgetRasToVoxelXform(src) ;
10436 V3_X(v_ras) = V3_Y(v_ras) = V3_Z(v_ras) = 0.0 ;
10437 MatrixMultiply(m_old_ras_to_voxel, v_ras, v_vox) ;
10438 printf("old RAS (0,0,0) -> (%2.0f, %2.0f, %2.0f)\n",
10439 VECTOR_ELT(v_vox,1), VECTOR_ELT(v_vox,2), VECTOR_ELT(v_vox,3)) ;
10440 MatrixMultiply(m_new_ras_to_voxel, v_ras, v_vox) ;
10441 printf("new RAS (0,0,0) -> (%2.0f, %2.0f, %2.0f)\n",
10442 VECTOR_ELT(v_vox,1), VECTOR_ELT(v_vox,2), VECTOR_ELT(v_vox,3)) ;
10443 MatrixFree(&m_new_ras_to_voxel) ; MatrixFree(&m_old_ras_to_voxel) ;
10444 }
10445
10446 MatrixFree(&v_vox) ; MatrixFree(&v_vox2) ; MatrixFree(&v_ras) ;
10447 MatrixFree(&m_voxel_to_ras) ; MatrixFree(&m_old_voxel_to_ras) ;
10448 }
10449
10450
10451 MatrixFree(&dp);
10452 MatrixFree(&sp);
10453 MatrixFree(&m);
10454
10455 return(dest);
10456
10457 } /* end MRIresample() */
10458
10459 int MRIlimits(MRI *mri, float *min, float *max)
10460 {
10461
10462 float val;
10463 int i, j, k;
10464
10465 if(mri == NULL)
10466 return(NO_ERROR);
10467
10468 if(mri->slices == NULL)
10469 return(NO_ERROR);
10470
10471 if(mri->type == MRI_UCHAR)
10472 {
10473 *min = *max = (float)MRIvox(mri, 0, 0, 0);
10474 for(i = 0;i < mri->width;i++)
10475 for(j = 0;j < mri->height;j++)
10476 for(k = 0;k < mri->depth;k++)
10477 {
10478 val = (float)MRIvox(mri, i, j, k);
10479 if(val < *min)
10480 *min = val;
10481 if(val > *max)
10482 *max = val;
10483 }
10484
10485 }
10486
10487 if(mri->type == MRI_SHORT)
10488 {
10489
10490 *min = *max = (float)MRISvox(mri, 0, 0, 0);
10491
10492 for(i = 0;i < mri->width;i++)
10493 for(j = 0;j < mri->height;j++)
10494 for(k = 0;k < mri->depth;k++)
10495 {
10496 val = (float)MRISvox(mri, i, j, k);
10497 if(val < *min)
10498 *min = val;
10499 if(val > *max)
10500 *max = val;
10501 }
10502
10503 }
10504
10505 if(mri->type == MRI_INT)
10506 {
10507
10508 *min = *max = (float)MRILvox(mri, 0, 0, 0);
10509
10510 for(i = 0;i < mri->width;i++)
10511 for(j = 0;j < mri->height;j++)
10512 for(k = 0;k < mri->depth;k++)
10513 {
10514 val = (float)MRILvox(mri, i, j, k);
10515 if(val < *min)
10516 *min = val;
10517 if(val > *max)
10518 *max = val;
10519 }
10520
10521 }
10522
10523 if(mri->type == MRI_LONG)
10524 {
10525
10526 *min = *max = (float)MRILvox(mri, 0, 0, 0);
10527
10528 for(i = 0;i < mri->width;i++)
10529 for(j = 0;j < mri->height;j++)
10530 for(k = 0;k < mri->depth;k++)
10531 {
10532 val = (float)MRILvox(mri, i, j, k);
10533 if(val < *min)
10534 *min = val;
10535 if(val > *max)
10536 *max = val;
10537 }
10538
10539 }
10540
10541 if(mri->type == MRI_FLOAT)
10542 {
10543
10544 *min = *max = (float)MRIFvox(mri, 0, 0, 0);
10545
10546 for(i = 0;i < mri->width;i++)
10547 for(j = 0;j < mri->height;j++)
10548 for(k = 0;k < mri->depth;k++)
10549 {
10550 val = (float)MRIFvox(mri, i, j, k);
10551 if(val < *min)
10552 *min = val;
10553 if(val > *max)
10554 *max = val;
10555 }
10556
10557 }
10558
10559 return(NO_ERROR);
10560
10561 } /* end MRIlimits() */
10562
10563 int MRIprintStats(MRI *mri, FILE *stream)
10564 {
10565
10566 float min, max, mean, std;
10567 int n;
10568 double com[3];
10569
10570 MRIstats(mri, &min, &max, &n, &mean, &std);
10571
10572 fprintf(stream, "%d values\n", n);
10573 fprintf(stream, "min = %g\n", min);
10574 fprintf(stream, "max = %g\n", max);
10575 fprintf(stream, "mean = %g\n", mean);
10576 fprintf(stream, "std = %g\n", std);
10577
10578 MRIcenterOfMass(mri, com, 0);
10579
10580 fprintf(stream, "com = %g %g %g\n", com[0], com[1], com[2]);
10581
10582 return(NO_ERROR);
10583
10584 } /* end MRIprintStats() */
10585
10586 int MRIstats
10587 (MRI *mri, float *min, float *max, int *n_voxels, float *mean, float *std)
10588 {
10589
10590 float val;
10591 float sum, sq_sum;
10592 int i, j, k, t;
10593 float n;
10594
10595 if(mri == NULL)
10596 return(NO_ERROR);
10597
10598 if(mri->slices == NULL)
10599 return(NO_ERROR);
10600
10601 sum = sq_sum = 0.0;
10602 *n_voxels = mri->width * mri->height * mri->depth * mri->nframes;
10603 n = (float)(*n_voxels);
10604
10605 if(mri->type == MRI_UCHAR)
10606 {
10607
10608 *max = *min = MRIseq_vox(mri, 0, 0, 0, 0);
10609
10610 for(i = 0;i < mri->width;i++)
10611 for(j = 0;j < mri->height;j++)
10612 for(k = 0;k < mri->depth;k++)
10613 for(t = 0;t < mri->nframes;t++)
10614 {
10615
10616 val = (float)MRIseq_vox(mri, i, j, k, t);
10617
10618 if(val < *min)
10619 *min = val;
10620 if(val > *max)
10621 *max = val;
10622
10623 sum += val;
10624 sq_sum += val * val;
10625
10626 }
10627
10628 }
10629
10630 if(mri->type == MRI_SHORT)
10631 {
10632
10633 *min = *max = (float)MRISseq_vox(mri, 0, 0, 0, 0);
10634
10635 for(i = 0;i < mri->width;i++)
10636 for(j = 0;j < mri->height;j++)
10637 for(k = 0;k < mri->depth;k++)
10638 for(t = 0;t < mri->nframes;t++)
10639 {
10640
10641 val = (float)MRISseq_vox(mri, i, j, k, t);
10642
10643 if(val < *min)
10644 *min = val;
10645 if(val > *max)
10646 *max = val;
10647
10648 sum += val;
10649 sq_sum += val * val;
10650
10651 }
10652
10653 }
10654
10655 if(mri->type == MRI_INT)
10656 {
10657
10658 *min = *max = (float)MRILseq_vox(mri, 0, 0, 0, 0);
10659
10660 for(i = 0;i < mri->width;i++)
10661 for(j = 0;j < mri->height;j++)
10662 for(k = 0;k < mri->depth;k++)
10663 for(t = 0;t < mri->nframes;t++)
10664 {
10665
10666 val = (float)MRILseq_vox(mri, i, j, k, t);
10667
10668 if(val < *min)
10669 *min = val;
10670 if(val > *max)
10671 *max = val;
10672
10673 sum += val;
10674 sq_sum += val * val;
10675
10676 }
10677
10678 }
10679
10680 if(mri->type == MRI_LONG)
10681 {
10682
10683 *min = *max = (float)MRILseq_vox(mri, 0, 0, 0, 0);
10684
10685 for(i = 0;i < mri->width;i++)
10686 for(j = 0;j < mri->height;j++)
10687 for(k = 0;k < mri->depth;k++)
10688 for(t = 0;t < mri->nframes;t++)
10689 {
10690
10691 val = (float)MRILseq_vox(mri, i, j, k, t);
10692
10693 if(val < *min)
10694 *min = val;
10695 if(val > *max)
10696 *max = val;
10697
10698 sum += val;
10699 sq_sum += val * val;
10700
10701 }
10702
10703 }
10704
10705 if(mri->type == MRI_FLOAT)
10706 {
10707
10708 *min = *max = (float)MRIFseq_vox(mri, 0, 0, 0, 0);
10709
10710 for(i = 0;i < mri->width;i++)
10711 for(j = 0;j < mri->height;j++)
10712 for(k = 0;k < mri->depth;k++)
10713 for(t = 0;t < mri->nframes;t++)
10714 {
10715
10716 val = (float)MRIFseq_vox(mri, i, j, k, t);
10717
10718 if(val < *min)
10719 *min = val;
10720 if(val > *max)
10721 *max = val;
10722
10723 sum += val;
10724 sq_sum += val * val;
10725
10726 }
10727
10728 }
10729
10730 *mean = sum / n;
10731 *std = (sq_sum - n * (*mean) * (*mean)) / (n - 1.0);
10732
10733 *std = sqrt(*std);
10734
10735 return(NO_ERROR);
10736
10737 } /* end MRIstats() */
10738
10739 float MRIvolumeDeterminant(MRI *mri)
10740 {
10741
10742 MATRIX *m;
10743 float det;
10744
10745 m = MatrixAlloc(4, 4, MATRIX_REAL);
10746 if(m == NULL)
10747 return(0.0);
10748
10749 stuff_four_by_four(m, mri->x_r, mri->y_r, mri->z_r, 0.0,
10750 mri->x_a, mri->y_a, mri->z_a, 0.0,
10751 mri->x_s, mri->y_s, mri->z_s, 0.0,
10752 0.0, 0.0, 0.0, 1.0);
10753
10754 det = MatrixDeterminant(m);
10755
10756 MatrixFree(&m);
10757
10758 return(det);
10759
10760 } /* end MRIvolumeDeterminant() */
10761
10762 int stuff_four_by_four(MATRIX *m, float m11, float m12, float m13, float m14,
10763 float m21, float m22, float m23, float m24,
10764 float m31, float m32, float m33, float m34,
10765 float m41, float m42, float m43, float m44)
10766 {
10767
10768 if(m == NULL)
10769 {
10770 ErrorReturn
10771 (ERROR_BADPARM,
10772 (ERROR_BADPARM,
10773 "stuff_four_by_four(): matrix is NULL"));
10774 }
10775
10776 if(m->rows != 4 || m->cols != 4)
10777 {
10778 ErrorReturn
10779 (ERROR_BADPARM,
10780 (ERROR_BADPARM,
10781 "stuff_four_by_four(): matrix is not four-by-four"));
10782 }
10783
10784 *MATRIX_RELT(m, 1, 1) = m11;
10785 *MATRIX_RELT(m, 1, 2) = m12;
10786 *MATRIX_RELT(m, 1, 3) = m13;
10787 *MATRIX_RELT(m, 1, 4) = m14;
10788 *MATRIX_RELT(m, 2, 1) = m21;
10789 *MATRIX_RELT(m, 2, 2) = m22;
10790 *MATRIX_RELT(m, 2, 3) = m23;
10791 *MATRIX_RELT(m, 2, 4) = m24;
10792 *MATRIX_RELT(m, 3, 1) = m31;
10793 *MATRIX_RELT(m, 3, 2) = m32;
10794 *MATRIX_RELT(m, 3, 3) = m33;
10795 *MATRIX_RELT(m, 3, 4) = m34;
10796 *MATRIX_RELT(m, 4, 1) = m41;
10797 *MATRIX_RELT(m, 4, 2) = m42;
10798 *MATRIX_RELT(m, 4, 3) = m43;
10799 *MATRIX_RELT(m, 4, 4) = m44;
10800
10801 return(NO_ERROR);
10802
10803 } /* end stuff_four_by_four() */
10804
10805 int apply_i_to_r(MRI *mri, MATRIX *m)
10806 {
10807
10808 float x_r, x_a, x_s;
10809 float y_r, y_a, y_s;
10810 float z_r, z_a, z_s;
10811 float mag;
10812 MATRIX *origin, *c;
10813
10814 x_r = *MATRIX_RELT(m, 1, 1);
10815 x_a = *MATRIX_RELT(m, 2, 1);
10816 x_s = *MATRIX_RELT(m, 3, 1);
10817 mag = sqrt(x_r*x_r + x_a*x_a + x_s*x_s);
10818 mri->x_r = x_r / mag; mri->x_a = x_a / mag; mri->x_s = x_s / mag;
10819 mri->xsize = mag;
10820
10821 y_r = *MATRIX_RELT(m, 1, 2);
10822 y_a = *MATRIX_RELT(m, 2, 2);
10823 y_s = *MATRIX_RELT(m, 3, 2);
10824 mag = sqrt(y_r*y_r + y_a*y_a + y_s*y_s);
10825 mri->y_r = y_r / mag; mri->y_a = y_a / mag; mri->y_s = y_s / mag;
10826 mri->ysize = mag;
10827
10828 z_r = *MATRIX_RELT(m, 1, 3);
10829 z_a = *MATRIX_RELT(m, 2, 3);
10830 z_s = *MATRIX_RELT(m, 3, 3);
10831 mag = sqrt(z_r*z_r + z_a*z_a + z_s*z_s);
10832 mri->z_r = z_r / mag; mri->z_a = z_a / mag; mri->z_s = z_s / mag;
10833 mri->zsize = mag;
10834
10835 origin = MatrixAlloc(4, 1, MATRIX_REAL);
10836 if(origin == NULL)
10837 {
10838 ErrorReturn
10839 (ERROR_BADPARM,
10840 (ERROR_BADPARM,
10841 "apply_i_to_r(): error allocating matrix"));
10842 }
10843 *MATRIX_RELT(origin, 1, 1) = (mri->width - 1.0) / 2.0;
10844 *MATRIX_RELT(origin, 2, 1) = (mri->height - 1.0) / 2.0;
10845 *MATRIX_RELT(origin, 3, 1) = (mri->depth - 1.0) / 2.0;
10846 *MATRIX_RELT(origin, 4, 1) = 1.0;
10847
10848 c = MatrixMultiply(m, origin, NULL);
10849 if(c == NULL)
10850 {
10851 MatrixFree(&origin);
10852 ErrorReturn
10853 (ERROR_BADPARM,
10854 (ERROR_BADPARM,
10855 "apply_i_to_r(): error multiplying matrices"));
10856 }
10857
10858 mri->c_r = *MATRIX_RELT(c, 1, 1);
10859 mri->c_a = *MATRIX_RELT(c, 2, 1);
10860 mri->c_s = *MATRIX_RELT(c, 3, 1);
10861
10862 MatrixFree(&origin);
10863 MatrixFree(&c);
10864
10865 mri->ras_good_flag = 1;
10866
10867 return(NO_ERROR);
10868
10869 } /* end apply_i_to_r() */
10870
10871 MATRIX *
10872 MRIrasXformToVoxelXform(MRI *mri_src, MRI *mri_dst, MATRIX *m_ras_xform,
10873 MATRIX *m_voxel_xform)
10874 {
10875 MATRIX *m_ras_to_voxel, *m_voxel_to_ras, *m_tmp ;
10876
10877 if (!mri_dst)
10878 mri_dst = mri_src ; /* assume they will be in the same space */
10879
10880 m_voxel_to_ras = MRIgetVoxelToRasXform(mri_src) ;
10881 m_ras_to_voxel = MRIgetRasToVoxelXform(mri_dst) ;
10882
10883 m_tmp = MatrixMultiply(m_ras_xform, m_voxel_to_ras, NULL) ;
10884 m_voxel_xform = MatrixMultiply(m_ras_to_voxel, m_tmp, m_voxel_xform) ;
10885
10886 MatrixFree(&m_voxel_to_ras); MatrixFree(&m_ras_to_voxel); MatrixFree(&m_tmp);
10887
10888 return(m_voxel_xform) ;
10889 }
10890
10891 MATRIX *
10892 MRIvoxelXformToRasXform(MRI *mri_src, MRI *mri_dst, MATRIX *m_voxel_xform,
10893 MATRIX *m_ras_xform)
10894 {
10895 MATRIX *m_ras_to_voxel, *m_voxel_to_ras, *m_tmp ;
10896
10897 if (!mri_dst)
10898 mri_dst = mri_src ; /* assume they will be in the same space */
10899
10900 m_ras_to_voxel = MRIgetRasToVoxelXform(mri_src) ;
10901 m_voxel_to_ras = MRIgetVoxelToRasXform(mri_dst) ;
10902
10903 m_tmp = MatrixMultiply(m_voxel_xform, m_ras_to_voxel, NULL) ;
10904 m_ras_xform = MatrixMultiply(m_voxel_to_ras, m_tmp, m_ras_xform) ;
10905
10906 MatrixFree(&m_voxel_to_ras); MatrixFree(&m_ras_to_voxel); MatrixFree(&m_tmp);
10907
10908 return(m_ras_xform) ;
10909 }
10910
10911 MATRIX *extract_r_to_i(MRI *mri)
10912 {
10913 MATRIX *m_ras_to_voxel, *m_voxel_to_ras ;
10914
10915 m_voxel_to_ras = extract_i_to_r(mri) ;
10916 m_ras_to_voxel = MatrixInverse(m_voxel_to_ras, NULL) ;
10917 MatrixFree(&m_voxel_to_ras) ;
10918 return(m_ras_to_voxel) ;
10919 }
10920
10921 int
10922 MRIsetVoxelToRasXform(MRI *mri, MATRIX *m_vox2ras)
10923 {
10924 float ci, cj, ck;
10925
10926 mri->x_r = *MATRIX_RELT(m_vox2ras, 1, 1) / mri->xsize ;
10927 mri->y_r = *MATRIX_RELT(m_vox2ras, 1, 2) / mri->ysize ;
10928 mri->z_r = *MATRIX_RELT(m_vox2ras, 1, 3) / mri->zsize ;
10929
10930 mri->x_a = *MATRIX_RELT(m_vox2ras, 2, 1) / mri->xsize ;
10931 mri->y_a = *MATRIX_RELT(m_vox2ras, 2, 2) / mri->ysize ;
10932 mri->z_a = *MATRIX_RELT(m_vox2ras, 2, 3) / mri->zsize ;
10933
10934 mri->x_s = *MATRIX_RELT(m_vox2ras, 3, 1) / mri->xsize ;
10935 mri->y_s = *MATRIX_RELT(m_vox2ras, 3, 2) / mri->ysize ;
10936 mri->z_s = *MATRIX_RELT(m_vox2ras, 3, 3) / mri->zsize ;
10937
10938 ci = (mri->width) / 2.0;
10939 cj = (mri->height) / 2.0;
10940 ck = (mri->depth) / 2.0;
10941 mri->c_r = *MATRIX_RELT(m_vox2ras, 1, 4) +
10942 (*MATRIX_RELT(m_vox2ras, 1, 1) * ci +
10943 *MATRIX_RELT(m_vox2ras, 1, 2) * cj +
10944 *MATRIX_RELT(m_vox2ras, 1, 3) * ck);
10945 mri->c_a = *MATRIX_RELT(m_vox2ras, 2, 4) +
10946 (*MATRIX_RELT(m_vox2ras, 2, 1) * ci +
10947 *MATRIX_RELT(m_vox2ras, 2, 2) * cj +
10948 *MATRIX_RELT(m_vox2ras, 2, 3) * ck);
10949 mri->c_s = *MATRIX_RELT(m_vox2ras, 3, 4) +
10950 (*MATRIX_RELT(m_vox2ras, 3, 1) * ci +
10951 *MATRIX_RELT(m_vox2ras, 3, 2) * cj +
10952 *MATRIX_RELT(m_vox2ras, 3, 3) * ck);
10953 MRIreInitCache(mri);
10954 return(NO_ERROR) ;
10955 }
10956
10957 // allocate memory and the user must free it.
10958 MATRIX *extract_i_to_r(MRI *mri)
10959 {
10960 MATRIX *m;
10961 float m11, m12, m13, m14;
10962 float m21, m22, m23, m24;
10963 float m31, m32, m33, m34;
10964 float ci, cj, ck;
10965
10966 m = MatrixAlloc(4, 4, MATRIX_REAL);
10967 if(m == NULL)
10968 {
10969 ErrorReturn
10970 (NULL,
10971 (ERROR_BADPARM,
10972 "extract_i_to_r(): error allocating matrix"));
10973 }
10974
10975 m11 = mri->xsize * mri->x_r;
10976 m12 = mri->ysize * mri->y_r;
10977 m13 = mri->zsize * mri->z_r;
10978 m21 = mri->xsize * mri->x_a;
10979 m22 = mri->ysize * mri->y_a;
10980 m23 = mri->zsize * mri->z_a;
10981 m31 = mri->xsize * mri->x_s;
10982 m32 = mri->ysize * mri->y_s;
10983 m33 = mri->zsize * mri->z_s;
10984
10985 ci = (mri->width) / 2.0;
10986 cj = (mri->height) / 2.0;
10987 ck = (mri->depth) / 2.0;
10988
10989 m14 = mri->c_r - (m11 * ci + m12 * cj + m13 * ck);
10990 m24 = mri->c_a - (m21 * ci + m22 * cj + m23 * ck);
10991 m34 = mri->c_s - (m31 * ci + m32 * cj + m33 * ck);
10992
10993 stuff_four_by_four(m, m11, m12, m13, m14,
10994 m21, m22, m23, m24,
10995 m31, m32, m33, m34,
10996 0.0, 0.0, 0.0, 1.0);
10997
10998
10999 return(m);
11000
11001 } /* end extract_i_to_r() */
11002
11003 /* eof */
11004 MRI *
11005 MRIscaleMeanIntensities(MRI *mri_src, MRI *mri_ref, MRI *mri_dst)
11006 {
11007 int width, height, depth, x, y, z, val ;
11008 double ref_mean, src_mean, nref_vox, nsrc_vox, scale ;
11009
11010 mri_dst = MRIcopy(mri_src, mri_dst) ;
11011
11012 width = mri_dst->width ; height = mri_dst->height ; depth = mri_dst->depth;
11013
11014 nref_vox = nsrc_vox = src_mean = ref_mean = 0.0 ;
11015 for (z = 0 ; z < depth ; z++)
11016 {
11017 for (y = 0 ; y < height ; y++)
11018 {
11019 for (x = 0 ; x < width ; x++)
11020 {
11021 if (MRIvox(mri_ref,x,y,z) > 10)
11022 {
11023 nref_vox++ ;
11024 ref_mean += (double)MRIvox(mri_ref, x, y, z) ;
11025 }
11026 if (MRIvox(mri_src,x,y,z) > 10)
11027 {
11028 src_mean += (double)MRIvox(mri_src, x, y, z) ;
11029 nsrc_vox++ ;
11030 }
11031 }
11032 }
11033 }
11034
11035 ref_mean /= nref_vox ; src_mean /= nsrc_vox ;
11036 fprintf(stderr, "mean brightnesses: ref = %2.1f, in = %2.1f\n",
11037 ref_mean, src_mean) ;
11038 scale = ref_mean / src_mean ;
11039 for (z = 0 ; z < depth ; z++)
11040 {
11041 for (y = 0 ; y < height ; y++)
11042 {
11043 for (x = 0 ; x < width ; x++)
11044 {
11045 val = MRIvox(mri_src, x, y, z) ;
11046 val = nint(val*scale) ;
11047 if (val > 255)
11048 val = 255 ;
11049 MRIvox(mri_src, x, y, z) = val ;
11050 }
11051 }
11052 }
11053
11054 return(mri_dst) ;
11055 }
11056
11057 MRI *MRIsmoothParcellation(MRI *mri, int smooth_parcellation_count)
11058 {
11059
11060 MRI *mri2;
11061 int i, j, k;
11062 short vals[26];
11063 int counts[32768];
11064 int c;
11065
11066 if(mri->type != MRI_SHORT)
11067 {
11068 ErrorReturn
11069 (NULL,
11070 (ERROR_UNSUPPORTED,
11071 "MRIsmoothParcellation(): only supported for shorts data"));
11072 }
11073
11074 mri2 = MRIcopy(mri, NULL);
11075 if(mri2 == NULL)
11076 {
11077 ErrorReturn
11078 (NULL,
11079 (ERROR_NOMEMORY,
11080 "MRIsmoothParcellation(): error copying structre"));
11081 }
11082
11083 for(i = 1;i < mri->width-1;i++)
11084 {
11085 for(j = 1;j < mri->height-1;j++)
11086 {
11087 for(k = 1;k < mri->depth-1;k++)
11088 {
11089
11090 memset(counts, 0x00, 32768 * sizeof(int));
11091
11092 vals[ 0] = MRISvox(mri, i+1, j+1, k+1);
11093 vals[ 1] = MRISvox(mri, i+1, j+1, k );
11094 vals[ 2] = MRISvox(mri, i+1, j+1, k-1);
11095 vals[ 3] = MRISvox(mri, i+1, j , k+1);
11096 vals[ 4] = MRISvox(mri, i+1, j , k );
11097 vals[ 5] = MRISvox(mri, i+1, j , k-1);
11098 vals[ 6] = MRISvox(mri, i+1, j-1, k+1);
11099 vals[ 7] = MRISvox(mri, i+1, j-1, k );
11100 vals[ 8] = MRISvox(mri, i+1, j-1, k-1);
11101
11102 vals[ 9] = MRISvox(mri, i , j+1, k+1);
11103 vals[10] = MRISvox(mri, i , j+1, k );
11104 vals[11] = MRISvox(mri, i , j+1, k-1);
11105 vals[12] = MRISvox(mri, i , j , k+1);
11106 /* --- ignore the voxel itself --- */
11107 vals[13] = MRISvox(mri, i , j , k-1);
11108 vals[14] = MRISvox(mri, i , j-1, k+1);
11109 vals[15] = MRISvox(mri, i , j-1, k );
11110 vals[16] = MRISvox(mri, i , j-1, k-1);
11111
11112 vals[17] = MRISvox(mri, i-1, j+1, k+1);
11113 vals[18] = MRISvox(mri, i-1, j+1, k );
11114 vals[19] = MRISvox(mri, i-1, j+1, k-1);
11115 vals[20] = MRISvox(mri, i-1, j , k+1);
11116 vals[21] = MRISvox(mri, i-1, j , k );
11117 vals[22] = MRISvox(mri, i-1, j , k-1);
11118 vals[23] = MRISvox(mri, i-1, j-1, k+1);
11119 vals[24] = MRISvox(mri, i-1, j-1, k );
11120 vals[25] = MRISvox(mri, i-1, j-1, k-1);
11121
11122 for(c = 0;c < 26;c++)
11123 counts[vals[c]]++;
11124
11125 for(c = 0;c < 26;c++)
11126 if(counts[vals[c]] >= smooth_parcellation_count)
11127 MRISvox(mri2, i, j, k) = vals[c];
11128
11129 }
11130 }
11131 }
11132
11133 return(mri2);
11134
11135 } /* end MRIsmoothParcellation() */
11136
11137 int
11138 MRIeraseBorderPlanes(MRI *mri)
11139 {
11140 int x, y, z ;
11141
11142 for (x = 0 ; x < mri->width ; x++)
11143 for (y = 0 ; y < mri->height ; y++)
11144 {
11145 MRIvox(mri, x, y, 0) = MRIvox(mri, x, y, mri->depth-1) = 0 ;
11146 }
11147
11148 for (y = 0 ; y < mri->height ; y++)
11149 for (z = 0 ; z < mri->depth ; z++)
11150 {
11151 MRIvox(mri, 0, y, z) = MRIvox(mri, mri->width-1, y, z) = 0 ;
11152 }
11153
11154 for (x = 0 ; x < mri->width ; x++)
11155 for (z = 0 ; z < mri->depth ; z++)
11156 {
11157 MRIvox(mri, x, 0, z) = MRIvox(mri, x, mri->height-1, z) = 0 ;
11158 }
11159
11160 return(NO_ERROR) ;
11161 }
11162 int
11163 MRIcopyPulseParameters(MRI *mri_src, MRI *mri_dst)
11164 {
11165 mri_dst->flip_angle = mri_src->flip_angle ;
11166 mri_dst->tr = mri_src->tr ;
11167 mri_dst->te = mri_src->te ;
11168 mri_dst->ti = mri_src->ti ;
11169 return(NO_ERROR) ;
11170 }
11171 float
11172 MRIfindNearestNonzero(MRI *mri, int wsize, Real xr, Real yr, Real zr)
11173 {
11174 int xk, yk, zk, xi, yi, zi, whalf, x, y, z ;
11175 float dist, min_dist, min_val, dx, dy, dz ;
11176
11177 x = mri->xi[nint(xr)] ; y = mri->yi[nint(yr)] ; z = mri->zi[nint(zr)] ;
11178 if (MRIvox(mri, x, y, z) > 0)
11179 return((float)MRIvox(mri, x, y, z)) ;
11180
11181 min_dist = 100000 ; min_val = 0 ;
11182 whalf = (wsize-1)/2 ;
11183 for (zk = -whalf ; zk <= whalf ; zk++)
11184 {
11185 zi = mri->zi[z+zk] ;
11186 dz = zi-zr ;
11187 for (yk = -whalf ; yk <= whalf ; yk++)
11188 {
11189 yi = mri->yi[y+yk] ;
11190 dy = yi-yr ;
11191 for (xk = -whalf ; xk <= whalf ; xk++)
11192 {
11193 xi = mri->xi[x+xk] ;
11194 dx = xi-xr ;
11195 if (MRIgetVoxVal(mri, xi, yi, zi,0) > 0)
11196 {
11197 dist = sqrt(dx*dx + dy*dy + dz*dz) ;
11198 if (dist < min_dist)
11199 {
11200 min_dist = dist ;
11201 min_val = MRIgetVoxVal(mri, xi, yi, zi,0) ;
11202 }
11203 }
11204 }
11205 }
11206 }
11207 return(min_val) ;
11208 }
11209 int
11210 MRIcountNonzeroInNbhd(MRI *mri, int wsize, int x, int y, int z)
11211 {
11212 int xk, yk, zk, xi, yi, zi, whalf, total ;
11213
11214 whalf = (wsize-1)/2 ;
11215 for (total = 0, zk = -whalf ; zk <= whalf ; zk++)
11216 {
11217 zi = mri->zi[z+zk] ;
11218 for (yk = -whalf ; yk <= whalf ; yk++)
11219 {
11220 yi = mri->yi[y+yk] ;
11221 for (xk = -whalf ; xk <= whalf ; xk++)
11222 {
11223 xi = mri->xi[x+xk] ;
11224 if (MRIgetVoxVal(mri, xi, yi, zi,0) > 0)
11225 total++ ;
11226 }
11227 }
11228 }
11229 return(total) ;
11230 }
11231 int
11232 MRIareNonzeroInNbhd(MRI *mri, int wsize, int x, int y, int z)
11233 {
11234 int xk, yk, zk, xi, yi, zi, whalf ;
11235
11236 whalf = (wsize-1)/2 ;
11237 for (zk = -whalf ; zk <= whalf ; zk++)
11238 {
11239 zi = mri->zi[z+zk] ;
11240 for (yk = -whalf ; yk <= whalf ; yk++)
11241 {
11242 yi = mri->yi[y+yk] ;
11243 for (xk = -whalf ; xk <= whalf ; xk++)
11244 {
11245 xi = mri->xi[x+xk] ;
11246 if (MRIgetVoxVal(mri, xi, yi, zi,0) > 0)
11247 return(1) ;
11248 }
11249 }
11250 }
11251 return(0) ;
11252 }
11253 float
11254 MRIfindNearestNonzeroLocation(MRI *mri, int wsize, Real xr, Real yr, Real zr,
11255 int *pxv, int *pyv, int *pzv)
11256 {
11257 int xk, yk, zk, xi, yi, zi, whalf, x, y, z ;
11258 float dist, min_dist, min_val, dx, dy, dz ;
11259
11260 x = nint(xr) ; y = nint(yr) ; z = nint(zr) ;
11261 if (MRIvox(mri, x, y, z) > 0)
11262 return((float)MRIvox(mri, x, y, z)) ;
11263
11264 min_dist = 100000 ; min_val = 0 ;
11265 whalf = (wsize-1)/2 ;
11266 for (zk = -whalf ; zk <= whalf ; zk++)
11267 {
11268 zi = mri->zi[z+zk] ;
11269 dz = zi-zr ;
11270 for (yk = -whalf ; yk <= whalf ; yk++)
11271 {
11272 yi = mri->yi[y+yk] ;
11273 dy = yi-yr ;
11274 for (xk = -whalf ; xk <= whalf ; xk++)
11275 {
11276 xi = mri->xi[x+xk] ;
11277 dx = xi-xr ;
11278 if (MRIvox(mri, xi, yi, zi) > 0)
11279 {
11280 dist = sqrt(dx*dx + dy*dy + dz*dz) ;
11281 if (dist < min_dist)
11282 {
11283 if (pxv)
11284 { *pxv = xi ; *pyv = yi ; *pzv = zi ;}
11285 min_dist = dist ;
11286 min_val = MRIvox(mri, xi, yi, zi) ;
11287 }
11288 }
11289 }
11290 }
11291 }
11292 return(min_val) ;
11293 }
11294
11295 MRI *
11296 MRIfromTalairach(MRI *mri_src, MRI *mri_dst)
11297 {
11298 int x, y, z, xv, yv, zv ;
11299 Real xt, yt, zt, xn, yn, zn, val ;
11300
11301 if (!mri_dst)
11302 mri_dst = MRIclone(mri_src, NULL) ;
11303
11304 for (x = 0 ; x < mri_dst->width ; x++)
11305 {
11306 xn = (Real)x ;
11307 for (y = 0 ; y < mri_dst->height ; y++)
11308 {
11309 yn = (Real)y ;
11310 for (z = 0 ; z < mri_dst->depth ; z++)
11311 {
11312 zn = (Real)z ;
11313 MRIvoxelToTalairachVoxel(mri_src, xn, yn, zn, &xt, &yt, &zt) ;
11314 xv = nint(xt) ; yv = nint(yt) ; zv = nint(zt) ;
11315 if ((xv >= 0 && xv < mri_src->width) &&
11316 (yv >= 0 && yv < mri_src->height) &&
11317 (zv >= 0 && zv < mri_src->depth))
11318 {
11319 MRIsampleVolume(mri_src, xt, yt, zt, &val) ;
11320 MRIvox(mri_dst, x, y, z) = val ;
11321 }
11322 else
11323 MRIvox(mri_dst, x, y, z) = 0 ;
11324 }
11325 }
11326 }
11327
11328 return(mri_dst) ;
11329 }
11330 MRI *
11331 MRItoTalairach(MRI *mri_src, MRI *mri_dst)
11332 {
11333 int x, y, z, xv, yv, zv ;
11334 Real xt, yt, zt, xn, yn, zn, val ;
11335
11336 if (!mri_dst)
11337 mri_dst = MRIclone(mri_src, NULL) ;
11338
11339 for (x = 0 ; x < mri_dst->width ; x++)
11340 {
11341 xt = (Real)x ;
11342 for (y = 0 ; y < mri_dst->height ; y++)
11343 {
11344 yt = (Real)y ;
11345 for (z = 0 ; z < mri_dst->depth ; z++)
11346 {
11347 zt = (Real)z ;
11348 MRItalairachVoxelToVoxel(mri_src, xt, yt, zt, &xn, &yn, &zn) ;
11349 xv = nint(xn) ; yv = nint(yn) ; zv = nint(zt) ;
11350 if ((xv >= 0 && xv < mri_src->width) &&
11351 (yv >= 0 && yv < mri_src->height) &&
11352 (zv >= 0 && zv < mri_src->depth))
11353 {
11354 MRIsampleVolume(mri_src, xn, yn, zn, &val) ;
11355 MRIvox(mri_dst, x, y, z) = val ;
11356 }
11357 else
11358 MRIvox(mri_dst, x, y, z) = 0 ;
11359 }
11360 }
11361 }
11362
11363 return(mri_dst) ;
11364 }
11365 /*-------------------------------------------------------------------
11366 MRIlog10() - computes the log10 of the values at each voxel and
11367 frame. If a value is zero, the result is set to 10000000000.0. If
11368 the negflag is set, then -log10 is computed. The result is stored
11369 in outmri. If outmri is NULL, the output MRI is alloced and its
11370 pointer returned.
11371 ------------------------------------------------------------------*/
11372 MRI *MRIlog10(MRI *inmri, MRI *outmri, int negflag)
11373 {
11374 int c, r, s, f;
11375 float val;
11376
11377 if(outmri==NULL){
11378 outmri = MRIallocSequence(inmri->width, inmri->height, inmri->depth,
11379 MRI_FLOAT, inmri->nframes);
11380 MRIcopyHeader(inmri,outmri);
11381
11382 if(outmri==NULL){
11383 printf("ERROR: fMRIlog10: could not alloc\n");
11384 return(NULL);
11385 }
11386 }
11387 else{
11388 if(inmri->width != outmri->width ||
11389 inmri->height != outmri->height ||
11390 inmri->depth != outmri->depth ||
11391 inmri->nframes != outmri->nframes){
11392 printf("ERROR: MRIlog10: output dimension mismatch\n");
11393 return(NULL);
11394 }
11395 if(outmri->type != MRI_FLOAT){
11396 printf("ERROR: MRIlog10: structure passed is not MRI_FLOAT\n");
11397 return(NULL);
11398 }
11399 }
11400
11401 for(c=0; c < inmri->width; c++){
11402 for(r=0; r < inmri->height; r++){
11403 for(s=0; s < inmri->depth; s++){
11404 for(f=0; f < inmri->nframes; f++){
11405 val = MRIgetVoxVal(inmri, c, r, s, f);
11406 if(val == 0) MRIFseq_vox(outmri,c,r,s,f) = 10000000000.0;
11407 else{
11408 if(negflag){
11409 if(val < 0) MRIFseq_vox(outmri,c,r,s,f) = log10(fabs(val));
11410 else MRIFseq_vox(outmri,c,r,s,f) = -log10(val);
11411 }
11412 else{
11413 if(val < 0) MRIFseq_vox(outmri,c,r,s,f) = -log10(fabs(val));
11414 else MRIFseq_vox(outmri,c,r,s,f) = log10(val);
11415 }
11416 }
11417 }
11418 }
11419 }
11420 }
11421
11422 return(outmri);
11423 }
11424 /*---------------------------------------------------------------------
11425 MRIrandn() - fills an MRI structure with values sampled from a
11426 normal distribution with mean avg and standard devation stddev.
11427 --------------------------------------------------------*/
11428 MRI *MRIrandn(int ncols, int nrows, int nslices, int nframes,
11429 float avg, float stddev, MRI *mri)
11430 {
11431 int c, r, s, f;
11432
11433 if(mri==NULL){
11434 mri = MRIallocSequence(ncols, nrows, nslices, MRI_FLOAT, nframes);
11435 if(mri==NULL){
11436 printf("ERROR: MRIrandn: could not alloc\n");
11437 return(NULL);
11438 }
11439 }
11440 else{
11441 if(mri->width != ncols || mri->height != nrows ||
11442 mri->depth != nslices || mri->nframes != nframes){
11443 printf("ERROR: MRIrandn: dimension mismatch\n");
11444 return(NULL);
11445 }
11446 if(mri->type != MRI_FLOAT){
11447 printf("ERROR: MRIrandn: structure passed is not MRI_FLOAT\n");
11448 return(NULL);
11449 }
11450 }
11451
11452 for(f=0; f<nframes; f++){
11453 for(s=0; s<nslices; s++){
11454 for(r=0; r<nrows; r++){
11455 for(c=0; c<ncols; c++){
11456 MRIFseq_vox(mri,c,r,s,f) =
11457 stddev*PDFgaussian() + avg;
11458 }
11459 }
11460 }
11461 }
11462
11463 return(mri);
11464 }
11465 /*---------------------------------------------------------------------
11466 MRIrande() - fills an MRI structure with values sampled from an
11467 Erlang distribution with mean avg and order order. The variance
11468 will be (avg^2)/order. Theoretical distribution is
11469 r = order
11470 pdf(x) = r*((r*(x-avg+1))^(r-1)) * exp(-r*(x-avg+1)) / (r-1)!
11471 when order=1, this generates an exponential distribution.
11472 --------------------------------------------------------*/
11473 MRI *MRIrande(int ncols, int nrows, int nslices, int nframes,
11474 float avg, int order, MRI *mri)
11475 {
11476 int c, r, s, f;
11477
11478 if(mri==NULL){
11479 mri = MRIallocSequence(ncols, nrows, nslices, MRI_FLOAT, nframes);
11480 if(mri==NULL){
11481 printf("ERROR: MRIrande: could not alloc\n");
11482 return(NULL);
11483 }
11484 }
11485 else{
11486 if(mri->width != ncols || mri->height != nrows ||
11487 mri->depth != nslices || mri->nframes != nframes){
11488 printf("ERROR: MRIrande: dimension mismatch\n");
11489 return(NULL);
11490 }
11491 if(mri->type != MRI_FLOAT){
11492 printf("ERROR: MRIrande: structure passed is not MRI_FLOAT\n");
11493 return(NULL);
11494 }
11495 }
11496
11497 avg = avg - 1; // PDFrande() already has average of 1
11498 for(f=0; f<nframes; f++){
11499 for(s=0; s<nslices; s++){
11500 for(r=0; r<nrows; r++){
11501 for(c=0; c<ncols; c++){
11502 MRIFseq_vox(mri,c,r,s,f) =
11503 PDFerlang(order) + avg;
11504 }
11505 }
11506 }
11507 }
11508
11509 return(mri);
11510 }
11511 /*---------------------------------------------------------------------
11512 MRIdrand48() - fills an MRI structure with values sampled from a
11513 the drand48 uniform random number generator. The user must specify
11514 the min and max. Note: the stddev = (max-min)*0.289. If mri is NULL,
11515 it will alloc a MRI_FLOAT volume, otherwise, it will use the type
11516 as specified in mri.
11517 --------------------------------------------------------*/
11518 MRI *MRIdrand48(int ncols, int nrows, int nslices, int nframes,
11519 float min, float max, MRI *mri)
11520 {
11521 int c, r, s, f, n;
11522 float range, v;
11523 BUFTYPE *pmri=NULL;
11524 short *psmri=NULL;
11525 int *pimri=NULL;
11526 long *plmri=NULL;
11527 float *pfmri=NULL;
11528
11529 if(mri==NULL){
11530 mri = MRIallocSequence(ncols, nrows, nslices, MRI_FLOAT, nframes);
11531 if(mri==NULL){
11532 printf("ERROR: MRIdrand48: could not alloc\n");
11533 return(NULL);
11534 }
11535 }
11536 else{
11537 if(mri->width != ncols || mri->height != nrows ||
11538 mri->depth != nslices || mri->nframes != nframes){
11539 printf("ERROR: MRIdrand48: dimension mismatch\n");
11540 return(NULL);
11541 }
11542 }
11543
11544 range = max-min;
11545 n = 0;
11546 for(f=0; f<nframes; f++){
11547 for(s=0; s<nslices; s++){
11548 for(r=0; r<nrows; r++){
11549 switch(mri->type){
11550 case MRI_UCHAR: pmri = mri->slices[n][r]; break;
11551 case MRI_SHORT: psmri = (short *) mri->slices[n][r]; break;
11552 case MRI_INT: pimri = (int *) mri->slices[n][r]; break;
11553 case MRI_LONG: plmri = (long *) mri->slices[n][r]; break;
11554 case MRI_FLOAT: pfmri = (float *) mri->slices[n][r]; break;
11555 }
11556 for(c=0; c<ncols; c++) {
11557 v = range*drand48() + min;
11558 switch(mri->type){
11559 case MRI_UCHAR: *pmri++ = (BUFTYPE) v; break;
11560 case MRI_SHORT: *psmri++ = (short) v; break;
11561 case MRI_INT: *pimri++ = (int) v; break;
11562 case MRI_LONG: *plmri++ = (long) v; break;
11563 case MRI_FLOAT: *pfmri++ = (float) v; break;
11564 }
11565 }
11566 }
11567 n++;
11568 }
11569 }
11570
11571 return(mri);
11572 }
11573 /*---------------------------------------------------------------------
11574 MRIsampleCDF() - fills an MRI structure with values sampled from a
11575 the given CDF. See PDFsampleCDF(). CDF[n] is the probability that
11576 the random number is <= xCDF[n].
11577 --------------------------------------------------------------------*/
11578 MRI *MRIsampleCDF(int ncols, int nrows, int nslices, int nframes,
11579 double *xCDF, double *CDF, int nCDF, MRI *mri)
11580 {
11581 int c, r, s, f;
11582
11583 if(mri==NULL){
11584 mri = MRIallocSequence(ncols, nrows, nslices, MRI_FLOAT, nframes);
11585 if(mri==NULL){
11586 printf("ERROR: MRIsampleCDF: could not alloc\n");
11587 return(NULL);
11588 }
11589 }
11590 else{
11591 if(mri->width != ncols || mri->height != nrows ||
11592 mri->depth != nslices || mri->nframes != nframes){
11593 printf("ERROR: MRIsampleCDF: dimension mismatch\n");
11594 return(NULL);
11595 }
11596 if(mri->type != MRI_FLOAT){
11597 printf("ERROR: MRIsampleCDF: structure passed is not MRI_FLOAT\n");
11598 return(NULL);
11599 }
11600 }
11601
11602 for(f=0; f<nframes; f++){
11603 for(s=0; s<nslices; s++){
11604 for(r=0; r<nrows; r++){
11605 for(c=0; c<ncols; c++){
11606 MRIFseq_vox(mri,c,r,s,f) = PDFsampleCDF(xCDF,CDF,nCDF);
11607 }
11608 }
11609 }
11610 }
11611
11612 return(mri);
11613 }
11614 /*---------------------------------------------------------------------
11615 MRIconst() - fills an MRI structure with the given value. If mri is
11616 NULL, it will alloc a MRI_FLOAT volume, otherwise, it will use the type
11617 as specified in mri.
11618 --------------------------------------------------------*/
11619 MRI *MRIconst(int ncols, int nrows, int nslices, int nframes,
11620 float val, MRI *mri)
11621 {
11622 int c, r, s, f, n;
11623 BUFTYPE *pmri=NULL;
11624 short *psmri=NULL;
11625 int *pimri=NULL;
11626 long *plmri=NULL;
11627 float *pfmri=NULL;
11628
11629 if(mri==NULL){
11630 mri = MRIallocSequence(ncols, nrows, nslices, MRI_FLOAT, nframes);
11631 if(mri==NULL){
11632 printf("ERROR: MRIdconst: could not alloc\n");
11633 return(NULL);
11634 }
11635 }
11636 else{
11637 if(mri->width != ncols || mri->height != nrows ||
11638 mri->depth != nslices || mri->nframes != nframes){
11639 printf("ERROR: MRIconst: dimension mismatch\n");
11640 return(NULL);
11641 }
11642 }
11643
11644 n = 0;
11645 for(f=0; f<nframes; f++){
11646 for(s=0; s<nslices; s++){
11647 for(r=0; r<nrows; r++){
11648 switch(mri->type){
11649 case MRI_UCHAR: pmri = mri->slices[n][r]; break;
11650 case MRI_SHORT: psmri = (short *) mri->slices[n][r]; break;
11651 case MRI_INT: pimri = (int *) mri->slices[n][r]; break;
11652 case MRI_LONG: plmri = (long *) mri->slices[n][r]; break;
11653 case MRI_FLOAT: pfmri = (float *) mri->slices[n][r]; break;
11654 }
11655 for(c=0; c<ncols; c++) {
11656 switch(mri->type){
11657 case MRI_UCHAR: *pmri++ = (BUFTYPE) val; break;
11658 case MRI_SHORT: *psmri++ = (short) val; break;
11659 case MRI_INT: *pimri++ = (int) val; break;
11660 case MRI_LONG: *plmri++ = (long) val; break;
11661 case MRI_FLOAT: *pfmri++ = (float) val; break;
11662 }
11663 }
11664 }
11665 n++;
11666 }
11667 }
11668
11669 return(mri);
11670 }
11671 /*--------------------------------------------------------------*/
11672
11673 int
11674 MRInormalizeSequence(MRI *mri, float target)
11675 {
11676 int x, y, z, frame ;
11677 double norm ;
11678 Real val ;
11679
11680 for (x = 0 ; x < mri->width ; x++)
11681 {
11682 for (y = 0 ; y < mri->height ; y++)
11683 {
11684 for (z = 0 ; z < mri->depth ; z++)
11685 {
11686 for (frame = 0, norm = 0 ; frame < mri->nframes ; frame++)
11687 {
11688 MRIsampleVolumeFrame(mri, x, y, z, frame, &val) ;
11689 norm += (val*val) ;
11690 }
11691 norm = sqrt(norm) / target ;
11692 if (FZERO(norm))
11693 norm = 1 ;
11694 for (frame = 0 ; frame < mri->nframes ; frame++)
11695 {
11696 switch (mri->type)
11697 {
11698 default:
11699 ErrorReturn
11700 (ERROR_UNSUPPORTED,
11701 (ERROR_UNSUPPORTED,
11702 "MRInormalizeSequence: unsupported input type %d",
11703 mri->type)) ;
11704 break ;
11705 case MRI_SHORT:
11706 MRISseq_vox(mri, x, y, z, frame) =
11707 MRISseq_vox(mri, x, y, z, frame) / norm ;
11708 break ;
11709 case MRI_FLOAT:
11710 MRIFseq_vox(mri, x, y, z, frame) /= norm ;
11711 break ;
11712 case MRI_UCHAR:
11713 MRIseq_vox(mri, x, y, z, frame) /= norm ;
11714 break ;
11715 }
11716 }
11717 }
11718 }
11719 }
11720
11721 return(NO_ERROR) ;
11722 }
11723
11724 double
11725 MRImeanInLabel(MRI *mri_src, MRI *mri_labeled, int label)
11726 {
11727 int x, y, z, nvox, l ;
11728 double mean = 0.0 ;
11729 float val ;
11730
11731 nvox = 0 ;
11732 for (x = 0 ; x < mri_src->width ; x++)
11733 {
11734 for (y = 0 ; y < mri_src->height ; y++)
11735 {
11736 for (z = 0 ; z < mri_src->depth ; z++)
11737 {
11738 l = nint(MRIgetVoxVal(mri_labeled, x, y, z, 0)) ;
11739 if (l == label)
11740 {
11741 val = MRIgetVoxVal(mri_src, x, y, z, 0) ;
11742 mean += val ;
11743 nvox++ ;
11744 }
11745 }
11746 }
11747 }
11748 if (!nvox)
11749 nvox = 1 ;
11750 return(mean/nvox) ;
11751 }
11752
11753 MRI *
11754 MRImakePositive(MRI *mri_src, MRI *mri_dst)
11755 {
11756 float fmin, fmax, val ;
11757 int x, y, z,f ;
11758
11759 MRIvalRange(mri_src, &fmin, &fmax) ;
11760 mri_dst = MRIcopy(mri_src, mri_dst) ;
11761 if (fmin >= 0)
11762 return(mri_dst) ;
11763
11764 for (f = 0 ; f < mri_dst->nframes ; f++)
11765 {
11766 for (x = 0 ; x < mri_dst->width ; x++)
11767 {
11768 for (y = 0 ; y < mri_dst->height ; y++)
11769 {
11770 for (z = 0 ; z < mri_dst->depth ; z++)
11771 {
11772 val = MRIgetVoxVal(mri_src, x, y, z, f) ;
11773 val -= fmin ;
11774 MRIsetVoxVal(mri_dst, x, y, z, f, val) ;
11775 }
11776 }
11777 }
11778 }
11779
11780 return(mri_dst) ;
11781 }
11782 MRI *
11783 MRIeraseNegative(MRI *mri_src, MRI *mri_dst)
11784 {
11785 int x, y, z ;
11786 float val ;
11787
11788 mri_dst = MRIcopy(mri_src, mri_dst) ;
11789
11790 for (x = 0 ; x < mri_src->width ; x++)
11791 {
11792 for (y = 0 ; y < mri_src->height ; y++)
11793 {
11794 for (z = 0 ; z < mri_src->depth ; z++)
11795 {
11796 val = MRIgetVoxVal(mri_src, x, y, z, 0) ;
11797 if (val < 0)
11798 MRIsetVoxVal(mri_dst, x, y, z, 0, 0) ;
11799 }
11800 }
11801 }
11802 return(mri_dst) ;
11803 }
11804 int
11805 MRIsampleVolumeSlice
11806 (MRI *mri, Real x, Real y, Real z, Real *pval, int slice_direction)
11807 {
11808 int OutOfBounds;
11809 int xm, xp, ym, yp, zm, zp, width, height, depth ;
11810 Real val, xmd, ymd, xpd, ypd ; /* d's are distances */
11811 Real val11, val12, val21, val22 ;
11812
11813 if (FEQUAL((int)x,x) && FEQUAL((int)y,y) && FEQUAL((int)z, z))
11814 return(MRIsampleVolumeType(mri, x, y, z, pval, SAMPLE_NEAREST)) ;
11815
11816 OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
11817 if(OutOfBounds == 1){
11818 /* unambiguously out of bounds */
11819 *pval = 0.0;
11820 return(NO_ERROR) ;
11821 }
11822
11823 width = mri->width ; height = mri->height ; depth = mri->depth ;
11824
11825 if (x >= width) x = width - 1.0 ;
11826 if (y >= height) y = height - 1.0 ;
11827 if (z >= depth) z = depth - 1.0 ;
11828 if (x < 0.0) x = 0.0 ;
11829 if (y < 0.0) y = 0.0 ;
11830 if (z < 0.0) z = 0.0 ;
11831
11832 xm = MAX((int)x, 0) ;
11833 xp = MIN(width-1, xm+1) ;
11834 ym = MAX((int)y, 0) ;
11835 yp = MIN(height-1, ym+1) ;
11836 zm = MAX((int)z, 0) ;
11837 zp = MIN(depth-1, zm+1) ;
11838
11839 xmd = x - (float)xm ;
11840 ymd = y - (float)ym ;
11841 xpd = (1.0f - xmd) ;
11842 ypd = (1.0f - ymd) ;
11843
11844 switch (slice_direction)
11845 {
11846 case MRI_CORONAL:
11847 zp = nint(z) ;
11848 val11 = MRIgetVoxVal(mri, xm, ym, zp, 0) ;
11849 val12 = MRIgetVoxVal(mri, xm, yp, zp, 0) ;
11850 val21 = MRIgetVoxVal(mri, xp, ym, zp, 0) ;
11851 val22 = MRIgetVoxVal(mri, xp, yp, zp, 0) ;
11852 *pval = val = xpd * ypd * val11 + xpd * ymd * val12 + xmd * ypd * val21 +
11853 xmd * ymd * val22 ;
11854 break ;
11855 default:
11856 ErrorReturn
11857 (ERROR_UNSUPPORTED,
11858 (ERROR_UNSUPPORTED,
11859 "MRIsampleVolumeSlice: unsupported direction %d", slice_direction)) ;
11860 break ;
11861 }
11862 return(NO_ERROR) ;
11863 }
11864
11865 float
11866 MRIvoxelsInLabelWithPartialVolumeEffects(MRI *mri, MRI *mri_vals, int label)
11867 {
11868 float volume, vox_vol ;
11869 int x, y, z, nbr_label_counts[MAX_CMA_LABELS];
11870 int label_counts[MAX_CMA_LABELS], this_label, border;
11871 int nbr_label, max_count, vox_label ;
11872 MRI *mri_border ;
11873 float label_means[MAX_CMA_LABELS], pv, mean_label, mean_nbr, val ;
11874
11875 vox_vol = mri->xsize*mri->ysize*mri->zsize ;
11876
11877 /* first find border voxels */
11878 mri_border = MRImarkLabelBorderVoxels(mri, NULL, label, 1, 1) ;
11879 if (DIAG_VERBOSE_ON && (Gdiag & DIAG_WRITE))
11880 MRIwrite(mri_border, "b.mgz") ;
11881 volume = 0 ;
11882 for (x = 0 ; x < mri->width ; x++)
11883 {
11884 for (y = 0 ; y < mri->height ; y++)
11885 {
11886 for (z = 0 ; z < mri->depth ; z++)
11887 {
11888 if (x == Gx && y == Gy && z == Gz)
11889 DiagBreak() ;
11890 vox_label = MRIgetVoxVal(mri, x, y, z, 0) ;
11891 border = MRIgetVoxVal(mri_border, x, y, z, 0) ;
11892 if ((vox_label != label) && (border == 0))
11893 continue ;
11894
11895 if (border == 0)
11896 volume += vox_vol ;
11897 else /* compute partial volume */
11898 {
11899 MRIcomputeLabelNbhd
11900 (mri, mri_vals, x, y, z,
11901 nbr_label_counts, label_means, 1, MAX_CMA_LABELS) ;
11902 MRIcomputeLabelNbhd
11903 (mri, mri_vals, x, y, z,
11904 label_counts, label_means, 7, MAX_CMA_LABELS) ;
11905 val =
11906 MRIgetVoxVal(mri_vals, x, y, z, 0) ; /* compute partial
11907 volume based on
11908 intensity */
11909 mean_label = label_means[vox_label] ;
11910 nbr_label = -1 ; max_count = 0 ;
11911 /* look for a label that is a nbr and is
11912 on the other side of val from the label mean */
11913 for (this_label = 0 ;
11914 this_label < MAX_CMA_LABELS ;
11915 this_label++)
11916 {
11917 if (this_label == vox_label)
11918 continue ;
11919 if (nbr_label_counts[this_label] == 0) /* not a nbr */
11920 continue ;
11921
11922 if ((label_counts[this_label] > max_count) &&
11923 ((label_means[this_label] - val) *
11924 (mean_label - val) < 0))
11925 {
11926 max_count = label_means[this_label] ;
11927 nbr_label = this_label ;
11928 }
11929 }
11930 if (vox_label != label &&
11931 nbr_label != label) /* this struct not in voxel */
11932 continue ;
11933
11934 if (max_count == 0) /* couldn't find an appropriate label */
11935 volume += vox_vol ;
11936 else /* compute partial volume pct */
11937 {
11938 mean_nbr = label_means[nbr_label] ;
11939 pv = (val - mean_nbr) / (mean_label - mean_nbr) ;
11940 if (vox_label == label)
11941 volume += vox_vol * pv ;
11942 else
11943 volume += vox_vol * (1-pv) ;
11944 if (pv < 0 || pv > 1)
11945 DiagBreak() ;
11946 }
11947 }
11948 }
11949 }
11950 }
11951
11952 MRIfree(&mri_border) ;
11953 return(volume) ;
11954 }
11955
11956 MRI *
11957 MRImakeDensityMap(MRI *mri, MRI *mri_vals, int label, MRI *mri_dst)
11958 {
11959 float vox_vol, volume ;
11960 int x, y, z, nbr_label_counts[MAX_CMA_LABELS];
11961 int label_counts[MAX_CMA_LABELS], this_label, border;
11962 int nbr_label, max_count, vox_label ;
11963 MRI *mri_border ;
11964 float label_means[MAX_CMA_LABELS], pv, mean_label, mean_nbr, val ;
11965
11966 if (mri_dst == NULL)
11967 mri_dst = MRIalloc(mri->width, mri->height, mri->depth, MRI_FLOAT) ;
11968
11969 /* first find border voxels */
11970 mri_border = MRImarkLabelBorderVoxels(mri, NULL, label, 1, 1) ;
11971 if (DIAG_VERBOSE_ON && (Gdiag & DIAG_WRITE))
11972 MRIwrite(mri_border, "b.mgz") ;
11973 vox_vol = mri->xsize*mri->ysize*mri->zsize ;
11974 for (x = 0 ; x < mri->width ; x++)
11975 {
11976 for (y = 0 ; y < mri->height ; y++)
11977 {
11978 for (z = 0 ; z < mri->depth ; z++)
11979 {
11980 if (x == Gx && y == Gy && z == Gz)
11981 DiagBreak() ;
11982 vox_label = MRIgetVoxVal(mri, x, y, z, 0) ;
11983 border = MRIgetVoxVal(mri_border, x, y, z, 0) ;
11984 if ((vox_label != label) && (border == 0))
11985 continue ;
11986
11987 volume = vox_vol ;
11988 if (border == 0)
11989 volume = vox_vol ;
11990 else /* compute partial volume */
11991 {
11992 MRIcomputeLabelNbhd
11993 (mri, mri_vals, x, y, z,
11994 nbr_label_counts, label_means, 1, MAX_CMA_LABELS) ;
11995 MRIcomputeLabelNbhd
11996 (mri, mri_vals, x, y, z,
11997 label_counts, label_means, 7, MAX_CMA_LABELS) ;
11998 val =
11999 MRIgetVoxVal(mri_vals, x, y, z, 0) ; /* compute partial
12000 volume based on
12001 intensity */
12002 mean_label = label_means[vox_label] ;
12003 nbr_label = -1 ; max_count = 0 ;
12004 /* look for a label that is a nbr and is
12005 on the other side of val from the label mean */
12006 for (this_label = 0 ;
12007 this_label < MAX_CMA_LABELS ;
12008 this_label++)
12009 {
12010 if (this_label == vox_label)
12011 continue ;
12012 if (nbr_label_counts[this_label] == 0) /* not a nbr */
12013 continue ;
12014
12015 if ((label_counts[this_label] > max_count) &&
12016 ((label_means[this_label] - val) *
12017 (mean_label - val) < 0))
12018 {
12019 max_count = label_means[this_label] ;
12020 nbr_label = this_label ;
12021 }
12022 }
12023 if (vox_label != label &&
12024 nbr_label != label) /* this struct not in voxel */
12025 continue ;
12026
12027 if (max_count > 0) /* compute partial volume pct */
12028 {
12029 mean_nbr = label_means[nbr_label] ;
12030 pv = (val - mean_nbr) / (mean_label - mean_nbr) ;
12031 if (vox_label == label)
12032 volume = pv*vox_vol ;
12033 else
12034 volume = vox_vol * (1-pv) ;
12035 if (pv < 0 || pv > 1)
12036 DiagBreak() ;
12037 }
12038 }
12039 MRIsetVoxVal(mri_dst, x, y, z, 0, volume) ;
12040 }
12041 }
12042 }
12043
12044 MRIfree(&mri_border) ;
12045 return(mri_dst) ;
12046 }
12047
12048 MRI *
12049 MRImarkLabelBorderVoxels
12050 (MRI *mri_src, MRI *mri_dst, int label, int mark, int six_connected)
12051 {
12052 int x, y, z, xk, yk, zk, xi, yi, zi, this_label, that_label, border ;
12053
12054 if (mri_dst == NULL)
12055 mri_dst = MRIclone(mri_src, NULL) ;
12056
12057 for (x = 0 ; x < mri_src->width ; x++)
12058 {
12059 for (y = 0 ; y < mri_src->height ; y++)
12060 {
12061 for (z = 0 ; z < mri_src->depth ; z++)
12062 {
12063 this_label = MRIgetVoxVal(mri_src, x, y, z, 0) ;
12064 border = 0 ;
12065 for (xk = -1 ; xk <= 1 && !border ; xk++)
12066 {
12067 xi = mri_src->xi[x+xk] ;
12068 for (yk = -1 ; yk <= 1 && !border ; yk++)
12069 {
12070 yi = mri_src->yi[y+yk] ;
12071 for (zk = -1 ; zk <= 1 ; zk++)
12072 {
12073 if (six_connected && (abs(xk)+abs(yk)+abs(zk) != 1))
12074 continue ;
12075 zi = mri_src->zi[z+zk] ;
12076 that_label = MRIgetVoxVal(mri_src, xi, yi, zi, 0) ;
12077 if (((this_label == label) &&
12078 (that_label != label)) ||
12079 ((this_label != label) &&
12080 (that_label == label)))
12081 {
12082 border = 1 ;
12083 break ;
12084 }
12085 }
12086 }
12087 }
12088 if (border)
12089 MRIsetVoxVal(mri_dst, x, y, z, 0, mark) ;
12090 }
12091 }
12092 }
12093
12094 return(mri_dst) ;
12095 }
12096
12097 int
12098 MRIcomputeLabelNbhd
12099 (MRI *mri_labels, MRI *mri_vals,
12100 int x, int y, int z, int *label_counts, float *label_means,
12101 int whalf, int max_labels)
12102 {
12103 int xi, yi, zi, xk, yk, zk, label ;
12104 float val ;
12105
12106 memset(label_counts, 0, sizeof(label_counts[0])*max_labels) ;
12107 memset(label_means, 0, sizeof(label_means[0])*max_labels) ;
12108 for (xk = -whalf ; xk <= whalf ; xk++)
12109 {
12110 xi = mri_vals->xi[x+xk] ;
12111 for (yk = -whalf ; yk <= whalf ; yk++)
12112 {
12113 yi = mri_vals->yi[y+yk] ;
12114 for (zk = -whalf ; zk <= whalf ; zk++)
12115 {
12116 zi = mri_vals->zi[z+zk] ;
12117 label = MRIgetVoxVal(mri_labels, xi, yi, zi, 0) ;
12118 val = MRIgetVoxVal(mri_vals, xi, yi, zi, 0) ;
12119 label_counts[label]++ ;
12120 label_means[label] += val ;
12121 }
12122 }
12123 }
12124
12125 for (label = 0 ; label < max_labels ; label++)
12126 if (label_counts[label] > 0)
12127 label_means[label] /= label_counts[label] ;
12128 return(NO_ERROR) ;
12129 }
12130
12131 /**
12132 * void MRIcalCRASforSampledVolume
12133 *
12134 * @param src MRI* volume
12135 * @param dst MRI* sampled volume
12136 * @param pr output ptr to c_r
12137 * @param pa output ptr to c_a
12138 * @param ps output ptr to c_s
12139 */
12140 void MRIcalcCRASforSampledVolume
12141 (MRI *src, MRI *dst, Real *pr, Real *pa, Real *ps)
12142 {
12143 // get the voxel position of the "center" voxel of the dst in the src volume
12144 // i.e. sample is 2, then get the voxel position 64 in the src volume
12145 // thus it is 128.5 (in the src) for 64 (in the dst)
12146 Real sx, sy, sz;
12147 int dx, dy, dz;
12148 int samplex, sampley, samplez;
12149
12150 // error check first
12151 if ((src->width)%(dst->width) != 0)
12152 ErrorExit
12153 (ERROR_BADPARM, "src width must be integer multiple of dst width");
12154 if ((src->height)%(dst->height) != 0)
12155 ErrorExit
12156 (ERROR_BADPARM, "src height must be integer multiple of dst height");
12157 if ((src->depth)%(dst->depth) != 0)
12158 ErrorExit
12159 (ERROR_BADPARM, "src depth must be integer multiple of dst depth");
12160
12161 samplex = src->width/dst->width;
12162 sampley = src->height/dst->height;
12163 samplez = src->depth/dst->depth;
12164
12165 // "center" voxel position in dst
12166 dx = dst->width/2; // if the length is odd,
12167 // then it does the right thing (truncation)
12168 dy = dst->height/2;// i.e. 0 1 2 then 3/2 = 1, 0 1 2 3 then 4/2=2
12169 dz = dst->depth/2;
12170 // corresponding position in src
12171 sx = dx*samplex + (samplex-1.)/2.; // ((dx*samplex - 0.5) +
12172 // ((dx+1)*samplex -0.5))/2.
12173 sy = dy*sampley + (sampley-1.)/2.;
12174 sz = dz*samplez + (samplez-1.)/2.;
12175 //
12176 // Example
12177 // | 0 1 2 | 3 4 5 | 6 7 8 | -(sample by 3).
12178 // | 0 | 1 | 2 |
12179 // 1 (3/2) in dst corresponds
12180 // to 1*3+(3-1)/2 = 4! in src
12181 //
12182 // | 0 1 2 3 | 4 5 6 7 | -(sample by 4)->0 1
12183 // | 0 | 1 | 1 (2/2) in dst corresponds
12184 // to 1*4+(4-1)/2 = 5.5 in src
12185
12186 // get ras of the "center" voxel position in dst
12187 if (!src->i_to_r__)
12188 {
12189 src->i_to_r__ = extract_i_to_r(src);
12190 src->r_to_i__ = extract_r_to_i(src);
12191 }
12192 TransformWithMatrix(src->i_to_r__, sx, sy, sz, pr, pa, ps);
12193
12194 if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
12195 fprintf(stderr, "c_ras for sample volume is (%f, %f, %f) "
12196 "compared with the src (%f, %f, %f)\n",
12197 *pr, *pa, *ps, src->c_r, src->c_a, src->c_s);
12198 }
12199
12200 /**
12201 * MRIcalcCRASfroExtractedVolume
12202 *
12203 * @param src MRI* src volume
12204 * @param x0 src start position of the extraction region
12205 * @param y0
12206 * @param z0
12207 * @param x1 target start position of the extracted region
12208 * @param y1
12209 * @param z1
12210 * @param pr output Real* c_r
12211 * @param pa c_a
12212 * @param ps c_s
12213 */
12214 void MRIcalcCRASforExtractedVolume
12215 (MRI *src, MRI *dst, int x0, int y0, int z0, int x1, int y1, int z1,
12216 Real *pr, Real *pa, Real *ps)
12217 {
12218 Real cx, cy, cz;
12219 // The "center" voxel position of the
12220 // extracted volume in the original voxel position
12221 // x1 of dst corresponds to x0 of src
12222 // Thus, the "center" of dst corresponds to that of the src is
12223 cx = x0+(Real)dst->width/2 - x1; // integer divide cutoff extra
12224 cy = y0+(Real)dst->height/2 - y1;
12225 cz = z0+(Real)dst->depth/2 - z1;
12226
12227 if (!src->i_to_r__)
12228 {
12229 src->i_to_r__ = extract_i_to_r(src);
12230 src->r_to_i__ = extract_r_to_i(src);
12231 }
12232 TransformWithMatrix(src->i_to_r__, cx, cy, cz, pr, pa, ps);
12233 // got where the RAS position of the new volume position
12234 // we have to translate so that we can get the same value
12235 // under the new volume
12236
12237 if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
12238 fprintf(stderr, "c_ras for sample volume is (%f, %f, %f) "
12239 "compared with the src (%f, %f, %f)\n",
12240 *pr, *pa, *ps, src->c_r, src->c_a, src->c_s);
12241 }
12242
12243 // transform is the hires to lowres vox-to-vox transform
12244 void MRIcalcCRASforHiresVolume
12245 (MRI *hires, MRI *lowres, MATRIX *vox_xform, Real *pr, Real *pa, Real *ps)
12246 {
12247 // get where the center of hires volume goes to in the lowres volume
12248 Real cx, cy, cz;
12249 Real dx, dy, dz;
12250 cx = hires->width/2; cy = hires->height/2; cz = hires->depth/2;
12251 TransformWithMatrix(vox_xform, cx, cy, cz, &dx, &dy, &dz);
12252 // get the c_ras values for this position
12253 TransformWithMatrix(lowres->i_to_r__, dx, dy, dz, pr, pa, ps);
12254 // if we use this c_ras value for the transformed hires volume, then
12255 // the volume will be containing the original points
12256 }
12257
12258 // transform is src to dst vox to vox transform
12259 // return rotated src whose center is at the right place
12260 // Just rotating the original volume make the non-zero voxels go
12261 // outside of the rotated volume. This routine will keep the
12262 // center of the rotated volume at the right location.
12263 MRI *
12264 MRIsrcTransformedCentered
12265 (MRI *src, MRI *dst, MATRIX *stod_voxtovox, int interp_method)
12266 {
12267 Real cr, ca, cs;
12268 MRI *rotated;
12269 MATRIX *stosrotVox;
12270 MATRIX *tmp;
12271
12272 // get the c_ras value for the rotated volume
12273 MRIcalcCRASforHiresVolume(src, dst, stod_voxtovox, &cr, &ca, &cs);
12274 rotated = MRIclone(src, NULL);
12275 // reset the rotated volume
12276 rotated->c_r = cr;
12277 rotated->c_a = ca;
12278 rotated->c_s = cs;
12279 MRIreInitCache(rotated); // recalculate the transform
12280 // the map is the following
12281 //
12282 // src --> RAS
12283 // | |
12284 // |given |
12285 // V V
12286 // dst --> RAS
12287 // | |
12288 // | (identity)
12289 // V |
12290 // src' --> RAS
12291 // new rotated src volume whose center is at the right location
12292 //
12293 tmp = MatrixMultiply(rotated->r_to_i__, dst->i_to_r__, NULL);
12294 stosrotVox = MatrixMultiply(tmp, stod_voxtovox, NULL);
12295 MRIlinearTransformInterp(src, rotated, stosrotVox, interp_method);
12296 return rotated;
12297 }
12298
12299 ////////////////////////////////////////////////////////////////////////////
12300 // No sample method ////////////////////////////////////////////////////////
12301 // using the src and orig_dst to modify
12302 // the direction cosines and c_(ras) value
12303 // so that it will be rotated in the RAS space but no pixel is sampled
12304 MRI *MRITransformedCenteredMatrix(MRI *src, MRI *orig_dst, MATRIX *m_L)
12305 {
12306 LTA *lta ;
12307 MRI *mri_dst ;
12308
12309 lta = LTAalloc(1, NULL) ;
12310 MatrixCopy(m_L, lta->xforms[0].m_L) ;
12311 lta->type = LINEAR_VOX_TO_VOX ;
12312 mri_dst = MRITransformedCentered(src, orig_dst, lta) ;
12313 LTAfree(<a) ;
12314 return(mri_dst) ;
12315 }
12316 MRI *MRITransformedCentered(MRI *src, MRI *orig_dst, LTA *lta)
12317 {
12318 MRI *dst = 0;
12319 Real cx, cy, cz;
12320 Real cr, ca, cs;
12321 MATRIX *dstToRas = 0;
12322 MATRIX *SI = 0;
12323 MATRIX *D = 0;
12324 LT *tran = <a->xforms[0];
12325
12326 dst = MRIcopy(src, NULL);
12327
12328 if (lta->num_xforms > 1)
12329 ErrorExit(ERROR_BADPARM, "The LTA contains more than one transforms.");
12330
12331 // first verify the consistency of the transform stored geometry vs. argument
12332 if (tran->dst.valid == 1)
12333 {
12334 // compare the one with orig_dst to the stored one
12335 VG dstvg, storedvg;
12336 getVolGeom(orig_dst, &dstvg);
12337 storedvg.valid = tran->dst.valid;
12338 storedvg.width = tran->dst.width;
12339 storedvg.height = tran->dst.height;
12340 storedvg.depth = tran->dst.depth;
12341 storedvg.xsize = tran->dst.xsize;
12342 storedvg.ysize = tran->dst.ysize;
12343 storedvg.zsize = tran->dst.zsize;
12344 storedvg.x_r = tran->dst.x_r;
12345 storedvg.x_a = tran->dst.x_a;
12346 storedvg.x_s = tran->dst.x_s;
12347 storedvg.y_r = tran->dst.y_r;
12348 storedvg.y_a = tran->dst.y_a;
12349 storedvg.y_s = tran->dst.y_s;
12350 storedvg.z_r = tran->dst.z_r;
12351 storedvg.z_a = tran->dst.z_a;
12352 storedvg.z_s = tran->dst.z_s;
12353 storedvg.c_r = tran->dst.c_r;
12354 storedvg.c_a = tran->dst.c_a;
12355 storedvg.c_s = tran->dst.c_s;
12356 if (!vg_isEqual(&dstvg, &storedvg))
12357 {
12358 fprintf
12359 (stderr,
12360 "WARNING: stored destination volume for the "
12361 "transform differes from the argument.");
12362 }
12363 }
12364 if (tran->src.valid == 1)
12365 {
12366 // compare the one with orig_dst to the stored one
12367 VG srcvg, storedvg;
12368 getVolGeom(src, &srcvg);
12369 storedvg.valid = tran->src.valid;
12370 storedvg.width = tran->src.width;
12371 storedvg.height = tran->src.height;
12372 storedvg.depth = tran->src.depth;
12373 storedvg.xsize = tran->src.xsize;
12374 storedvg.ysize = tran->src.ysize;
12375 storedvg.zsize = tran->src.zsize;
12376 storedvg.x_r = tran->src.x_r;
12377 storedvg.x_a = tran->src.x_a;
12378 storedvg.x_s = tran->src.x_s;
12379 storedvg.y_r = tran->src.y_r;
12380 storedvg.y_a = tran->src.y_a;
12381 storedvg.y_s = tran->src.y_s;
12382 storedvg.z_r = tran->src.z_r;
12383 storedvg.z_a = tran->src.z_a;
12384 storedvg.z_s = tran->src.z_s;
12385 storedvg.c_r = tran->src.c_r;
12386 storedvg.c_a = tran->src.c_a;
12387 storedvg.c_s = tran->src.c_s;
12388 if (!vg_isEqual(&srcvg, &storedvg))
12389 {
12390 fprintf(stderr, "WARNING: stored destination volume for the "
12391 "transform differes from the argument.");
12392 }
12393 }
12394
12395 if (lta->type == LINEAR_RAS_TO_RAS)
12396 {
12397 MATRIX *tmp;
12398 //
12399 // src --> RAS
12400 // | |
12401 // | M | Y
12402 // V V
12403 // orig_dst --> RAS
12404 //
12405 // transform it to the vox-to-vox
12406 // now calculate M
12407 tmp = MatrixMultiply(tran->m_L, src->i_to_r__, NULL);
12408 MatrixFree(&tran->m_L);
12409 tran->m_L = MatrixMultiply(orig_dst->r_to_i__, tmp, NULL);
12410 MatrixFree(&tmp);
12411 lta->type = LINEAR_VOX_TO_VOX;
12412 }
12413
12414 if (lta->type != LINEAR_VOX_TO_VOX)
12415 ErrorExit
12416 (ERROR_BADPARM,
12417 "The LTA does not contain LINEASR_RAS_TO_RAS nor LINEAR_VOX_TO_VOX.");
12418 //
12419 // src --> RAS
12420 // | |
12421 // | M | Y
12422 // V V
12423 // orig_dst --> RAS
12424 // | |
12425 // | (identity)
12426 // V |
12427 // dst --> RAS
12428 // new rotated src volume whose center is at the right location
12429 // ?
12430 // we try src->dst is identity (no sampling)
12431 //
12432 // Y = i_to_r(orig_dst) * M * r_to_i(src)
12433 //
12434 // Thus we have simpler picture
12435 //
12436 // src -----> RAS
12437 // | |
12438 // (identity) (Y)
12439 // | |
12440 // V V
12441 // dst -----> RAS
12442 // (???)
12443 //
12444 // Thus
12445 // (???) = Y * i_to_r(src)
12446 // = i_to_r(orig_dst) * M * r_to_i(src) * i_to_r(src)
12447 //
12448 // (???) = i_to_r(orig_dst) * M (A)
12449 //
12450 // Thus we derive direction cosines and c_(ras) from ???
12451 //
12452 // (???) = ( X T ) ( S 0 ) where S is the voxel size
12453 // ( 0 1 ) ( 0 1 )
12454 // or
12455 // ( X T ) = (???) * (S^(-1) 0 ) (B)
12456 // ( 0 1 ) ( 0 1 )
12457 //
12458 //
12459 dstToRas = MatrixMultiply(orig_dst->i_to_r__, tran->m_L, NULL);
12460
12461 SI = MatrixAlloc(4, 4, MATRIX_REAL);
12462 *MATRIX_RELT(SI, 1, 1) = 1./dst->xsize ;
12463 *MATRIX_RELT(SI, 2, 2) = 1./dst->ysize ;
12464 *MATRIX_RELT(SI, 3, 3) = 1./dst->zsize ;
12465 *MATRIX_RELT(SI, 4, 4) = 1. ;
12466
12467 D = MatrixMultiply(dstToRas, SI, NULL);
12468
12469 dst->x_r = *MATRIX_RELT(D, 1, 1);
12470 dst->x_a = *MATRIX_RELT(D, 2, 1);
12471 dst->x_s = *MATRIX_RELT(D, 3, 1);
12472 dst->y_r = *MATRIX_RELT(D, 1, 2);
12473 dst->y_a = *MATRIX_RELT(D, 2, 2);
12474 dst->y_s = *MATRIX_RELT(D, 3, 2);
12475 dst->z_r = *MATRIX_RELT(D, 1, 3);
12476 dst->z_a = *MATRIX_RELT(D, 2, 3);
12477 dst->z_s = *MATRIX_RELT(D, 3, 3);
12478
12479 MatrixFree(&D);
12480 MatrixFree(&SI);
12481
12482 // c_ras is calculated by
12483 //
12484 // ( X T )(S 0)(dstwidth/2 ) = (c_r)
12485 // or i_to_r(orig_dst) * M * (dstwidth/2 ) = C'
12486 // ( 0 1 )(0 1)(dstheight/2) (c_a)
12487 // (dstheight/2)
12488 // (dstdepth/2 ) (c_s)
12489 // (dstdepth/2 )
12490 // ( 1 ) ( 1 ) ( 1 )
12491 //
12492 // This is the same as the original center point
12493 // is mapped to orig_dst and then obtaining
12494 // its ras position! (because src and dst has the
12495 // same volume size). The only difference
12496 // is its orientation with respect to orig_dst RAS. Good
12497 //
12498 // get where the center of hires volume goes to in the lowres volume
12499 cx = dst->width/2; cy = dst->height/2; cz = dst->depth/2;
12500 // get the c_ras values for this position
12501 TransformWithMatrix(dstToRas, cx, cy, cz, &cr, &ca, &cs);
12502 // if we use this c_ras value for the transformed hires volume, then
12503 // the volume will be containing the original points
12504 dst->c_r = cr;
12505 dst->c_a = ca;
12506 dst->c_s = cs;
12507
12508 // when you change the direction cosine, you have to do this
12509 MRIreInitCache(dst);
12510
12511 MatrixFree(&dstToRas);
12512
12513 return dst;
12514 }
12515 int
12516 MRIcropBoundingBox(MRI *mri, MRI_REGION *box)
12517 {
12518 box->x = MAX(0, box->x) ; box->y = MAX(0, box->y) ;box->z = MAX(0, box->z) ;
12519 box->dx = MIN(mri->width-box->x-1, box->dx) ;
12520 box->dy = MIN(mri->height-box->y-1, box->dy) ;
12521 box->dz = MIN(mri->depth-box->z-1, box->dz) ;
12522 return(NO_ERROR) ;
12523 }
12524
12525 MATRIX *
12526 MRIgetVoxelToVoxelXform(MRI *mri_src, MRI *mri_dst)
12527 {
12528 MATRIX *m_ras2vox_dst, *m_vox2ras_src, *m_vox2vox ;
12529
12530 m_vox2ras_src = MRIgetVoxelToRasXform(mri_src) ;
12531 m_ras2vox_dst = MRIgetRasToVoxelXform(mri_dst) ;
12532 m_vox2vox = MatrixMultiply(m_ras2vox_dst, m_vox2ras_src, NULL) ;
12533 MatrixFree(&m_vox2ras_src) ; MatrixFree(&m_ras2vox_dst) ;
12534 return(m_vox2vox) ;
12535 }
12536
12537 /*--------------------------------------------------------------
12538 MRIfovCol(mri) - computes the edge-to-edge FOV in the column
12539 direction. fov is in mm.
12540 -------------------------------------------------------------*/
12541 float MRIfovCol(MRI *mri)
12542 {
12543 MATRIX *M,*v,*a,*b,*d;
12544 float fov;
12545
12546 M = MRIgetVoxelToRasXform(mri) ;
12547 v = MatrixAlloc(4,1,MATRIX_REAL);
12548 v->rptr[1][4] = 1;
12549 v->rptr[1][1] = mri->width-1+0.5; // edge of last column
12550 a = MatrixMultiply(M,v,NULL); // xyz of last column
12551 v->rptr[1][1] = -0.5; // edge of first column
12552 b = MatrixMultiply(M,v,NULL); // xyz of first column
12553 d = MatrixSubtract(a,b,NULL); // xyz difference
12554 fov = VectorLen(d); // fov is in mm
12555 MatrixFree(&M);
12556 MatrixFree(&v);
12557 MatrixFree(&a);
12558 MatrixFree(&b);
12559 MatrixFree(&d);
12560
12561 //printf("MRIfovCol() %g\n",fov);
12562 return(fov);
12563 }
12564 /* ---------------------------------------------------------------------
12565 MRIorientationStringToDircos() - sets the direction cosines of to
12566 be that dictated by the Orientation String. This is helpful for
12567 setting the direction cosines when the information is not present
12568 in a header (eg, with FSL analyze format). The Orientation String
12569 is a three character string indicating the primary direction of
12570 each axis in the 3d matrix. The characters can be L,R,A,P,I,S. The
12571 string must be valid (see MRIcheckOrientationString). If the string
12572 is not valid, the errors are printed and a 1 is returned. Eg, of
12573 valid strings are RAS, LPS, LAI. Invalid are ABC (B and C are not
12574 valid), RAP (the AP axis is represented twice, IS axis not at all).
12575 There are 48 possible valid strings. This should only be used to
12576 get the direction cosines "about right".
12577 --------------------------------------------------------------------*/
12578
12579 int MRIorientationStringToDircos(MRI *mri, char *ostr)
12580 {
12581 int c,r=0;
12582 double Mdc[3][3], v=0;
12583 char *errstr;
12584
12585 errstr = MRIcheckOrientationString(ostr);
12586 if(errstr != NULL){
12587 printf("ERROR: in orientation string %s\n",ostr);
12588 printf("%s",errstr);
12589 free(errstr);
12590 return(1);
12591 }
12592
12593 // Initialize the matrix of direction cosines (Mdc)
12594 for(c=0; c<3; c++) for(r=0; r<3; r++) Mdc[r][c] = 0;
12595
12596 // Each column of Mdc corresponds to a different axis which corresonds to
12597 // a different letter in the orientation string. The value of the letter
12598 // determine which row of the Mdc will be affected.
12599 for(c=0; c<3; c++){
12600 switch(toupper(ostr[c])){
12601 case 'L': r=0; v=-1; break;
12602 case 'R': r=0; v=+1; break;
12603 case 'P': r=1; v=-1; break;
12604 case 'A': r=1; v=+1; break;
12605 case 'I': r=2; v=-1; break;
12606 case 'S': r=2; v=+1; break;
12607 }
12608 Mdc[r][c] = v;
12609 }
12610 mri->x_r = Mdc[0][0];
12611 mri->x_a = Mdc[1][0];
12612 mri->x_s = Mdc[2][0];
12613
12614 mri->y_r = Mdc[0][1];
12615 mri->y_a = Mdc[1][1];
12616 mri->y_s = Mdc[2][1];
12617
12618 mri->z_r = Mdc[0][2];
12619 mri->z_a = Mdc[1][2];
12620 mri->z_s = Mdc[2][2];
12621
12622 return(0);
12623 }
12624 /* ---------------------------------------------------------------
12625 MRIcheckOrientationString() - this checks the orientation string
12626 to make sure that it is valid. "Valid" means that all axes are
12627 represented exactly once and no invalid characters are present
12628 in the string. Case-insensitive. Returns NULL if everything is
12629 ok, otherwise is returns a string that lists all the errors
12630 it encountered.
12631 ---------------------------------------------------------------*/
12632 char *MRIcheckOrientationString(char *ostr)
12633 {
12634 int c, nsag=0, ncor=0, nax=0, err;
12635 char errstr[1000], *errstrret=NULL;
12636
12637 errstr[0] = '\0';
12638 err = 0;
12639
12640 for(c=0; c<3; c++){
12641 switch(toupper(ostr[c])){
12642 case 'L': nsag++; break;
12643 case 'R': nsag++; break;
12644 case 'P': ncor++; break;
12645 case 'A': ncor++; break;
12646 case 'I': nax++; break;
12647 case 'S': nax++; break;
12648 default:
12649 sprintf(errstr,"%s Character %c in position %d is invalid.\n",
12650 errstr,ostr[c],c+1);
12651 err = 1;
12652 break;
12653 }
12654 }
12655
12656 if(nsag > 1){
12657 sprintf(errstr,"%s LR axis represented multiple times.\n",errstr);
12658 err = 1;
12659 }
12660 if(ncor > 1){
12661 sprintf(errstr,"%s PA axis represented multiple times.\n",errstr);
12662 err = 1;
12663 }
12664 if(nax > 1){
12665 sprintf(errstr,"%s IS axis represented multiple times.\n",errstr);
12666 err = 1;
12667 }
12668 if(nsag == 0){
12669 sprintf(errstr,"%s LR axis not represented.\n",errstr);
12670 err = 1;
12671 }
12672 if(ncor == 0){
12673 sprintf(errstr,"%s PA axis not represented.\n",errstr);
12674 err = 1;
12675 }
12676 if(nax == 0){
12677 sprintf(errstr,"%s IS axis not represented.\n",errstr);
12678 err = 1;
12679 }
12680
12681 if(err){
12682 errstrret = (char *) calloc(sizeof(char),strlen(errstr)+1);
12683 memcpy(errstrret,errstr,strlen(errstr));
12684 }
12685
12686 return(errstrret);
12687 }
12688 /*------------------------------------------------------------------
12689 MRIdircosToOrientationString() - examines the direction cosines and
12690 creates an Orientation String. The Orientation String is a three
12691 character string indicating the primary direction of each axis
12692 in the 3d matrix. The characters can be L,R,A,P,I,S. Case is not
12693 important, but upper case is used here. If ras_good_flag == 0,
12694 then ostr = ??? and 1 is returned.
12695 ------------------------------------------------------------------*/
12696 int MRIdircosToOrientationString(MRI *mri, char *ostr)
12697 {
12698 int c;
12699 float Mdc[3][3], sag, cor, ax;
12700
12701 if(! mri->ras_good_flag){
12702 ostr[0] = '?';
12703 ostr[1] = '?';
12704 ostr[2] = '?';
12705 return(1);
12706 }
12707
12708 Mdc[0][0] = mri->x_r;
12709 Mdc[1][0] = mri->x_a;
12710 Mdc[2][0] = mri->x_s;
12711
12712 Mdc[0][1] = mri->y_r;
12713 Mdc[1][1] = mri->y_a;
12714 Mdc[2][1] = mri->y_s;
12715
12716 Mdc[0][2] = mri->z_r;
12717 Mdc[1][2] = mri->z_a;
12718 Mdc[2][2] = mri->z_s;
12719
12720 for(c=0; c<3; c++) ostr[c] = '\0';
12721
12722 for(c=0; c<3; c++){
12723 sag = Mdc[0][c]; // LR axis
12724 cor = Mdc[1][c]; // PA axis
12725 ax = Mdc[2][c]; // IS axis
12726 //printf("c = %d, sag = %g, cor = %g, ax = %g\n",c,sag,cor,ax);
12727 if(fabs(sag) > fabs(cor) && fabs(sag) > fabs(ax)){
12728 if(sag > 0) ostr[c] = 'R';
12729 else ostr[c] = 'L';
12730 continue;
12731 }
12732 if(fabs(cor) > fabs(ax)){
12733 if(cor > 0) ostr[c] = 'A';
12734 else ostr[c] = 'P';
12735 continue;
12736 }
12737 if(ax > 0) ostr[c] = 'S';
12738 else ostr[c] = 'I';
12739 }
12740 return(0);
12741
12742 }
12743 /*-------------------------------------------------------------------
12744 MRIsliceDirectionName() - returns the name of the primary slice
12745 orientation base on the direction cosine. If mri->ras_good_flag=0,
12746 then "unknown" is returned.
12747 -------------------------------------------------------------------*/
12748 char *MRIsliceDirectionName(MRI *mri)
12749 {
12750 char ostr[4];
12751 char *slicedir = NULL;
12752 char *rtstr;
12753 int len;
12754
12755 ostr[3] = '\0';
12756
12757 MRIdircosToOrientationString(mri, ostr);
12758 if(toupper(ostr[2]) == 'L'|| toupper(ostr[2]) == 'R')
12759 slicedir = "sagittal";
12760 if(toupper(ostr[2]) == 'P'|| toupper(ostr[2]) == 'A')
12761 slicedir = "coronal";
12762 if(toupper(ostr[2]) == 'I'|| toupper(ostr[2]) == 'S')
12763 slicedir = "axial";
12764 if(! mri->ras_good_flag) slicedir = "unknown";
12765
12766 len = strlen(slicedir);
12767 rtstr = (char *) calloc(sizeof(char),len+1);
12768 memcpy(rtstr,slicedir,len);
12769
12770 return(rtstr);
12771 }
12772 MRI *
12773 MRIdistanceTransform
12774 (MRI *mri_src, MRI *mri_dist, int label, float max_dist, int mode)
12775 {
12776 int x, y, z, width, height, depth, xi, yi, zi;
12777 int xk, yk, zk, changed, found, i ;
12778 MRI *mri_processed ;
12779 float dist, min_dist ;
12780 VOXEL_LIST *vl_current, *vl_new ;
12781
12782 width = mri_src->width ; height = mri_src->height ; depth = mri_src->depth ;
12783 if (max_dist < 0)
12784 max_dist = 2*MAX(MAX(width,height),depth);
12785 if (mri_dist == NULL)
12786 {
12787 mri_dist = MRIalloc(width, height, depth, MRI_FLOAT) ;
12788 MRIcopyHeader(mri_src, mri_dist) ;
12789 }
12790 else
12791 MRIclear(mri_dist) ;
12792
12793 if (mode != DTRANS_MODE_OUTSIDE)
12794 vl_current = VLSTcreate(mri_src, label, label, NULL, 0, 1) ;
12795 else
12796 vl_current = VLSTcreate(mri_src, label, label, NULL, 0, 0) ;
12797 vl_new = VLSTdilate(vl_current, VL_DILATE_REPLACE, NULL) ;
12798
12799 mri_processed = VLSTcreateMri(vl_current, 128) ;
12800 if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
12801 MRIwrite(mri_processed, "p.mgz") ;
12802
12803 do
12804 {
12805 for (i = 0 ; i < vl_new->nvox ; i++)
12806 {
12807 x = vl_new->xi[i] ;
12808 y = vl_new->yi[i] ;
12809 z = vl_new->zi[i] ;
12810 found = 0 ; min_dist = 1e8 ;
12811 for (xk = -1 ; xk <= 1 ; xk++) // find min dist of nbrs
12812 {
12813 xi = mri_src->xi[x+xk] ;
12814 for (yk = -1 ; yk <= 1 ; yk++)
12815 {
12816 yi = mri_src->yi[y+yk] ;
12817 for (zk = -1 ; zk <= 1 ; zk++)
12818 {
12819 zi = mri_src->zi[z+zk] ;
12820 if (MRIvox(mri_processed, xi, yi, zi) == 0)
12821 continue ;
12822 dist = MRIgetVoxVal(mri_dist, xi, yi, zi, 0) ;
12823 dist += sqrt(xk*xk+yk*yk+zk*zk) ;
12824 if (found == 0 || dist < min_dist)
12825 {
12826 found = 1 ;
12827 min_dist = dist ;
12828 }
12829 }
12830 }
12831 }
12832
12833 if (found > 0)
12834 {
12835 changed++ ;
12836 MRIsetVoxVal(mri_dist, x, y, z, 0, min_dist) ;
12837 }
12838 else
12839 DiagBreak() ;
12840 }
12841
12842 VLSTfree(&vl_current) ;
12843 VLSTaddToMri(vl_new, mri_processed, 128) ;
12844 vl_current = vl_new ;
12845 vl_new = VLSTdilate(vl_current, VL_DILATE_REPLACE, mri_processed) ;
12846 #if 0
12847 if (vl_new == NULL)
12848 printf("complete\n") ;
12849 else
12850 printf("examining %d voxels...\n", vl_new->nvox) ;
12851 #endif
12852 } while (vl_new != NULL) ;
12853
12854 if (mode != DTRANS_MODE_OUTSIDE) // set interior distances to negative vals
12855 {
12856 int x, y, z ;
12857
12858 for (x = 0 ; x < mri_src->width ; x++)
12859 {
12860 for (y = 0 ; y < mri_src->height ; y++)
12861 {
12862 for (z = 0 ; z < mri_src->depth ; z++)
12863 {
12864 if (x == Gx && y == Gy && z == Gz)
12865 DiagBreak() ;
12866 if (FEQUAL(MRIgetVoxVal(mri_src, x, y, z, 0), label))
12867 {
12868 dist = MRIgetVoxVal(mri_dist, x, y, z, 0) ;
12869 if (!FZERO(dist))
12870 MRIsetVoxVal(mri_dist, x, y, z, 0, -dist) ;
12871 }
12872 }
12873 }
12874 }
12875 }
12876
12877 if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
12878 MRIwrite(mri_dist, "dist.mgz") ;
12879 VLSTfree(&vl_current) ;
12880 MRIfree(&mri_processed) ;
12881
12882 if (mode == DTRANS_MODE_UNSIGNED)
12883 MRIabs(mri_dist, mri_dist) ;
12884 return(mri_dist) ;
12885 }
12886
12887 /*-------------------------------------------------------------------
12888 MRIreverseSliceOrder() - reverses the order of the slices WITHOUT
12889 changing the gemoetry information. This is specially desgined to
12890 undo the reversal that Siemens sometimes makes to volumes. If
12891 using FreeSurfer unpacking (ie, DICOMRead.c), it should only need
12892 to be done to mosaics. Note: cannot be done in-place!
12893 -------------------------------------------------------------------*/
12894 MRI *MRIreverseSliceOrder(MRI *invol, MRI *outvol)
12895 {
12896 int c,r,s1,s2,f;
12897 double val;
12898
12899 if(invol == outvol){
12900 printf("ERROR: MRIreverseSliceOrder: cannot be done in-place\n");
12901 return(NULL);
12902 }
12903
12904 outvol = MRIclone(invol,outvol);
12905
12906 s2 = invol->depth;
12907 for(s1=0; s1 < invol->depth; s1++){
12908 s2--;
12909 for(c=0; c < invol->width; c++){
12910 for(r=0; r < invol->height; r++){
12911 for(f=0; f < invol->nframes; f++){
12912 val = MRIgetVoxVal(invol,c,r,s1,f);
12913 MRIsetVoxVal(outvol,c,r,s2,f,val);
12914 }
12915 }
12916 }
12917 }
12918
12919 return(outvol);
12920 }
12921 /*-------------------------------------------------------------------
12922 MRIcopyVolGeomToMRI - copies the volume geometry passed in into the MRI
12923 structure.
12924 -------------------------------------------------------------------*/
12925 int
12926 MRIcopyVolGeomToMRI(MRI *mri, VOL_GEOM *vg)
12927 {
12928 mri->xsize = vg->xsize ;
12929 mri->ysize = vg->ysize ;
12930 mri->zsize = vg->zsize ;
12931 mri->x_r = vg->x_r;
12932 mri->y_r = vg->y_r;
12933 mri->z_r = vg->z_r;
12934 mri->c_r = vg->c_r;
12935 mri->x_a = vg->x_a;
12936 mri->y_a = vg->y_a;
12937 mri->z_a = vg->z_a;
12938 mri->c_a = vg->c_a;
12939 mri->x_s = vg->x_s;
12940 mri->y_s = vg->y_s;
12941 mri->z_s = vg->z_s;
12942 mri->c_s = vg->c_s;
12943 return(NO_ERROR) ;
12944 }
12945
12946 #define NDIRS 3
12947 static int dirs[NDIRS][3] =
12948 {
12949 { 0, 0, 1},
12950 { 0, 1, 0},
12951 { 1, 0, 0}
12952 } ;
12953
12954 MRI *
12955 MRInonMaxSuppress(MRI *mri_src, MRI *mri_sup, float thresh, int thresh_dir)
12956 {
12957 int x, y, z, i, max_i ;
12958 Real val, dx, dy, dz, Ix, Iy, Iz;
12959 Real dot, max_dot, p1_x, p1_y, p1_z, p2_x, p2_y, p2_z;
12960 Real p3_x, p3_y, p3_z, nx, ny, nz, u, xf, yf, zf, oval, numer, denom ;
12961
12962 mri_sup = MRIcopy(mri_src, mri_sup) ;
12963
12964 for (x = 0 ; x < mri_src->width ; x++)
12965 {
12966 for (y = 0 ; y < mri_src->height ; y++)
12967 {
12968 for (z = 0 ; z < mri_src->depth ; z++)
12969 {
12970 if (x == Gx && y == Gy && z == Gz)
12971 DiagBreak() ;
12972 val = MRIgetVoxVal(mri_src, x, y, z,0) ;
12973 val = val*thresh_dir ;
12974 if (val <= thresh)
12975 {
12976 MRIsetVoxVal(mri_sup, x, y, z, 0, 0.0) ;
12977 continue ;
12978 }
12979 MRIsampleVolumeGradient(mri_src, x, y, z, &Ix, &Iy, &Iz) ;
12980 dx = dirs[0][0] ; dy = dirs[0][1] ; dz = dirs[0][2] ;
12981 max_i = 0 ;
12982 max_dot = fabs(dx*Ix+dy*Iy+dz*Iz) ;
12983 for (i = 1 ; i < NDIRS ; i++)
12984 {
12985 // compute intersection of gradient
12986 // direction with coordinate planes
12987 dx = dirs[i][0] ; dy = dirs[i][1] ; dz = dirs[i][2] ;
12988 dot = fabs(dx*Ix+dy*Iy+dz*Iz) ;
12989 if (dot > max_dot)
12990 {
12991 max_i = i ;
12992 max_dot = dot ;
12993 }
12994 }
12995 // normal to coordinate plane -
12996 // compute intersections of gradient dir with plane
12997 nx = dirs[max_i][0] ;
12998 ny = dirs[max_i][1] ;
12999 nz = dirs[max_i][2] ;
13000 p1_x = x ; p1_y = y ; p1_z = z ; // point on line
13001 p2_x = x+Ix ; p2_y = y+Iy ; p2_z = z+Iz ; // 2nd point on
13002 // gradient line
13003 p3_x = x+nx ; p3_y = y+ny ; p3_z = z+nz ; // point on plane
13004 numer =
13005 nx * (p3_x - p1_x) +
13006 ny * (p3_y - p1_y) +
13007 nz * (p3_z - p1_z) ;
13008 denom =
13009 nx * (p2_x - p1_x) +
13010 ny * (p2_y - p1_y) +
13011 nz * (p2_z - p1_z) ;
13012 if (DZERO(denom))
13013 {
13014 DiagBreak() ;
13015 continue ;
13016 }
13017 u = numer / denom ;
13018 xf = p1_x + u * Ix ; yf = p1_y + u * Iy ; zf = p1_z + u * Iz ;
13019 MRIsampleVolume(mri_src, xf, yf, zf, &oval) ;
13020 oval = oval*thresh_dir ;
13021 if (oval > val) // not at a maximum
13022 {
13023 MRIsetVoxVal(mri_sup, x, y, z, 0, 0) ;
13024 continue ;
13025 }
13026 xf = p1_x - u * Ix ; yf = p1_y - u * Iy ; zf = p1_z - u * Iz ;
13027 MRIsampleVolume(mri_src, xf, yf, zf, &oval) ;
13028 oval = oval*thresh_dir ;
13029 if (oval > val) // not at a maximum
13030 {
13031 MRIsetVoxVal(mri_sup, x, y, z, 0, 0) ;
13032 continue ;
13033 }
13034 }
13035 }
13036 }
13037
13038 return(mri_sup) ;
13039 }
13040 MRI *
13041 MRIextractRegionAndPad
13042 (MRI *mri_src, MRI *mri_dst, MRI_REGION *region, int pad)
13043 {
13044 MRI *mri_tmp ;
13045 MRI_REGION box ;
13046
13047 if (region == NULL)
13048 {
13049 region = & box ;
13050 box.x = box.y = box.z = 0 ;
13051 box.dx = mri_src->width ;
13052 box.dy = mri_src->height ;
13053 box.dz = mri_src->depth ;
13054 }
13055 mri_dst =
13056 MRIalloc
13057 (region->dx+2*pad, region->dy+2*pad, region->dz+2*pad, mri_src->type) ;
13058 MRIcopyHeader(mri_src, mri_dst) ;
13059 mri_tmp = MRIextractInto(mri_src, NULL, region->x, region->y, region->z,
13060 region->dx, region->dy, region->dz, 0, 0, 0) ;
13061 MRIextractInto
13062 (mri_tmp, mri_dst, 0, 0, 0,
13063 region->dx, region->dy, region->dz, pad, pad, pad);
13064 return(mri_dst) ;
13065 }
13066
13067 MRI *
13068 MRIsetValuesOutsideRegion
13069 (MRI *mri_src, MRI_REGION *region, MRI *mri_dst, float val)
13070 {
13071 int x, y, z ;
13072
13073 mri_dst = MRIcopy(mri_src, mri_dst) ;
13074
13075 for (x = 0 ; x < mri_dst->width ; x++)
13076 {
13077 if (x >= region->x && x < region->x+region->dx)
13078 continue ;
13079 for (y = 0 ; y < mri_dst->height ; y++)
13080 {
13081 if (y >= region->y && y < region->y+region->dy)
13082 continue ;
13083 for (z = 0 ; z < mri_dst->depth ; z++)
13084 {
13085 if (z >= region->z && z < region->z+region->dz)
13086 continue ;
13087 MRIsetVoxVal(mri_dst, x, y, z, 0, val) ;
13088 }
13089 }
13090 }
13091
13092 return(mri_dst) ;
13093 }
13094
13095 int
13096 MRIlabelsInNbhd(MRI *mri, int x, int y, int z, int whalf, int label)
13097 {
13098 int xi, yi, zi, xk, yk, zk, count ;
13099
13100 for (count = 0, zk = -whalf ; zk <= whalf ; zk++)
13101 {
13102 zi = mri->zi[z+zk] ;
13103 for (yk = -whalf ; yk <= whalf ; yk++)
13104 {
13105 yi = mri->yi[y+yk] ;
13106 for (xk = -whalf ; xk <= whalf ; xk++)
13107 {
13108 xi = mri->xi[x+xk] ;
13109 if (MRIvox(mri, xi, yi, zi) == label)
13110 count++;
13111 }
13112 }
13113 }
13114 return(count) ;
13115 }
13116
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.- [get | view] (2009-01-26 22:35:32, 12.9 KB) [[attachment:fio.c]]
- [get | view] (2009-01-26 22:35:32, 1.3 KB) [[attachment:fio.h]]
- [get | view] (2009-01-26 22:35:32, 5.9 KB) [[attachment:load_mgh.m]]
- [get | view] (2009-01-26 22:35:32, 9.3 KB) [[attachment:matrix.h]]
- [get | view] (2009-01-26 22:35:32, 390.2 KB) [[attachment:mri.c]]
- [get | view] (2009-01-26 22:35:32, 48.5 KB) [[attachment:mri.h]]
- [get | view] (2009-01-26 22:35:32, 94.4 KB) [[attachment:mri_convert.c]]
- [get | view] (2009-01-26 22:35:32, 14.1 KB) [[attachment:mri_info.c]]
- [get | view] (2009-01-26 22:35:32, 395.4 KB) [[attachment:mriio.c]]
- [get | view] (2009-01-26 22:35:32, 2.4 KB) [[attachment:save_mgh.m]]
- [get | view] (2009-01-26 22:35:32, 2.2 KB) [[attachment:tags.c]]
- [get | view] (2009-01-26 22:35:32, 0.9 KB) [[attachment:tags.h]]
You are not allowed to attach a file to this page.