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, \
2172 VECTOR_ELT(v,3)=z, VECTOR_ELT(v,4)=r) ;
2173
2174 int
2175 MRIvoxelToWorld(MRI *mri, Real xv, Real yv, Real zv,
2176 Real *pxw, Real *pyw, Real *pzw)
2177 {
2178 VECTOR *vw, *vv;
2179 MATRIX *RfromI;
2180
2181 // if the transform is not cached yet, then
2182 if (!mri->i_to_r__)
2183 mri->i_to_r__ = extract_i_to_r(mri);
2184 if (!mri->r_to_i__)
2185 mri->r_to_i__ = extract_r_to_i(mri);
2186
2187 RfromI = mri->i_to_r__; // extract_i_to_r(mri);
2188
2189 vv = VectorAlloc(4, MATRIX_REAL) ;
2190 V4_LOAD(vv, xv, yv, zv, 1.) ;
2191 vw = MatrixMultiply(RfromI, vv, NULL) ;
2192 *pxw = V3_X(vw);
2193 *pyw = V3_Y(vw);
2194 *pzw = V3_Z(vw);
2195
2196 // MatrixFree(&RfromI);
2197 VectorFree(&vv);
2198 VectorFree(&vw);
2199 return(NO_ERROR) ;
2200 }
2201 /*-----------------------------------------------------
2202 ------------------------------------------------------*/
2203 int
2204 MRIworldToTalairachVoxel(MRI *mri, Real xw, Real yw, Real zw,
2205 Real *pxv, Real *pyv, Real *pzv)
2206 {
2207 Real xt, yt, zt ;
2208
2209 transform_point(mri->linear_transform, xw, yw, zw, &xt, &yt, &zt) ;
2210 MRIworldToVoxel(mri, xt, yt, zt, pxv, pyv, pzv) ;
2211 return(NO_ERROR) ;
2212 }
2213 /*-----------------------------------------------------
2214 ------------------------------------------------------*/
2215 int MRIworldToVoxelIndex(MRI *mri, Real xw, Real yw, Real zw,
2216 int *pxv, int *pyv, int *pzv)
2217 {
2218 Real xv, yv, zv;
2219 MRIworldToVoxel(mri, xw, yw, zw, &xv, &yv, &zv);
2220 *pxv = (int) xv;
2221 *pyv = (int) yv;
2222 *pzv = (int) zv;
2223
2224 /*
2225 switch (getSliceDirection(mri))
2226 {
2227 case MRI_CORONAL:
2228 #if 0
2229 *pxv = ((Real)mri->xend - xw) / mri->xsize ;
2230 *pzv = (yw - (Real)mri->zstart) / mri->zsize ;
2231 *pyv = (-zw - (Real)mri->ystart) / mri->ysize ;
2232 #else
2233 trans_SetBounds ( mri->xstart, mri->xend, mri->ystart, mri->yend,
2234 mri->zstart, mri->zend );
2235 trans_SetResolution ( mri->xsize, mri->ysize, mri->zsize );
2236 trans_RASToVoxelIndex(xw, yw, zw, pxv, pyv, pzv) ;
2237 #endif
2238 break ;
2239 default:
2240 ErrorReturn(ERROR_UNSUPPORTED,
2241 (ERROR_UNSUPPORTED,
2242 "MRIworldToVoxel: unsupported slice direction %d",
2243 getSliceDirection(mri))) ;
2244 break ;
2245 }
2246 */
2247 return(NO_ERROR) ;
2248 }
2249
2250 /*
2251 int MRIvoxelToSurfaceRAS and int MRIsurfaceRASToVoxel
2252
2253 get the surfaceRAS values from original voxel
2254 Note that this is different from MRIvoxelToWorld().
2255
2256 Note that currently MATRIX uses float** to store data.
2257 Going around the circle of transform causes error accumulation quickly.
2258 I noticed that 7 x 10^(-6) is very common.
2259
2260 */
2261
2262 MATRIX *surfaceRASFromVoxel_(MRI *mri)
2263 {
2264 // Derivation (avoid expensive matrix calculation)
2265 //
2266 // orig -----(rasFromVoxel)------> RAS (scanner RAS or physical RAS)
2267 // | |
2268 //(conformedVoxelFromVoxel) (1)
2269 // | |
2270 // V V
2271 //conformed--(RASfromConformed)----->RAS (scanner RAS or physical RAS)
2272 // | |
2273 // (1) (surfaceRASFromRAS)
2274 // | |
2275 // V V
2276 //conformed-(surfaceRASFromConformed)->surfaceRAS
2277 //
2278 //
2279 // where RASFromConformed = [ -1 0 0 s1 ] where s1 = c_r + 128
2280 // [ 0 0 1 s2 ] s2 = c_a - 128
2281 // [ 0 -1 0 s3 ] s3 = c_s + 128
2282 // [ 0 0 0 1 ]
2283 //
2284 // surfaceRASFromConformed= [ -1 0 0 128 ]
2285 // [ 0 0 1 -128 ]
2286 // [ 0 -1 0 128 ]
2287 // [ 0 0 0 1 ]
2288 // Therefore
2289 // surfaceRASFromRAS= [ 1 0 0 -c_r] just a translation matrix
2290 // [ 0 1 0 -c_a]
2291 // [ 0 0 1 -c_s]
2292 // [ 0 0 0 1 ]
2293 //
2294 // surfaceRASFromVoxel = surfaceRASFromRAS (x) rasFromVoxel
2295 //
2296 // i.e. applying translation on RASFromVoxel
2297 //
2298 // This means tha
2299 //
2300 // if RASFromVoxel = ( X | T ), then
2301 // ( 0 | 1 )
2302 //
2303 // surfaceRASFromVoxel = ( 1 | -C) * ( X | T ) = ( X | T - C )
2304 // ( 0 | 1 ) ( 0 | 1 ) ( 0 | 1 )
2305 //
2306 MATRIX *rasFromVoxel;
2307 MATRIX *sRASFromVoxel;
2308 double m14, m24, m34;
2309
2310 // if the transform is not cached yet, then
2311 if (!mri->i_to_r__)
2312 mri->i_to_r__ = extract_i_to_r(mri);
2313 if (!mri->r_to_i__)
2314 mri->r_to_i__ = extract_r_to_i(mri);
2315
2316 rasFromVoxel = mri->i_to_r__; // extract_i_to_r(mri);
2317
2318 sRASFromVoxel = MatrixCopy(rasFromVoxel, NULL);
2319 // MatrixFree(&rasFromVoxel);
2320 // modify
2321 m14 = *MATRIX_RELT(sRASFromVoxel, 1,4);
2322 *MATRIX_RELT(sRASFromVoxel, 1,4) = m14 - mri->c_r;
2323 m24 = *MATRIX_RELT(sRASFromVoxel, 2,4);
2324 *MATRIX_RELT(sRASFromVoxel, 2,4) = m24 - mri->c_a;
2325 m34 = *MATRIX_RELT(sRASFromVoxel, 3,4);
2326 *MATRIX_RELT(sRASFromVoxel, 3,4) = m34 - mri->c_s;
2327
2328 return sRASFromVoxel;
2329 }
2330
2331 MATRIX *surfaceRASFromRAS_(MRI *mri)
2332 {
2333 MATRIX *sRASFromRAS;
2334 sRASFromRAS = MatrixAlloc(4, 4, MATRIX_REAL);
2335 MatrixIdentity(4, sRASFromRAS);
2336 *MATRIX_RELT(sRASFromRAS, 1,4) = - mri->c_r;
2337 *MATRIX_RELT(sRASFromRAS, 2,4) = - mri->c_a;
2338 *MATRIX_RELT(sRASFromRAS, 3,4) = - mri->c_s;
2339 return sRASFromRAS;
2340 }
2341
2342 MATRIX *RASFromSurfaceRAS_(MRI *mri)
2343 {
2344 MATRIX *RASFromSRAS;
2345 RASFromSRAS = MatrixAlloc(4, 4, MATRIX_REAL);
2346 MatrixIdentity(4, RASFromSRAS);
2347 *MATRIX_RELT(RASFromSRAS, 1,4) = mri->c_r;
2348 *MATRIX_RELT(RASFromSRAS, 2,4) = mri->c_a;
2349 *MATRIX_RELT(RASFromSRAS, 3,4) = mri->c_s;
2350 return RASFromSRAS;
2351 }
2352
2353 int MRIRASToSurfaceRAS(MRI *mri, Real xr, Real yr, Real zr,
2354 Real *xsr, Real *ysr, Real *zsr)
2355 {
2356 MATRIX *surfaceRASFromRAS=0;
2357 VECTOR *v, *sr;
2358 v = VectorAlloc(4, MATRIX_REAL);
2359 V4_LOAD(v, xr, yr, zr, 1.);
2360 surfaceRASFromRAS = surfaceRASFromRAS_(mri);
2361 sr = MatrixMultiply(surfaceRASFromRAS, v, NULL);
2362 *xsr = V3_X(sr);
2363 *ysr = V3_Y(sr);
2364 *zsr = V3_Z(sr);
2365 MatrixFree(&surfaceRASFromRAS);
2366 VectorFree(&v);
2367 VectorFree(&sr);
2368 return (NO_ERROR);
2369 }
2370
2371 int MRIsurfaceRASToRAS(MRI *mri, Real xsr, Real ysr, Real zsr,
2372 Real *xr, Real *yr, Real *zr)
2373 {
2374 MATRIX *RASFromSurfaceRAS=0;
2375 VECTOR *v, *r;
2376 v = VectorAlloc(4, MATRIX_REAL);
2377 V4_LOAD(v, xsr, ysr, zsr, 1.);
2378 RASFromSurfaceRAS = RASFromSurfaceRAS_(mri);
2379 r = MatrixMultiply(RASFromSurfaceRAS, v, NULL);
2380 *xr = V3_X(r);
2381 *yr = V3_Y(r);
2382 *zr = V3_Z(r);
2383 MatrixFree(&RASFromSurfaceRAS);
2384 VectorFree(&v);
2385 VectorFree(&r);
2386 return (NO_ERROR);
2387 }
2388
2389
2390 int MRIvoxelToSurfaceRAS(MRI *mri, Real xv, Real yv, Real zv,
2391 Real *xs, Real *ys, Real *zs)
2392 {
2393 MATRIX *sRASFromVoxel;
2394 VECTOR *vv, *sr;
2395
2396 sRASFromVoxel = surfaceRASFromVoxel_(mri);
2397 // calculate the surface ras value
2398 vv = VectorAlloc(4, MATRIX_REAL);
2399 V4_LOAD(vv, xv, yv, zv, 1.);
2400 sr = MatrixMultiply(sRASFromVoxel, vv, NULL);
2401 *xs = V3_X(sr);
2402 *ys = V3_Y(sr);
2403 *zs = V3_Z(sr);
2404
2405 MatrixFree(&sRASFromVoxel);
2406 VectorFree(&vv);
2407 VectorFree(&sr);
2408
2409 return (NO_ERROR);
2410 }
2411
2412 MATRIX *voxelFromSurfaceRAS_(MRI *mri)
2413 {
2414 MATRIX *voxelFromSRAS =0;
2415 //////////////////////////////////////////////////////////////////
2416 // it turned out that this can be done easily without taking inverse
2417 // Note the surfaceRASFromVoxel_ is given by
2418 //
2419 // ( X | T - C)
2420 // ( 0 | 1 )
2421 // Note, however, that we define C by
2422 //
2423 // ( X | T ) (S/2) = ( C ) where S = (w/2, h/2, d/2)^t
2424 // ( 0 | 1 ) ( 1 ) ( 1 )
2425 // Thus
2426 // X*S/2 + T = C
2427 // or
2428 // T - C = - X*S/2
2429 // or
2430 // surfaceRASFromVoxel = ( X | - X*S/2 )
2431 // ( 0 | 1 )
2432 // whose inverse is given by
2433 //
2434 // voxelFromSurfaceRAS = ( X ^(-1)| S/2 )
2435 // ( 0 | 1 )
2436 //
2437 // since
2438 // ( X^(-1) S/2) ( X -X*S/2) = ( 1 S/2 - S/2) = 1
2439 // ( 0 1 ) ( 0 1 ) ( 0 1 )
2440 //
2441 // thus get r_to_i__ and set translation part to S/2 is the quickest way
2442 /////////////////////////////////////////////////////////////////////
2443 // if the transform is not cached yet, then
2444 if (!mri->i_to_r__)
2445 mri->i_to_r__ = extract_i_to_r(mri);
2446 if (!mri->r_to_i__)
2447 mri->r_to_i__ = extract_r_to_i(mri);
2448
2449 voxelFromSRAS = MatrixCopy(mri->r_to_i__, NULL);
2450 // modify translation part
2451 *MATRIX_RELT(voxelFromSRAS, 1,4) = mri->width/2;
2452 *MATRIX_RELT(voxelFromSRAS, 2,4) = mri->height/2;
2453 *MATRIX_RELT(voxelFromSRAS, 3,4) = mri->depth/2;
2454
2455 #if 0
2456 // no more expensive inverse
2457 MATRIX *sRASFromVoxel = surfaceRASFromVoxel_(mri);
2458 MATRIX *voxelFromSRAS = MatrixInverse(sRASFromVoxel, NULL);
2459 MatrixFree(&sRASFromVoxel) ;
2460 #endif
2461
2462 return voxelFromSRAS;
2463 }
2464
2465 /* extract the RASToVoxel Matrix */
2466 MATRIX *GetSurfaceRASToVoxelMatrix(MRI *mri){
2467 return voxelFromSurfaceRAS_(mri);
2468 }
2469
2470 int MRIsurfaceRASToVoxel(MRI *mri, Real xr, Real yr, Real zr,
2471 Real *xv, Real *yv, Real *zv)
2472 {
2473 MATRIX *voxelFromSRAS;
2474 static VECTOR *sr = NULL, *vv = NULL;
2475
2476 voxelFromSRAS=voxelFromSurfaceRAS_(mri);
2477 if (sr == NULL)
2478 sr = VectorAlloc(4, MATRIX_REAL);
2479 V4_LOAD(sr, xr, yr, zr, 1.);
2480 vv = MatrixMultiply(voxelFromSRAS, sr, vv);
2481 *xv = V3_X(vv);
2482 *yv = V3_Y(vv);
2483 *zv = V3_Z(vv);
2484
2485 MatrixFree(&voxelFromSRAS);
2486 // VectorFree(&sr);
2487 // VectorFree(&vv);
2488
2489 return (NO_ERROR);
2490 }
2491
2492 /*------------------------------------------------------*/
2493 int
2494 MRIworldToVoxel(MRI *mri, Real xw, Real yw, Real zw,
2495 Real *pxv, Real *pyv, Real *pzv)
2496 {
2497 VECTOR *vv, *vw;
2498 MATRIX *IfromR;
2499
2500 // if transform is not cached yet, then
2501 if (!mri->r_to_i__)
2502 mri->r_to_i__ = extract_r_to_i(mri);
2503 if (!mri->i_to_r__)
2504 mri->i_to_r__ = extract_i_to_r(mri);
2505
2506 IfromR = mri->r_to_i__;
2507 vw = VectorAlloc(4, MATRIX_REAL) ;
2508 V4_LOAD(vw, xw, yw, zw, 1.) ;
2509 vv = MatrixMultiply(IfromR, vw, NULL) ;
2510 *pxv = V3_X(vv);
2511 *pyv = V3_Y(vv);
2512 *pzv = V3_Z(vv);
2513
2514 VectorFree(&vv);
2515 VectorFree(&vw);
2516
2517 return(NO_ERROR) ;
2518 }
2519 /*-----------------------------------------------------
2520 ------------------------------------------------------*/
2521 int
2522 MRIinitHeader(MRI *mri)
2523 {
2524 mri->ptype = 2 ;
2525
2526 /* most of these are in mm */
2527 mri->imnr0 = 1 ;
2528 mri->imnr1 = mri->depth ;
2529 mri->fov = mri->width ;
2530 mri->thick = 1.0 ;
2531 mri->xsize = 1.0 ;
2532 mri->ysize = 1.0 ;
2533 mri->zsize = 1.0 ;
2534 mri->ps = 1 ;
2535 mri->xstart = -mri->width/2.0 ;
2536 mri->xend = mri->width/2.0 ;
2537 mri->ystart = -mri->height/2.0 ;
2538 mri->yend = mri->height/2.0 ;
2539 mri->zstart = -mri->depth/2.0 ;
2540 mri->zend = mri->depth/2 ;
2541 // coronal
2542 mri->x_r = -1;
2543 mri->x_a = 0.;
2544 mri->x_s = 0.;
2545 //
2546 mri->y_r = 0.;
2547 mri->y_a = 0.;
2548 mri->y_s = -1;
2549 //
2550 mri->z_r = 0.;
2551 mri->z_a = 1;
2552 mri->z_s = 0.;
2553 //
2554 mri->c_r = mri->c_a = mri->c_s = 0.0;
2555
2556 mri->ras_good_flag = 1;
2557 mri->gdf_image_stem[0] = '\0';
2558 mri->tag_data = NULL;
2559 mri->tag_data_size = 0;
2560
2561 if (!mri->i_to_r__)
2562 mri->i_to_r__ = extract_i_to_r(mri);
2563 if (!mri->r_to_i__)
2564 mri->r_to_i__ = extract_r_to_i(mri);
2565
2566 return(NO_ERROR) ;
2567 }
2568
2569 /**
2570 * MRIreInitCache
2571 *
2572 * @param mri MRI* whose header information was modified
2573 *
2574 * @return NO_ERROR
2575 */
2576 int MRIreInitCache(MRI *mri)
2577 {
2578 if (mri->i_to_r__)
2579 {
2580 MatrixFree(&mri->i_to_r__);
2581 mri->i_to_r__ = 0;
2582 }
2583 if (mri->r_to_i__)
2584 {
2585 MatrixFree(&mri->r_to_i__);
2586 mri->r_to_i__ = 0;
2587 }
2588 mri->i_to_r__ = extract_i_to_r(mri);
2589 mri->r_to_i__ = extract_r_to_i(mri);
2590
2591 return (NO_ERROR);
2592 }
2593
2594 /*-----------------------------------------------------
2595 Parameters:
2596
2597 Returns value:
2598
2599 Description
2600 change the direction of slices
2601 ------------------------------------------------------*/
2602 MRI *
2603 MRIextract(MRI *mri_src, MRI *mri_dst, int x0, int y0, int z0,
2604 int dx, int dy, int dz)
2605 {
2606 return(MRIextractInto(mri_src, mri_dst, x0, y0, z0, dx, dy, dz, 0, 0, 0)) ;
2607 }
2608 /*-----------------------------------------------------
2609 Parameters:
2610
2611 Returns value:
2612
2613 Description
2614 Extract a cubic region of an MR image and return it to the caller
2615 ------------------------------------------------------*/
2616 MRI *
2617 MRIextractRegion(MRI *mri_src, MRI *mri_dst, MRI_REGION *region)
2618 {
2619 return(MRIextractInto(mri_src, mri_dst, region->x, region->y, region->z,
2620 region->dx, region->dy, region->dz, 0, 0, 0)) ;
2621 }
2622 /*-----------------------------------------------------
2623 Parameters:
2624
2625 Returns value:
2626
2627 Description
2628 Extract a cubic region of an MR image and return it to the caller
2629 ------------------------------------------------------*/
2630 MRI *
2631 MRIextractIntoRegion(MRI *mri_src, MRI *mri_dst, int x0, int y0, int z0,
2632 MRI_REGION *region)
2633 {
2634 return(MRIextractInto(mri_src, mri_dst, x0, y0, z0, region->dx, region->dy,
2635 region->dz, region->x, region->y, region->z)) ;
2636 }
2637 /*-----------------------------------------------------
2638 Parameters:
2639
2640 Returns value:
2641
2642 Description
2643 Extract a cubic region of an MR image and return it to the caller
2644 ------------------------------------------------------*/
2645 MRI *
2646 MRIextractInto(MRI *mri_src, MRI *mri_dst, int x0, int y0, int z0,
2647 int dx, int dy, int dz, int x1, int y1, int z1)
2648 {
2649 int width, height, depth, ys, zs, yd, zd, bytes, frame, xsize,ysize,zsize,
2650 dst_alloced = 0 ;
2651 Real c_r, c_a, c_s;
2652
2653 width = mri_src->width ;
2654 depth = mri_src->depth ;
2655 height = mri_src->height ;
2656
2657 if (z0 >= depth || y0 >= height || x0 >= width)
2658 ErrorReturn(NULL,
2659 (ERROR_BADPARM,
2660 "MRIextractInto: bad src location (%d, %d, %d)", x0,y0,z0));
2661 // validation
2662 if (x0 < 0)
2663 x0 = 0 ;
2664 if (y0 < 0)
2665 y0 = 0 ;
2666 if (z0 < 0)
2667 z0 = 0 ;
2668 if (x0+dx > width)
2669 dx = (width - x0) ;
2670 if (y0+dy > height)
2671 dy = (height - y0) ;
2672 if (z0+dz > depth)
2673 dz = (depth - z0) ;
2674 if (x1 < 0)
2675 x1 = 0 ;
2676 if (y1 < 0)
2677 y1 = 0 ;
2678 if (z1 < 0)
2679 z1 = 0 ;
2680
2681 if (!mri_dst)
2682 {
2683 mri_dst = MRIallocSequence(dx, dy, dz, mri_src->type, mri_src->nframes) ;
2684 MRIcopyHeader(mri_src, mri_dst) ;
2685 mri_dst->imnr0 = z0 + mri_src->imnr0 - z1 ;
2686 mri_dst->imnr1 = mri_dst->imnr0 + dz - 1 ;
2687 dst_alloced = 1 ;
2688 }
2689
2690 if (mri_src->type != mri_dst->type)
2691 {
2692 MRIfree(&mri_dst) ;
2693 ErrorReturn(NULL,
2694 (ERROR_BADPARM,
2695 "MRIextractInto: src and dst types must match"));
2696 }
2697
2698 if (x1+dx > mri_dst->width)
2699 dx = (mri_dst->width - x1) ;
2700 if (y1+dy > mri_dst->height)
2701 dy = (mri_dst->height - y1) ;
2702 if (z1+dz > mri_dst->depth)
2703 dz = (mri_dst->depth - z1) ;
2704
2705 xsize = mri_src->xsize ;
2706 ysize = mri_src->ysize ;
2707 zsize = mri_src->zsize ;
2708
2709 if (dst_alloced)
2710 {
2711 mri_dst->xstart += x0*xsize ;
2712 mri_dst->xend = mri_dst->xstart + dx*xsize ;
2713 mri_dst->ystart += y0*ysize ;
2714 mri_dst->yend = mri_dst->ystart + dy*ysize ;
2715 mri_dst->zstart += z0*zsize ;
2716 mri_dst->zend = mri_dst->zstart + dz*zsize ;
2717 }
2718
2719 bytes = dx ;
2720 switch (mri_src->type)
2721 {
2722 case MRI_FLOAT:
2723 bytes *= sizeof(float) ;
2724 break ;
2725 case MRI_LONG:
2726 bytes *= sizeof(long) ;
2727 break ;
2728 case MRI_INT:
2729 bytes *= sizeof(int) ;
2730 break ;
2731 case MRI_SHORT:
2732 bytes *= sizeof(short) ;
2733 break ;
2734 default:
2735 break ;
2736 }
2737
2738 for (frame = 0 ; frame < mri_src->nframes ; frame++)
2739 {
2740 for (zd = z1, zs = z0 ; zs < z0+dz ; zs++, zd++)
2741 {
2742 for (yd = y1, ys = y0 ; ys < y0+dy ; ys++, yd++)
2743 {
2744 switch (mri_src->type)
2745 {
2746 case MRI_UCHAR:
2747 memcpy(&MRIseq_vox(mri_dst, x1, yd, zd,frame),
2748 &MRIseq_vox(mri_src,x0,ys,zs,frame), bytes);
2749 break ;
2750 case MRI_FLOAT:
2751 memcpy(&MRIFseq_vox(mri_dst, x1, yd, zd,frame),
2752 &MRIFseq_vox(mri_src,x0,ys,zs,frame), bytes);
2753 break ;
2754 case MRI_SHORT:
2755 memcpy(&MRISseq_vox(mri_dst, x1, yd, zd,frame),
2756 &MRISseq_vox(mri_src,x0,ys,zs,frame), bytes);
2757 break ;
2758 case MRI_LONG:
2759 memcpy(&MRILseq_vox(mri_dst, x1, yd, zd,frame),
2760 &MRILseq_vox(mri_src,x0,ys,zs,frame), bytes);
2761 break ;
2762 }
2763 }
2764 }
2765 }
2766 // calculate c_ras
2767 MRIcalcCRASforExtractedVolume
2768 (mri_src, mri_dst, x0, y0, z0, x1, y1, z1, &c_r, &c_a, &c_s);
2769 mri_dst->c_r = c_r;
2770 mri_dst->c_a = c_a;
2771 mri_dst->c_s = c_s;
2772 // initialize cached transform
2773 MRIreInitCache(mri_dst);
2774
2775 return(mri_dst) ;
2776 }
2777 /*-----------------------------------------------------
2778 Parameters:
2779
2780 Returns value:
2781
2782 Description
2783 change the direction of slices
2784 ------------------------------------------------------*/
2785 MRI *
2786 MRIreslice(MRI *mri_src, MRI *mri_dst, int slice_direction)
2787 {
2788 int width, height, depth, x1, x2, x3 ;
2789 BUFTYPE *psrc, val, *pdst ;
2790
2791 int src_slice_direction = getSliceDirection(mri_src);
2792 if (slice_direction == src_slice_direction)
2793 {
2794 mri_dst = MRIcopy(mri_src, NULL) ;
2795 return(mri_dst) ;
2796 }
2797
2798 width = mri_src->width ;
2799 height = mri_src->height ;
2800 depth = mri_src->depth ;
2801
2802
2803 if ((src_slice_direction == MRI_SAGITTAL &&
2804 slice_direction == MRI_CORONAL) ||
2805 (src_slice_direction == MRI_CORONAL &&
2806 slice_direction == MRI_SAGITTAL))
2807 {
2808 /*
2809 coronal images are back to front of the head, thus the depth axis
2810 points from the nose to the back of the head, with x from neck to
2811 crown, and y from ear to ear.
2812 */
2813 /* x1 --> x3
2814 x2 --> x2
2815 x3 --> x1
2816 */
2817 if (!mri_dst)
2818 {
2819 mri_dst = MRIalloc(depth, height, width, mri_src->type) ;
2820 MRIcopyHeader(mri_src, mri_dst) ;
2821 }
2822 else if (depth != mri_dst->width || height != mri_dst->height ||
2823 width != mri_dst->depth)
2824 {
2825 ErrorReturn(NULL,
2826 (ERROR_BADPARM,
2827 "MRIreslice: invalid destination size (%d, %d, %d)",
2828 mri_dst->width, mri_dst->height, mri_dst->depth)) ;
2829 }
2830
2831 for (x3 = 0 ; x3 < depth ; x3++)
2832 {
2833 for (x2 = 0 ; x2 < height ; x2++)
2834 {
2835 psrc = &MRIvox(mri_src, 0, x2, x3) ;
2836 for (x1 = 0 ; x1 < width ; x1++)
2837 {
2838 /* swap so in place transformations are possible */
2839 mri_dst->slices[x1][x2][x3] = *psrc++ ;
2840 }
2841 }
2842 }
2843 }
2844 else
2845 if ((src_slice_direction == MRI_HORIZONTAL &&
2846 slice_direction == MRI_CORONAL) ||
2847 (src_slice_direction == MRI_CORONAL &&
2848 slice_direction == MRI_HORIZONTAL))
2849 {
2850 /*
2851 horizontal images are top to bottom of the head, thus the depth axis
2852 points from the top of the head to the neck, with x from ear to ear
2853 and y from nose to back of head.
2854 */
2855 /* x3 --> x2
2856 x2 --> x3
2857 x1 --> x1
2858 */
2859 if (!mri_dst)
2860 {
2861 mri_dst = MRIalloc(width, depth, height, mri_src->type) ;
2862 MRIcopyHeader(mri_src, mri_dst) ;
2863 }
2864 else if (depth != mri_dst->height || height != mri_dst->depth ||
2865 width != mri_dst->width)
2866 ErrorReturn(NULL,
2867 (ERROR_BADPARM,
2868 "MRIreslice: invalid destination size (%d, %d, %d)",
2869 mri_dst->width, mri_dst->height, mri_dst->depth)) ;
2870
2871 for (x3 = 0 ; x3 < depth ; x3++)
2872 {
2873 for (x2 = 0 ; x2 < height ; x2++)
2874 {
2875 psrc = &MRIvox(mri_src, 0, x2, x3) ;
2876 pdst = &MRIvox(mri_dst, 0, x3, x2) ;
2877 for (x1 = 0 ; x1 < width ; x1++)
2878 {
2879 /* swap so in place transformations are possible */
2880 *pdst++ = *psrc++ ;
2881 }
2882 }
2883 }
2884 }
2885 else
2886 if ((src_slice_direction == MRI_SAGITTAL &&
2887 slice_direction == MRI_HORIZONTAL))
2888 {
2889 /*
2890 horizontal images are top to bottom of the head,
2891 thus the depth axis
2892 points from the top of the head to the neck, with x from
2893 ear to ear
2894 and y from nose to back of head.
2895 */
2896 /* x3 --> x2
2897 x1 --> x3
2898 x2 --> x1
2899 */
2900 if (!mri_dst)
2901 {
2902 mri_dst = MRIalloc(width, depth, height, mri_src->type) ;
2903 MRIcopyHeader(mri_src, mri_dst) ;
2904 }
2905 else if (depth != mri_dst->height || height != mri_dst->depth ||
2906 width != mri_dst->width)
2907 ErrorReturn(NULL,
2908 (ERROR_BADPARM,
2909 "MRIreslice: invalid destination size (%d, %d, %d)",
2910 mri_dst->width, mri_dst->height, mri_dst->depth)) ;
2911
2912 for (x3 = 0 ; x3 < depth ; x3++)
2913 {
2914 for (x2 = 0 ; x2 < height ; x2++)
2915 {
2916 psrc = &MRIvox(mri_src, 0, x2, x3) ;
2917 for (x1 = 0 ; x1 < width ; x1++)
2918 {
2919 /* swap so in place transformations are possible */
2920 mri_dst->slices[x2][x1][x3] = *psrc++ ;
2921 }
2922 }
2923 }
2924 }
2925 else
2926 if (src_slice_direction == MRI_HORIZONTAL &&
2927 slice_direction == MRI_SAGITTAL)
2928 {
2929 /*
2930 horizontal images are top to bottom of the head,
2931 thus the depth axis
2932 points from the top of the head to the neck,
2933 with x from ear to ear
2934 and y from nose to back of head.
2935 */
2936 /* x2 --> x3
2937 x3 --> x1
2938 x1 --> x2
2939 */
2940 if (!mri_dst)
2941 {
2942 mri_dst = MRIalloc(width, depth, height, mri_src->type) ;
2943 MRIcopyHeader(mri_src, mri_dst) ;
2944 }
2945 else if (depth != mri_dst->height || height != mri_dst->depth ||
2946 width != mri_dst->width)
2947 ErrorReturn(NULL,
2948 (ERROR_BADPARM,
2949 "MRIreslice: invalid destination size (%d, %d, %d)",
2950 mri_dst->width, mri_dst->height, mri_dst->depth)) ;
2951
2952 for (x3 = 0 ; x3 < depth ; x3++)
2953 {
2954 for (x2 = 0 ; x2 < height ; x2++)
2955 {
2956 psrc = &MRIvox(mri_src, 0, x2, x3) ;
2957 for (x1 = 0 ; x1 < width ; x1++)
2958 {
2959 /* swap so in place transformations are possible */
2960 mri_dst->slices[x1][x3][x2] = *psrc++ ;
2961 }
2962 }
2963 }
2964 }
2965 else
2966 switch (src_slice_direction)
2967 {
2968 default:
2969 MRIfree(&mri_dst) ;
2970 ErrorReturn(NULL,
2971 (ERROR_BADPARM,
2972 "MRIreslice: mri_src unknown slice direction %d",
2973 src_slice_direction)) ;
2974 break ;
2975 case MRI_CORONAL:
2976 /*
2977 coronal images are back to front of the head,
2978 thus the depth axis
2979 points from the nose to the back of the head,
2980 with x from neck to
2981 crown, and y from ear to ear.
2982 */
2983 switch (slice_direction)
2984 {
2985 case MRI_SAGITTAL:
2986 /* x1 --> x3
2987 x2 --> x2
2988 x3 --> x1
2989 */
2990 if (!mri_dst)
2991 {
2992 mri_dst = MRIalloc(depth, height, width, mri_src->type) ;
2993 MRIcopyHeader(mri_src, mri_dst) ;
2994 }
2995 else if (depth != mri_dst->width ||
2996 height != mri_dst->height ||
2997 width != mri_dst->depth)
2998 ErrorReturn
2999 (NULL,
3000 (ERROR_BADPARM,
3001 "MRIreslice: invalid destination size (%d, %d, %d)",
3002 mri_dst->width, mri_dst->height, mri_dst->depth)) ;
3003
3004 for (x3 = 0 ; x3 < depth ; x3++)
3005 {
3006 for (x2 = 0 ; x2 < height ; x2++)
3007 {
3008 psrc = &MRIvox(mri_src, 0, x2, x3) ;
3009 for (x1 = 0 ; x1 < width ; x1++)
3010 {
3011 /* swap so in place transformations
3012 are possible */
3013 val = *psrc++ ;
3014 #if 0
3015 mri_dst->slices[x3][x2][x1] =
3016 mri_src->slices[x1][x2][x3] ;
3017 #endif
3018 mri_dst->slices[x1][x2][x3] = val ;
3019 }
3020 }
3021 }
3022 break ;
3023 case MRI_HORIZONTAL:
3024 break ;
3025 }
3026 break ;
3027 case MRI_SAGITTAL:
3028 /*
3029 sagittal images are slices in
3030 the plane of the nose, with depth going
3031 from ear to ear.
3032 */
3033 break ;
3034 }
3035 setDirectionCosine(mri_dst, slice_direction);
3036 mri_dst->ras_good_flag = 0;
3037 return(mri_dst) ;
3038 }
3039 /*-----------------------------------------------------
3040 Parameters:
3041
3042 Returns value:
3043
3044 Description
3045 Set an MRI intensity values to 0
3046 ------------------------------------------------------*/
3047 int
3048 MRIclear(MRI *mri)
3049 {
3050 int width, depth, height, bytes, y, z, frame, nframes ;
3051
3052 width = mri->width ;
3053 height = mri->height ;
3054 depth = mri->depth ;
3055 nframes = mri->nframes ;
3056 bytes = width ;
3057
3058 switch (mri->type)
3059 {
3060 case MRI_UCHAR:
3061 bytes *= sizeof(unsigned char) ;
3062 break ;
3063 case MRI_BITMAP:
3064 bytes /= 8 ;
3065 break ;
3066 case MRI_FLOAT:
3067 bytes *= sizeof(float) ;
3068 break ;
3069 case MRI_LONG:
3070 bytes *= sizeof(long) ;
3071 break ;
3072 case MRI_INT:
3073 bytes *= sizeof(int) ;
3074 break ;
3075 case MRI_SHORT:
3076 bytes *= sizeof(short) ;
3077 break ;
3078 default:
3079 ErrorReturn(ERROR_UNSUPPORTED,
3080 (ERROR_UNSUPPORTED,
3081 "MRIclear: unsupported input type %d", mri->type)) ;
3082 break ;
3083 }
3084
3085 for (frame = 0 ; frame < nframes ; frame++)
3086 {
3087 for (z = 0 ; z < depth ; z++)
3088 {
3089 for (y = 0 ; y < height ; y++)
3090 memset(mri->slices[z+frame*depth][y], 0, bytes) ;
3091 }
3092 }
3093
3094 return(NO_ERROR) ;
3095 }
3096 /*-----------------------------------------------------
3097 Parameters:
3098
3099 Returns value:
3100
3101 Description
3102 find the principle components of a (binary) MRI. The
3103 eigenvectors are the columns of the matrix mEvectors, the
3104 eigenvalues are returned in the array evalues and the means
3105 in means (these last two must be three elements long.)
3106 ------------------------------------------------------*/
3107 int
3108 MRIcenterOfMass(MRI *mri,double *means, BUFTYPE threshold)
3109 {
3110 int width, height, depth, x, y, z ;
3111 long npoints ;
3112 double mx, my, mz, weight ;
3113 Real val ;
3114
3115 width = mri->width ;
3116 height = mri->height ;
3117 depth = mri->depth ;
3118
3119 mx = my = mz = weight = 0.0f ; npoints = 0L ;
3120
3121 for (z = 0 ; z < depth ; z++)
3122 {
3123 for (y = 0 ; y < height ; y++)
3124 {
3125 for (x = 0 ; x < width ; x++)
3126 {
3127 MRIsampleVolumeType(mri, x, y, z, &val, SAMPLE_NEAREST) ;
3128 if (val > threshold)
3129 {
3130 weight += val ;
3131 mx += (float)x*val ;
3132 my += (float)y*val ;
3133 mz += (float)z*val ;
3134 npoints++ ;
3135 }
3136 }
3137 }
3138 }
3139
3140 if (weight > 0.0)
3141 {
3142 mx /= weight ;
3143 my /= weight ;
3144 mz /= weight ;
3145 means[0] = mx ;
3146 means[1] = my ;
3147 means[2] = mz ;
3148 }
3149 else
3150 means[0] = means[1] = means[2] = 0.0f ;
3151
3152
3153 return(NO_ERROR) ;
3154 }
3155 /*-----------------------------------------------------
3156 Parameters:
3157
3158 Returns value:
3159
3160 Description
3161 find the principle components of a (binary) MRI. The
3162 eigenvectors are the columns of the matrix mEvectors, the
3163 eigenvalues are returned in the array evalues and the means
3164 in means (these last two must be three elements long.)
3165 ------------------------------------------------------*/
3166 int
3167 MRIprincipleComponents(MRI *mri, MATRIX *mEvectors, float *evalues,
3168 double *means, BUFTYPE threshold)
3169 {
3170 int width, height, depth, x, y, z ;
3171 BUFTYPE *psrc, val ;
3172 long npoints ;
3173 MATRIX *mCov, *mX, *mXT, *mTmp ;
3174 double mx, my, mz, weight ;
3175
3176 if (mri->type != MRI_UCHAR)
3177 ErrorReturn(ERROR_UNSUPPORTED,
3178 (ERROR_UNSUPPORTED,
3179 "MRIprincipleComponents: unsupported input type %d",
3180 mri->type)) ;
3181
3182 width = mri->width ;
3183 height = mri->height ;
3184 depth = mri->depth ;
3185
3186 mx = my = mz = weight = 0.0f ; npoints = 0L ;
3187
3188 for (z = 0 ; z < depth ; z++)
3189 {
3190 for (y = 0 ; y < height ; y++)
3191 {
3192 psrc = &MRIvox(mri, 0, y, z) ;
3193 for (x = 0 ; x < width ; x++)
3194 {
3195 val = *psrc++ ;
3196 if (val > threshold)
3197 {
3198 weight += val ;
3199 mx += (float)x*val ;
3200 my += (float)y*val ;
3201 mz += (float)z*val ;
3202 npoints++ ;
3203 }
3204 }
3205 }
3206 }
3207
3208 if (weight > 0.0)
3209 {
3210 mx /= weight ;
3211 my /= weight ;
3212 mz /= weight ;
3213 means[0] = mx ;
3214 means[1] = my ;
3215 means[2] = mz ;
3216 }
3217 else
3218 means[0] = means[1] = means[2] = 0.0f ;
3219
3220 mX = MatrixAlloc(3, 1, MATRIX_REAL) ; /* zero-mean coordinate vector */
3221 mXT = NULL ; /* transpose of above */
3222 mTmp = MatrixAlloc(3, 3, MATRIX_REAL) ; /* tmp matrix for covariance */
3223 mCov = MatrixAlloc(3, 3, MATRIX_REAL) ; /* covariance matrix */
3224
3225 for (z = 0 ; z < depth ; z++)
3226 {
3227 for (y = 0 ; y < height ; y++)
3228 {
3229 psrc = &MRIvox(mri, 0, y, z) ;
3230 for (x = 0 ; x < width ; x++)
3231 {
3232 val = *psrc++ ;
3233 if (val > threshold)
3234 {
3235 mX->rptr[1][1] = (x - (int)mx)*val ;
3236 mX->rptr[2][1] = (y - (int)my)*val ;
3237 mX->rptr[3][1] = (z - (int)mz)*val ;
3238 mXT = MatrixTranspose(mX, mXT) ;
3239 mTmp = MatrixMultiply(mX, mXT, mTmp) ;
3240 mCov = MatrixAdd(mTmp, mCov, mCov) ;
3241 }
3242 }
3243 }
3244 }
3245
3246 if (weight > 0)
3247 MatrixScalarMul(mCov, 1.0f/weight, mCov) ;
3248
3249 MatrixEigenSystem(mCov, evalues, mEvectors) ;
3250
3251 return(NO_ERROR) ;
3252 }
3253 /*-----------------------------------------------------
3254 Parameters:
3255
3256 Returns value:
3257
3258 Description
3259 find the principle components of a (binary) MRI. The
3260 eigenvectors are the columns of the matrix mEvectors, the
3261 eigenvalues are returned in the array evalues and the means
3262 in means (these last two must be three elements long.)
3263 ------------------------------------------------------*/
3264 int
3265 MRIbinaryPrincipleComponents(MRI *mri, MATRIX *mEvectors, float *evalues,
3266 double *means, BUFTYPE threshold)
3267 {
3268 int width, height, depth, x, y, z ;
3269 BUFTYPE *psrc, val ;
3270 long npoints ;
3271 MATRIX *mCov, *mX, *mXT, *mTmp ;
3272 double mx, my, mz, weight ;
3273
3274 if (mri->type != MRI_UCHAR)
3275 ErrorReturn(ERROR_UNSUPPORTED,
3276 (ERROR_UNSUPPORTED,
3277 "MRIprincipleComponents: unsupported input type %d",
3278 mri->type)) ;
3279
3280 width = mri->width ;
3281 height = mri->height ;
3282 depth = mri->depth ;
3283
3284 mx = my = mz = weight = 0.0f ; npoints = 0L ;
3285
3286 for (z = 0 ; z < depth ; z++)
3287 {
3288 for (y = 0 ; y < height ; y++)
3289 {
3290 psrc = &MRIvox(mri, 0, y, z) ;
3291 for (x = 0 ; x < width ; x++)
3292 {
3293 val = *psrc++ ;
3294 if (val > threshold)
3295 {
3296 weight++ ;
3297 mx += (float)x ;
3298 my += (float)y ;
3299 mz += (float)z ;
3300 npoints++ ;
3301 }
3302 }
3303 }
3304 }
3305
3306 if (weight > 0.0)
3307 {
3308 mx /= weight ;
3309 my /= weight ;
3310 mz /= weight ;
3311 means[0] = mx ;
3312 means[1] = my ;
3313 means[2] = mz ;
3314 }
3315 else
3316 means[0] = means[1] = means[2] = 0.0f ;
3317
3318 mX = MatrixAlloc(3, 1, MATRIX_REAL) ; /* zero-mean coordinate vector */
3319 mXT = NULL ; /* transpose of above */
3320 mTmp = MatrixAlloc(3, 3, MATRIX_REAL) ; /* tmp matrix for covariance */
3321 mCov = MatrixAlloc(3, 3, MATRIX_REAL) ; /* covariance matrix */
3322
3323 for (z = 0 ; z < depth ; z++)
3324 {
3325 for (y = 0 ; y < height ; y++)
3326 {
3327 psrc = &MRIvox(mri, 0, y, z) ;
3328 for (x = 0 ; x < width ; x++)
3329 {
3330 val = *psrc++ ;
3331 if (val > threshold)
3332 {
3333 mX->rptr[1][1] = (x - (int)mx) ;
3334 mX->rptr[2][1] = (y - (int)my) ;
3335 mX->rptr[3][1] = (z - (int)mz) ;
3336 mXT = MatrixTranspose(mX, mXT) ;
3337 mTmp = MatrixMultiply(mX, mXT, mTmp) ;
3338 mCov = MatrixAdd(mTmp, mCov, mCov) ;
3339 }
3340 }
3341 }
3342 }
3343
3344 if (weight > 0)
3345 MatrixScalarMul(mCov, 1.0f/weight, mCov) ;
3346
3347 MatrixEigenSystem(mCov, evalues, mEvectors) ;
3348
3349 return(NO_ERROR) ;
3350 }
3351 /*-----------------------------------------------------
3352 Parameters:
3353
3354 Returns value:
3355
3356 Description
3357 threshold an MRI.
3358 ------------------------------------------------------*/
3359 MRI *
3360 MRIthresholdRangeInto(MRI *mri_src,MRI *mri_dst,BUFTYPE low_val,BUFTYPE hi_val)
3361 {
3362 int width, height, depth, x, y, z ;
3363 BUFTYPE *psrc, *pdst, val ;
3364 float *pfsrc, *pfdst, fval ;
3365
3366 if (!mri_dst)
3367 mri_dst = MRIclone(mri_src, NULL) ;
3368
3369 width = mri_src->width ;
3370 height = mri_src->height ;
3371 depth = mri_src->depth ;
3372
3373 switch (mri_src->type)
3374 {
3375 case MRI_UCHAR:
3376 for (z = 0 ; z < depth ; z++)
3377 {
3378 for (y = 0 ; y < height ; y++)
3379 {
3380 psrc = &MRIvox(mri_src, 0, y, z) ;
3381 pdst = &MRIvox(mri_dst, 0, y, z) ;
3382 for (x = 0 ; x < width ; x++, pdst++)
3383 {
3384 val = *psrc++ ;
3385 if (val >= low_val && val <= hi_val)
3386 *pdst = val ;
3387 else
3388 *pdst = 0 ;
3389 }
3390 }
3391 }
3392 break ;
3393 case MRI_FLOAT:
3394 for (z = 0 ; z < depth ; z++)
3395 {
3396 for (y = 0 ; y < height ; y++)
3397 {
3398 pfsrc = &MRIFvox(mri_src, 0, y, z) ;
3399 pfdst = &MRIFvox(mri_dst, 0, y, z) ;
3400 for (x = 0 ; x < width ; x++, pdst++)
3401 {
3402 fval = *pfsrc++ ;
3403 if (fval >= low_val && fval <= hi_val)
3404 *pfdst = fval ;
3405 else
3406 *pfdst = 0 ;
3407 }
3408 }
3409 }
3410 break ;
3411 default:
3412 ErrorReturn(mri_dst,
3413 (ERROR_UNSUPPORTED,
3414 "MRIthresholdRangeInto: unsupported type %d",
3415 mri_src->type)) ;
3416 break ;
3417 }
3418 return(mri_dst) ;
3419 }
3420 /*-----------------------------------------------------
3421 Parameters:
3422
3423 Returns value:
3424
3425 Description
3426 threshold an MRI.
3427 ------------------------------------------------------*/
3428 MRI *
3429 MRIthreshold(MRI *mri_src, MRI *mri_dst, float threshold)
3430 {
3431 int width, height, depth, x, y, z ;
3432 float val ;
3433
3434 if (!mri_dst)
3435 mri_dst = MRIclone(mri_src, NULL) ;
3436
3437 width = mri_src->width ;
3438 height = mri_src->height ;
3439 depth = mri_src->depth ;
3440
3441 for (z = 0 ; z < depth ; z++)
3442 {
3443 for (y = 0 ; y < height ; y++)
3444 {
3445 for (x = 0 ; x < width ; x++)
3446 {
3447 val = MRIgetVoxVal(mri_src, x, y, z, 0) ;
3448 if (val < threshold)
3449 val = 0 ;
3450 MRIsetVoxVal(mri_dst, x, y, z, 0, val) ;
3451 }
3452 }
3453 }
3454
3455 return(mri_dst) ;
3456 }
3457 /*-----------------------------------------------------
3458 Parameters:
3459
3460 Returns value:
3461
3462 Description
3463 threshold an MRI.
3464 ------------------------------------------------------*/
3465 MRI *
3466 MRIinvertContrast(MRI *mri_src, MRI *mri_dst, float threshold)
3467 {
3468 int width, height, depth, x, y, z ;
3469 BUFTYPE *psrc, *pdst, val ;
3470
3471 if (!mri_dst)
3472 mri_dst = MRIclone(mri_src, NULL) ;
3473
3474 width = mri_src->width ;
3475 height = mri_src->height ;
3476 depth = mri_src->depth ;
3477
3478 for (z = 0 ; z < depth ; z++)
3479 {
3480 for (y = 0 ; y < height ; y++)
3481 {
3482 psrc = &MRIvox(mri_src, 0, y, z) ;
3483 pdst = &MRIvox(mri_dst, 0, y, z) ;
3484 for (x = 0 ; x < width ; x++)
3485 {
3486 val = *psrc++ ;
3487 if (val > threshold)
3488 val = 255 - val ;
3489 *pdst++ = val ;
3490 }
3491 }
3492 }
3493
3494 return(mri_dst) ;
3495 }
3496 /*-----------------------------------------------------
3497 Parameters:
3498
3499 Returns value:
3500
3501 Description
3502 threshold an MRI.
3503 ------------------------------------------------------*/
3504 MRI *
3505 MRIbinarize(MRI *mri_src, MRI *mri_dst, BUFTYPE threshold, BUFTYPE low_val,
3506 BUFTYPE hi_val)
3507 {
3508 int width, height, depth, x, y, z, f ;
3509 Real val ;
3510
3511 if (!mri_dst)
3512 mri_dst = MRIclone(mri_src, NULL) ;
3513
3514 width = mri_src->width ;
3515 height = mri_src->height ;
3516 depth = mri_src->depth ;
3517
3518 for (f = 0 ; f < mri_src->nframes ; f++)
3519 {
3520 for (z = 0 ; z < depth ; z++)
3521 {
3522 for (y = 0 ; y < height ; y++)
3523 {
3524 for (x = 0 ; x < width ; x++)
3525 {
3526 MRIsampleVolumeFrameType
3527 (mri_src, x, y, z, f, SAMPLE_NEAREST, &val) ;
3528 if (val < threshold)
3529 val = low_val ;
3530 else
3531 val = hi_val ;
3532 MRIsetVoxVal(mri_dst, x, y, z, f, val) ;
3533 }
3534 }
3535 }
3536 }
3537
3538 return(mri_dst) ;
3539 }
3540
3541 /*-----------------------------------------------------*/
3542 MRI *MRIsubtract(MRI *mri1, MRI *mri2, MRI *mri_dst)
3543 {
3544 int nframes, width, height, depth, x, y, z, f, s ;
3545 float v1, v2, v=0.0;
3546 BUFTYPE *p1=NULL, *p2=NULL, *pdst=NULL ;
3547 short *ps1=NULL, *ps2=NULL, *psdst=NULL ;
3548 int *pi1=NULL, *pi2=NULL, *pidst=NULL ;
3549 long *pl1=NULL, *pl2=NULL, *pldst=NULL ;
3550 float *pf1=NULL, *pf2=NULL, *pfdst=NULL ;
3551
3552 width = mri1->width ;
3553 height = mri1->height ;
3554 depth = mri1->depth ;
3555 nframes = mri1->nframes ;
3556 if(nframes == 0) nframes = 1;
3557
3558 if (!mri_dst){
3559 mri_dst = MRIallocSequence(width, height, depth, mri1->type,nframes) ;
3560 MRIcopyHeader(mri1, mri_dst) ;
3561 }
3562
3563 if(mri1->type != mri2->type){
3564 /* Generic but slow */
3565 for (f = 0 ; f < nframes ; f++){
3566 for (z = 0 ; z < depth ; z++){
3567 for (y = 0 ; y < height ; y++){
3568 for (x = 0 ; x < width ; x++){
3569 v1 = MRIgetVoxVal(mri1,x,y,z,f);
3570 v2 = MRIgetVoxVal(mri2,x,y,z,f);
3571 v = v1-v2;
3572 MRIsetVoxVal(mri_dst,x,y,z,f,v);
3573 }
3574 }
3575 }
3576 }
3577 return(mri_dst) ;
3578 }
3579
3580
3581 s = 0;
3582 for (f = 0 ; f < nframes ; f++){
3583 for (z = 0 ; z < depth ; z++){
3584 for (y = 0 ; y < height ; y++){
3585
3586 switch(mri_dst->type){
3587 case MRI_UCHAR: pdst = mri_dst->slices[s][y] ; break;
3588 case MRI_SHORT: psdst = (short *) mri_dst->slices[s][y] ; break;
3589 case MRI_INT: pidst = (int *) mri_dst->slices[s][y] ; break;
3590 case MRI_LONG: pldst = (long *) mri_dst->slices[s][y] ; break;
3591 case MRI_FLOAT: pfdst = (float *) mri_dst->slices[s][y] ; break;
3592 }
3593 switch(mri1->type){
3594 case MRI_UCHAR:
3595 p1 = mri1->slices[s][y] ;
3596 p2 = mri2->slices[s][y] ;
3597 break;
3598 case MRI_SHORT:
3599 ps1 = (short *) mri1->slices[s][y] ;
3600 ps2 = (short *) mri2->slices[s][y] ;
3601 break;
3602 case MRI_INT:
3603 pi1 = (int *) mri1->slices[s][y] ;
3604 pi2 = (int *) mri2->slices[s][y] ;
3605 break;
3606 case MRI_LONG:
3607 pl1 = (long *) mri1->slices[s][y] ;
3608 pl2 = (long *) mri2->slices[s][y] ;
3609 break;
3610 case MRI_FLOAT:
3611 pf1 = (float *) mri1->slices[s][y] ;
3612 pf2 = (float *) mri2->slices[s][y] ;
3613 break;
3614 }
3615
3616 for (x = 0 ; x < width ; x++){
3617
3618 switch(mri1->type){
3619 case MRI_UCHAR: v = (float)(*p1++) - (float)(*p2++); break;
3620 case MRI_SHORT: v = (float)(*ps1++) - (float)(*ps2++); break;
3621 case MRI_INT: v = (float)(*pi1++) - (float)(*pi2++); break;
3622 case MRI_LONG: v = (float)(*pl1++) - (float)(*pl2++); break;
3623 case MRI_FLOAT: v = (float)(*pf1++) - (float)(*pf2++); break;
3624 }
3625
3626 switch(mri_dst->type){
3627 case MRI_UCHAR: (*pdst++) = (BUFTYPE) v; break;
3628 case MRI_SHORT: (*psdst++) = (short) v; break;
3629 case MRI_INT: (*pidst++) = (int) v; break;
3630 case MRI_LONG: (*pldst++) = (long) v; break;
3631 case MRI_FLOAT: (*pfdst++) = (float) v; break;
3632 }
3633
3634 }
3635 }
3636 s++;
3637 }
3638 }
3639
3640 return(mri_dst) ;
3641 }
3642 #if 0
3643 /*------------------------------------------------------
3644 MRIsubtract(mri1,mri2,mridiff) - computes mri1-mri2.
3645 ------------------------------------------------------*/
3646 MRI *MRIsubtract(MRI *mri1, MRI *mri2, MRI *mri_dst)
3647 {
3648 int nframes, width, height, depth, x, y, z, f ;
3649 float v1, v2, vdiff;
3650
3651 width = mri1->width ;
3652 height = mri1->height ;
3653 depth = mri1->depth ;
3654 nframes = mri1->nframes ;
3655 if(nframes == 0) nframes = 1;
3656
3657 if (!mri_dst){
3658 mri_dst = MRIallocSequence(width, height, depth, mri1->type,nframes) ;
3659 MRIcopyHeader(mri1, mri_dst) ;
3660 }
3661
3662 for (z = 0 ; z < depth ; z++){
3663 for (y = 0 ; y < height ; y++){
3664 for (x = 0 ; x < width ; x++){
3665 for (f = 0 ; f < nframes ; f++){
3666 v1 = MRIgetVoxVal(mri1,x,y,z,f);
3667 v2 = MRIgetVoxVal(mri2,x,y,z,f);
3668 vdiff = v1-v2;
3669 MRIsetVoxVal(mri_dst,x,y,z,f,vdiff);
3670 }
3671 }
3672 }
3673 }
3674 return(mri_dst) ;
3675 }
3676 #endif
3677 /*-----------------------------------------------------
3678 ------------------------------------------------------*/
3679 MRI *
3680 MRIabsdiff(MRI *mri1, MRI *mri2, MRI *mri_dst)
3681 {
3682 int width, height, depth, x, y, z ;
3683 BUFTYPE *p1, *p2, *pdst, v1, v2 ;
3684 float f1, f2 ;
3685
3686 width = mri1->width ;
3687 height = mri1->height ;
3688 depth = mri1->depth ;
3689
3690 if (!mri_dst)
3691 {
3692 mri_dst = MRIalloc(width, height, depth, mri1->type) ;
3693 MRIcopyHeader(mri1, mri_dst) ;
3694 }
3695
3696 if (mri1->type == MRI_UCHAR && mri2->type == MRI_UCHAR)
3697 {
3698 for (z = 0 ; z < depth ; z++)
3699 {
3700 for (y = 0 ; y < height ; y++)
3701 {
3702 p1 = mri1->slices[z][y] ;
3703 p2 = mri2->slices[z][y] ;
3704 pdst = mri_dst->slices[z][y] ;
3705 for (x = 0 ; x < width ; x++)
3706 {
3707 v1 = *p1++ ;
3708 v2 = *p2++ ;
3709 if (v1 > v2)
3710 *pdst++ = v1 - v2 ;
3711 else
3712 *pdst++ = v2 - v1 ;
3713 }
3714 }
3715 }
3716 }
3717 else
3718 {
3719 for (z = 0 ; z < depth ; z++)
3720 {
3721 for (y = 0 ; y < height ; y++)
3722 {
3723 for (x = 0 ; x < width ; x++)
3724 {
3725 f1 = MRIgetVoxVal(mri1, x, y, z, 0) ;
3726 f2 = MRIgetVoxVal(mri2, x, y, z, 0) ;
3727 MRIsetVoxVal(mri_dst, x, y, z, 0, fabs(f1 - f2)) ;
3728 }
3729 }
3730 }
3731 }
3732 return(mri_dst) ;
3733 }
3734 /*-----------------------------------------------------
3735 ------------------------------------------------------*/
3736 MRI *MRIabs(MRI *mri_src, MRI *mri_dst)
3737 {
3738 int width, height, depth, nframes, x, y, z,f ;
3739 float val;
3740
3741 width = mri_src->width ;
3742 height = mri_src->height ;
3743 depth = mri_src->depth ;
3744 nframes = mri_src->nframes;
3745
3746 if (!mri_dst){
3747 mri_dst = MRIallocSequence(width, height, depth, mri_src->type, nframes) ;
3748 MRIcopyHeader(mri_src, mri_dst) ;
3749 }
3750
3751 for (z = 0 ; z < depth ; z++){
3752 for (y = 0 ; y < height ; y++){
3753 for (x = 0 ; x < width ; x++){
3754 for (f = 0 ; f < nframes ; f++){
3755 val = fabs(MRIgetVoxVal(mri_src,x,y,z,f));
3756 MRIsetVoxVal(mri_src,x,y,z,f,val);
3757 }
3758 }
3759 }
3760 }
3761 return(mri_dst) ;
3762 }
3763 /*-----------------------------------------------------*/
3764 MRI * MRIadd(MRI *mri1, MRI *mri2, MRI *mri_dst)
3765 {
3766 int nframes, width, height, depth, x, y, z, f, s ;
3767 float v1, v2, v=0.0;
3768 BUFTYPE *p1=NULL, *p2=NULL, *pdst=NULL ;
3769 short *ps1=NULL, *ps2=NULL, *psdst=NULL ;
3770 int *pi1=NULL, *pi2=NULL, *pidst=NULL ;
3771 long *pl1=NULL, *pl2=NULL, *pldst=NULL ;
3772 float *pf1=NULL, *pf2=NULL, *pfdst=NULL ;
3773
3774 width = mri1->width ;
3775 height = mri1->height ;
3776 depth = mri1->depth ;
3777 nframes = mri1->nframes ;
3778 if(nframes == 0) nframes = 1;
3779
3780 if (!mri_dst){
3781 mri_dst = MRIallocSequence(width, height, depth, mri1->type,nframes) ;
3782 MRIcopyHeader(mri1, mri_dst) ;
3783 }
3784
3785 if(mri1->type == MRI_UCHAR || (mri1->type != mri2->type)){
3786 /* Generic but slow */
3787 for (f = 0 ; f < nframes ; f++){
3788 for (z = 0 ; z < depth ; z++){
3789 for (y = 0 ; y < height ; y++){
3790 for (x = 0 ; x < width ; x++){
3791 v1 = MRIgetVoxVal(mri1,x,y,z,f);
3792 v2 = MRIgetVoxVal(mri2,x,y,z,f);
3793 v = v1+v2;
3794 if (mri_dst->type == MRI_UCHAR && v > 255)
3795 v = 255 ;
3796 MRIsetVoxVal(mri_dst,x,y,z,f,v);
3797 }
3798 }
3799 }
3800 }
3801 return(mri_dst) ;
3802 }
3803
3804
3805 s = 0;
3806 for (f = 0 ; f < nframes ; f++){
3807 for (z = 0 ; z < depth ; z++){
3808 for (y = 0 ; y < height ; y++){
3809
3810 switch(mri_dst->type){
3811 case MRI_UCHAR: pdst = mri_dst->slices[s][y] ; break;
3812 case MRI_SHORT: psdst = (short *) mri_dst->slices[s][y] ; break;
3813 case MRI_INT: pidst = (int *) mri_dst->slices[s][y] ; break;
3814 case MRI_LONG: pldst = (long *) mri_dst->slices[s][y] ; break;
3815 case MRI_FLOAT: pfdst = (float *) mri_dst->slices[s][y] ; break;
3816 }
3817
3818 switch(mri1->type){
3819 case MRI_UCHAR:
3820 p1 = mri1->slices[s][y] ;
3821 p2 = mri2->slices[s][y] ;
3822 break;
3823 case MRI_SHORT:
3824 ps1 = (short *) mri1->slices[s][y] ;
3825 ps2 = (short *) mri2->slices[s][y] ;
3826 break;
3827 case MRI_INT:
3828 pi1 = (int *) mri1->slices[s][y] ;
3829 pi2 = (int *) mri2->slices[s][y] ;
3830 break;
3831 case MRI_LONG:
3832 pl1 = (long *) mri1->slices[s][y] ;
3833 pl2 = (long *) mri2->slices[s][y] ;
3834 break;
3835 case MRI_FLOAT:
3836 pf1 = (float *) mri1->slices[s][y] ;
3837 pf2 = (float *) mri2->slices[s][y] ;
3838 break;
3839 }
3840
3841 for (x = 0 ; x < width ; x++){
3842
3843 switch(mri_dst->type){
3844 case MRI_UCHAR:
3845 switch(mri1->type){
3846 case MRI_UCHAR: (*pdst++) = (BUFTYPE) ((*p1++)+(*p2++)); break;
3847 case MRI_SHORT: (*pdst++) = (BUFTYPE) ((*ps1++)+(*ps2++)); break;
3848 case MRI_INT: (*pdst++) = (BUFTYPE) ((*pi1++)+(*pi2++)); break;
3849 case MRI_LONG: (*pdst++) = (BUFTYPE) ((*pl1++)+(*pl2++)); break;
3850 case MRI_FLOAT: (*pdst++) = (BUFTYPE) ((*pf1++)+(*pf2++)); break;
3851 }
3852 break;
3853 case MRI_SHORT:
3854 switch(mri1->type){
3855 case MRI_UCHAR: (*psdst++) = ((short)(*p1++)+(*p2++)); break;
3856 case MRI_SHORT: (*psdst++) = (short) ((*ps1++)+(*ps2++)); break;
3857 case MRI_INT: (*psdst++) = (short) ((*pi1++)+(*pi2++)); break;
3858 case MRI_LONG: (*psdst++) = (short) ((*pl1++)+(*pl2++)); break;
3859 case MRI_FLOAT: (*psdst++) = (short) ((*pf1++)+(*pf2++)); break;
3860 }
3861 break;
3862 case MRI_INT:
3863 switch(mri1->type){
3864 case MRI_UCHAR: (*pidst++) = ((int)(*p1++)+(*p2++)); break;
3865 case MRI_SHORT: (*pidst++) = ((int)(*ps1++)+(*ps2++)); break;
3866 case MRI_INT: (*pidst++) = (int) ((*pi1++)+(*pi2++)); break;
3867 case MRI_LONG: (*pidst++) = (int) ((*pl1++)+(*pl2++)); break;
3868 case MRI_FLOAT: (*pidst++) = (int) ((*pf1++)+(*pf2++)); break;
3869 }
3870 break;
3871 case MRI_LONG:
3872 switch(mri1->type){
3873 case MRI_UCHAR: (*pldst++) = ((long)(*p1++)+(*p2++)); break;
3874 case MRI_SHORT: (*pldst++) = ((long)(*ps1++)+(*ps2++)); break;
3875 case MRI_INT: (*pldst++) = ((long)(*pi1++)+(*pi2++)); break;
3876 case MRI_LONG: (*pldst++) = (long) ((*pl1++)+(*pl2++)); break;
3877 case MRI_FLOAT: (*pldst++) = (long) ((*pf1++)+(*pf2++)); break;
3878 }
3879 break;
3880 case MRI_FLOAT:
3881 switch(mri1->type){
3882 case MRI_UCHAR: (*pfdst++) = ((float)(*p1++)+(*p2++)); break;
3883 case MRI_SHORT: (*pfdst++) = ((float)(*ps1++)+(*ps2++)); break;
3884 case MRI_INT: (*pfdst++) = ((float)(*pi1++)+(*pi2++)); break;
3885 case MRI_LONG: (*pfdst++) = ((float)(*pl1++)+(*pl2++)); break;
3886 case MRI_FLOAT: (*pfdst++) = (*pf1++)+(*pf2++); break;
3887 }
3888 break;
3889 }
3890 }
3891 }
3892 s++;
3893 }
3894 }
3895
3896 return(mri_dst) ;
3897 }
3898 /*-----------------------------------------------------------
3899 MRIaverage() - computes average of source and destination.
3900 ------------------------------------------------------*/
3901 MRI *
3902 MRIaverage(MRI *mri_src, int dof, MRI *mri_dst)
3903 {
3904 int width, height, depth, x, y, z, f ;
3905 Real src, dst ;
3906
3907 width = mri_src->width ;
3908 height = mri_src->height ;
3909 depth = mri_src->depth ;
3910
3911 if (!mri_dst)
3912 {
3913 mri_dst = MRIalloc(width, height, depth, mri_src->type) ;
3914 MRIcopyHeader(mri_src, mri_dst) ;
3915 }
3916
3917 if (!MRIcheckSize(mri_src, mri_dst,0,0,0))
3918 ErrorReturn(NULL,
3919 (ERROR_BADPARM,"MRIaverage: incompatible volume dimensions"));
3920 #if 0
3921 if ((mri_src->type != MRI_UCHAR) || (mri_dst->type != MRI_UCHAR))
3922 ErrorReturn(NULL,
3923 (ERROR_UNSUPPORTED,
3924 "MRISaverage: unsupported voxel format %d",mri_src->type));
3925 #endif
3926
3927 for (f = 0 ; f < mri_src->nframes ; f++)
3928 {
3929 for (z = 0 ; z < depth ; z++)
3930 {
3931 for (y = 0 ; y < height ; y++)
3932 {
3933 for (x = 0 ; x < width ; x++)
3934 {
3935 MRIsampleVolumeFrameType
3936 (mri_src, x, y, z, f, SAMPLE_NEAREST, &src) ;
3937 MRIsampleVolumeFrameType
3938 (mri_dst, x, y, z, f, SAMPLE_NEAREST, &dst) ;
3939 MRIsetVoxVal
3940 (mri_dst, x, y, z, f, (dst*dof+src)/(Real)(dof+1)) ;
3941 }
3942 }
3943 }
3944 }
3945 return(mri_dst) ;
3946 }
3947 /*-----------------------------------------------------
3948 Parameters:
3949
3950 Returns value:
3951
3952 Description
3953
3954 ------------------------------------------------------*/
3955 MRI *
3956 MRImultiply(MRI *mri1, MRI *mri2, MRI *mri_dst)
3957 {
3958 int width, height, depth, x, y, z ;
3959 float f1, f2 ;
3960
3961 width = mri1->width ;
3962 height = mri1->height ;
3963 depth = mri1->depth ;
3964
3965 if (!mri_dst)
3966 {
3967 mri_dst = MRIalloc(width, height, depth, mri1->type) ;
3968 MRIcopyHeader(mri1, mri_dst) ;
3969 }
3970
3971 for (z = 0 ; z < depth ; z++)
3972 {
3973 for (y = 0 ; y < height ; y++)
3974 {
3975 for (x = 0 ; x < width ; x++)
3976 {
3977 f1 = MRIgetVoxVal(mri1, x, y, z, 0) ;
3978 f2 = MRIgetVoxVal(mri2, x, y, z, 0) ;
3979 MRIsetVoxVal(mri_dst, x, y, z, 0, f1*f2) ;
3980 }
3981 }
3982 }
3983 return(mri_dst) ;
3984 }
3985 /*-----------------------------------------------------
3986 Parameters:
3987
3988 Returns value:
3989
3990 Description
3991
3992 ------------------------------------------------------*/
3993 MRI *
3994 MRIscaleAndMultiply(MRI *mri1, float scale, MRI *mri2, MRI *mri_dst)
3995 {
3996 int width, height, depth, x, y, z ;
3997 BUFTYPE *p1, *p2, *pdst ;
3998 float out_val ;
3999
4000 width = mri1->width ;
4001 height = mri1->height ;
4002 depth = mri1->depth ;
4003
4004 if (!mri_dst)
4005 {
4006 mri_dst = MRIalloc(width, height, depth, mri1->type) ;
4007 MRIcopyHeader(mri1, mri_dst) ;
4008 }
4009
4010 for (z = 0 ; z < depth ; z++)
4011 {
4012 for (y = 0 ; y < height ; y++)
4013 {
4014 p1 = mri1->slices[z][y] ;
4015 p2 = mri2->slices[z][y] ;
4016 pdst = mri_dst->slices[z][y] ;
4017 for (x = 0 ; x < width ; x++)
4018 {
4019 out_val = *p1++ * (*p2++/scale) ;
4020 if (out_val > 255)
4021 out_val = 255 ;
4022 else if (out_val < 0)
4023 out_val = 0 ;
4024 *pdst++ = (BUFTYPE)nint(out_val) ;
4025 }
4026 }
4027 }
4028 return(mri_dst) ;
4029 }
4030 /*-----------------------------------------------------
4031 Parameters:
4032
4033 Returns value:
4034
4035 Description
4036
4037 ------------------------------------------------------*/
4038 MRI *
4039 MRIdivide(MRI *mri1, MRI *mri2, MRI *mri_dst)
4040 {
4041 int width, height, depth, x, y, z ;
4042 BUFTYPE *p1, *p2, *pdst ;
4043
4044 width = mri1->width ;
4045 height = mri1->height ;
4046 depth = mri1->depth ;
4047
4048 if (!mri_dst)
4049 {
4050 mri_dst = MRIalloc(width, height, depth, mri1->type) ;
4051 MRIcopyHeader(mri1, mri_dst) ;
4052 }
4053
4054 if (mri1->type != MRI_UCHAR || mri2->type != MRI_UCHAR)
4055 {
4056 Real val1, val2, dst ;
4057
4058 for (z = 0 ; z < depth ; z++)
4059 {
4060 for (y = 0 ; y < height ; y++)
4061 {
4062 pdst = mri_dst->slices[z][y] ;
4063 for (x = 0 ; x < width ; x++)
4064 {
4065 if (x == Gx && y == Gy && z==Gz)
4066 DiagBreak() ;
4067 val1 = MRIgetVoxVal(mri1, x, y, z, 0) ;
4068 val2 = MRIgetVoxVal(mri2, x, y, z, 0) ;
4069 if (FZERO(val2))
4070 {
4071 dst = FZERO(val1) ? 0 : 255 ;
4072 }
4073 else
4074 dst = val1 / val2 ;
4075 if (abs(dst) > 1000)
4076 DiagBreak() ;
4077 MRIsetVoxVal(mri_dst, x, y, z, 0, dst) ;
4078 }
4079 }
4080 }
4081 }
4082 else /* both UCHAR volumes */
4083 {
4084 for (z = 0 ; z < depth ; z++)
4085 {
4086 for (y = 0 ; y < height ; y++)
4087 {
4088 p1 = mri1->slices[z][y] ;
4089 p2 = mri2->slices[z][y] ;
4090 pdst = mri_dst->slices[z][y] ;
4091 for (x = 0 ; x < width ; x++)
4092 {
4093 if (!*p2)
4094 {
4095 *pdst = FZERO(*p1) ? 0 : 255 ;
4096 p2++ ;
4097 }
4098 else
4099 *pdst++ = *p1++ / *p2++ ;
4100 }
4101 }
4102 }
4103 }
4104 return(mri_dst) ;
4105 }
4106 /*-----------------------------------------------------
4107 MRIclone() - create a copy of an mri struct. Copies
4108 header info and allocs the pixel space (but does not
4109 copy pixel data).
4110 ------------------------------------------------------*/
4111 MRI *MRIclone(MRI *mri_src, MRI *mri_dst)
4112 {
4113 if (!mri_dst)
4114 mri_dst =
4115 MRIallocSequence(mri_src->width, mri_src->height,mri_src->depth,
4116 mri_src->type, mri_src->nframes);
4117
4118 MRIcopyHeader(mri_src, mri_dst) ;
4119 return(mri_dst) ;
4120 }
4121 /*---------------------------------------------------------------------
4122 MRIcloneSpace() - create a copy of an mri struct but allows user to
4123 set nframes (ie, all the spatial stuff is copied). Copies header
4124 info and allocs the pixel space (but does not copy pixel data).
4125 -------------------------------------------------------------------*/
4126 MRI *MRIcloneBySpace(MRI *mri_src, int nframes)
4127 {
4128 MRI *mri_dst;
4129 mri_dst = MRIallocSequence(mri_src->width, mri_src->height,mri_src->depth,
4130 mri_src->type, nframes);
4131 MRIcopyHeader(mri_src, mri_dst) ;
4132 mri_dst->nframes = nframes;
4133 return(mri_dst) ;
4134 }
4135 /*-----------------------------------------------------
4136 Description
4137 Copy one MRI into another (including header info)
4138 ------------------------------------------------------*/
4139 MRI *
4140 MRIcloneRoi(MRI *mri_src, MRI *mri_dst)
4141 {
4142 int w, h, d ;
4143
4144 w = mri_src->width - mri_src->roi.x ;
4145 h = mri_src->height - mri_src->roi.y ;
4146 d = mri_src->depth - mri_src->roi.z ;
4147 mri_dst = MRIallocSequence(w, h, d, MRI_FLOAT, mri_src->nframes) ;
4148 MRIcopyHeader(mri_src, mri_dst) ;
4149 mri_dst->xstart = mri_src->xstart + mri_src->roi.x * mri_src->xsize ;
4150 mri_dst->ystart = mri_src->ystart + mri_src->roi.y * mri_src->ysize ;
4151 mri_dst->zstart = mri_src->zstart + mri_src->roi.z * mri_src->zsize ;
4152 mri_dst->xend = mri_src->xstart + w * mri_src->xsize ;
4153 mri_dst->yend = mri_src->ystart + h * mri_src->ysize ;
4154 mri_dst->zend = mri_src->zstart + d * mri_src->zsize ;
4155 return(mri_dst) ;
4156 }
4157 /*-----------------------------------------------------
4158 Parameters:
4159
4160 Returns value:
4161
4162 Description
4163 Copy one MRI into another (including header info and data)
4164 ------------------------------------------------------*/
4165 MRI *
4166 MRIcopy(MRI *mri_src, MRI *mri_dst)
4167 {
4168 int width, height, depth, bytes, x, y, z, frame, val ;
4169 float *fdst, *fsrc ;
4170 BUFTYPE *csrc, *cdst ;
4171 int dest_ptype, *isrc;
4172 short *ssrc, *sdst ;
4173
4174 if (mri_src == mri_dst)
4175 return(mri_dst) ;
4176 width = mri_src->width ;
4177 height = mri_src->height ;
4178 depth = mri_src->depth ;
4179
4180 if (!mri_dst)
4181 {
4182 if(mri_src->slices)
4183 mri_dst = MRIallocSequence(width, height, depth, mri_src->type,
4184 mri_src->nframes) ;
4185 else
4186 mri_dst = MRIallocHeader(width, height, depth, mri_src->type);
4187 }
4188 dest_ptype = mri_dst->ptype;
4189 MRIcopyHeader(mri_src, mri_dst) ;
4190 mri_dst->ptype = dest_ptype;
4191
4192 if(!mri_src->slices)
4193 return(mri_dst);
4194
4195 if (mri_src->type == mri_dst->type)
4196 {
4197 bytes = width ;
4198 switch (mri_src->type)
4199 {
4200 case MRI_UCHAR:
4201 bytes *= sizeof(BUFTYPE) ;
4202 break ;
4203 case MRI_SHORT:
4204 bytes *= sizeof(short);
4205 break;
4206 case MRI_FLOAT:
4207 bytes *= sizeof(float) ;
4208 break ;
4209 case MRI_INT:
4210 bytes *= sizeof(int) ;
4211 break ;
4212 case MRI_LONG:
4213 bytes *= sizeof(long) ;
4214 break ;
4215 }
4216
4217 for (frame = 0 ; frame < mri_src->nframes ; frame++)
4218 {
4219 for (z = 0 ; z < depth ; z++)
4220 {
4221 for (y = 0 ; y < height ; y++)
4222 {
4223 memcpy(mri_dst->slices[z+frame*depth][y],
4224 mri_src->slices[z+frame*depth][y], bytes) ;
4225 }
4226 }
4227 }
4228 }
4229 else
4230 {
4231 switch (mri_src->type)
4232 {
4233 case MRI_FLOAT:
4234 switch (mri_dst->type)
4235 {
4236 case MRI_SHORT: /* float --> short */
4237 for (frame = 0 ; frame < mri_src->nframes ; frame++)
4238 {
4239 for (z = 0 ; z < depth ; z++)
4240 {
4241 for (y = 0 ; y < height ; y++)
4242 {
4243 sdst = &MRISseq_vox(mri_dst, 0, y, z, frame) ;
4244 fsrc = &MRIFseq_vox(mri_src, 0, y, z, frame) ;
4245 for (x = 0 ; x < width ; x++)
4246 {
4247 val = nint(*fsrc++) ;
4248 *sdst++ = (short)val ;
4249 }
4250 }
4251 }
4252 }
4253 break ;
4254 case MRI_UCHAR: /* float --> unsigned char */
4255 for (frame = 0 ; frame < mri_src->nframes ; frame++)
4256 {
4257 for (z = 0 ; z < depth ; z++)
4258 {
4259 for (y = 0 ; y < height ; y++)
4260 {
4261 cdst = &MRIseq_vox(mri_dst, 0, y, z, frame) ;
4262 fsrc = &MRIFseq_vox(mri_src, 0, y, z, frame) ;
4263 for (x = 0 ; x < width ; x++)
4264 {
4265 val = nint(*fsrc++) ;
4266 if (val > 255)
4267 val = 255 ;
4268 *cdst++ = (BUFTYPE)val ;
4269 }
4270 }
4271 }
4272 }
4273 break ;
4274 default:
4275 ErrorReturn(NULL,
4276 (ERROR_BADPARM,
4277 "MRIcopy: src type %d & dst type %d unsupported",
4278 mri_src->type, mri_dst->type)) ;
4279 break ;
4280 }
4281 break ;
4282 case MRI_UCHAR:
4283 switch (mri_dst->type)
4284 {
4285 case MRI_FLOAT: /* unsigned char --> float */
4286 for (frame = 0 ; frame < mri_src->nframes ; frame++)
4287 {
4288 for (z = 0 ; z < depth ; z++)
4289 {
4290 for (y = 0 ; y < height ; y++)
4291 {
4292 fdst = &MRIFseq_vox(mri_dst, 0, y, z, frame) ;
4293 csrc = &MRIseq_vox(mri_src, 0, y, z, frame) ;
4294 for (x = 0 ; x < width ; x++)
4295 *fdst++ = (float)*csrc++ ;
4296 }
4297 }
4298 }
4299 break ;
4300 default:
4301 ErrorReturn(NULL,
4302 (ERROR_BADPARM,
4303 "MRIcopy: src type %d & dst type %d unsupported",
4304 mri_src->type, mri_dst->type)) ;
4305 break ;
4306 }
4307 break ;
4308 case MRI_SHORT:
4309 switch (mri_dst->type)
4310 {
4311 case MRI_FLOAT: /* short --> float */
4312 for (frame = 0 ; frame < mri_src->nframes ; frame++)
4313 {
4314 for (z = 0 ; z < depth ; z++)
4315 {
4316 for (y = 0 ; y < height ; y++)
4317 {
4318 fdst = &MRIFseq_vox(mri_dst, 0, y, z, frame) ;
4319 ssrc = &MRISseq_vox(mri_src, 0, y, z, frame) ;
4320 for (x = 0 ; x < width ; x++)
4321 {
4322 if (z == 113 && y == 143 && x == 161)
4323 DiagBreak() ;
4324 *fdst++ = (float)*ssrc++ ;
4325 }
4326 }
4327 }
4328 }
4329 break ;
4330 case MRI_UCHAR:
4331 for (frame = 0 ; frame < mri_src->nframes ; frame++)
4332 {
4333 for (z = 0 ; z < depth ; z++)
4334 {
4335 for (y = 0 ; y < height ; y++)
4336 {
4337 cdst = &MRIseq_vox(mri_dst, 0, y, z, frame) ;
4338 ssrc = &MRISseq_vox(mri_src, 0, y, z, frame) ;
4339 for (x = 0 ; x < width ; x++)
4340 {
4341 *cdst++ = (float)*ssrc++ ;
4342 }
4343 }
4344 }
4345 }
4346 break ;
4347 default:
4348 ErrorReturn(NULL,
4349 (ERROR_BADPARM,
4350 "MRIcopy: src type %d & dst type %d unsupported",
4351 mri_src->type, mri_dst->type)) ;
4352 break ;
4353 }
4354 break ;
4355 case MRI_INT:
4356 switch (mri_dst->type)
4357 {
4358 case MRI_FLOAT: /* unsigned char --> float */
4359 for (frame = 0 ; frame < mri_src->nframes ; frame++)
4360 {
4361 for (z = 0 ; z < depth ; z++)
4362 {
4363 for (y = 0 ; y < height ; y++)
4364 {
4365 fdst = &MRIFseq_vox(mri_dst, 0, y, z, frame) ;
4366 isrc = &MRIIseq_vox(mri_src, 0, y, z, frame) ;
4367 for (x = 0 ; x < width ; x++)
4368 *fdst++ = (float)*isrc++ ;
4369 }
4370 }
4371 }
4372 break ;
4373 default:
4374 ErrorReturn(NULL,
4375 (ERROR_BADPARM,
4376 "MRIcopy: src type %d & dst type %d unsupported",
4377 mri_src->type, mri_dst->type)) ;
4378 break ;
4379 }
4380 break ;
4381 default:
4382 ErrorReturn(NULL,
4383 (ERROR_BADPARM,
4384 "MRIcopy: src type %d & dst type %d unsupported",
4385 mri_src->type, mri_dst->type)) ;
4386 break ; /* in case someone removes the errorreturn */
4387 }
4388 }
4389 return(mri_dst) ;
4390 }
4391 /*
4392 make MAX_INDEX way larger than it has to be. This will give
4393 some headroom for bad (e.g. poorly registered) images without
4394 sacrificing too much space.
4395 */
4396 #define MAX_INDEX 500
4397 /*-----------------------------------------------------
4398 Parameters:
4399
4400 Returns value:
4401
4402 Description
4403 allocate a lookup table that allows indices which
4404 are outside the image region.
4405 ------------------------------------------------------*/
4406 int
4407 MRIallocIndices(MRI *mri)
4408 {
4409 int width, height, depth, i ;
4410
4411 width = mri->width ;
4412 height = mri->height ;
4413 depth = mri->depth ;
4414 mri->xi = (int *)calloc(width+2*MAX_INDEX, sizeof(int)) ;
4415 if (!mri->xi)
4416 ErrorExit(ERROR_NO_MEMORY,
4417 "MRIallocIndices: could not allocate %d elt index array",
4418 width+2*MAX_INDEX) ;
4419 mri->yi = (int *)calloc(height+2*MAX_INDEX, sizeof(int)) ;
4420 if (!mri->yi)
4421 ErrorExit(ERROR_NO_MEMORY,
4422 "MRIallocIndices: could not allocate %d elt index array",
4423 height+2*MAX_INDEX) ;
4424 mri->zi = (int *)calloc(depth+2*MAX_INDEX, sizeof(int)) ;
4425 if (!mri->zi)
4426 ErrorExit(ERROR_NO_MEMORY,
4427 "MRIallocIndices: could not allocate %d elt index array",
4428 depth+2*MAX_INDEX) ;
4429
4430 /*
4431 indexing into these arrays returns valid pixel indices from
4432 -MAX_INDEX to width+MAX_INDEX
4433 */
4434 mri->xi += MAX_INDEX ;
4435 mri->yi += MAX_INDEX ;
4436 mri->zi += MAX_INDEX ;
4437 for (i = -MAX_INDEX ; i < width+MAX_INDEX ; i++)
4438 {
4439 if (i <= 0)
4440 mri->xi[i] = 0 ;
4441 else if (i >= width)
4442 mri->xi[i] = width-1 ;
4443 else
4444 mri->xi[i] = i ;
4445 }
4446 for (i = -MAX_INDEX ; i < height+MAX_INDEX ; i++)
4447 {
4448 if (i <= 0)
4449 mri->yi[i] = 0 ;
4450 else if (i >= height)
4451 mri->yi[i] = height-1 ;
4452 else
4453 mri->yi[i] = i ;
4454 }
4455 for (i = -MAX_INDEX ; i < depth+MAX_INDEX ; i++)
4456 {
4457 if (i <= 0)
4458 mri->zi[i] = 0 ;
4459 else if (i >= depth)
4460 mri->zi[i] = depth-1 ;
4461 else
4462 mri->zi[i] = i ;
4463 }
4464
4465 return(NO_ERROR) ;
4466 }
4467 /*-----------------------------------------------------
4468 Parameters:
4469
4470 Returns value:
4471
4472 Description
4473 allocate an MRI data structure as well as space for
4474 the image data
4475 ------------------------------------------------------*/
4476 MRI *
4477 MRIallocSequence(int width, int height, int depth, int type, int nframes)
4478 {
4479 MRI *mri ;
4480 int slice, row, bpp ;
4481 BUFTYPE *buf ;
4482
4483 mris_alloced++ ;
4484
4485 if ((width <= 0) || (height <= 0) || (depth <= 0))
4486 ErrorReturn(NULL,
4487 (ERROR_BADPARM, "MRIalloc(%d, %d, %d): bad parm",
4488 width, height, depth)) ;
4489 #if 1
4490 mri = MRIallocHeader(width, height, depth, type) ;
4491 MRIinitHeader(mri) ;
4492 #else
4493 mri = (MRI *)calloc(1, sizeof(MRI)) ;
4494 if (!mri)
4495 ErrorExit(ERROR_NO_MEMORY, "MRIalloc: could not allocate MRI\n") ;
4496
4497 mri->scale = 1 ;
4498 mri->height = height ;
4499 mri->width = width ;
4500 mri->yinvert = 1 ;
4501 mri->depth = depth ;
4502 mri->type = type ;
4503 #endif
4504 mri->nframes = nframes ;
4505 MRIallocIndices(mri) ;
4506 mri->slices = (BUFTYPE ***)calloc(depth*nframes, sizeof(BUFTYPE **)) ;
4507 if (!mri->slices)
4508 ErrorExit(ERROR_NO_MEMORY,
4509 "MRIalloc: could not allocate %d slices\n", mri->depth) ;
4510
4511 for (slice = 0 ; slice < depth*nframes ; slice++)
4512 {
4513 /* allocate pointer to array of rows */
4514 mri->slices[slice] = (BUFTYPE **)calloc(mri->height, sizeof(BUFTYPE *)) ;
4515 if (!mri->slices[slice])
4516 ErrorExit
4517 (ERROR_NO_MEMORY,
4518 "MRIalloc(%d, %d, %d): could not allocate "
4519 "%d bytes for %dth slice\n",
4520 height, width, depth, mri->height*sizeof(BUFTYPE *), slice) ;
4521
4522 #if USE_ELECTRIC_FENCE
4523 switch (mri->type)
4524 {
4525 case MRI_BITMAP:
4526 bpp = 1 ;
4527 break ;
4528 case MRI_UCHAR:
4529 bpp = 8 ;
4530 break ;
4531 case MRI_TENSOR:
4532 case MRI_FLOAT:
4533 bpp = sizeof(float) * 8 ;
4534 break ;
4535 case MRI_INT:
4536 bpp = sizeof(int) * 8 ;
4537 break ;
4538 case MRI_SHORT:
4539 bpp = sizeof(short) * 8 ;
4540 break ;
4541 case MRI_LONG:
4542 bpp = sizeof(long) * 8 ;
4543 break ;
4544 default:
4545 ErrorReturn(NULL,
4546 (ERROR_BADPARM,
4547 "MRIalloc(%d, %d, %d, %d): unknown type",
4548 width, height, depth, mri->type)) ;
4549 break ;
4550 }
4551 bpp /= 8 ;
4552 buf = (BUFTYPE *)calloc((mri->width*mri->height*bpp), 1) ;
4553 if (buf == NULL)
4554 ErrorExit
4555 (ERROR_NO_MEMORY,
4556 "MRIalloc(%d, %d, %d): could not allocate "
4557 "%d bytes for %dth slice\n",
4558 height, width, depth, (mri->width*mri->height*bpp), slice) ;
4559 for (row = 0 ; row < mri->height ; row++)
4560 {
4561 mri->slices[slice][row] = buf+(row*mri->width*bpp) ;
4562 }
4563 #else
4564 /* allocate each row */
4565 for (row = 0 ; row < mri->height ; row++)
4566 {
4567 switch (mri->type)
4568 {
4569 case MRI_BITMAP:
4570 mri->slices[slice][row] =
4571 (BUFTYPE*)calloc(mri->width/8,sizeof(BUFTYPE));
4572 break ;
4573 case MRI_UCHAR:
4574 mri->slices[slice][row] =
4575 (BUFTYPE*)calloc(mri->width,sizeof(BUFTYPE));
4576 break ;
4577 case MRI_TENSOR:
4578 case MRI_FLOAT:
4579 mri->slices[slice][row] =
4580 (BUFTYPE *)calloc(mri->width, sizeof(float));
4581 break ;
4582 case MRI_INT:
4583 mri->slices[slice][row] =
4584 (BUFTYPE *)calloc(mri->width, sizeof(int)) ;
4585 break ;
4586 case MRI_SHORT:
4587 mri->slices[slice][row] =
4588 (BUFTYPE *)calloc(mri->width, sizeof(short));
4589 break ;
4590 case MRI_LONG:
4591 mri->slices[slice][row] =
4592 (BUFTYPE *)calloc(mri->width, sizeof(long)) ;
4593 break ;
4594 default:
4595 ErrorReturn(NULL,
4596 (ERROR_BADPARM,
4597 "MRIalloc(%d, %d, %d, %d): unknown type",
4598 width, height, depth, mri->type)) ;
4599 break ;
4600 }
4601
4602 if (!mri->slices[slice][row])
4603 ErrorExit
4604 (ERROR_NO_MEMORY,
4605 "MRIalloc(%d,%d,%d): could not allocate "
4606 "%dth row in %dth slice\n",
4607 width,height,depth, slice, row) ;
4608 }
4609 #endif
4610 }
4611
4612 return(mri) ;
4613 }
4614 /*-----------------------------------------------------
4615 Parameters:
4616
4617 Returns value:
4618
4619 Description
4620 allocate an MRI data structure but not space for
4621 the image data
4622 ------------------------------------------------------*/
4623 MRI *
4624 MRIallocHeader(int width, int height, int depth, int type)
4625 {
4626 MRI *mri ;
4627
4628 mri = (MRI *)calloc(1, sizeof(MRI)) ;
4629 if (!mri)
4630 ErrorExit(ERROR_NO_MEMORY, "MRIalloc: could not allocate MRI\n") ;
4631
4632 mri->imnr0 = 1 ;
4633 mri->imnr1 = depth;
4634 mri->fov = width ;
4635 mri->thick = 1.0 ;
4636 mri->scale = 1 ;
4637 mri->roi.dx = mri->width = width ;
4638 mri->roi.dy = mri->height = height ;
4639 mri->roi.dz = mri->depth = depth ;
4640 mri->yinvert = 1 ;
4641 mri->xsize = mri->ysize = mri->zsize = 1 ;
4642 mri->type = type ;
4643 mri->nframes = 1 ;
4644 mri->xi = mri->yi = mri->zi = NULL ;
4645 mri->slices = NULL ;
4646 mri->ps = 1 ;
4647 mri->xstart = -mri->width/2.0 ;
4648 mri->xend = mri->width/2.0 ;
4649 mri->ystart = -mri->height/2.0 ;
4650 mri->yend = mri->height/2.0 ;
4651 mri->zstart = -mri->depth/2.0 ;
4652 mri->zend = mri->depth/2 ;
4653 //
4654 mri->x_r = -1;
4655 mri->x_a = 0.;
4656 mri->x_s = 0.;
4657 //
4658 mri->y_r = 0.;
4659 mri->y_a = 0.;
4660 mri->y_s = -1;
4661 //
4662 mri->z_r = 0.;
4663 mri->z_a = 1.;
4664 mri->z_s = 0.;
4665 //
4666 mri->c_r = mri->c_a = mri->c_s = 0.0;
4667 mri->ras_good_flag = 0;
4668 mri->brightness = 1;
4669 mri->register_mat = NULL;
4670 mri->subject_name[0] = '\0';
4671 mri->path_to_t1[0] = '\0';
4672 mri->fname_format[0] = '\0';
4673 mri->gdf_image_stem[0] = '\0';
4674 mri->tag_data = NULL;
4675 mri->tag_data_size = 0;
4676
4677 mri->i_to_r__ = extract_i_to_r(mri);
4678 mri->r_to_i__ = extract_r_to_i(mri);
4679
4680 return(mri) ;
4681 }
4682 /*-----------------------------------------------------
4683 Parameters:
4684
4685 Returns value:
4686
4687 Description
4688 allocate an MRI data structure as well as space for
4689 the image data
4690 ------------------------------------------------------*/
4691 MRI *
4692 MRIalloc(int width, int height, int depth, int type)
4693 {
4694 return(MRIallocSequence(width, height, depth, type, 1)) ;
4695 }
4696 /*-----------------------------------------------------
4697 Parameters:
4698
4699 Returns value:
4700
4701 Description
4702 Free and MRI data structure and all its attached memory
4703 ------------------------------------------------------*/
4704 int
4705 MRIfree(MRI **pmri)
4706 {
4707 MRI *mri ;
4708 int slice, i ;
4709 #if !USE_ELECTRIC_FENCE
4710 int row ;
4711 #endif
4712
4713 mris_alloced-- ;
4714 mri = *pmri ;
4715 if (!mri)
4716 ErrorReturn(ERROR_BADPARM, (ERROR_BADPARM, "MRIfree: null pointer\n")) ;
4717
4718 if (mri->xi)
4719 free(mri->xi-MAX_INDEX) ;
4720 if (mri->yi)
4721 free(mri->yi-MAX_INDEX) ;
4722 if (mri->zi)
4723 free(mri->zi-MAX_INDEX) ;
4724
4725 if (mri->slices)
4726 {
4727 for (slice = 0 ; slice < mri->depth*mri->nframes ; slice++)
4728 {
4729 if (mri->slices[slice])
4730 {
4731 #if USE_ELECTRIC_FENCE
4732 free(mri->slices[slice][0]) ;
4733 #else
4734 for (row = 0 ; row < mri->height ; row++)
4735 free(mri->slices[slice][row]) ;
4736 #endif
4737 free(mri->slices[slice]) ;
4738 }
4739 }
4740 free(mri->slices) ;
4741 }
4742
4743 if (mri->free_transform)
4744 delete_general_transform(&mri->transform) ;
4745
4746 if(mri->register_mat != NULL)
4747 MatrixFree(&(mri->register_mat));
4748
4749 if (mri->i_to_r__)
4750 MatrixFree(&mri->i_to_r__);
4751 if (mri->r_to_i__)
4752 MatrixFree(&mri->r_to_i__);
4753
4754 for (i = 0 ; i < mri->ncmds ; i++)
4755 free(mri->cmdlines[i]) ;
4756
4757 free(mri) ;
4758 *pmri = NULL ;
4759
4760 return(NO_ERROR) ;
4761 }
4762 /*-----------------------------------------------------
4763 Parameters:
4764
4765 Returns value:
4766
4767 Description
4768 Free and MRI data structure and all its attached memory
4769 ------------------------------------------------------*/
4770 int
4771 MRIfreeFrames(MRI *mri, int start_frame)
4772 {
4773 int slice, row, end_frame ;
4774
4775 end_frame = mri->nframes-1 ;
4776 if (!mri)
4777 ErrorReturn(ERROR_BADPARM, (ERROR_BADPARM, "MRIfree: null pointer\n")) ;
4778
4779 if (mri->slices)
4780 {
4781 for (slice = start_frame*mri->depth ;
4782 slice < mri->depth*end_frame ; slice++)
4783 {
4784 if (mri->slices[slice])
4785 {
4786 for (row = 0 ; row < mri->height ; row++)
4787 free(mri->slices[slice][row]) ;
4788 free(mri->slices[slice]) ;
4789 }
4790 }
4791 }
4792
4793 mri->nframes -= (end_frame-start_frame+1) ;
4794 return(NO_ERROR) ;
4795 }
4796 /*-----------------------------------------------------
4797 Parameters:
4798
4799 Returns value:
4800
4801 Description
4802 Dump the MRI header to a file
4803 ------------------------------------------------------*/
4804 int
4805 MRIdump(MRI *mri, FILE *fp)
4806 {
4807 fprintf(fp, "%6.6s = %s\n", "fname", mri->fname);
4808 fprintf(fp, "%6.6s = %d\n", "height", mri->height);
4809 fprintf(fp, "%6.6s = %d\n", "width", mri->width);
4810 fprintf(fp, "%6.6s = %d\n", "depth", mri->depth);
4811 fprintf(fp, "%6.6s = %d\n", "nframes", mri->nframes);
4812 fprintf(fp, "%6.6s = %d\n", "imnr0", mri->imnr0);
4813 fprintf(fp, "%6.6s = %d\n", "imnr1", mri->imnr1);
4814 fprintf(fp, "%6.6s = %d\n", "xnum", mri->width);
4815 fprintf(fp, "%6.6s = %d\n", "ynum", mri->height);
4816 fprintf(fp, "%6.6s = %f\n", "fov", mri->fov);
4817 fprintf(fp, "%6.6s = %f\n", "thick", mri->thick);
4818 fprintf(fp, "%6.6s = %f\n", "xstart", mri->xstart); /* strtx */
4819 fprintf(fp, "%6.6s = %f\n", "xend", mri->xend); /* endx */
4820 fprintf(fp, "%6.6s = %f\n", "ystart", mri->ystart); /* strty */
4821 fprintf(fp, "%6.6s = %f\n", "yend", mri->yend); /* endy */
4822 fprintf(fp, "%6.6s = %f\n", "zstart", mri->zstart); /* strtz */
4823 fprintf(fp, "%6.6s = %f\n", "zend", mri->zend); /* endz */
4824 fprintf(fp, "%6.6s = %d\n", "type", mri->type);
4825 fprintf(fp, "%6.6s = %f\n", "xsize", mri->xsize);
4826 fprintf(fp, "%6.6s = %f\n", "ysize", mri->ysize);
4827 fprintf(fp, "%6.6s = %f\n", "zsize", mri->zsize);
4828 fprintf(fp, "%6.6s = %f %f %f\n", "x ras", mri->x_r, mri->x_a, mri->x_s);
4829 fprintf(fp, "%6.6s = %f %f %f\n", "y ras", mri->y_r, mri->y_a, mri->y_s);
4830 fprintf(fp, "%6.6s = %f %f %f\n", "z ras", mri->z_r, mri->z_a, mri->z_s);
4831 fprintf(fp, "%6.6s = %f %f %f\n", "c ras", mri->c_r, mri->c_a, mri->c_s);
4832 fprintf(fp, "%s = %f\n", "det(xyz_ras)", MRIvolumeDeterminant(mri));
4833 fprintf(fp, "%s = %d\n", "ras_good_flag", mri->ras_good_flag);
4834 fprintf(fp, "%s = %d\n", "brightness", mri->brightness);
4835 fprintf(fp, "%s = %s\n", "subject_name", mri->subject_name);
4836 fprintf(fp, "%s = %s\n", "path_to_t1", mri->path_to_t1);
4837 fprintf(fp, "%s = %s\n", "fname_format", mri->fname_format);
4838 if(mri->register_mat != NULL)
4839 {
4840 fprintf(fp, "%s = \n", "register_mat");
4841 MatrixPrint(fp, mri->register_mat);
4842 }
4843 return(NO_ERROR) ;
4844 }
4845 /*-----------------------------------------------------
4846 Parameters:
4847
4848 Returns value:
4849
4850 Description
4851 Dump the non-zero elements of an MRI buffer to a file
4852 ------------------------------------------------------*/
4853 int
4854 MRIdumpBuffer(MRI *mri, FILE *fp)
4855 {
4856 int x, y, z ;
4857
4858 for (z = 0 ; z < mri->depth ; z++)
4859 {
4860 for (y = 0 ; y < mri->height ; y++)
4861 {
4862 for (x = 0 ; x < mri->width ; x++)
4863 {
4864 switch (mri->type)
4865 {
4866 case MRI_UCHAR:
4867 if (!FZERO(mri->slices[z][y][x]))
4868 fprintf
4869 (fp,
4870 "[%d][%d][%d]: %d\n",
4871 x,y,z,(int)mri->slices[z][y][x]);
4872 break ;
4873 case MRI_FLOAT:
4874 /* if (!FZERO(MRIFvox(mri,x,y,z)))*/
4875 fprintf
4876 (fp,
4877 "[%d][%d][%d]: %2.3f\n",
4878 x,y,z, MRIFvox(mri,x,y,z));
4879 break ;
4880 }
4881 }
4882 }
4883 }
4884 return(NO_ERROR) ;
4885 }
4886 /*-----------------------------------------------------
4887 Parameters:
4888
4889 Returns value:
4890
4891 Description
4892 Find the peak intensity in an MRI image
4893 ------------------------------------------------------*/
4894 int
4895 MRIpeak(MRI *mri, int *px, int *py, int *pz)
4896 {
4897 int max_row, max_col, max_slice, row, col, slice, width, height, depth ;
4898 BUFTYPE val, max_val, *im ;
4899 long lval, lmax_val, *lim ;
4900 int ival, imax_val, *iim ;
4901 float fval, fmax_val, *fim ;
4902
4903 max_val = 0 ;
4904 lmax_val = 0L ;
4905 imax_val = 0 ;
4906 fmax_val = 0.0f ;
4907 max_row = max_col = max_slice = -1 ; /* to prevent compiler warning */
4908 width = mri->width ;
4909 height = mri->height ;
4910 depth = mri->depth ;
4911 for (slice = 0 ; slice < depth ; slice++)
4912 {
4913 for (row = 0 ; row < height ; row++)
4914 {
4915 switch (mri->type)
4916 {
4917 case MRI_UCHAR:
4918 im = mri->slices[slice][row] ;
4919 for (col = 0 ; col < width ; col++)
4920 {
4921 val = *im++ ;
4922 if (val > max_val)
4923 {
4924 max_val = val ;
4925 max_row = row ;
4926 max_col = col ;
4927 max_slice = slice ;
4928 }
4929 }
4930 break ;
4931 case MRI_LONG:
4932 lim = (long *)mri->slices[slice][row] ;
4933 for (col = 0 ; col < width ; col++)
4934 {
4935 lval = *lim++ ;
4936 if (lval > lmax_val)
4937 {
4938 lmax_val = lval ;
4939 max_row = row ;
4940 max_col = col ;
4941 max_slice = slice ;
4942 }
4943 }
4944 break ;
4945 case MRI_FLOAT:
4946 fim = (float *)mri->slices[slice][row] ;
4947 for (col = 0 ; col < width ; col++)
4948 {
4949 fval = *fim++ ;
4950 if (fval > fmax_val)
4951 {
4952 fmax_val = fval ;
4953 max_row = row ;
4954 max_col = col ;
4955 max_slice = slice ;
4956 }
4957 }
4958 break ;
4959 case MRI_INT:
4960 iim = (int *)mri->slices[slice][row] ;
4961 for (col = 0 ; col < width ; col++)
4962 {
4963 ival = *iim++ ;
4964 if (ival > imax_val)
4965 {
4966 imax_val = ival ;
4967 max_row = row ;
4968 max_col = col ;
4969 max_slice = slice ;
4970 }
4971 }
4972 break ;
4973 }
4974 }
4975 }
4976
4977 *px = max_col ;
4978 *py = max_row ;
4979 *pz = max_slice ;
4980 return(NO_ERROR) ;
4981 }
4982 /*--------------------------------------------------------------
4983 Description: Copy the header information from one MRI into another.
4984 Does not copy the dimension lengths, only the geometry, pulse seq,
4985 etc.
4986 ------------------------------------------------------*/
4987 int MRIcopyHeader(MRI *mri_src, MRI *mri_dst)
4988 {
4989 int i ;
4990
4991 mri_dst->dof = mri_src->dof ;
4992 mri_dst->mean = mri_src->mean ;
4993 mri_dst->xsize = mri_src->xsize ;
4994 mri_dst->ysize = mri_src->ysize ;
4995 mri_dst->zsize = mri_src->zsize ;
4996 if (mri_src->linear_transform)
4997 {
4998 copy_general_transform(&mri_src->transform, &mri_dst->transform) ;
4999 mri_dst->linear_transform = mri_src->linear_transform ;
5000 mri_dst->inverse_linear_transform = mri_src->inverse_linear_transform ;
5001 mri_dst->linear_transform =
5002 get_linear_transform_ptr(&mri_dst->transform) ;
5003 mri_dst->inverse_linear_transform =
5004 get_inverse_linear_transform_ptr(&mri_dst->transform) ;
5005 mri_dst->free_transform = 1 ;
5006 }
5007 strcpy(mri_dst->transform_fname, mri_src->transform_fname) ;
5008 if (mri_dst->depth == mri_src->depth)
5009 {
5010 mri_dst->imnr0 = mri_src->imnr0 ;
5011 mri_dst->imnr1 = mri_src->imnr1 ;
5012 }
5013 mri_dst->ptype = mri_src->ptype ;
5014 mri_dst->fov = mri_src->fov ;
5015 mri_dst->thick = mri_src->thick ;
5016 mri_dst->ps = mri_src->ps ;
5017 mri_dst->location = mri_src->location ;
5018 mri_dst->xstart = mri_src->xstart ;
5019 mri_dst->xend = mri_src->xend ;
5020 mri_dst->ystart = mri_src->ystart ;
5021 mri_dst->yend = mri_src->yend ;
5022 mri_dst->zstart = mri_src->zstart ;
5023 mri_dst->zend = mri_src->zend ;
5024 mri_dst->flip_angle = mri_src->flip_angle ;
5025 mri_dst->tr = mri_src->tr ;
5026 mri_dst->te = mri_src->te ;
5027 mri_dst->ti = mri_src->ti ;
5028 strcpy(mri_dst->fname, mri_src->fname) ;
5029 mri_dst->x_r = mri_src->x_r;
5030 mri_dst->x_a = mri_src->x_a;
5031 mri_dst->x_s = mri_src->x_s;
5032 mri_dst->y_r = mri_src->y_r;
5033 mri_dst->y_a = mri_src->y_a;
5034 mri_dst->y_s = mri_src->y_s;
5035 mri_dst->z_r = mri_src->z_r;
5036 mri_dst->z_a = mri_src->z_a;
5037 mri_dst->z_s = mri_src->z_s;
5038 mri_dst->c_r = mri_src->c_r;
5039 mri_dst->c_a = mri_src->c_a;
5040 mri_dst->c_s = mri_src->c_s;
5041 mri_dst->ras_good_flag = mri_src->ras_good_flag;
5042
5043 mri_dst->brightness = mri_src->brightness;
5044 if(mri_src->register_mat != NULL)
5045 MatrixCopy(mri_src->register_mat, mri_dst->register_mat);
5046 else
5047 mri_dst->register_mat = NULL;
5048 strcpy(mri_dst->subject_name, mri_src->subject_name);
5049 strcpy(mri_dst->path_to_t1, mri_src->path_to_t1);
5050 strcpy(mri_dst->fname_format, mri_src->fname_format);
5051
5052 strcpy(mri_dst->gdf_image_stem, mri_src->gdf_image_stem);
5053
5054 mri_dst->i_to_r__ = MatrixCopy(mri_src->i_to_r__, mri_dst->i_to_r__);
5055 mri_dst->r_to_i__ = MatrixCopy(mri_src->r_to_i__, mri_dst->r_to_i__);
5056
5057 for (i = 0 ; i < mri_src->ncmds ; i++)
5058 {
5059 mri_dst->cmdlines[i] =
5060 (char *)calloc(strlen(mri_src->cmdlines[i])+1, sizeof(char)) ;
5061 strcpy(mri_dst->cmdlines[i], mri_src->cmdlines[i]) ;
5062 }
5063 mri_dst->ncmds = mri_src->ncmds ;
5064 return(NO_ERROR) ;
5065 }
5066 /*-----------------------------------------------------
5067 Parameters:
5068
5069 Returns value:
5070
5071 Description
5072 Translate the MRI image mri_src by the vector
5073 dx, dy, dz and store the result in mri_dst.
5074 ------------------------------------------------------*/
5075 MRI *
5076 MRItranslate(MRI *mri_src, MRI *mri_dst, double dx, double dy, double dz)
5077 {
5078 int y1, y2, y3, width, height, depth ;
5079 BUFTYPE *pdst ;
5080 Real x1, x2, x3, val ;
5081
5082 width = mri_src->width ;
5083 height = mri_src->height ;
5084 depth = mri_src->depth ;
5085 if (!mri_dst)
5086 mri_dst = MRIclone(mri_src, NULL) ;
5087 else
5088 MRIclear(mri_dst) ;
5089
5090 for (y3 = 0 ; y3 < depth ; y3++)
5091 {
5092 x3 = (Real)y3 - dz ;
5093 if (x3 < 0 || x3 >= depth)
5094 continue ;
5095
5096 for (y2 = 0 ; y2 < height ; y2++)
5097 {
5098 x2 = (Real)y2 - dy ;
5099 if (x2 < 0 || x2 >= height)
5100 continue ;
5101
5102 pdst = &MRIvox(mri_dst, 0, y2, y3) ;
5103 for (y1 = 0 ; y1 < width ; y1++, pdst++)
5104 {
5105 x1 = (Real)y1 - dx ;
5106 if (x1 >= 0 && x1 < width)
5107 {
5108 MRIsampleVolume(mri_src, x1, x2, x3, &val) ;
5109 *pdst = (BUFTYPE)nint(val) ;
5110 }
5111 }
5112 }
5113 }
5114
5115 mri_dst->ras_good_flag = 0;
5116
5117 return(mri_dst) ;
5118 }
5119 /*-----------------------------------------------------
5120 Parameters:
5121
5122 Returns value:
5123
5124 Description
5125 Rotate mri_src around the Y axis and return the
5126 result in mri_dst
5127 ------------------------------------------------------*/
5128 MRI *
5129 MRIrotateX(MRI *mri_src, MRI *mri_dst, float x_angle)
5130 {
5131 int width, height, depth ;
5132 MATRIX *m, *mO ;
5133
5134 width = mri_src->width ;
5135 height = mri_src->height ;
5136 depth = mri_src->depth ;
5137 if (!mri_dst)
5138 mri_dst = MRIclone(mri_src, NULL) ;
5139 else
5140 MRIclear(mri_dst) ;
5141
5142 m = MatrixAllocRotation(3, x_angle, X_ROTATION) ;
5143
5144 mO = MatrixAlloc(3, 1, MATRIX_REAL) ;
5145 mO->rptr[1][1] = mri_src->width / 2 ;
5146 mO->rptr[2][1] = mri_src->height / 2 ;
5147 mO->rptr[3][1] = mri_src->depth / 2 ;
5148
5149 /* build rotation matrix */
5150 mri_dst = MRIrotate(mri_src, NULL, m, mO) ;
5151 MatrixFree(&m) ;
5152 MatrixFree(&mO) ;
5153
5154 mri_dst->ras_good_flag = 0;
5155
5156 return(mri_dst) ;
5157 }
5158 /*-----------------------------------------------------
5159 Parameters:
5160
5161 Returns value:
5162
5163 Description
5164 Rotate mri_src around the Y axis and return the
5165 result in mri_dst
5166 ------------------------------------------------------*/
5167 MRI *
5168 MRIrotateY(MRI *mri_src, MRI *mri_dst, float y_angle)
5169 {
5170 int width, height, depth ;
5171 MATRIX *m, *mO ;
5172
5173 width = mri_src->width ;
5174 height = mri_src->height ;
5175 depth = mri_src->depth ;
5176 if (!mri_dst)
5177 mri_dst = MRIclone(mri_src, NULL) ;
5178 else
5179 MRIclear(mri_dst) ;
5180
5181 /* origin of coordinate system */
5182 mO = MatrixAlloc(3, 1, MATRIX_REAL) ;
5183 mO->rptr[1][1] = mri_src->width / 2 ;
5184 mO->rptr[2][1] = mri_src->height / 2 ;
5185 mO->rptr[3][1] = mri_src->depth / 2 ;
5186
5187 m = MatrixAllocRotation(3, y_angle, Y_ROTATION) ;
5188
5189 /* build rotation matrix */
5190 mri_dst = MRIrotate(mri_src, NULL, m, mO) ;
5191 MatrixFree(&m) ;
5192 MatrixFree(&mO) ;
5193
5194 mri_dst->ras_good_flag = 0;
5195
5196 return(mri_dst) ;
5197 }
5198 /*-----------------------------------------------------
5199 Parameters:
5200
5201 Returns value:
5202
5203 Description
5204 Rotate mri_src around the Z axis and return the
5205 result in mri_dst
5206 ------------------------------------------------------*/
5207 MRI *
5208 MRIrotateZ(MRI *mri_src, MRI *mri_dst, float z_angle)
5209 {
5210 int width, height, depth ;
5211 MATRIX *m, *mO ;
5212
5213 width = mri_src->width ;
5214 height = mri_src->height ;
5215 depth = mri_src->depth ;
5216 if (!mri_dst)
5217 mri_dst = MRIclone(mri_src, NULL) ;
5218 else
5219 MRIclear(mri_dst) ;
5220
5221 m = MatrixAllocRotation(3, z_angle, Z_ROTATION) ;
5222 mO = MatrixAlloc(3, 1, MATRIX_REAL) ;
5223 mO->rptr[1][1] = mri_src->width / 2 ;
5224 mO->rptr[2][1] = mri_src->height / 2 ;
5225 mO->rptr[3][1] = mri_src->depth / 2 ;
5226
5227 mri_dst = MRIrotate(mri_src, NULL, m, mO) ;
5228 MatrixFree(&m) ;
5229 MatrixFree(&mO) ;
5230
5231 mri_dst->ras_good_flag = 0;
5232
5233 return(mri_dst) ;
5234 }
5235 /*-----------------------------------------------------
5236 Parameters:
5237
5238 Returns value:
5239
5240 Description
5241 Rotate mri_src around the Y axis and return the
5242 result in mri_dst
5243 ------------------------------------------------------*/
5244 MRI *
5245 MRIrotateX_I(MRI *mri_src, MRI *mri_dst, float x_angle)
5246 {
5247 int width, height, depth ;
5248 MATRIX *m ;
5249
5250 width = mri_src->width ;
5251 height = mri_src->height ;
5252 depth = mri_src->depth ;
5253 if (!mri_dst)
5254 mri_dst = MRIclone(mri_src, NULL) ;
5255 else
5256 MRIclear(mri_dst) ;
5257
5258 m = MatrixAllocRotation(3, x_angle, X_ROTATION) ;
5259
5260 /* build rotation matrix */
5261 mri_dst = MRIrotate_I(mri_src, NULL, m, NULL) ;
5262 MatrixFree(&m) ;
5263
5264 mri_dst->ras_good_flag = 0;
5265
5266 return(mri_dst) ;
5267 }
5268 /*-----------------------------------------------------
5269 Parameters:
5270
5271 Returns value:
5272
5273 Description
5274 Rotate mri_src around the Y axis and return the
5275 result in mri_dst
5276 ------------------------------------------------------*/
5277 MRI *
5278 MRIrotateY_I(MRI *mri_src, MRI *mri_dst, float y_angle)
5279 {
5280 int width, height, depth ;
5281 MATRIX *m ;
5282
5283 width = mri_src->width ;
5284 height = mri_src->height ;
5285 depth = mri_src->depth ;
5286 if (!mri_dst)
5287 mri_dst = MRIclone(mri_src, NULL) ;
5288 else
5289 MRIclear(mri_dst) ;
5290
5291 m = MatrixAllocRotation(3, y_angle, Y_ROTATION) ;
5292
5293 /* build rotation matrix */
5294 mri_dst = MRIrotate_I(mri_src, NULL, m, NULL) ;
5295 MatrixFree(&m) ;
5296
5297 mri_dst->ras_good_flag = 0;
5298
5299 return(mri_dst) ;
5300 }
5301 /*-----------------------------------------------------
5302 Parameters:
5303
5304 Returns value:
5305
5306 Description
5307 Rotate mri_src around the Z axis and return the
5308 result in mri_dst
5309 ------------------------------------------------------*/
5310 MRI *
5311 MRIrotateZ_I(MRI *mri_src, MRI *mri_dst, float z_angle)
5312 {
5313 int width, height, depth ;
5314 MATRIX *m ;
5315
5316 width = mri_src->width ;
5317 height = mri_src->height ;
5318 depth = mri_src->depth ;
5319 if (!mri_dst)
5320 mri_dst = MRIclone(mri_src, NULL) ;
5321 else
5322 MRIclear(mri_dst) ;
5323
5324 m = MatrixAllocRotation(3, z_angle, Z_ROTATION) ;
5325 mri_dst = MRIrotate_I(mri_src, NULL, m, NULL) ;
5326 MatrixFree(&m) ;
5327
5328 mri_dst->ras_good_flag = 0;
5329
5330 return(mri_dst) ;
5331 }
5332 /*-----------------------------------------------------
5333 Parameters:
5334
5335 Returns value:
5336
5337 Description
5338 Scale the MRI image mri_src by sx,sy,sz in the
5339 x, y, and z directions respectively.
5340 ------------------------------------------------------*/
5341 MRI *
5342 MRIscale(MRI *mri_src, MRI *mri_dst, float sx, float sy, float sz)
5343 {
5344 int width, height, depth ;
5345 MATRIX *m ;
5346
5347 width = mri_src->width ;
5348 height = mri_src->height ;
5349 depth = mri_src->depth ;
5350 if (!mri_dst)
5351 {
5352 mri_dst = MRIalloc(width, height, depth, mri_src->type) ;
5353 MRIcopyHeader(mri_src, mri_dst) ;
5354 }
5355
5356 m = MatrixAlloc(4, 4, MATRIX_REAL) ;
5357
5358 /* build rotation matrix */
5359 m->rptr[1][1] = sx ;
5360 m->rptr[2][2] = sy ;
5361 m->rptr[3][3] = sz ;
5362 m->rptr[4][4] = 1.0 ;
5363 mri_dst = MRIlinearTransform(mri_src, NULL, m) ;
5364 MatrixFree(&m) ;
5365
5366 mri_dst->ras_good_flag = 0;
5367
5368 return(mri_dst) ;
5369 }
5370 /*-----------------------------------------------------
5371 Parameters:
5372
5373 Returns value:
5374
5375 Description
5376 Rotate about the point mO
5377 ------------------------------------------------------*/
5378 MRI *
5379 MRIrotate(MRI *mri_src, MRI *mri_dst, MATRIX *mR, MATRIX *mO)
5380 {
5381 int x1, x2, x3, y1, y2, y3, width, height, depth, y1o, y2o, y3o, freeit ;
5382 MATRIX *mX, *mY ; /* original and transformed coordinate systems */
5383 MATRIX *mRinv ; /* inverse of R */
5384
5385 mRinv = MatrixInverse(mR, NULL) ;
5386 if (!mRinv)
5387 ErrorReturn(NULL,(ERROR_BADPARM,"MRIrotate: rotation matrix is singular"));
5388
5389 width = mri_src->width ;
5390 height = mri_src->height ;
5391 depth = mri_src->depth ;
5392 if (!mri_dst)
5393 mri_dst = MRIclone(mri_src, NULL) ;
5394 else
5395 MRIclear(mri_dst) ;
5396
5397 if (!mO)
5398 {
5399 mO = MatrixAlloc(3, 1, MATRIX_REAL) ;
5400 mO->rptr[1][1] = mri_src->width / 2 ;
5401 mO->rptr[2][1] = mri_src->height / 2 ;
5402 mO->rptr[3][1] = mri_src->depth / 2 ;
5403 freeit = 1 ;
5404 }
5405 else
5406 freeit = 0 ;
5407
5408 mX = MatrixAlloc(3, 1, MATRIX_REAL) ; /* input coordinates */
5409 mY = MatrixAlloc(3, 1, MATRIX_REAL) ; /* transformed coordinates */
5410
5411
5412 y1o = mO->rptr[1][1] ;
5413 y2o = mO->rptr[2][1] ;
5414 y3o = mO->rptr[3][1] ;
5415 for (y3 = 0 ; y3 < depth ; y3++)
5416 {
5417 mY->rptr[3][1] = y3 - y3o ;
5418 for (y2 = 0 ; y2 < height ; y2++)
5419 {
5420 mY->rptr[2][1] = y2 - y2o ;
5421 for (y1 = 0 ; y1 < width ; y1++)
5422 {
5423 mY->rptr[1][1] = y1 - y1o ;
5424 MatrixMultiply(mRinv, mY, mX) ;
5425 MatrixAdd(mX, mO, mX) ;
5426
5427 /* should do bilinear interpolation here */
5428 x1 = nint(mX->rptr[1][1]) ;
5429 x2 = nint(mX->rptr[2][1]) ;
5430 x3 = nint(mX->rptr[3][1]) ;
5431 if (x1 >= 0 && x1 < width &&
5432 x2 >= 0 && x2 < height &&
5433 x3 >= 0 && x3 < depth)
5434 mri_dst->slices[y3][y2][y1] = mri_src->slices[x3][x2][x1] ;
5435 }
5436 }
5437 }
5438
5439 MatrixFree(&mX) ;
5440 MatrixFree(&mRinv) ;
5441 MatrixFree(&mY) ;
5442 if (freeit)
5443 MatrixFree(&mO) ;
5444
5445 mri_dst->ras_good_flag = 0;
5446
5447 return(mri_dst) ;
5448 }
5449 /*-----------------------------------------------------
5450 Parameters:
5451
5452 Returns value:
5453
5454 Description
5455 Rotate about the point mO using trilinear interpolation
5456 ------------------------------------------------------*/
5457 MRI *
5458 MRIrotate_I(MRI *mri_src, MRI *mri_dst, MATRIX *mR, MATRIX *mO)
5459 {
5460 int y1, y2, y3, width, height, depth, y1o, y2o, y3o, freeit ;
5461 MATRIX *mX, *mY ; /* original and transformed coordinate systems */
5462 MATRIX *mRinv ; /* inverse of R */
5463 float x1, x2, x3 ;
5464 Real val ;
5465
5466 mRinv = MatrixInverse(mR, NULL) ;
5467 if (!mRinv)
5468 ErrorReturn(NULL,(ERROR_BADPARM,
5469 "MRIrotate_I: rotation matrix is singular"));
5470
5471 width = mri_src->width ;
5472 height = mri_src->height ;
5473 depth = mri_src->depth ;
5474 if (!mri_dst)
5475 mri_dst = MRIclone(mri_src, NULL) ;
5476 else
5477 MRIclear(mri_dst) ;
5478
5479 if (!mO)
5480 {
5481 mO = MatrixAlloc(3, 1, MATRIX_REAL) ;
5482 mO->rptr[1][1] = mri_src->width / 2 ;
5483 mO->rptr[2][1] = mri_src->height / 2 ;
5484 mO->rptr[3][1] = mri_src->depth / 2 ;
5485 freeit = 1 ;
5486 }
5487 else
5488 freeit = 0 ;
5489
5490 mX = MatrixAlloc(3, 1, MATRIX_REAL) ; /* input coordinates */
5491 mY = MatrixAlloc(3, 1, MATRIX_REAL) ; /* transformed coordinates */
5492
5493
5494 y1o = mO->rptr[1][1] ;
5495 y2o = mO->rptr[2][1] ;
5496 y3o = mO->rptr[3][1] ;
5497 if (Gdiag == 99)
5498 MatrixPrint(stdout, mRinv) ;
5499 if (Gdiag == 99)
5500 MatrixPrint(stdout, mO) ;
5501 for (y3 = 0 ; y3 < depth ; y3++)
5502 {
5503 mY->rptr[3][1] = y3 - y3o ;
5504 for (y2 = 0 ; y2 < height ; y2++)
5505 {
5506 mY->rptr[2][1] = y2 - y2o ;
5507 for (y1 = 0 ; y1 < width ; y1++)
5508 {
5509 mY->rptr[1][1] = y1 - y1o ;
5510 MatrixMultiply(mRinv, mY, mX) ;
5511 MatrixAdd(mX, mO, mX) ;
5512
5513 /* do trilinear interpolation here */
5514 x1 = mX->rptr[1][1] ;
5515 x2 = mX->rptr[2][1] ;
5516 x3 = mX->rptr[3][1] ;
5517
5518 MRIsampleVolume(mri_src, x1, x2, x3, &val) ;
5519 mri_dst->slices[y3][y2][y1] = (BUFTYPE)nint(val) ;
5520 }
5521 }
5522 }
5523
5524 MatrixFree(&mX) ;
5525 MatrixFree(&mRinv) ;
5526 MatrixFree(&mY) ;
5527 if (freeit)
5528 MatrixFree(&mO) ;
5529
5530 mri_dst->ras_good_flag = 0;
5531
5532 return(mri_dst) ;
5533 }
5534 /*-----------------------------------------------------
5535 Parameters:
5536
5537 Returns value:
5538
5539 Description
5540 Perform an affine coordinate transformation x' = Ax + B on
5541 the MRI image mri_src into mri_dst
5542 ------------------------------------------------------*/
5543 MRI *
5544 MRIaffine(MRI *mri_src, MRI *mri_dst, MATRIX *mA, MATRIX *mB)
5545 {
5546 int x1, x2, x3, y1, y2, y3, width, height, depth ;
5547 MATRIX *mX, *mY ; /* original and transformed coordinate systems */
5548
5549 width = mri_src->width ;
5550 height = mri_src->height ;
5551 depth = mri_src->depth ;
5552 if (!mri_dst)
5553 {
5554 mri_dst = MRIalloc(width, height, depth, mri_src->type) ;
5555 MRIcopyHeader(mri_src, mri_dst) ;
5556 }
5557
5558 mX = MatrixAlloc(3, 1, MATRIX_REAL) ; /* input coordinates */
5559 mY = MatrixAlloc(3, 1, MATRIX_REAL) ; /* transformed coordinates */
5560
5561 for (x3 = 0 ; x3 < depth ; x3++)
5562 {
5563 mX->rptr[3][1] = x3 ;
5564 for (x2 = 0 ; x2 < height ; x2++)
5565 {
5566 mX->rptr[2][1] = x2 ;
5567 for (x1 = 0 ; x1 < width ; x1++)
5568 {
5569 mX->rptr[1][1] = x1 ;
5570 if (mA)
5571 MatrixMultiply(mA, mX, mY) ;
5572 else
5573 MatrixCopy(mX, mY) ;
5574 if (mB)
5575 MatrixAdd(mY, mB, mY) ;
5576 y1 = nint(mY->rptr[1][1]) ;
5577 y2 = nint(mY->rptr[2][1]) ;
5578 y3 = nint(mY->rptr[3][1]) ;
5579 if (y1 >= 0 && y1 < width &&
5580 y2 >= 0 && y2 < height &&
5581 y3 >= 0 && y3 < depth)
5582 mri_dst->slices[y3][y2][y1] = mri_src->slices[x3][x2][x1] ;
5583 }
5584 }
5585 }
5586
5587
5588 MatrixFree(&mX) ;
5589 MatrixFree(&mY) ;
5590
5591 mri_dst->ras_good_flag = 0;
5592
5593 return(mri_dst) ;
5594 }
5595 /*-----------------------------------------------------
5596 Parameters:
5597
5598 Returns value:
5599
5600 Description
5601 Convert a slice of an MRI data structure into a HIPS image.
5602 ------------------------------------------------------*/
5603 IMAGE *
5604 MRItoImageView(MRI *mri, IMAGE *I, int slice, int view, int frame)
5605 {
5606 int width, height, depth, x, y, yp, w, h, d,
5607 xm, ym, zm, format ;
5608 float fmin, fmax ;
5609 Real val ;
5610 int src_slice_direction;
5611 int xsign, ysign;
5612
5613 xsign=ysign=1; // let compiler be satisfied
5614
5615 src_slice_direction = getSliceDirection(mri);
5616 // only strict slice direction is supported
5617 if (src_slice_direction == MRI_UNDEFINED)
5618 ErrorReturn(NULL,
5619 (ERROR_UNSUPPORTED,
5620 "MRItoImageView(%d, %d): unsupported view/slice direction %d",
5621 slice, view, src_slice_direction)) ;
5622
5623 // generic routines to get the right axes
5624 //
5625 // should be able to do this in generic terms.
5626 // don't have time to do that
5627 //
5628 // Define the view to be the following:
5629 // coronal = (-R, -S)
5630 // sagittal = ( A, -S)
5631 // horizontal = (-R, A)
5632 //
5633 // translate these direction into (x,y)
5634 d = w = h = xm = ym = zm = 0 ; /* silly compiler warnings */
5635 width = mri->width ;
5636 height = mri->height ;
5637 depth = mri->depth ;
5638
5639 switch(src_slice_direction)
5640 {
5641 case MRI_CORONAL: // x direction can be -R or R,
5642 // y direction can be -S or S, z direction can be -A or A
5643 // +/-1 0 0
5644 // 0 0 +/-1
5645 // 0 +/-1 0
5646 switch(view)
5647 {
5648 case MRI_CORONAL:
5649 w = width; h = height; d = depth;
5650 xsign = (mri->x_r > 0) ? -1 : 1; ysign = (mri->y_s > 0) ? -1 : 1;
5651 break;
5652 case MRI_SAGITTAL:
5653 w = depth; h = height; d = width;
5654 xsign = (mri->z_a > 0) ? 1 : -1; ysign = (mri->y_s > 0) ? -1 : 1;
5655 break;
5656 case MRI_HORIZONTAL:
5657 w = width; h = depth; d = height;
5658 xsign = (mri->x_r > 0) ? -1 : 1; ysign = (mri->z_a > 0) ? 1 : -1;
5659 break;
5660 }
5661 break;
5662 case MRI_SAGITTAL: // x direction can be -A or A,
5663 // y direction can be -S or S, z direction can be -R or R
5664 // 0 0 +/-1
5665 // +/-1 0 0
5666 // 0 +/-1 0
5667 switch(view)
5668 {
5669 case MRI_CORONAL:
5670 w = depth; h = height; d = width;
5671 xsign =
5672 (mri->z_r > 0) ? -1 : 1; ysign = (mri->y_s > 0) ? -1 : 1;
5673 break;
5674 case MRI_SAGITTAL:
5675 w = width; h = height; d = depth;
5676 xsign = (mri->x_a > 0) ? 1 : -1; ysign = (mri->y_s > 0) ? -1 : 1;
5677 break;
5678 case MRI_HORIZONTAL:
5679 w = depth; h = width; d = height;
5680 xsign = (mri->z_r > 0) ? -1 : 1; ysign = (mri->x_a > 0) ? 1 : -1;
5681 break;
5682 }
5683 break;
5684 case MRI_HORIZONTAL: // x direction can be -R or R,
5685 // y direction can be -A or A, z direction can be -S or S
5686 // +/-1 0 0
5687 // 0 +/-1 0
5688 // 0 0 +/-1
5689 switch(view)
5690 {
5691 case MRI_CORONAL:
5692 w = width; h = depth; d = height;
5693 xsign = (mri->x_r > 0) ? -1 : 1; ysign = (mri->z_s > 0) ? -1 : 1;
5694 break;
5695 case MRI_SAGITTAL:
5696 w = height; h = depth; d = width;
5697 xsign = (mri->y_a > 0) ? 1 : -1; ysign = (mri->z_s > 0) ? -1 : 1;
5698 break;
5699 case MRI_HORIZONTAL:
5700 w = width; h = height; d = depth;
5701 xsign = (mri->x_r > 0) ? -1 : 1; ysign = (mri->y_a > 0) ? 1 : -1;
5702 break;
5703 }
5704 break;
5705 default:
5706 ErrorReturn
5707 (NULL,
5708 (ERROR_UNSUPPORTED,
5709 "MRItoImageView(%d, %d): unsupported view/slice direction %d",
5710 slice, view, src_slice_direction)) ;
5711 }
5712 if (slice < 0 || slice >= d)
5713 ErrorReturn(NULL, (ERROR_BADPARM, "MRItoImageView: bad slice %d\n",slice));
5714
5715 #if 0
5716 format = (mri->type == MRI_UCHAR) ? PFBYTE :
5717 mri->type == MRI_INT ? PFINT :
5718 mri->type == MRI_FLOAT ? PFFLOAT :
5719 mri->type == MRI_SHORT ? PFFLOAT : PFBYTE ;
5720 #else
5721 format = PFBYTE ;
5722 #endif
5723
5724 if (I && ((I->rows != h) || (I->cols != w) || (I->pixel_format != format)))
5725 {
5726 ImageFree(&I);
5727 I = NULL ; /* must allocate a new one */
5728 }
5729 if (!I)
5730 I = ImageAlloc(h, w, format, 1) ;
5731
5732 fmin = 10000000 ; fmax = -fmin ;
5733
5734 // Image values assigned from MRI
5735 // we need to gert min and max in IMAGE
5736 for (y = 0 ; y < h ; y++)
5737 {
5738 for (x = 0 ; x < w ; x++)
5739 {
5740 switch(src_slice_direction)
5741 {
5742 case MRI_CORONAL:
5743 switch (view) /* calculate coordinates in MR structure */
5744 {
5745 case MRI_CORONAL:
5746 xm = (xsign> 0) ? x : (w - 1 -x);
5747 ym = (ysign> 0) ? y : (h - 1 -y);
5748 zm = slice ;
5749 break ;
5750 case MRI_SAGITTAL:
5751 xm = slice ;
5752 ym = (ysign>0) ? y : (h - 1 - y);
5753 zm = (xsign>0) ? x : (w - 1 - x);
5754 break ;
5755 case MRI_HORIZONTAL:
5756 xm = (xsign>0) ? x : (w - 1 - x);
5757 ym = slice ;
5758 zm = (ysign>0) ? y : (h - 1 - y);
5759 break ;
5760 }
5761 break;
5762 case MRI_SAGITTAL:
5763 switch (view) /* calculate coordinates in MR structure */
5764 {
5765 case MRI_CORONAL:
5766 xm = slice;
5767 ym = (ysign>0) ? y : (h - 1 - y);
5768 zm = (xsign>0) ? x : (w - 1 - x);
5769 break ;
5770 case MRI_SAGITTAL:
5771 xm = (xsign>0) ? x : (w - 1 - x);
5772 ym = (ysign>0) ? y : (h - 1 - y);
5773 zm = slice ;
5774 break ;
5775 case MRI_HORIZONTAL:
5776 xm = (ysign>0) ? y : (h - 1 - y);
5777 ym = slice;
5778 zm = (xsign>0) ? x : (w - 1 - x);
5779 break ;
5780 }
5781 break;
5782 case MRI_HORIZONTAL:
5783 switch (view) /* calculate coordinates in MR structure */
5784 {
5785 case MRI_CORONAL:
5786 xm = (xsign>0) ? x : (w - 1 - x);
5787 ym = slice ;
5788 zm = (ysign>0) ? y : (h - 1 - y);
5789 break ;
5790 case MRI_SAGITTAL:
5791 xm = slice ;
5792 ym = (xsign>0) ? x : (w - 1 - x);
5793 zm = (ysign>0) ? y : (h - 1 - y);
5794 break ;
5795 case MRI_HORIZONTAL:
5796 xm = (xsign>0) ? x : (w - 1 - x);
5797 ym = (ysign>0) ? y : (h - 1 - y);
5798 zm = slice ;
5799 break ;
5800 }
5801 break;
5802 }
5803 MRIsampleVolumeFrame(mri, xm, ym, zm, frame, &val) ;
5804 // check min max
5805 if (val > fmax)
5806 fmax = val ;
5807 if (val < fmin)
5808 fmin = val ;
5809 }
5810 }
5811 if (FZERO(fmax-fmin))
5812 ErrorReturn(I, (ERROR_BADPARM, "MRItoImageView: constant image")) ;
5813
5814 // after all these calculation, we are going to do it again?
5815 for (y = 0 ; y < h ; y++)
5816 {
5817
5818 for (x = 0 ; x < w ; x++)
5819 {
5820 switch(src_slice_direction)
5821 {
5822 case MRI_CORONAL:
5823 switch (view) /* calculate coordinates in MR structure */
5824 {
5825 case MRI_CORONAL:
5826 xm = (xsign> 0) ? x : (w - 1 -x);
5827 ym = (ysign> 0) ? y : (h - 1 -y);
5828 zm = slice ;
5829 break ;
5830 case MRI_SAGITTAL:
5831 xm = slice ;
5832 ym = (ysign>0) ? y : (h - 1 - y);
5833 zm = (xsign>0) ? x : (w - 1 - x);
5834 break ;
5835 case MRI_HORIZONTAL:
5836 xm = (xsign>0) ? x : (w - 1 - x);
5837 ym = slice ;
5838 zm = (ysign>0) ? y : (h - 1 - y);
5839 break ;
5840 }
5841 break;
5842 case MRI_SAGITTAL:
5843 switch (view) /* calculate coordinates in MR structure */
5844 {
5845 case MRI_CORONAL:
5846 xm = slice;
5847 ym = (ysign>0) ? y : (h - 1 - y);
5848 zm = (xsign>0) ? x : (w - 1 - x);
5849 break ;
5850 case MRI_SAGITTAL:
5851 xm = (xsign>0) ? x : (w - 1 - x);
5852 ym = (ysign>0) ? y : (h - 1 - y);
5853 zm = slice ;
5854 break ;
5855 case MRI_HORIZONTAL:
5856 xm = (ysign>0) ? y : (h - 1 - y);
5857 ym = slice;
5858 zm = (xsign>0) ? x : (w - 1 - x);
5859 break ;
5860 }
5861 break;
5862 case MRI_HORIZONTAL:
5863 switch (view) /* calculate coordinates in MR structure */
5864 {
5865 case MRI_CORONAL:
5866 xm = (xsign>0) ? x : (w - 1 - x);
5867 ym = slice ;
5868 zm = (ysign>0) ? y : (h - 1 - y);
5869 break ;
5870 case MRI_SAGITTAL:
5871 xm = slice ;
5872 ym = (xsign>0) ? x : (w - 1 - x);
5873 zm = (ysign>0) ? y : (h - 1 - y);
5874 break ;
5875 case MRI_HORIZONTAL:
5876 xm = (xsign>0) ? x : (w - 1 - x);
5877 ym = (ysign>0) ? y : (h - 1 - y);
5878 zm = slice ;
5879 break ;
5880 }
5881 break;
5882 }
5883 MRIsampleVolumeFrame(mri, xm, ym, zm, frame, &val) ;
5884 yp = h - (y+1) ; /* hips coordinate system is inverted */
5885 *IMAGEpix(I, x, yp) = (byte)(255.0 * (val - fmin) / (fmax - fmin)) ;
5886 }
5887 }
5888
5889 return(I) ;
5890 }
5891 /*-----------------------------------------------------
5892 Parameters:
5893
5894 Returns value:
5895
5896 Description
5897 Convert a slice of an MRI data structure into a HIPS image.
5898 ------------------------------------------------------*/
5899 IMAGE *
5900 MRItoImage(MRI *mri, IMAGE *I, int slice)
5901 {
5902 int width, height, y, yp ;
5903
5904 width = mri->width ;
5905 height = mri->height ;
5906 if (slice < 0 || slice >= mri->depth)
5907 ErrorReturn(NULL, (ERROR_BADPARM, "MRItoImage: bad slice %d\n", slice)) ;
5908
5909 if (!I)
5910 {
5911 I = ImageAlloc(height, width,
5912 mri->type == MRI_UCHAR ? PFBYTE :
5913 mri->type == MRI_INT ? PFINT :
5914 mri->type == MRI_FLOAT ? PFFLOAT : PFBYTE, 1) ;
5915 }
5916
5917 for (y = 0 ; y < height ; y++)
5918 {
5919 yp = height - (y+1) ;
5920
5921 #if 0
5922 if (mri->type == MRI_UCHAR)
5923 image_to_buffer(I->image, mri, slice) ;
5924 else
5925 #endif
5926 switch (mri->type)
5927 {
5928 case MRI_INT:
5929 memcpy
5930 (IMAGEIpix(I, 0, yp),mri->slices[slice][y],width*sizeof(int)) ;
5931 break ;
5932 case MRI_FLOAT:
5933 memcpy
5934 (IMAGEFpix(I, 0, yp),mri->slices[slice][y],width*sizeof(float));
5935 break ;
5936 case MRI_UCHAR:
5937 memcpy(IMAGEpix(I, 0, yp), mri->slices[slice][y],
5938 width*sizeof(unsigned char)) ;
5939 break ;
5940 default:
5941 case MRI_LONG:
5942 ImageFree(&I) ;
5943 ErrorReturn
5944 (NULL,
5945 (ERROR_UNSUPPORTED,
5946 "MRItoImage: unsupported type %d",
5947 mri->type)) ;
5948 break ;
5949 }
5950 }
5951
5952 return(I) ;
5953 }
5954
5955 MRI *
5956 ImageToMRI(IMAGE *I)
5957 {
5958 MRI *mri;
5959 int width, height, depth, type, nframes, y, yp, x ;
5960 int frames;
5961
5962 type = MRI_UCHAR; // to make compiler happy
5963 width = I->ocols;
5964 height = I->orows;
5965 depth = 1;
5966 nframes = I->num_frame;
5967
5968 switch(I->pixel_format)
5969 {
5970 case PFBYTE:
5971 type = MRI_UCHAR;
5972 break;
5973 case PFSHORT:
5974 type = MRI_SHORT;
5975 break;
5976 case PFINT:
5977 type = MRI_INT;
5978 break;
5979 case PFFLOAT:
5980 type = MRI_FLOAT;
5981 break;
5982 case PFDOUBLE:
5983 case PFCOMPLEX:
5984 default:
5985 ErrorExit
5986 (ERROR_BADPARM, "IMAGE type = %d not supported\n", I->pixel_format);
5987 break;
5988 }
5989 // allocate memory
5990 if (nframes <= 1)
5991 mri = MRIalloc(width, height, depth, type);
5992 else
5993 mri = MRIallocSequence(width, height, depth, type, nframes);
5994
5995 // just fake the size
5996 mri->nframes = nframes;
5997 mri->imnr0 = 1;
5998 mri->imnr1 = 1;
5999 mri->thick = mri->ps = 1.0;
6000 mri->xsize = mri->ysize = mri->zsize = 1.0;
6001 mri->xend = mri->width * mri->xsize / 2.0;
6002 mri->xstart = -mri->xend;
6003 mri->yend = mri->height * mri->ysize / 2.0;
6004 mri->ystart = -mri->yend;
6005 mri->zend = mri->depth * mri->zsize / 2.0;
6006 mri->zstart = -mri->zend;
6007 mri->fov = ((mri->xend - mri->xstart) > (mri->yend - mri->ystart) ?
6008 (mri->xend - mri->xstart) : (mri->yend - mri->ystart));
6009 // set orientation to be coronal
6010 mri->x_r = -1; mri->y_r = 0; mri->z_r = 0; mri->c_r = 0;
6011 mri->x_a = 0; mri->y_a = 0; mri->z_a = 1; mri->c_a = 0;
6012 mri->x_s = 0; mri->y_s = -1; mri->z_s = 0; mri->c_s = 0;
6013
6014 // hips coordinate system is inverted
6015 for (frames = 0; frames < nframes; ++frames)
6016 {
6017
6018 for (y = 0 ; y < height ; y++)
6019 {
6020 yp = height - (y+1) ;
6021
6022 for (x = 0; x < width; ++x)
6023 {
6024 switch (mri->type)
6025 {
6026 case MRI_UCHAR:
6027 MRIseq_vox(mri, x, y, 0, frames) = *IMAGEpix(I, x, yp);
6028 break ;
6029 case MRI_SHORT:
6030 MRISseq_vox(mri, x, y, 0, frames) = *IMAGESpix(I, x, yp);
6031 break;
6032 case MRI_INT:
6033 MRIIseq_vox(mri, x, y, 0, frames) = *IMAGEIpix(I, x, yp);
6034 break ;
6035 case MRI_FLOAT:
6036 MRIFseq_vox(mri, x, y, 0, frames) = *IMAGEFpix(I, x, yp);
6037 break ;
6038 default:
6039 ErrorReturn
6040 (NULL,
6041 (ERROR_UNSUPPORTED,
6042 "MRItoImage: unsupported type %d",
6043 mri->type)) ;
6044 break ;
6045 }
6046 }
6047 }
6048 } // frames
6049 return(mri) ;
6050 }
6051
6052 /*-----------------------------------------------------
6053 Parameters:
6054
6055 Returns value:
6056
6057 Description
6058 Build an MRI from all values s.t. min_val <= val <= max_val
6059 ------------------------------------------------------*/
6060 MRI *
6061 MRIextractValues(MRI *mri_src, MRI *mri_dst, float min_val, float max_val)
6062 {
6063 BUFTYPE *psrc, *pdst, val ;
6064 float *pfsrc, *pfdst, fval ;
6065 int frame, x, y, z, width, height, depth ;
6066
6067 width = mri_src->width ;
6068 height = mri_src->height ;
6069 depth = mri_src->depth ;
6070 if (!mri_dst)
6071 mri_dst = MRIclone(mri_src, NULL) ;
6072
6073 for (frame = 0 ; frame < mri_src->nframes ; frame++)
6074 {
6075 for (z = 0 ; z < depth ; z++)
6076 {
6077 for (y = 0 ; y < height ; y++)
6078 {
6079 switch (mri_src->type)
6080 {
6081 case MRI_UCHAR:
6082 psrc = &MRIseq_vox(mri_src, 0, y, z, frame) ;
6083 pdst = &MRIseq_vox(mri_dst, 0, y, z, frame) ;
6084 for (x = 0 ; x < width ; x++)
6085 {
6086 val = *psrc++ ;
6087 if ((val < min_val) || (val > max_val))
6088 val = 0 ;
6089 *pdst++ = val ;
6090 }
6091 break ;
6092 case MRI_FLOAT:
6093 pfsrc = &MRIFseq_vox(mri_src, 0, y, z, frame) ;
6094 pfdst = &MRIFseq_vox(mri_dst, 0, y, z, frame) ;
6095 for (x = 0 ; x < width ; x++)
6096 {
6097 fval = *pfsrc++ ;
6098 if ((fval < min_val) || (fval > max_val))
6099 fval = 0.0f ;
6100 *pfdst++ = fval ;
6101 }
6102 break ;
6103 default:
6104 ErrorReturn
6105 (NULL,
6106 (ERROR_UNSUPPORTED,
6107 "MRIextractValues: unsupported type %d",mri_src->type));
6108 }
6109 }
6110 }
6111 }
6112
6113 return(mri_dst) ;
6114 }
6115 /*-----------------------------------------------------
6116 Parameters:
6117
6118 Returns value:
6119
6120 Description
6121 ------------------------------------------------------*/
6122 MRI *
6123 MRIupsample2(MRI *mri_src, MRI *mri_dst)
6124 {
6125 int width, depth, height, x, y, z ;
6126 BUFTYPE *pdst ;
6127 short *psdst ;
6128 float *pfdst ;
6129
6130 if (mri_dst && mri_src->type != mri_dst->type)
6131 ErrorReturn
6132 (NULL,
6133 (ERROR_UNSUPPORTED, "MRIupsample2: source and dst must be same type"));
6134
6135 width = 2*mri_src->width ;
6136 height = 2*mri_src->height ;
6137 depth = 2*mri_src->depth ;
6138
6139 if (!mri_dst)
6140 {
6141 mri_dst = MRIalloc(width, height, depth, mri_src->type) ;
6142 MRIcopyHeader(mri_src, mri_dst) ;
6143 }
6144
6145 for (z = 0 ; z < depth ; z++)
6146 {
6147 for (y = 0 ; y < height ; y++)
6148 {
6149 switch (mri_src->type)
6150 {
6151 case MRI_UCHAR:
6152 pdst = &MRIvox(mri_dst, 0, y, z) ;
6153 for (x = 0 ; x < width ; x++)
6154 *pdst++ = MRIvox(mri_src, x/2, y/2, z/2) ;
6155 break ;
6156 case MRI_SHORT:
6157 psdst = &MRISvox(mri_dst, 0, y, z) ;
6158 for (x = 0 ; x < width ; x++)
6159 *psdst++ = MRISvox(mri_src, x/2, y/2, z/2) ;
6160 break ;
6161 case MRI_FLOAT:
6162 pfdst = &MRIFvox(mri_dst, 0, y, z) ;
6163 for (x = 0 ; x < width ; x++)
6164 *pfdst++ = MRIFvox(mri_src, x/2, y/2, z/2) ;
6165 break ;
6166 default:
6167 ErrorReturn
6168 (NULL,
6169 (ERROR_UNSUPPORTED,
6170 "MRIupsample2: unsupported src type %d", mri_src->type)) ;
6171 }
6172
6173 }
6174 }
6175
6176 mri_dst->imnr0 = mri_src->imnr0 ;
6177 mri_dst->imnr1 = mri_src->imnr0 + mri_dst->depth - 1 ;
6178
6179 mri_dst->xsize = mri_src->xsize/2 ;
6180 mri_dst->ysize = mri_src->ysize/2 ;
6181 mri_dst->zsize = mri_src->zsize/2 ;
6182
6183 mri_dst->ras_good_flag = 0;
6184
6185 return(mri_dst) ;
6186 }
6187 MRI *
6188 MRIdownsample2LabeledVolume(MRI *mri_src, MRI *mri_dst)
6189 {
6190 int width, depth, height, x, y, z, x1, y1, z1, counts[256], label,
6191 max_count, out_label ;
6192 BUFTYPE *psrc ;
6193
6194 if (mri_src->type != MRI_UCHAR)
6195 ErrorReturn(NULL,
6196 (ERROR_UNSUPPORTED,
6197 "MRIdownsample2LabeledVolume: source must be UCHAR"));
6198
6199 width = mri_src->width/2 ;
6200 height = mri_src->height/2 ;
6201 depth = mri_src->depth/2 ;
6202
6203 if (!mri_dst)
6204 {
6205 mri_dst = MRIalloc(width, height, depth, mri_src->type) ;
6206 MRIcopyHeader(mri_src, mri_dst) ;
6207 }
6208
6209 MRIclear(mri_dst) ;
6210 for (z = 0 ; z < depth ; z++)
6211 {
6212 for (y = 0 ; y < height ; y++)
6213 {
6214 for (x = 0 ; x < width ; x++)
6215 {
6216 memset(counts, 0, sizeof(counts)) ;
6217 if (x == 96 && y == 66 && z == 56)
6218 DiagBreak() ;
6219 for (z1 = 2*z ; z1 <= 2*z+1 ; z1++)
6220 {
6221 for (y1 = 2*y ; y1 <= 2*y+1 ; y1++)
6222 {
6223 psrc = &MRIvox(mri_src, 2*x, y1, z1) ;
6224 for (x1 = 2*x ; x1 <= 2*x+1 ; x1++)
6225 {
6226 label = *psrc++ ;
6227 counts[label]++ ;
6228 }
6229 }
6230 }
6231 for (out_label = label = 0, max_count = counts[0] ;
6232 label <= 255 ;
6233 label++)
6234 {
6235 if (counts[label] > max_count)
6236 {
6237 out_label = label ;
6238 max_count = counts[label] ;
6239 }
6240 }
6241 MRIvox(mri_dst, x, y, z) = out_label ;
6242 }
6243 }
6244 }
6245
6246 mri_dst->imnr0 = mri_src->imnr0 ;
6247 mri_dst->imnr1 = mri_src->imnr0 + mri_dst->depth - 1 ;
6248 mri_dst->xsize = mri_src->xsize*2 ;
6249 mri_dst->ysize = mri_src->ysize*2 ;
6250 mri_dst->zsize = mri_src->zsize*2 ;
6251
6252 mri_dst->ras_good_flag = 0;
6253
6254 return(mri_dst) ;
6255 }
6256 /*-----------------------------------------------------
6257 Parameters:
6258
6259 Returns value:
6260
6261 Description
6262 ------------------------------------------------------*/
6263 MRI *
6264 MRIdownsample2(MRI *mri_src, MRI *mri_dst)
6265 {
6266 int width, depth, height, x, y, z, x1, y1, z1 ;
6267 BUFTYPE *psrc ;
6268 short *pssrc ;
6269 float val ;
6270
6271 if (mri_dst && mri_src->type != mri_dst->type)
6272 ErrorReturn
6273 (NULL,
6274 (ERROR_UNSUPPORTED,
6275 "MRIdownsample2: source and dst must be same type"));
6276
6277 width = mri_src->width/2 ;
6278 height = mri_src->height/2 ;
6279 depth = mri_src->depth/2 ;
6280
6281 if (!mri_dst)
6282 {
6283 mri_dst = MRIalloc(width, height, depth, mri_src->type) ;
6284 MRIcopyHeader(mri_src, mri_dst) ;
6285 }
6286
6287 MRIclear(mri_dst) ;
6288 for (z = 0 ; z < depth ; z++)
6289 {
6290 for (y = 0 ; y < height ; y++)
6291 {
6292 for (x = 0 ; x < width ; x++)
6293 {
6294 for (val = 0.0f, z1 = 2*z ; z1 <= 2*z+1 ; z1++)
6295 {
6296 for (y1 = 2*y ; y1 <= 2*y+1 ; y1++)
6297 {
6298 switch (mri_src->type)
6299 {
6300 case MRI_UCHAR:
6301 psrc = &MRIvox(mri_src, 2*x, y1, z1) ;
6302 for (x1 = 2*x ; x1 <= 2*x+1 ; x1++)
6303 val += *psrc++ ;
6304 break ;
6305 case MRI_SHORT:
6306 pssrc = &MRISvox(mri_src, 2*x, y1, z1) ;
6307 for (x1 = 2*x ; x1 <= 2*x+1 ; x1++)
6308 val += *pssrc++ ;
6309 break ;
6310 default:
6311 ErrorReturn
6312 (NULL,
6313 (ERROR_UNSUPPORTED,
6314 "MRIdownsample2: unsupported input type %d",
6315 mri_src->type));
6316 }
6317 }
6318 }
6319 switch (mri_src->type)
6320 {
6321 case MRI_UCHAR:
6322 MRIvox(mri_dst, x, y, z) = (BUFTYPE)nint(val/8.0f) ;
6323 break ;
6324 case MRI_SHORT:
6325 MRISvox(mri_dst, x, y, z) = (short)nint(val/8.0f) ;
6326 break ;
6327 }
6328 }
6329 }
6330 }
6331
6332 mri_dst->imnr0 = mri_src->imnr0 ;
6333 mri_dst->imnr1 = mri_src->imnr0 + mri_dst->depth - 1 ;
6334 mri_dst->xsize = mri_src->xsize*2 ;
6335 mri_dst->ysize = mri_src->ysize*2 ;
6336 mri_dst->zsize = mri_src->zsize*2 ;
6337
6338 mri_dst->ras_good_flag = 0;
6339
6340 return(mri_dst) ;
6341 }
6342 /*-------------------------------------------------------------
6343 MRI MRIvalueFill(MRI *mri, float value) -- fills an mri volume
6344 with the given value. Type of mri can be anything.
6345 -------------------------------------------------------------*/
6346 int MRIvalueFill(MRI *mri, float value)
6347 {
6348 int c,r,s,f;
6349
6350 for(c=0; c < mri->width; c++){
6351 for(r=0; r < mri->height; r++){
6352 for(s=0; s < mri->depth; s++){
6353 for(f=0; f < mri->nframes; f++){
6354 switch(mri->type){
6355 case MRI_UCHAR:
6356 MRIseq_vox(mri,c,r,s,f) = (unsigned char) (nint(value));
6357 break;
6358 case MRI_SHORT:
6359 MRISseq_vox(mri,c,r,s,f) = (short) (nint(value));
6360 break;
6361 case MRI_INT:
6362 MRIIseq_vox(mri,c,r,s,f) = (int) (nint(value));
6363 break;
6364 case MRI_FLOAT:
6365 MRIFseq_vox(mri,c,r,s,f) = value;
6366 break;
6367 }
6368 }
6369 }
6370 }
6371 }
6372
6373 return(0);
6374 }
6375 /*-----------------------------------------------------
6376 Parameters:
6377
6378 Returns value:
6379
6380 Description
6381 Iteratively set all voxels in mri_dst that neighbor
6382 a voxel that has already been filled (starting with the seed),
6383 and for which the corresponding voxel in mri_src is
6384 below threshold.
6385 ------------------------------------------------------*/
6386 MRI *
6387 MRIfill(MRI *mri_src, MRI *mri_dst, int seed_x, int seed_y,
6388 int seed_z, int threshold, int fill_val, int max_count)
6389 {
6390 int width, height, depth, x, y, z, nfilled, xmin, xmax, ymin, ymax,
6391 zmin, zmax, on, x0, x1, y0, y1, z0, z1 ;
6392 BUFTYPE *psrc, *pdst, val ;
6393
6394 width = mri_src->width ;
6395 height = mri_src->height ;
6396 depth = mri_src->depth ;
6397 if (!mri_dst)
6398 mri_dst = MRIclone(mri_src, NULL) ;
6399
6400 if (seed_x < 0)
6401 seed_x = 0 ;
6402 else if (seed_x >= width)
6403 seed_x = width-1 ;
6404 if (seed_y < 0)
6405 seed_y = 0 ;
6406 else if (seed_y >= height)
6407 seed_y = height-1 ;
6408 if (seed_z < 0)
6409 seed_z = 0 ;
6410 else if (seed_z >= depth)
6411 seed_z = depth-1 ;
6412
6413 xmin = MAX(seed_x-1,0) ; xmax = MIN(seed_x+1, width-1) ;
6414 ymin = MAX(seed_y-1,0) ; ymax = MIN(seed_y+1, height-1) ;
6415 zmin = MAX(seed_z-1,0) ; zmax = MIN(seed_z+1, depth-1) ;
6416
6417 /* replace all occurrences of fill_val with fill_val-1 */
6418 for (z = 0 ; z < depth ; z++)
6419 {
6420 for (y = 0 ; y < height ; y++)
6421 {
6422 pdst = &MRIvox(mri_dst, 0, y, z) ;
6423 for (x = 0 ; x < width ; x++, pdst++)
6424 {
6425 val = *pdst ;
6426 if (val == fill_val)
6427 *pdst = val-1 ;
6428 }
6429 }
6430 }
6431
6432 MRIvox(mri_dst, seed_x, seed_y, seed_z) = fill_val ;
6433 do
6434 {
6435 z0 = zmin ; z1 = zmax ; y0 = ymin ; y1 = ymax ; x0 = xmin ; x1 = xmax ;
6436 nfilled = 0 ;
6437 for (z = zmin ; z <= zmax ; z++)
6438 {
6439 for (y = ymin ; y <= ymax ; y++)
6440 {
6441 psrc = &MRIvox(mri_src, xmin, y, z) ;
6442 pdst = &MRIvox(mri_dst, xmin, y, z) ;
6443 for (x = xmin ; x <= xmax ; x++, psrc++, pdst++)
6444 {
6445 val = *psrc ;
6446 if ((val > threshold) || (*pdst == fill_val))
6447 continue ;
6448
6449 on = 0 ;
6450 if (x > 0)
6451 on = (MRIvox(mri_dst, x-1, y, z) == fill_val) ;
6452 if (!on && (x < width-1))
6453 on = (MRIvox(mri_dst, x+1, y, z) == fill_val) ;
6454 if (!on && (y > 0))
6455 on = (MRIvox(mri_dst, x, y-1, z) == fill_val) ;
6456 if (!on && (y < height-1))
6457 on = (MRIvox(mri_dst, x, y+1, z) == fill_val) ;
6458 if (!on && (z > 0))
6459 on = (MRIvox(mri_dst, x, y, z-1) == fill_val) ;
6460 if (!on && (z < depth-1))
6461 on = (MRIvox(mri_dst, x, y, z+1) == fill_val) ;
6462 if (on)
6463 {
6464 if (x <= x0)
6465 x0 = MAX(x-1,0) ;
6466 if (x >= x1)
6467 x1 = MIN(x+1,width-1) ;
6468 if (y <= y0)
6469 y0 = MAX(y-1,0) ;
6470 if (y >= y1)
6471 y1 = MIN(y+1,height-1) ;
6472 if (z <= z0)
6473 z0 = MAX(z-1,0) ;
6474 if (z >= z1)
6475 z1 = MIN(z+1,depth-1) ;
6476 nfilled++ ;
6477 *pdst = fill_val ;
6478 }
6479 }
6480 }
6481 }
6482 zmin = z0 ; zmax = z1 ; ymin = y0 ; ymax = y1 ; xmin = x0 ; xmax = x1 ;
6483 /* fprintf(stderr, "# filled = %d\n", nfilled) ;*/
6484 if ((max_count > 0) && (nfilled > max_count))
6485 break ;
6486 } while (nfilled > 0) ;
6487
6488 return(mri_dst) ;
6489 }
6490 /*-----------------------------------------------------
6491 Parameters:
6492
6493 Returns value:
6494
6495 Description
6496 ------------------------------------------------------*/
6497 MRI *
6498 MRIfillFG(MRI *mri_src, MRI *mri_dst, int seed_x, int seed_y,
6499 int seed_z, int threshold, int fill_val, int *npix)
6500 {
6501 int width, height, depth, x, y, z, nfilled, xmin, xmax, ymin, ymax,
6502 zmin, zmax, on, x0, x1, y0, y1, z0, z1, total_pix ;
6503 BUFTYPE *psrc, *pdst, val ;
6504
6505 width = mri_src->width ;
6506 height = mri_src->height ;
6507 depth = mri_src->depth ;
6508 if (!mri_dst)
6509 mri_dst = MRIclone(mri_src, NULL) ;
6510
6511 if (seed_x < 0)
6512 seed_x = 0 ;
6513 else if (seed_x >= width)
6514 seed_x = width-1 ;
6515 if (seed_y < 0)
6516 seed_y = 0 ;
6517 else if (seed_y >= height)
6518 seed_y = width-1 ;
6519 if (seed_z < 0)
6520 seed_z = 0 ;
6521 else if (seed_z >= depth)
6522 seed_z = width-1 ;
6523
6524 xmin = MAX(seed_x-1,0) ; xmax = MIN(seed_x+1, width-1) ;
6525 ymin = MAX(seed_y-1,0) ; ymax = MIN(seed_y+1, height-1) ;
6526 zmin = MAX(seed_z-1,0) ; zmax = MIN(seed_z+1, depth-1) ;
6527
6528 /* replace all occurrences of fill_val with fill_val-1 */
6529 for (z = 0 ; z < depth ; z++)
6530 {
6531 for (y = 0 ; y < height ; y++)
6532 {
6533 pdst = &MRIvox(mri_dst, 0, y, z) ;
6534 for (x = 0 ; x < width ; x++, pdst++)
6535 {
6536 val = *pdst ;
6537 if (val == fill_val)
6538 *pdst = val-1 ;
6539 }
6540 }
6541 }
6542
6543 MRIvox(mri_dst, seed_x, seed_y, seed_z) = fill_val ;
6544 total_pix = 1 ; /* include the seed point */
6545 do
6546 {
6547 z0 = zmin ; z1 = zmax ; y0 = ymin ; y1 = ymax ; x0 = xmin ; x1 = xmax ;
6548 nfilled = 0 ;
6549 for (z = zmin ; z <= zmax ; z++)
6550 {
6551 for (y = ymin ; y <= ymax ; y++)
6552 {
6553 psrc = &MRIvox(mri_src, xmin, y, z) ;
6554 pdst = &MRIvox(mri_dst, xmin, y, z) ;
6555 for (x = xmin ; x <= xmax ; x++, psrc++, pdst++)
6556 {
6557 val = *psrc ;
6558 if ((val < threshold) || (*pdst == fill_val))
6559 continue ;
6560
6561 on = 0 ;
6562 if (x > 0)
6563 on = (MRIvox(mri_dst, x-1, y, z) == fill_val) ;
6564 if (!on && (x < width-1))
6565 on = (MRIvox(mri_dst, x+1, y, z) == fill_val) ;
6566 if (!on && (y > 0))
6567 on = (MRIvox(mri_dst, x, y-1, z) == fill_val) ;
6568 if (!on && (y < height-1))
6569 on = (MRIvox(mri_dst, x, y+1, z) == fill_val) ;
6570 if (!on && (z > 0))
6571 on = (MRIvox(mri_dst, x, y, z-1) == fill_val) ;
6572 if (!on && (z < depth-1))
6573 on = (MRIvox(mri_dst, x, y, z+1) == fill_val) ;
6574 if (on)
6575 {
6576 if (x <= x0)
6577 x0 = MAX(x-1,0) ;
6578 if (x >= x1)
6579 x1 = MIN(x+1,width-1) ;
6580 if (y <= y0)
6581 y0 = MAX(y-1,0) ;
6582 if (y >= y1)
6583 y1 = MIN(y+1,height-1) ;
6584 if (z <= z0)
6585 z0 = MAX(z-1,0) ;
6586 if (z >= z1)
6587 z1 = MIN(z+1,depth-1) ;
6588 nfilled++ ;
6589 *pdst = fill_val ;
6590 }
6591 }
6592 }
6593 }
6594 zmin = z0 ; zmax = z1 ; ymin = y0 ; ymax = y1 ; xmin = x0 ; xmax = x1 ;
6595 total_pix += nfilled ;
6596 /* fprintf(stderr, "# filled = %d\n", nfilled) ;*/
6597 } while (nfilled > 0) ;
6598
6599 if (npix)
6600 *npix = total_pix ;
6601 return(mri_dst) ;
6602 }
6603 /*-----------------------------------------------------
6604 Parameters:
6605
6606 Returns value:
6607
6608 Description
6609 ------------------------------------------------------*/
6610 MRI *
6611 MRIfillBG(MRI *mri_src, MRI *mri_dst, int seed_x, int seed_y,
6612 int seed_z, int threshold, int fill_val, int *npix)
6613 {
6614 int width, height, depth, x, y, z, nfilled, xmin, xmax, ymin, ymax,
6615 zmin, zmax, on, x0, x1, y0, y1, z0, z1, total_pix ;
6616 BUFTYPE *psrc, *pdst, val ;
6617
6618 width = mri_src->width ;
6619 height = mri_src->height ;
6620 depth = mri_src->depth ;
6621 if (!mri_dst)
6622 mri_dst = MRIclone(mri_src, NULL) ;
6623
6624 if (seed_x < 0)
6625 seed_x = 0 ;
6626 else if (seed_x >= width)
6627 seed_x = width-1 ;
6628 if (seed_y < 0)
6629 seed_y = 0 ;
6630 else if (seed_y >= height)
6631 seed_y = width-1 ;
6632 if (seed_z < 0)
6633 seed_z = 0 ;
6634 else if (seed_z >= depth)
6635 seed_z = width-1 ;
6636
6637 xmin = MAX(seed_x-1,0) ; xmax = MIN(seed_x+1, width-1) ;
6638 ymin = MAX(seed_y-1,0) ; ymax = MIN(seed_y+1, height-1) ;
6639 zmin = MAX(seed_z-1,0) ; zmax = MIN(seed_z+1, depth-1) ;
6640
6641 /* replace all occurrences of fill_val with fill_val-1 */
6642 for (z = 0 ; z < depth ; z++)
6643 {
6644 for (y = 0 ; y < height ; y++)
6645 {
6646 pdst = &MRIvox(mri_dst, 0, y, z) ;
6647 for (x = 0 ; x < width ; x++, pdst++)
6648 {
6649 val = *pdst ;
6650 if (val == fill_val)
6651 *pdst = val-1 ;
6652 }
6653 }
6654 }
6655
6656 MRIvox(mri_dst, seed_x, seed_y, seed_z) = fill_val ;
6657 total_pix = 0 ;
6658 do
6659 {
6660 z0 = zmin ; z1 = zmax ; y0 = ymin ; y1 = ymax ; x0 = xmin ; x1 = xmax ;
6661 nfilled = 0 ;
6662 for (z = zmin ; z <= zmax ; z++)
6663 {
6664 for (y = ymin ; y <= ymax ; y++)
6665 {
6666 psrc = &MRIvox(mri_src, xmin, y, z) ;
6667 pdst = &MRIvox(mri_dst, xmin, y, z) ;
6668 for (x = xmin ; x <= xmax ; x++, psrc++, pdst++)
6669 {
6670 if (z == 130 && (y == 145 || y == 146) && x == 142)
6671 DiagBreak() ;
6672 val = *psrc ;
6673 if ((val > threshold) || (*pdst == fill_val))
6674 continue ;
6675
6676 on = 0 ;
6677 if (x > 0)
6678 on = (MRIvox(mri_dst, x-1, y, z) == fill_val) ;
6679 if (!on && (x < width-1))
6680 on = (MRIvox(mri_dst, x+1, y, z) == fill_val) ;
6681 if (!on && (y > 0))
6682 on = (MRIvox(mri_dst, x, y-1, z) == fill_val) ;
6683 if (!on && (y < height-1))
6684 on = (MRIvox(mri_dst, x, y+1, z) == fill_val) ;
6685 if (!on && (z > 0))
6686 on = (MRIvox(mri_dst, x, y, z-1) == fill_val) ;
6687 if (!on && (z < depth-1))
6688 on = (MRIvox(mri_dst, x, y, z+1) == fill_val) ;
6689 if (on)
6690 {
6691 if (z == 130 && (y == 145 || y == 146) && x == 142)
6692 DiagBreak() ;
6693 if (x <= x0)
6694 x0 = MAX(x-1,0) ;
6695 if (x >= x1)
6696 x1 = MIN(x+1,width-1) ;
6697 if (y <= y0)
6698 y0 = MAX(y-1,0) ;
6699 if (y >= y1)
6700 y1 = MIN(y+1,height-1) ;
6701 if (z <= z0)
6702 z0 = MAX(z-1,0) ;
6703 if (z >= z1)
6704 z1 = MIN(z+1,depth-1) ;
6705 nfilled++ ;
6706 *pdst = fill_val ;
6707 }
6708 }
6709 }
6710 }
6711 zmin = z0 ; zmax = z1 ; ymin = y0 ; ymax = y1 ; xmin = x0 ; xmax = x1 ;
6712 total_pix += nfilled ;
6713 /* fprintf(stderr, "# filled = %d\n", nfilled) ;*/
6714 } while (nfilled > 0) ;
6715
6716 if (npix)
6717 *npix = total_pix ;
6718 return(mri_dst) ;
6719 }
6720 /*-----------------------------------------------------
6721 Parameters:
6722
6723 Returns value:
6724
6725 Description
6726 ------------------------------------------------------*/
6727 int
6728 MRIsetResolution(MRI *mri, float xres, float yres, float zres)
6729 {
6730 mri->ps = (xres+yres+zres) / 3.0f ;
6731 mri->xsize = xres ;
6732 mri->ysize = yres ;
6733 mri->zsize = zres ;
6734 mri->xstart *= xres ; mri->xend *= xres ;
6735 mri->ystart *= yres ; mri->yend *= yres ;
6736 mri->zstart *= zres ; mri->zend *= zres ;
6737 mri->thick = MAX(MAX(xres,yres),zres) ;
6738 #if 0
6739 mri->x_r = mri->x_r * xres ;
6740 mri->x_a = mri->x_a * xres ;
6741 mri->x_s = mri->x_s * xres ;
6742 mri->y_r = mri->y_r * yres ;
6743 mri->y_a = mri->y_a * yres ;
6744 mri->y_s = mri->y_s * yres ;
6745 mri->z_r = mri->z_r * zres ;
6746 mri->z_a = mri->z_a * zres ;
6747 mri->z_s = mri->z_s * zres ;
6748 #endif
6749 return(NO_ERROR) ;
6750 }
6751 /*-----------------------------------------------------
6752 Parameters:
6753
6754 Returns value:
6755
6756 Description
6757 ------------------------------------------------------*/
6758 int
6759 MRIsetTransform(MRI *mri, General_transform *transform)
6760 {
6761 mri->transform = *transform ;
6762 mri->linear_transform = get_linear_transform_ptr(transform) ;
6763 mri->inverse_linear_transform = get_inverse_linear_transform_ptr(transform) ;
6764
6765 return(NO_ERROR) ;
6766 }
6767 /*-----------------------------------------------------
6768 Parameters:
6769
6770 Returns value:
6771
6772 Description
6773 ------------------------------------------------------*/
6774 MRI *
6775 MRIextractTalairachPlane(MRI *mri_src, MRI *mri_dst, int orientation,
6776 int x, int y, int z, int wsize)
6777 {
6778 Real e1_x, e1_y, e1_z, e2_x, e2_y, e2_z, xbase, ybase, zbase ;
6779 int whalf, xk, yk, xi, yi, zi ;
6780 Real ex, ey, ez, len, x0, y0, z0 ;
6781
6782 whalf = (wsize-1)/2 ;
6783
6784 if (!mri_dst)
6785 {
6786 mri_dst = MRIalloc(wsize, wsize, 1, MRI_UCHAR) ;
6787 MRIcopyHeader(mri_src, mri_dst) ;
6788 mri_dst->xstart = x-whalf*mri_dst->xsize ;
6789 mri_dst->ystart = y-whalf*mri_dst->ysize ;
6790 mri_dst->zstart = z-whalf*mri_dst->zsize ;
6791 mri_dst->xend = mri_dst->xstart + wsize*mri_dst->xsize ;
6792 mri_dst->yend = mri_dst->ystart + wsize*mri_dst->ysize ;
6793 mri_dst->zend = mri_dst->zstart + wsize*mri_dst->zsize ;
6794 mri_dst->imnr0 = z + mri_src->imnr0 ;
6795 mri_dst->imnr1 = mri_dst->imnr0 ;
6796 }
6797
6798 MRIvoxelToTalairachVoxel(mri_src, x, y, z, &x0, &y0, &z0) ;
6799 switch (orientation)
6800 {
6801 default:
6802 case MRI_CORONAL: /* basis vectors in x-y plane */
6803 /* the 'x' basis vector */
6804 ex = (Real)x0+1 ; ey = (Real)y0 ; ez = (Real)z0 ;
6805 MRItalairachVoxelToVoxel(mri_src, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
6806 e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
6807
6808 /* the 'y' basis vector */
6809 ex = (Real)x0 ; ey = (Real)y0+1 ; ez = (Real)z0 ;
6810 MRItalairachVoxelToVoxel(mri_src, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
6811 e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
6812 break ;
6813 case MRI_HORIZONTAL: /* basis vectors in x-z plane */
6814 /* the 'x' basis vector */
6815 ex = (Real)x0+1 ; ey = (Real)y0 ; ez = (Real)z0 ;
6816 MRItalairachVoxelToVoxel(mri_src, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
6817 e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
6818
6819 /* the 'y' basis vector */
6820 ex = (Real)x0 ; ey = (Real)y0 ; ez = (Real)z0+1 ;
6821 MRItalairachVoxelToVoxel(mri_src, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
6822 e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
6823 break ;
6824 case MRI_SAGITTAL: /* basis vectors in y-z plane */
6825 /* the 'x' basis vector */
6826 ex = (Real)x0 ; ey = (Real)y0 ; ez = (Real)z0+1.0 ;
6827 MRItalairachVoxelToVoxel(mri_src, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
6828 e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
6829
6830 /* the 'y' basis vector */
6831 ex = (Real)x0 ; ey = (Real)y0+1.0 ; ez = (Real)z0 ;
6832 MRItalairachVoxelToVoxel(mri_src, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
6833 e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
6834 break ;
6835 }
6836
6837 len = sqrt(e1_x*e1_x + e1_y*e1_y + e1_z*e1_z) ;
6838 /* e1_x /= len ; e1_y /= len ; e1_z /= len ;*/
6839 len = sqrt(e2_x*e2_x + e2_y*e2_y + e2_z*e2_z) ;
6840 /* e2_x /= len ; e2_y /= len ; e2_z /= len ;*/
6841
6842 for (yk = -whalf ; yk <= whalf ; yk++)
6843 {
6844 xbase = (float)x + (float)yk * e2_x ;
6845 ybase = (float)y + (float)yk * e2_y ;
6846 zbase = (float)z + (float)yk * e2_z ;
6847 for (xk = -whalf ; xk <= whalf ; xk++)
6848 {
6849 /* in-plane vect. is linear combination of scaled basis vects */
6850 xi = mri_src->xi[nint(xbase + xk*e1_x)] ;
6851 yi = mri_src->yi[nint(ybase + xk*e1_y)] ;
6852 zi = mri_src->zi[nint(zbase + xk*e1_z)] ;
6853 MRIvox(mri_dst, xk+whalf,yk+whalf,0) = MRIvox(mri_src, xi, yi, zi) ;
6854 }
6855 }
6856
6857 return(mri_dst) ;
6858 }
6859 /*-----------------------------------------------------
6860 Parameters:
6861
6862 Returns value:
6863
6864 Description
6865 ------------------------------------------------------*/
6866 MRI *
6867 MRIextractArbitraryPlane(MRI *mri_src, MRI *mri_dst,
6868 Real e1_x, Real e1_y, Real e1_z,
6869 Real e2_x, Real e2_y, Real e2_z,
6870 int x, int y, int z, int wsize)
6871 {
6872 Real xbase, ybase, zbase ;
6873 int whalf, xk, yk, xi, yi, zi ;
6874
6875 whalf = (wsize-1)/2 ;
6876
6877 if (!mri_dst)
6878 {
6879 mri_dst = MRIalloc(wsize, wsize, 1, MRI_UCHAR) ;
6880 MRIcopyHeader(mri_src, mri_dst) ;
6881 mri_dst->xstart = x-whalf*mri_dst->xsize ;
6882 mri_dst->ystart = y-whalf*mri_dst->ysize ;
6883 mri_dst->zstart = z-whalf*mri_dst->zsize ;
6884 mri_dst->xend = mri_dst->xstart + wsize*mri_dst->xsize ;
6885 mri_dst->yend = mri_dst->ystart + wsize*mri_dst->ysize ;
6886 mri_dst->zend = mri_dst->zstart + wsize*mri_dst->zsize ;
6887 mri_dst->imnr0 = z + mri_src->imnr0 ;
6888 mri_dst->imnr1 = mri_dst->imnr0 ;
6889 }
6890
6891
6892
6893 for (yk = -whalf ; yk <= whalf ; yk++)
6894 {
6895 xbase = (float)x + (float)yk * e2_x ;
6896 ybase = (float)y + (float)yk * e2_y ;
6897 zbase = (float)z + (float)yk * e2_z ;
6898 for (xk = -whalf ; xk <= whalf ; xk++)
6899 {
6900 /* in-plane vect. is linear combination of scaled basis vects */
6901 xi = mri_src->xi[nint(xbase + xk*e1_x)] ;
6902 yi = mri_src->yi[nint(ybase + xk*e1_y)] ;
6903 zi = mri_src->zi[nint(zbase + xk*e1_z)] ;
6904 MRIvox(mri_dst, xk+whalf,yk+whalf,0) = MRIvox(mri_src, xi, yi, zi) ;
6905 }
6906 }
6907
6908 return(mri_dst) ;
6909 }
6910 /*-----------------------------------------------------
6911 Parameters:
6912
6913 Returns value:
6914
6915 Description
6916 ------------------------------------------------------*/
6917 int
6918 MRIeraseTalairachPlaneNew(MRI *mri, MRI *mri_mask, int orientation, int x,
6919 int y, int z, int wsize, int fill_val)
6920 {
6921 Real e1_x, e1_y, e1_z, e2_x, e2_y, e2_z, xbase, ybase, zbase ;
6922 int whalf, xk, yk, xi, yi, zi, xki, yki, x0, y0 ;
6923 Real ex, ey, ez, len, xt0, yt0, zt0 ;
6924
6925 whalf = (wsize-1)/2 ;
6926
6927 x0 = mri_mask->width/2 ; y0 = mri_mask->height/2 ;
6928 MRIvoxelToTalairachVoxel(mri, x, y, z, &xt0, &yt0, &zt0) ;
6929 switch (orientation)
6930 {
6931 default:
6932 case MRI_CORONAL: /* basis vectors in x-y plane */
6933 /* the 'x' basis vector */
6934 ex = (Real)xt0+1 ; ey = (Real)yt0 ; ez = (Real)zt0 ;
6935 MRItalairachVoxelToVoxel(mri, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
6936 e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
6937
6938 /* the 'y' basis vector */
6939 ex = (Real)xt0 ; ey = (Real)yt0+1 ; ez = (Real)zt0 ;
6940 MRItalairachVoxelToVoxel(mri, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
6941 e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
6942 break ;
6943 case MRI_HORIZONTAL: /* basis vectors in x-z plane */
6944 /* the 'x' basis vector */
6945 ex = (Real)xt0+1 ; ey = (Real)yt0 ; ez = (Real)zt0 ;
6946 MRItalairachVoxelToVoxel(mri, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
6947 e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
6948
6949 /* the 'y' basis vector */
6950 ex = (Real)xt0 ; ey = (Real)yt0 ; ez = (Real)zt0+1 ;
6951 MRItalairachVoxelToVoxel(mri, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
6952 e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
6953 break ;
6954 case MRI_SAGITTAL: /* basis vectors in y-z plane */
6955 /* the 'x' basis vector */
6956 ex = (Real)xt0 ; ey = (Real)yt0 ; ez = (Real)zt0+1.0 ;
6957 MRItalairachVoxelToVoxel(mri, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
6958 e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
6959
6960 /* the 'y' basis vector */
6961 ex = (Real)xt0 ; ey = (Real)yt0+1.0 ; ez = (Real)zt0 ;
6962 MRItalairachVoxelToVoxel(mri, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
6963 e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
6964 break ;
6965 }
6966
6967 /*
6968 don't want to normalize basis - they are orthonormal in magnet space,
6969 not necessarily Talairach space.
6970 */
6971 len = sqrt(e1_x*e1_x + e1_y*e1_y + e1_z*e1_z) ;
6972 /* e1_x /= len ; e1_y /= len ; e1_z /= len ;*/
6973 len = sqrt(e2_x*e2_x + e2_y*e2_y + e2_z*e2_z) ;
6974 /* e2_x /= len ; e2_y /= len ; e2_z /= len ;*/
6975
6976 for (yk = -whalf ; yk <= whalf ; yk++)
6977 {
6978 xbase = (float)x + (float)yk * e2_x ;
6979 ybase = (float)y + (float)yk * e2_y ;
6980 zbase = (float)z + (float)yk * e2_z ;
6981 for (xk = -whalf ; xk <= whalf ; xk++)
6982 {
6983 /* in-plane vect. is linear combination of scaled basis vects */
6984 xi = mri->xi[nint(xbase + xk*e1_x)] ;
6985 yi = mri->yi[nint(ybase + xk*e1_y)] ;
6986 zi = mri->zi[nint(zbase + xk*e1_z)] ;
6987 xki = mri_mask->xi[xk+x0] ; yki = mri_mask->yi[yk+y0] ;
6988 if (MRIvox(mri_mask, xki, yki,0))
6989 MRIvox(mri, xi, yi, zi) = fill_val ;
6990 }
6991 }
6992
6993 return(NO_ERROR) ;
6994 }
6995 /*-----------------------------------------------------
6996 Parameters:
6997
6998 Returns value:
6999
7000 Description
7001 ------------------------------------------------------*/
7002 int
7003 MRIeraseTalairachPlane(MRI *mri, MRI *mri_mask, int orientation, int x, int y,
7004 int z, int wsize, int fill_val)
7005 {
7006 Real e1_x, e1_y, e1_z, e2_x, e2_y, e2_z, xbase, ybase, zbase ;
7007 int whalf, xk, yk, xi, yi, zi ;
7008 Real ex, ey, ez, len ;
7009
7010 whalf = (wsize-1)/2 ;
7011
7012 switch (orientation)
7013 {
7014 default:
7015 case MRI_CORONAL: /* basis vectors in x-y plane */
7016 /* the 'x' basis vector */
7017 ex = (Real)x+1 ; ey = (Real)y ; ez = (Real)z ;
7018 MRIvoxelToTalairachVoxel(mri, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
7019 e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
7020
7021 /* the 'y' basis vector */
7022 ex = (Real)x ; ey = (Real)y+1 ; ez = (Real)z ;
7023 MRIvoxelToTalairachVoxel(mri, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
7024 e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
7025 break ;
7026 case MRI_HORIZONTAL: /* basis vectors in x-z plane */
7027 /* the 'x' basis vector */
7028 ex = (Real)x+1 ; ey = (Real)y ; ez = (Real)z ;
7029 MRIvoxelToTalairachVoxel(mri, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
7030 e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
7031
7032 /* the 'y' basis vector */
7033 ex = (Real)x ; ey = (Real)y ; ez = (Real)z+1 ;
7034 MRIvoxelToTalairachVoxel(mri, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
7035 e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
7036 break ;
7037 case MRI_SAGITTAL: /* basis vectors in y-z plane */
7038 /* the 'x' basis vector */
7039 ex = (Real)x ; ey = (Real)y ; ez = (Real)z+1.0 ;
7040 MRIvoxelToTalairachVoxel(mri, ex, ey, ez, &e1_x, &e1_y, &e1_z) ;
7041 e1_x -= (Real)x ; e1_y -= (Real)y ; e1_z -= (Real)z ;
7042
7043 /* the 'y' basis vector */
7044 ex = (Real)x ; ey = (Real)y+1.0 ; ez = (Real)z ;
7045 MRIvoxelToTalairachVoxel(mri, ex, ey, ez, &e2_x, &e2_y, &e2_z) ;
7046 e2_x -= (Real)x ; e2_y -= (Real)y ; e2_z -= (Real)z ;
7047 break ;
7048 }
7049
7050 /*
7051 don't want to normalize basis - they are orthonormal in magnet space,
7052 not necessarily Talairach space.
7053 */
7054 len = sqrt(e1_x*e1_x + e1_y*e1_y + e1_z*e1_z) ;
7055 /* e1_x /= len ; e1_y /= len ; e1_z /= len ;*/
7056 len = sqrt(e2_x*e2_x + e2_y*e2_y + e2_z*e2_z) ;
7057 /* e2_x /= len ; e2_y /= len ; e2_z /= len ;*/
7058
7059 for (yk = -whalf ; yk <= whalf ; yk++)
7060 {
7061 xbase = (float)x + (float)yk * e2_x ;
7062 ybase = (float)y + (float)yk * e2_y ;
7063 zbase = (float)z + (float)yk * e2_z ;
7064 for (xk = -whalf ; xk <= whalf ; xk++)
7065 {
7066 /* in-plane vect. is linear combination of scaled basis vects */
7067 xi = mri->xi[nint(xbase + xk*e1_x)] ;
7068 yi = mri->yi[nint(ybase + xk*e1_y)] ;
7069 zi = mri->zi[nint(zbase + xk*e1_z)] ;
7070 if (MRIvox(mri_mask, xk+whalf,yk+whalf,0))
7071 MRIvox(mri, xi, yi, zi) = fill_val ;
7072 }
7073 }
7074
7075 return(NO_ERROR) ;
7076 }
7077 /*-----------------------------------------------------
7078 Parameters:
7079
7080 Returns value:
7081
7082 Description
7083 ------------------------------------------------------*/
7084 MRI *
7085 MRIextractPlane(MRI *mri_src, MRI *mri_dst, int orientation, int where)
7086 {
7087 int x, y, z, width, height ;
7088
7089 switch (orientation)
7090 {
7091 default:
7092 case MRI_CORONAL: /* basis vectors in x-y plane */
7093 width = mri_src->width ; height = mri_src->height ;
7094 break ;
7095 case MRI_HORIZONTAL: /* basis vectors in x-z plane */
7096 width = mri_src->width ; height = mri_src->depth ;
7097 break ;
7098 case MRI_SAGITTAL: /* basis vectors in y-z plane */
7099 width = mri_src->depth ; height = mri_src->height ;
7100 break ;
7101 }
7102
7103 if (!mri_dst)
7104 {
7105 mri_dst = MRIalloc(width, height, 1, MRI_UCHAR) ;
7106 MRIcopyHeader(mri_src, mri_dst) ;
7107 mri_dst->zstart = where ; mri_dst->zend = where+1 ;
7108 mri_dst->imnr0 = 0 ; mri_dst->imnr1 = 1 ;
7109 }
7110 switch (orientation)
7111 {
7112 default:
7113 case MRI_CORONAL: /* basis vectors in x-y plane */
7114 for (x = 0 ; x < mri_src->width ; x++)
7115 {
7116 for (y = 0 ; y < mri_src->height ; y++)
7117 MRIvox(mri_dst, x, y, 0) = MRIvox(mri_src, x, y, where) ;
7118 }
7119 break ;
7120 case MRI_HORIZONTAL: /* basis vectors in x-z plane */
7121 for (x = 0 ; x < mri_src->width ; x++)
7122 {
7123 for (z = 0 ; z < mri_src->depth ; z++)
7124 MRIvox(mri_dst, x, z, 0) = MRIvox(mri_src, x, where, z) ;
7125 }
7126 break ;
7127 case MRI_SAGITTAL: /* basis vectors in y-z plane */
7128 for (z = 0 ; z < mri_src->depth ; z++)
7129 {
7130 for (y = 0 ; y < mri_src->height ; y++)
7131 MRIvox(mri_dst, z, y, 0) = MRIvox(mri_src, where, y, z) ;
7132 }
7133 break ;
7134 }
7135
7136 return(mri_dst) ;
7137 }
7138 /*-----------------------------------------------------
7139 Parameters:
7140
7141 Returns value:
7142
7143 Description
7144 ------------------------------------------------------*/
7145 MRI *
7146 MRIfillPlane
7147 (MRI *mri_mask, MRI *mri_dst, int orientation, int where, int fillval)
7148 {
7149 int x, y, z, width, height ;
7150
7151 switch (orientation)
7152 {
7153 default:
7154 case MRI_CORONAL: /* basis vectors in x-y plane */
7155 width = mri_mask->width ; height = mri_mask->height ;
7156 break ;
7157 case MRI_HORIZONTAL: /* basis vectors in x-z plane */
7158 width = mri_mask->width ; height = mri_mask->depth ;
7159 break ;
7160 case MRI_SAGITTAL: /* basis vectors in y-z plane */
7161 width = mri_mask->depth ; height = mri_mask->height ;
7162 break ;
7163 }
7164
7165 switch (orientation)
7166 {
7167 default:
7168 case MRI_CORONAL: /* basis vectors in x-y plane */
7169 for (x = 0 ; x < mri_dst->width ; x++)
7170 {
7171 for (y = 0 ; y < mri_dst->height ; y++)
7172 if (MRIvox(mri_mask, x, y, 0))
7173 MRIvox(mri_dst, x, y, where) = fillval ;
7174 }
7175 break ;
7176 case MRI_HORIZONTAL: /* basis vectors in x-z plane */
7177 for (x = 0 ; x < mri_dst->width ; x++)
7178 {
7179 for (z = 0 ; z < mri_dst->depth ; z++)
7180 {
7181 if (MRIvox(mri_mask, x, z, 0))
7182 MRIvox(mri_dst, x, where, z) = fillval ;
7183 }
7184 }
7185 break ;
7186 case MRI_SAGITTAL: /* basis vectors in y-z plane */
7187 for (z = 0 ; z < mri_dst->depth ; z++)
7188 {
7189 for (y = 0 ; y < mri_dst->height ; y++)
7190 if (MRIvox(mri_mask, z, y, 0))
7191 MRIvox(mri_dst, where, y, z) = fillval ;
7192 }
7193 break ;
7194 }
7195
7196 return(mri_dst) ;
7197 }
7198 /*-----------------------------------------------------
7199 Parameters:
7200
7201 Returns value:
7202
7203 Description
7204 ------------------------------------------------------*/
7205 int
7206 MRIerasePlane(MRI *mri, float x0, float y0, float z0,
7207 float dx, float dy, float dz, int fill_val)
7208 {
7209 int *pxi, *pyi, *pzi, xi, yi, zi, x, y, z ;
7210 float e1_x, e1_y, e1_z, e2_x, e2_y, e2_z, maxlen, l1, l2 ;
7211
7212 maxlen = MAX(mri->width, mri->height) ; maxlen = MAX(maxlen, mri->depth) ;
7213
7214 /* don't care about sign (right-hand rule) */
7215 e1_x = dz*dz - dx*dy ;
7216 e1_y = dx*dx - dy*dz ;
7217 e1_z = dy*dy - dz*dx ;
7218 l1 = sqrt(e1_x*e1_x + e1_y*e1_y + e1_z*e1_z) ;
7219 e1_x /= l1 ; e1_y /= l1 ; e1_z /= l1 ;
7220
7221 e2_x = e1_y*dz - e1_z*dy ;
7222 e2_y = e1_x*dz - e1_z*dx ;
7223 e2_z = e1_y*dx - e1_x*dy ;
7224 l2 = sqrt(e2_x*e2_x + e2_y*e2_y + e2_z*e2_z) ;
7225 e2_x /= l2 ; e2_y /= l2 ; e2_z /= l2 ;
7226
7227 pxi = mri->xi ; pyi = mri->yi ; pzi = mri->zi ;
7228 maxlen *= 1.5 ; /* make sure to get entire extent */
7229 for (l1 = -maxlen/2 ; l1 <= maxlen/2 ; l1 += 0.5f)
7230 {
7231 for (l2 = -maxlen/2 ; l2 <= maxlen/2 ; l2 += 0.5f)
7232 {
7233 x = nint(x0 + l1 * e1_x + l2 * e2_x) ; xi = pxi[x] ;
7234 y = nint(y0 + l1 * e1_y + l2 * e2_y) ; yi = pyi[y] ;
7235 z = nint(z0 + l1 * e1_z + l2 * e2_z) ; zi = pzi[z] ;
7236 MRIvox(mri, xi, yi, zi) = fill_val ;
7237 }
7238 }
7239
7240 return(NO_ERROR) ;
7241 }
7242 /*-----------------------------------------------------
7243 Parameters:
7244
7245 Returns value:
7246
7247 Description
7248 Interpolate the volume to cubic voxels.
7249 ------------------------------------------------------*/
7250 MRI *
7251 MRIinterpolate(MRI *mri_src, MRI *mri_dst)
7252 {
7253 int xs, ys, zs, xd, yd, zd, max_dim, xorig, yorig, zorig, dorig ;
7254 float sx, sy, sz, psize ;
7255 int width, height, depth, i ;
7256 float xsmd, ysmd, zsmd, xspd, yspd, zspd, weights[8], fout ;
7257 int xsp, xsm, ysp, ysm, zsp, zsm ; /* surrounding coordinates */
7258 float vals[8], outval ;
7259
7260 width = mri_src->width ; height = mri_src->height ; depth = mri_src->depth;
7261 if (width > height)
7262 {
7263 max_dim = width > depth ? width : depth ;
7264 psize = width > depth ? mri_src->xsize : mri_src->zsize ;
7265 }
7266 else
7267 {
7268 max_dim = height > depth ? height : depth ;
7269 psize = height > depth ? mri_src->ysize : mri_src->zsize ;
7270 }
7271
7272 if (!mri_dst)
7273 {
7274 mri_dst = MRIalloc(max_dim, max_dim, max_dim, mri_src->type) ;
7275 MRIcopyHeader(mri_src, mri_dst) ;
7276 }
7277
7278 mri_dst->xsize = mri_dst->ysize = mri_dst->zsize = psize ;
7279 sx = (float)width / (float)max_dim ;
7280 sy = (float)height / (float)max_dim ;
7281 sz = (float)depth / (float)max_dim ;
7282
7283 mri_dst->imnr0 = 1;
7284 mri_dst->imnr1 = mri_dst->depth;
7285 mri_dst->xstart = -mri_dst->xsize * mri_dst->width / 2;
7286 mri_dst->xend = -mri_dst->xstart;
7287 mri_dst->ystart = -mri_dst->ysize * mri_dst->height / 2;
7288 mri_dst->yend = -mri_dst->ystart;
7289 mri_dst->zstart = -mri_dst->zsize * mri_dst->depth / 2;
7290 mri_dst->zend = -mri_dst->zstart;
7291
7292 xorig = (width-1)/2 ; yorig = (height-1)/2 ; zorig = (depth-1)/2 ;
7293 dorig = (max_dim-1)/2 ;
7294
7295 /*
7296 for each output voxel, find the 8 nearest input voxels and interpolate
7297 the output voxel from them.
7298 */
7299 for (zd = 0 ; zd < max_dim ; zd++)
7300 {
7301 printf("interpolate: %d/%d\n",zd+1,max_dim);
7302 for (yd = 0 ; yd < max_dim ; yd++)
7303 {
7304 for (xd = 0 ; xd < max_dim ; xd++)
7305 {
7306 /* do trilinear interpolation here */
7307 xs = sx*(xd-dorig) + xorig ;
7308 ys = sy*(yd-dorig) + yorig ;
7309 zs = sz*(zd-dorig) + zorig ;
7310
7311 /*
7312 these boundary conditions will cause
7313 reflection across the border
7314 for the 1st negative pixel.
7315 */
7316 if (xs > -1 && xs < width &&
7317 ys > -1 && ys < height &&
7318 zs > -1 && zs < depth)
7319 {
7320 xsm = (int)xs ;
7321 xsp = MIN(width-1, xsm+1) ;
7322 ysm = (int)ys ;
7323 ysp = MIN(height-1, ysm+1) ;
7324 zsm = (int)zs ;
7325 zsp = MIN(depth-1, zsm+1) ;
7326 xsmd = xs - (float)xsm ;
7327 ysmd = ys - (float)ysm ;
7328 zsmd = zs - (float)zsm ;
7329 xspd = (1.0f - xsmd) ;
7330 yspd = (1.0f - ysmd) ;
7331 zspd = (1.0f - zsmd) ;
7332
7333 /* vals[0] = mri_src->slices[zsm][ysm][xsm] ;
7334 vals[1] = mri_src->slices[zsm][ysm][xsp] ;
7335 vals[2] = mri_src->slices[zsm][ysp][xsm] ;
7336 vals[3] = mri_src->slices[zsm][ysp][xsp] ;
7337 vals[4] = mri_src->slices[zsp][ysm][xsm] ;
7338 vals[5] = mri_src->slices[zsp][ysm][xsp] ;
7339 vals[6] = mri_src->slices[zsp][ysp][xsm] ;
7340 vals[7] = mri_src->slices[zsp][ysp][xsp] ;
7341 */
7342 /* different vox types... */
7343 vals[0] = MRIFvox(mri_src, xsm, ysm, zsm);
7344 vals[1] = MRIFvox(mri_src, xsp, ysm, zsm);
7345 vals[2] = MRIFvox(mri_src, xsm, ysp, zsm);
7346 vals[3] = MRIFvox(mri_src, xsp, ysp, zsm);
7347 vals[4] = MRIFvox(mri_src, xsm, ysm, zsp);
7348 vals[5] = MRIFvox(mri_src, xsp, ysm, zsp);
7349 vals[6] = MRIFvox(mri_src, xsm, ysp, zsp);
7350 vals[7] = MRIFvox(mri_src, xsp, ysp, zsp);
7351
7352 weights[0] = zsmd * ysmd * xsmd ;
7353 weights[1] = zsmd * ysmd * xspd ;
7354 weights[2] = zsmd * yspd * xsmd ;
7355 weights[3] = zsmd * yspd * xspd ;
7356 weights[4] = zspd * ysmd * xsmd ;
7357 weights[5] = zspd * ysmd * xspd ;
7358 weights[6] = zspd * yspd * xsmd ;
7359 weights[7] = zspd * yspd * xspd ;
7360 /*
7361 for(i = 0;i < 8;i++)
7362 printf("%d, %f, %f\n",i,vals[i], weights[i]);
7363 */
7364 for (fout = 0.0f, i = 0 ; i < 8 ; i++)
7365 fout += (float)vals[i] * weights[i] ;
7366 outval = (float)nint(fout) ;
7367 MRIvox(mri_dst, xd, yd, zd) = (BUFTYPE)nint(fout) ;
7368
7369 }
7370 }
7371 }
7372 }
7373
7374 mri_dst->ras_good_flag = 0;
7375
7376 return(mri_dst) ;
7377 }
7378 /*-----------------------------------------------------
7379 Parameters:
7380
7381 Returns value:
7382
7383 Description
7384 ------------------------------------------------------*/
7385 int
7386 MRIsampleVolumeFrame(MRI *mri,Real x,Real y,Real z,int frame,Real *pval)
7387 {
7388 int OutOfBounds;
7389 int xm, xp, ym, yp, zm, zp, width, height, depth ;
7390 Real val, xmd, ymd, zmd, xpd, ypd, zpd ; /* d's are distances */
7391
7392 if (FEQUAL((int)x,x) && FEQUAL((int)y,y) && FEQUAL((int)z, z))
7393 return(MRIsampleVolumeFrameType
7394 (mri, x, y, z, frame, SAMPLE_NEAREST, pval)) ;
7395
7396 if (frame >= mri->nframes)
7397 {
7398 *pval = 1.0 ;
7399 return(NO_ERROR) ;
7400 }
7401
7402 OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
7403 if(OutOfBounds == 1){
7404 /* unambiguoulsy out of bounds */
7405 *pval = 0.0;
7406 return(NO_ERROR) ;
7407 }
7408
7409 width = mri->width ; height = mri->height ; depth = mri->depth ;
7410 if (x >= width)
7411 x = width - 1.0 ;
7412 if (y >= height)
7413 y = height - 1.0 ;
7414 if (z >= depth)
7415 z = depth - 1.0 ;
7416 if (x < 0.0)
7417 x = 0.0 ;
7418 if (y < 0.0)
7419 y = 0.0 ;
7420 if (z < 0.0)
7421 z = 0.0 ;
7422
7423 xm = MAX((int)x, 0) ;
7424 xp = MIN(width-1, xm+1) ;
7425 ym = MAX((int)y, 0) ;
7426 yp = MIN(height-1, ym+1) ;
7427 zm = MAX((int)z, 0) ;
7428 zp = MIN(depth-1, zm+1) ;
7429
7430 xmd = x - (float)xm ;
7431 ymd = y - (float)ym ;
7432 zmd = z - (float)zm ;
7433 xpd = (1.0f - xmd) ;
7434 ypd = (1.0f - ymd) ;
7435 zpd = (1.0f - zmd) ;
7436
7437 switch (mri->type)
7438 {
7439 case MRI_UCHAR:
7440 *pval = val =
7441 xpd * ypd * zpd * (Real)MRIseq_vox(mri, xm, ym, zm, frame) +
7442 xpd * ypd * zmd * (Real)MRIseq_vox(mri, xm, ym, zp, frame) +
7443 xpd * ymd * zpd * (Real)MRIseq_vox(mri, xm, yp, zm, frame) +
7444 xpd * ymd * zmd * (Real)MRIseq_vox(mri, xm, yp, zp, frame) +
7445 xmd * ypd * zpd * (Real)MRIseq_vox(mri, xp, ym, zm, frame) +
7446 xmd * ypd * zmd * (Real)MRIseq_vox(mri, xp, ym, zp, frame) +
7447 xmd * ymd * zpd * (Real)MRIseq_vox(mri, xp, yp, zm, frame) +
7448 xmd * ymd * zmd * (Real)MRIseq_vox(mri, xp, yp, zp, frame) ;
7449 break ;
7450 case MRI_FLOAT:
7451 *pval = val =
7452 xpd * ypd * zpd * (Real)MRIFseq_vox(mri, xm, ym, zm, frame) +
7453 xpd * ypd * zmd * (Real)MRIFseq_vox(mri, xm, ym, zp, frame) +
7454 xpd * ymd * zpd * (Real)MRIFseq_vox(mri, xm, yp, zm, frame) +
7455 xpd * ymd * zmd * (Real)MRIFseq_vox(mri, xm, yp, zp, frame) +
7456 xmd * ypd * zpd * (Real)MRIFseq_vox(mri, xp, ym, zm, frame) +
7457 xmd * ypd * zmd * (Real)MRIFseq_vox(mri, xp, ym, zp, frame) +
7458 xmd * ymd * zpd * (Real)MRIFseq_vox(mri, xp, yp, zm, frame) +
7459 xmd * ymd * zmd * (Real)MRIFseq_vox(mri, xp, yp, zp, frame) ;
7460 break ;
7461 case MRI_SHORT:
7462 *pval = val =
7463 xpd * ypd * zpd * (Real)MRISseq_vox(mri, xm, ym, zm, frame) +
7464 xpd * ypd * zmd * (Real)MRISseq_vox(mri, xm, ym, zp, frame) +
7465 xpd * ymd * zpd * (Real)MRISseq_vox(mri, xm, yp, zm, frame) +
7466 xpd * ymd * zmd * (Real)MRISseq_vox(mri, xm, yp, zp, frame) +
7467 xmd * ypd * zpd * (Real)MRISseq_vox(mri, xp, ym, zm, frame) +
7468 xmd * ypd * zmd * (Real)MRISseq_vox(mri, xp, ym, zp, frame) +
7469 xmd * ymd * zpd * (Real)MRISseq_vox(mri, xp, yp, zm, frame) +
7470 xmd * ymd * zmd * (Real)MRISseq_vox(mri, xp, yp, zp, frame) ;
7471 break ;
7472 case MRI_INT:
7473 *pval = val =
7474 xpd * ypd * zpd * (Real)MRIIseq_vox(mri, xm, ym, zm, frame) +
7475 xpd * ypd * zmd * (Real)MRIIseq_vox(mri, xm, ym, zp, frame) +
7476 xpd * ymd * zpd * (Real)MRIIseq_vox(mri, xm, yp, zm, frame) +
7477 xpd * ymd * zmd * (Real)MRIIseq_vox(mri, xm, yp, zp, frame) +
7478 xmd * ypd * zpd * (Real)MRIIseq_vox(mri, xp, ym, zm, frame) +
7479 xmd * ypd * zmd * (Real)MRIIseq_vox(mri, xp, ym, zp, frame) +
7480 xmd * ymd * zpd * (Real)MRIIseq_vox(mri, xp, yp, zm, frame) +
7481 xmd * ymd * zmd * (Real)MRIIseq_vox(mri, xp, yp, zp, frame) ;
7482 break ;
7483 case MRI_LONG:
7484 *pval = val =
7485 xpd * ypd * zpd * (Real)MRILseq_vox(mri, xm, ym, zm, frame) +
7486 xpd * ypd * zmd * (Real)MRILseq_vox(mri, xm, ym, zp, frame) +
7487 xpd * ymd * zpd * (Real)MRILseq_vox(mri, xm, yp, zm, frame) +
7488 xpd * ymd * zmd * (Real)MRILseq_vox(mri, xm, yp, zp, frame) +
7489 xmd * ypd * zpd * (Real)MRILseq_vox(mri, xp, ym, zm, frame) +
7490 xmd * ypd * zmd * (Real)MRILseq_vox(mri, xp, ym, zp, frame) +
7491 xmd * ymd * zpd * (Real)MRILseq_vox(mri, xp, yp, zm, frame) +
7492 xmd * ymd * zmd * (Real)MRILseq_vox(mri, xp, yp, zp, frame) ;
7493 break ;
7494 default:
7495 ErrorReturn(ERROR_UNSUPPORTED,
7496 (ERROR_UNSUPPORTED,
7497 "MRIsampleVolumeFrame: unsupported type %d", mri->type)) ;
7498 break ;
7499 }
7500 return(NO_ERROR) ;
7501 }
7502
7503
7504
7505 /*---------------------------------------------------------------------------
7506 Purpose: to return the approximate fraction of a voxel centered
7507 at the given point
7508 is labeled with a given label by the labeled volume: mri
7509
7510 Input: mri is the labeled volume. Ea voxel contains the uchar label index
7511 x,y,z is the floating point location of the center of a voxel
7512 whose labeling is to be determined. The voxel is examined to see
7513 how much of it is labeled with the label, ucharLabel
7514
7515 Output: pval is the fraction which the given voxel location is labeled
7516 by ucharLabel
7517 returns NO_ERROR or ERROR_UNSUPPORTED if an unsupported
7518 (non-uchar) mri labeled volume is passed in
7519 AAM: 7/26/00
7520 --------------------------------------------------------------------------*/
7521
7522 #ifndef uchar
7523 #define uchar unsigned char
7524 #endif
7525 int
7526 MRIsampleLabeledVolume
7527 (MRI *mri, Real x, Real y, Real z, Real *pval, unsigned char ucharLabel)
7528 {
7529 /* m's are the mri grid locations less than x (or y or z)
7530 (i.e. floor(x), p's are essentially rounding up to the next
7531 grid location greater than x */
7532 int xm, xp, ym, yp, zm, zp;
7533 int width, height, depth ;
7534 Real xmd, ymd, zmd, xpd, ypd, zpd ; /* d's are distances */
7535 uchar ucharDmmm;
7536 uchar ucharDmmp;
7537 uchar ucharDmpm;
7538 uchar ucharDmpp;
7539 uchar ucharDpmm;
7540 uchar ucharDpmp;
7541 uchar ucharDppm;
7542 uchar ucharDppp;
7543
7544
7545 *pval=0.0;
7546
7547
7548
7549 width = mri->width ;
7550 height = mri->height ;
7551 depth = mri->depth ;
7552 /* if (x >= width)
7553 x = width - 1.0 ;
7554 if (y >= height)
7555 y = height - 1.0 ;
7556 if (z >= depth)
7557 z = depth - 1.0 ;
7558 if (x < 0.0)
7559 x = 0.0 ;
7560 if (y < 0.0)
7561 y = 0.0 ;
7562 if (z < 0.0)
7563 z = 0.0 ;
7564 */
7565
7566 /* if the x,y,z point is out of range
7567 then return that none of the given voxel was labeled by ucharLabel */
7568 if (x >= width) return(NO_ERROR) ;
7569 if (y >= height) return(NO_ERROR) ;
7570 if (z >= depth) return(NO_ERROR) ;
7571 if (x < 0.0) return(NO_ERROR) ;
7572 if (y < 0.0) return(NO_ERROR) ;
7573 if (z < 0.0) return(NO_ERROR) ;
7574
7575 xm = MAX((int)x, 0) ;
7576 xp = MIN(width-1, xm+1) ;
7577 ym = MAX((int)y, 0) ;
7578 yp = MIN(height-1, ym+1) ;
7579 zm = MAX((int)z, 0) ;
7580 zp = MIN(depth-1, zm+1) ;
7581
7582 ucharDmmm = MRIvox(mri, xm, ym, zm) == ucharLabel ? 1 : 0;
7583 ucharDmmp = MRIvox(mri, xm, ym, zp) == ucharLabel ? 1 : 0;
7584 ucharDmpm = MRIvox(mri, xm, yp, zm) == ucharLabel ? 1 : 0;
7585 ucharDmpp = MRIvox(mri, xm, yp, zp) == ucharLabel ? 1 : 0;
7586 ucharDpmm = MRIvox(mri, xp, ym, zm) == ucharLabel ? 1 : 0;
7587 ucharDpmp = MRIvox(mri, xp, ym, zp) == ucharLabel ? 1 : 0;
7588 ucharDppm = MRIvox(mri, xp, yp, zm) == ucharLabel ? 1 : 0;
7589 ucharDppp = MRIvox(mri, xp, yp, zp) == ucharLabel ? 1 : 0;
7590
7591 xmd = x - (float)xm ;
7592 ymd = y - (float)ym ;
7593 zmd = z - (float)zm ;
7594 xpd = (1.0f - xmd) ;
7595 ypd = (1.0f - ymd) ;
7596 zpd = (1.0f - zmd) ;
7597
7598
7599
7600 switch (mri->type)
7601 {
7602 case MRI_UCHAR:
7603 *pval =
7604 xpd * ypd * zpd * (Real)ucharDmmm +
7605 xpd * ypd * zmd * (Real)ucharDmmp +
7606 xpd * ymd * zpd * (Real)ucharDmpm +
7607 xpd * ymd * zmd * (Real)ucharDmpp +
7608 xmd * ypd * zpd * (Real)ucharDpmm +
7609 xmd * ypd * zmd * (Real)ucharDpmp +
7610 xmd * ymd * zpd * (Real)ucharDppm +
7611 xmd * ymd * zmd * (Real)ucharDppp ;
7612 break ;
7613 default:
7614 ErrorReturn(ERROR_UNSUPPORTED,
7615 (ERROR_UNSUPPORTED,
7616 "MRIsampleVolume: unsupported type %d", mri->type)) ;
7617 break ;
7618 }
7619 return(NO_ERROR) ;
7620 }
7621 /*-----------------------------------------------------
7622 Parameters:
7623
7624 Returns value:
7625
7626 Description
7627 ------------------------------------------------------*/
7628 int
7629 MRIsampleVolumeType(MRI *mri, Real x, Real y, Real z, Real *pval, int type)
7630 {
7631 int xv, yv, zv ;
7632 int OutOfBounds;
7633
7634 switch (type)
7635 {
7636 default:
7637 case SAMPLE_NEAREST:
7638 break ;
7639 case SAMPLE_TRILINEAR:
7640 return(MRIsampleVolume(mri, x, y, z, pval)) ;
7641 case SAMPLE_CUBIC:
7642 return(MRIcubicSampleVolume(mri, x, y, z, pval)) ;
7643 case SAMPLE_SINC:
7644 return(MRIsincSampleVolume(mri, x, y, z, 5, pval)) ;
7645 }
7646
7647 OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
7648 if(OutOfBounds == 1){
7649 /* unambiguously out of bounds */
7650 *pval = 0.0;
7651 return(NO_ERROR) ;
7652 }
7653
7654 xv = nint(x) ; yv = nint(y) ; zv = nint(z) ;
7655 if (xv < 0)
7656 xv = 0 ;
7657 if (xv >= mri->width)
7658 xv = mri->width-1 ;
7659 if (yv < 0)
7660 yv = 0 ;
7661 if (yv >= mri->height)
7662 yv = mri->height-1 ;
7663 if (zv < 0)
7664 zv = 0 ;
7665 if (zv >= mri->depth)
7666 zv = mri->depth-1 ;
7667
7668 switch (mri->type)
7669 {
7670 case MRI_UCHAR:
7671 *pval = (float)MRIvox(mri, xv, yv, zv) ;
7672 break ;
7673 case MRI_SHORT:
7674 *pval = (float)MRISvox(mri, xv, yv, zv) ;
7675 break ;
7676 case MRI_INT:
7677 *pval = (float)MRIIvox(mri, xv, yv, zv) ;
7678 break ;
7679 case MRI_FLOAT:
7680 *pval = MRIFvox(mri, xv, yv, zv) ;
7681 break ;
7682 default:
7683 *pval = 0 ;
7684 ErrorReturn
7685 (ERROR_UNSUPPORTED,
7686 (ERROR_UNSUPPORTED,
7687 "MRIsampleVolumeType: unsupported volume type %d",
7688 mri->type)) ;
7689 }
7690 return(NO_ERROR) ;
7691 }
7692 /*-----------------------------------------------------
7693 Parameters:
7694
7695 Returns value:
7696
7697 Description
7698 ------------------------------------------------------*/
7699 int
7700 MRIsampleVolumeFrameType
7701 (MRI *mri, Real x, Real y, Real z, int frame, int type, Real *pval)
7702 {
7703 int xv, yv, zv ;
7704 int OutOfBounds;
7705
7706 if (FEQUAL((int)x,x) && FEQUAL((int)y,y) && FEQUAL((int)z, z))
7707 type = SAMPLE_NEAREST ;
7708
7709 switch (type)
7710 {
7711 case SAMPLE_NEAREST:
7712 break ;
7713 case SAMPLE_TRILINEAR:
7714 return(MRIsampleVolumeFrame(mri, x, y, z, frame, pval)) ;
7715 default:
7716 /*E* add SAMPLE_CUBIC here? */
7717 case SAMPLE_SINC:
7718 ErrorReturn
7719 (ERROR_UNSUPPORTED,
7720 (ERROR_UNSUPPORTED,
7721 "MRIsampleVolumeFrameType(%d): unsupported interpolation type",
7722 type));
7723 /* return(MRIsincSampleVolume(mri, x, y, z, 5, pval)) ;*/
7724 }
7725
7726 OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
7727 if(OutOfBounds == 1){
7728 /* unambiguously out of bounds */
7729 *pval = 0.0;
7730 return(NO_ERROR) ;
7731 }
7732
7733 xv = nint(x) ; yv = nint(y) ; zv = nint(z) ;
7734 if (xv < 0)
7735 xv = 0 ;
7736 if (xv >= mri->width)
7737 xv = mri->width-1 ;
7738 if (yv < 0)
7739 yv = 0 ;
7740 if (yv >= mri->height)
7741 yv = mri->height-1 ;
7742 if (zv < 0)
7743 zv = 0 ;
7744 if (zv >= mri->depth)
7745 zv = mri->depth-1 ;
7746
7747 switch (mri->type)
7748 {
7749 case MRI_UCHAR:
7750 *pval = (float)MRIseq_vox(mri, xv, yv, zv, frame) ;
7751 break ;
7752 case MRI_SHORT:
7753 *pval = (float)MRISseq_vox(mri, xv, yv, zv, frame) ;
7754 break ;
7755 case MRI_INT:
7756 *pval = (float)MRIIseq_vox(mri, xv, yv, zv, frame) ;
7757 break ;
7758 case MRI_FLOAT:
7759 *pval = MRIFseq_vox(mri, xv, yv, zv, frame) ;
7760 break ;
7761 default:
7762 *pval = 0 ;
7763 ErrorReturn
7764 (ERROR_UNSUPPORTED,
7765 (ERROR_UNSUPPORTED,
7766 "MRIsampleVolumeFrameType: unsupported volume type %d",
7767 mri->type)) ;
7768 }
7769 return(NO_ERROR) ;
7770 }
7771
7772
7773 int
7774 MRIinterpolateIntoVolume(MRI *mri, Real x, Real y, Real z, Real val)
7775 {
7776 int OutOfBounds;
7777 int xm, xp, ym, yp, zm, zp, width, height, depth ;
7778 Real xmd, ymd, zmd, xpd, ypd, zpd ; /* d's are distances */
7779
7780 OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
7781 if(OutOfBounds == 1){
7782 /* unambiguously out of bounds */
7783 return(NO_ERROR) ;
7784 }
7785
7786 width = mri->width ; height = mri->height ; depth = mri->depth ;
7787
7788 if (x >= width) x = width - 1.0 ;
7789 if (y >= height) y = height - 1.0 ;
7790 if (z >= depth) z = depth - 1.0 ;
7791 if (x < 0.0) x = 0.0 ;
7792 if (y < 0.0) y = 0.0 ;
7793 if (z < 0.0) z = 0.0 ;
7794
7795 xm = MAX((int)x, 0) ;
7796 xp = MIN(width-1, xm+1) ;
7797 ym = MAX((int)y, 0) ;
7798 yp = MIN(height-1, ym+1) ;
7799 zm = MAX((int)z, 0) ;
7800 zp = MIN(depth-1, zm+1) ;
7801
7802 xmd = x - (float)xm ;
7803 ymd = y - (float)ym ;
7804 zmd = z - (float)zm ;
7805 xpd = (1.0f - xmd) ;
7806 ypd = (1.0f - ymd) ;
7807 zpd = (1.0f - zmd) ;
7808
7809 switch (mri->type)
7810 {
7811 case MRI_UCHAR:
7812 MRIvox(mri, xm, ym, zm) += nint(xpd * ypd * zpd * val) ;
7813 MRIvox(mri, xm, ym, zp) += nint(xpd * ypd * zmd * val) ;
7814 MRIvox(mri, xm, yp, zm) += nint(xpd * ymd * zpd * val) ;
7815 MRIvox(mri, xm, yp, zp) += nint(xpd * ymd * zmd * val) ;
7816 MRIvox(mri, xp, ym, zm) += nint(xmd * ypd * zpd * val) ;
7817 MRIvox(mri, xp, ym, zp) += nint(xmd * ypd * zmd * val) ;
7818 MRIvox(mri, xp, yp, zm) += nint(xmd * ymd * zpd * val) ;
7819 MRIvox(mri, xp, yp, zp) += nint(xmd * ymd * zmd * val) ;
7820 break ;
7821 case MRI_FLOAT:
7822 MRIFvox(mri, xm, ym, zm) += (xpd * ypd * zpd * val) ;
7823 MRIFvox(mri, xm, ym, zp) += (xpd * ypd * zmd * val) ;
7824 MRIFvox(mri, xm, yp, zm) += (xpd * ymd * zpd * val) ;
7825 MRIFvox(mri, xm, yp, zp) += (xpd * ymd * zmd * val) ;
7826 MRIFvox(mri, xp, ym, zm) += (xmd * ypd * zpd * val) ;
7827 MRIFvox(mri, xp, ym, zp) += (xmd * ypd * zmd * val) ;
7828 MRIFvox(mri, xp, yp, zm) += (xmd * ymd * zpd * val) ;
7829 MRIFvox(mri, xp, yp, zp) += (xmd * ymd * zmd * val) ;
7830 break ;
7831 case MRI_SHORT:
7832 MRISvox(mri, xm, ym, zm) += nint(xpd * ypd * zpd * val) ;
7833 MRISvox(mri, xm, ym, zp) += nint(xpd * ypd * zmd * val) ;
7834 MRISvox(mri, xm, yp, zm) += nint(xpd * ymd * zpd * val) ;
7835 MRISvox(mri, xm, yp, zp) += nint(xpd * ymd * zmd * val) ;
7836 MRISvox(mri, xp, ym, zm) += nint(xmd * ypd * zpd * val) ;
7837 MRISvox(mri, xp, ym, zp) += nint(xmd * ypd * zmd * val) ;
7838 MRISvox(mri, xp, yp, zm) += nint(xmd * ymd * zpd * val) ;
7839 MRISvox(mri, xp, yp, zp) += nint(xmd * ymd * zmd * val) ;
7840 break ;
7841 case MRI_INT:
7842 MRIIvox(mri, xm, ym, zm) += nint(xpd * ypd * zpd * val) ;
7843 MRIIvox(mri, xm, ym, zp) += nint(xpd * ypd * zmd * val) ;
7844 MRIIvox(mri, xm, yp, zm) += nint(xpd * ymd * zpd * val) ;
7845 MRIIvox(mri, xm, yp, zp) += nint(xpd * ymd * zmd * val) ;
7846 MRIIvox(mri, xp, ym, zm) += nint(xmd * ypd * zpd * val) ;
7847 MRIIvox(mri, xp, ym, zp) += nint(xmd * ypd * zmd * val) ;
7848 MRIIvox(mri, xp, yp, zm) += nint(xmd * ymd * zpd * val) ;
7849 MRIIvox(mri, xp, yp, zp) += nint(xmd * ymd * zmd * val) ;
7850 break ;
7851 case MRI_LONG:
7852 MRILvox(mri, xm, ym, zm) += nint(xpd * ypd * zpd * val) ;
7853 MRILvox(mri, xm, ym, zp) += nint(xpd * ypd * zmd * val) ;
7854 MRILvox(mri, xm, yp, zm) += nint(xpd * ymd * zpd * val) ;
7855 MRILvox(mri, xm, yp, zp) += nint(xpd * ymd * zmd * val) ;
7856 MRILvox(mri, xp, ym, zm) += nint(xmd * ypd * zpd * val) ;
7857 MRILvox(mri, xp, ym, zp) += nint(xmd * ypd * zmd * val) ;
7858 MRILvox(mri, xp, yp, zm) += nint(xmd * ymd * zpd * val) ;
7859 MRILvox(mri, xp, yp, zp) += nint(xmd * ymd * zmd * val) ;
7860 break ;
7861 default:
7862 ErrorReturn(ERROR_UNSUPPORTED,
7863 (ERROR_UNSUPPORTED,
7864 "MRIsampleVolume: unsupported type %d", mri->type)) ;
7865 break ;
7866 }
7867 return(NO_ERROR) ;
7868 }
7869
7870 /*-------------------------------------------------------------------
7871 MRIsampleVolume() - performs trilinear interpolation on a
7872 single-frame volume. See MRIsampleSeqVolume() for sampling
7873 multi-frame.
7874 -------------------------------------------------------------------*/
7875 int
7876 MRIsampleVolume(MRI *mri, Real x, Real y, Real z, Real *pval)
7877 {
7878 int OutOfBounds;
7879 int xm, xp, ym, yp, zm, zp, width, height, depth ;
7880 Real val, xmd, ymd, zmd, xpd, ypd, zpd ; /* d's are distances */
7881
7882 if (FEQUAL((int)x,x) && FEQUAL((int)y,y) && FEQUAL((int)z, z))
7883 return(MRIsampleVolumeType(mri, x, y, z, pval, SAMPLE_NEAREST)) ;
7884
7885 OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
7886 if(OutOfBounds == 1){
7887 /* unambiguously out of bounds */
7888 *pval = 0.0;
7889 return(NO_ERROR) ;
7890 }
7891
7892 width = mri->width ; height = mri->height ; depth = mri->depth ;
7893
7894 if (x >= width) x = width - 1.0 ;
7895 if (y >= height) y = height - 1.0 ;
7896 if (z >= depth) z = depth - 1.0 ;
7897 if (x < 0.0) x = 0.0 ;
7898 if (y < 0.0) y = 0.0 ;
7899 if (z < 0.0) z = 0.0 ;
7900
7901 xm = MAX((int)x, 0) ;
7902 xp = MIN(width-1, xm+1) ;
7903 ym = MAX((int)y, 0) ;
7904 yp = MIN(height-1, ym+1) ;
7905 zm = MAX((int)z, 0) ;
7906 zp = MIN(depth-1, zm+1) ;
7907
7908 xmd = x - (float)xm ;
7909 ymd = y - (float)ym ;
7910 zmd = z - (float)zm ;
7911 xpd = (1.0f - xmd) ;
7912 ypd = (1.0f - ymd) ;
7913 zpd = (1.0f - zmd) ;
7914
7915 switch (mri->type)
7916 {
7917 case MRI_UCHAR:
7918 *pval = val =
7919 xpd * ypd * zpd * (Real)MRIvox(mri, xm, ym, zm) +
7920 xpd * ypd * zmd * (Real)MRIvox(mri, xm, ym, zp) +
7921 xpd * ymd * zpd * (Real)MRIvox(mri, xm, yp, zm) +
7922 xpd * ymd * zmd * (Real)MRIvox(mri, xm, yp, zp) +
7923 xmd * ypd * zpd * (Real)MRIvox(mri, xp, ym, zm) +
7924 xmd * ypd * zmd * (Real)MRIvox(mri, xp, ym, zp) +
7925 xmd * ymd * zpd * (Real)MRIvox(mri, xp, yp, zm) +
7926 xmd * ymd * zmd * (Real)MRIvox(mri, xp, yp, zp) ;
7927 break ;
7928 case MRI_FLOAT:
7929 *pval = val =
7930 xpd * ypd * zpd * (Real)MRIFvox(mri, xm, ym, zm) +
7931 xpd * ypd * zmd * (Real)MRIFvox(mri, xm, ym, zp) +
7932 xpd * ymd * zpd * (Real)MRIFvox(mri, xm, yp, zm) +
7933 xpd * ymd * zmd * (Real)MRIFvox(mri, xm, yp, zp) +
7934 xmd * ypd * zpd * (Real)MRIFvox(mri, xp, ym, zm) +
7935 xmd * ypd * zmd * (Real)MRIFvox(mri, xp, ym, zp) +
7936 xmd * ymd * zpd * (Real)MRIFvox(mri, xp, yp, zm) +
7937 xmd * ymd * zmd * (Real)MRIFvox(mri, xp, yp, zp) ;
7938 break ;
7939 case MRI_SHORT:
7940 *pval = val =
7941 xpd * ypd * zpd * (Real)MRISvox(mri, xm, ym, zm) +
7942 xpd * ypd * zmd * (Real)MRISvox(mri, xm, ym, zp) +
7943 xpd * ymd * zpd * (Real)MRISvox(mri, xm, yp, zm) +
7944 xpd * ymd * zmd * (Real)MRISvox(mri, xm, yp, zp) +
7945 xmd * ypd * zpd * (Real)MRISvox(mri, xp, ym, zm) +
7946 xmd * ypd * zmd * (Real)MRISvox(mri, xp, ym, zp) +
7947 xmd * ymd * zpd * (Real)MRISvox(mri, xp, yp, zm) +
7948 xmd * ymd * zmd * (Real)MRISvox(mri, xp, yp, zp) ;
7949 break ;
7950 case MRI_INT:
7951 *pval = val =
7952 xpd * ypd * zpd * (Real)MRIIvox(mri, xm, ym, zm) +
7953 xpd * ypd * zmd * (Real)MRIIvox(mri, xm, ym, zp) +
7954 xpd * ymd * zpd * (Real)MRIIvox(mri, xm, yp, zm) +
7955 xpd * ymd * zmd * (Real)MRIIvox(mri, xm, yp, zp) +
7956 xmd * ypd * zpd * (Real)MRIIvox(mri, xp, ym, zm) +
7957 xmd * ypd * zmd * (Real)MRIIvox(mri, xp, ym, zp) +
7958 xmd * ymd * zpd * (Real)MRIIvox(mri, xp, yp, zm) +
7959 xmd * ymd * zmd * (Real)MRIIvox(mri, xp, yp, zp) ;
7960 break ;
7961 case MRI_LONG:
7962 *pval = val =
7963 xpd * ypd * zpd * (Real)MRILvox(mri, xm, ym, zm) +
7964 xpd * ypd * zmd * (Real)MRILvox(mri, xm, ym, zp) +
7965 xpd * ymd * zpd * (Real)MRILvox(mri, xm, yp, zm) +
7966 xpd * ymd * zmd * (Real)MRILvox(mri, xm, yp, zp) +
7967 xmd * ypd * zpd * (Real)MRILvox(mri, xp, ym, zm) +
7968 xmd * ypd * zmd * (Real)MRILvox(mri, xp, ym, zp) +
7969 xmd * ymd * zpd * (Real)MRILvox(mri, xp, yp, zm) +
7970 xmd * ymd * zmd * (Real)MRILvox(mri, xp, yp, zp) ;
7971 break ;
7972 default:
7973 ErrorReturn(ERROR_UNSUPPORTED,
7974 (ERROR_UNSUPPORTED,
7975 "MRIsampleVolume: unsupported type %d", mri->type)) ;
7976 break ;
7977 }
7978 return(NO_ERROR) ;
7979 }
7980
7981 /*------------------------------------------------------------------
7982 MRIsampleSeqVolume() - performs trilinear interpolation on a
7983 multi-frame volume. valvect is a vector of length nframes. No error
7984 checking for first and last frame. The caller is able to specify
7985 first frame and last frame so that all frames do not have to be
7986 sampled at the same time (this can be important in time-sensative
7987 applications).
7988 -------------------------------------------------------------------*/
7989 int MRIsampleSeqVolume(MRI *mri, Real x, Real y, Real z, float *valvect,
7990 int firstframe, int lastframe)
7991 {
7992 int OutOfBounds;
7993 int f,xm, xp, ym, yp, zm, zp, width, height, depth ;
7994 Real xmd, ymd, zmd, xpd, ypd, zpd ; /* d's are distances */
7995
7996 OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
7997 if(OutOfBounds == 1){
7998 /* unambiguously out of bounds */
7999 for(f=firstframe; f <= lastframe; f++) valvect[f] = 0.0;
8000 return(NO_ERROR) ;
8001 }
8002
8003 width = mri->width ; height = mri->height ; depth = mri->depth ;
8004
8005 if (x >= width) x = width - 1.0 ;
8006 if (y >= height) y = height - 1.0 ;
8007 if (z >= depth) z = depth - 1.0 ;
8008 if (x < 0.0) x = 0.0 ;
8009 if (y < 0.0) y = 0.0 ;
8010 if (z < 0.0) z = 0.0 ;
8011
8012 xm = MAX((int)x, 0) ;
8013 xp = MIN(width-1, xm+1) ;
8014 ym = MAX((int)y, 0) ;
8015 yp = MIN(height-1, ym+1) ;
8016 zm = MAX((int)z, 0) ;
8017 zp = MIN(depth-1, zm+1) ;
8018
8019 xmd = x - (float)xm ;
8020 ymd = y - (float)ym ;
8021 zmd = z - (float)zm ;
8022 xpd = (1.0f - xmd) ;
8023 ypd = (1.0f - ymd) ;
8024 zpd = (1.0f - zmd) ;
8025
8026 for(f = firstframe; f <= lastframe; f++){
8027 switch (mri->type) {
8028 case MRI_UCHAR:
8029 valvect[f] =
8030 xpd * ypd * zpd * (Real)MRIseq_vox(mri, xm, ym, zm, f) +
8031 xpd * ypd * zmd * (Real)MRIseq_vox(mri, xm, ym, zp, f) +
8032 xpd * ymd * zpd * (Real)MRIseq_vox(mri, xm, yp, zm, f) +
8033 xpd * ymd * zmd * (Real)MRIseq_vox(mri, xm, yp, zp, f) +
8034 xmd * ypd * zpd * (Real)MRIseq_vox(mri, xp, ym, zm, f) +
8035 xmd * ypd * zmd * (Real)MRIseq_vox(mri, xp, ym, zp, f) +
8036 xmd * ymd * zpd * (Real)MRIseq_vox(mri, xp, yp, zm, f) +
8037 xmd * ymd * zmd * (Real)MRIseq_vox(mri, xp, yp, zp, f) ;
8038 break ;
8039 case MRI_FLOAT:
8040 valvect[f] =
8041 xpd * ypd * zpd * (Real)MRIFseq_vox(mri, xm, ym, zm, f) +
8042 xpd * ypd * zmd * (Real)MRIFseq_vox(mri, xm, ym, zp, f) +
8043 xpd * ymd * zpd * (Real)MRIFseq_vox(mri, xm, yp, zm, f) +
8044 xpd * ymd * zmd * (Real)MRIFseq_vox(mri, xm, yp, zp, f) +
8045 xmd * ypd * zpd * (Real)MRIFseq_vox(mri, xp, ym, zm, f) +
8046 xmd * ypd * zmd * (Real)MRIFseq_vox(mri, xp, ym, zp, f) +
8047 xmd * ymd * zpd * (Real)MRIFseq_vox(mri, xp, yp, zm, f) +
8048 xmd * ymd * zmd * (Real)MRIFseq_vox(mri, xp, yp, zp, f) ;
8049 break ;
8050 case MRI_SHORT:
8051 valvect[f] =
8052 xpd * ypd * zpd * (Real)MRISseq_vox(mri, xm, ym, zm, f) +
8053 xpd * ypd * zmd * (Real)MRISseq_vox(mri, xm, ym, zp, f) +
8054 xpd * ymd * zpd * (Real)MRISseq_vox(mri, xm, yp, zm, f) +
8055 xpd * ymd * zmd * (Real)MRISseq_vox(mri, xm, yp, zp, f) +
8056 xmd * ypd * zpd * (Real)MRISseq_vox(mri, xp, ym, zm, f) +
8057 xmd * ypd * zmd * (Real)MRISseq_vox(mri, xp, ym, zp, f) +
8058 xmd * ymd * zpd * (Real)MRISseq_vox(mri, xp, yp, zm, f) +
8059 xmd * ymd * zmd * (Real)MRISseq_vox(mri, xp, yp, zp, f) ;
8060 break ;
8061 case MRI_INT:
8062 valvect[f] =
8063 xpd * ypd * zpd * (Real)MRIIseq_vox(mri, xm, ym, zm, f) +
8064 xpd * ypd * zmd * (Real)MRIIseq_vox(mri, xm, ym, zp, f) +
8065 xpd * ymd * zpd * (Real)MRIIseq_vox(mri, xm, yp, zm, f) +
8066 xpd * ymd * zmd * (Real)MRIIseq_vox(mri, xm, yp, zp, f) +
8067 xmd * ypd * zpd * (Real)MRIIseq_vox(mri, xp, ym, zm, f) +
8068 xmd * ypd * zmd * (Real)MRIIseq_vox(mri, xp, ym, zp, f) +
8069 xmd * ymd * zpd * (Real)MRIIseq_vox(mri, xp, yp, zm, f) +
8070 xmd * ymd * zmd * (Real)MRIIseq_vox(mri, xp, yp, zp, f) ;
8071 break ;
8072 case MRI_LONG:
8073 valvect[f] =
8074 xpd * ypd * zpd * (Real)MRILseq_vox(mri, xm, ym, zm, f) +
8075 xpd * ypd * zmd * (Real)MRILseq_vox(mri, xm, ym, zp, f) +
8076 xpd * ymd * zpd * (Real)MRILseq_vox(mri, xm, yp, zm, f) +
8077 xpd * ymd * zmd * (Real)MRILseq_vox(mri, xm, yp, zp, f) +
8078 xmd * ypd * zpd * (Real)MRILseq_vox(mri, xp, ym, zm, f) +
8079 xmd * ypd * zmd * (Real)MRILseq_vox(mri, xp, ym, zp, f) +
8080 xmd * ymd * zpd * (Real)MRILseq_vox(mri, xp, yp, zm, f) +
8081 xmd * ymd * zmd * (Real)MRILseq_vox(mri, xp, yp, zp, f) ;
8082 break ;
8083 default:
8084 ErrorReturn(ERROR_UNSUPPORTED,
8085 (ERROR_UNSUPPORTED,
8086 "MRIsampleSeqVolume: unsupported type %d", mri->type)) ;
8087 break ;
8088 }
8089 }/* end loop over frames */
8090
8091 return(NO_ERROR) ;
8092 }
8093
8094 /*-----------------------------------------------------
8095 used by MRIcubicSampleVolume
8096 ------------------------------------------------------*/
8097
8098 double
8099 localeval(Real x, int iter)
8100 {
8101 double p;
8102 switch (iter)
8103 {
8104 case 0:
8105 p = ((2-x)*x-1)*x; break;
8106 case 1:
8107 p = (3*x-5)*x*x+2; break;
8108 case 2:
8109 p = ((4-3*x)*x+1)*x; break;
8110 case 3:
8111 p = (x-1)*x*x; break;
8112 default:
8113 ErrorReturn(ERROR_UNSUPPORTED,
8114 (ERROR_UNSUPPORTED,
8115 "localeval: called wrong by MRIcubicSampleVolume!")) ;
8116 }
8117 return(p);
8118 }
8119
8120 /*-----------------------------------------------------
8121 Parameters:
8122
8123 Returns value:
8124
8125 Description
8126
8127 by analogy with
8128 /usr/pubsw/common/matlab/6.5/toolbox/matlab/polyfun/interp3.m
8129
8130 uses localeval above
8131
8132 ------------------------------------------------------*/
8133 int
8134 MRIcubicSampleVolume(MRI *mri, Real x, Real y, Real z, Real *pval)
8135 {
8136 int OutOfBounds;
8137 int width, height, depth ;
8138 int ix_low,iy_low,iz_low,ix,iy,iz;
8139 double val,xx,yy,zz,fx,fy,fz,vv[4][4][4];
8140
8141 if (FEQUAL((int)x,x) && FEQUAL((int)y,y) && FEQUAL((int)z, z))
8142 return(MRIsampleVolumeType(mri, x, y, z, pval, SAMPLE_NEAREST)) ;
8143
8144 OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
8145 if(OutOfBounds == 1){
8146 /* unambiguously out of bounds */
8147 *pval = val = 0.0;
8148 return(NO_ERROR) ;
8149 }
8150 width = mri->width ; height = mri->height ; depth = mri->depth ;
8151
8152 /*E* I suppose these are for "ambiguously out of bounds" - within .5vox */
8153
8154 /*E* I think this needs an edit - x is Real, whatever that is, not
8155 int, so any x>= width-1 should be set to width-1.
8156 if (x >= width) x = width - 1.0 ;
8157 if (y >= height) y = height - 1.0 ;
8158 if (z >= depth) z = depth - 1.0 ;
8159 */
8160
8161 if (x > width-1.0) x = width - 1.0 ;
8162 if (y > height-1.0) y = height - 1.0 ;
8163 if (z > depth-1.0) z = depth - 1.0 ;
8164 if (x < 0.0) x = 0.0 ;
8165 if (y < 0.0) y = 0.0 ;
8166 if (z < 0.0) z = 0.0 ;
8167
8168 ix_low = floor((double)x);
8169 if ((ix_low = floor((double)x)) < width-1)
8170 xx = x - ix_low;
8171 else
8172 {
8173 ix_low--;
8174 xx = 1;
8175 }
8176 iy_low = floor((double)y);
8177 if ((iy_low = floor((double)y)) < height-1)
8178 yy = y - iy_low;
8179 else
8180 {
8181 iy_low--;
8182 yy = 1;
8183 }
8184 iz_low = floor((double)z);
8185 if ((iz_low = floor((double)z)) < depth-1)
8186 zz = z - iz_low;
8187 else
8188 {
8189 iz_low--;
8190 zz = 1;
8191 }
8192
8193 /*E* build a little box of the local points plus boundary stuff -
8194 for this rev accept zeroes for the border expansion */
8195
8196 for(iz= MAX(0,1-iz_low); iz<MIN(4,depth+1-iz_low); iz++)
8197 {
8198 for(iy= MAX(0,1-iy_low); iy<MIN(4,height+1-iy_low); iy++)
8199 {
8200 for(ix= MAX(0,1-ix_low); ix<MIN(4,width+1-ix_low); ix++)
8201 {
8202 switch (mri->type)
8203 {
8204 case MRI_UCHAR:
8205 vv[ix][iy][iz] =
8206 (double)MRIvox(mri,ix_low-1+ix,iy_low-1+iy,iz_low-1+iz);
8207 break;
8208 case MRI_FLOAT:
8209 vv[ix][iy][iz] =
8210 (double)MRIFvox(mri,ix_low-1+ix,iy_low-1+iy,iz_low-1+iz);
8211 break;
8212 case MRI_SHORT:
8213 vv[ix][iy][iz] =
8214 (double)MRISvox(mri,ix_low-1+ix,iy_low-1+iy,iz_low-1+iz);
8215 break;
8216 case MRI_INT:
8217 vv[ix][iy][iz] =
8218 (double)MRIIvox(mri,ix_low-1+ix,iy_low-1+iy,iz_low-1+iz);
8219 break;
8220 case MRI_LONG:
8221 vv[ix][iy][iz] =
8222 (double)MRILvox(mri,ix_low-1+ix,iy_low-1+iy,iz_low-1+iz);
8223 break;
8224 default:
8225 ErrorReturn(ERROR_UNSUPPORTED,
8226 (ERROR_UNSUPPORTED,
8227 "MRIcubicSampleVolume: unsupported type %d",
8228 mri->type)) ;
8229 break ;
8230 }
8231 }
8232 }
8233 }
8234
8235 val = 0;
8236
8237 for(iz=0; iz<=3; iz++)
8238 {
8239 fz = localeval(zz,iz);
8240 for(iy=0; iy<=3; iy++)
8241 {
8242 fy = localeval(yy,iy);
8243 for(ix=0; ix<=3; ix++)
8244 {
8245 fx = localeval(xx,ix);
8246 val += (Real)(vv[ix][iy][iz]*fx*fy*fz);
8247 }
8248 }
8249 }
8250
8251 *pval = val/8.;
8252
8253 return(NO_ERROR);
8254 }
8255
8256 /*-----------------------------------------------------
8257 Parameters:
8258
8259 Returns value:
8260
8261 Description
8262 ------------------------------------------------------*/
8263 #define IMIN(a,b) (a < b ? a : b)
8264 #define IMAX(a,b) (a > b ? a : b)
8265 double ham_sinc(double x,double fullwidth)
8266 {
8267 double ham;
8268 if( fabs(x) < 1.0e-5)
8269 ham = 1.0;
8270 else {
8271 ham = sin(PI*x)/(PI*x);
8272 ham *= 0.54 + 0.46 * cos(2.0*PI*x/fullwidth);
8273 }
8274 return ham;
8275 }
8276
8277 /*-------------------------------------------------------------------------*/
8278 int
8279 MRIsincSampleVolume(MRI *mri, Real x, Real y, Real z, int hw, Real *pval)
8280 {
8281
8282 int OutOfBounds;
8283 int width, height, depth ;
8284 int nwidth;
8285 int ix_low,ix_high,iy_low,iy_high,iz_low,iz_high;
8286 int jx1,jy1,jz1,jx_rel,jy_rel,jz_rel;
8287 double coeff_x[128],coeff_y[128],coeff_z[128];
8288 double coeff_x_sum,coeff_y_sum,coeff_z_sum;
8289 double sum_x,sum_y,sum_z;
8290 double xsize,ysize,zsize;
8291
8292 OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
8293 if(OutOfBounds == 1){
8294 /* unambiguously out of bounds */
8295 *pval = 0.0;
8296 return(NO_ERROR) ;
8297 }
8298
8299 xsize = mri->xsize; ysize=mri->ysize; zsize=mri->zsize;
8300 width = mri->width ; height = mri->height ; depth = mri->depth ;
8301 if (x >= width) x = width - 1.0 ;
8302 if (y >= height) y = height - 1.0 ;
8303 if (z >= depth) z = depth - 1.0 ;
8304 if (x < 0.0) x = 0.0 ;
8305 if (y < 0.0) y = 0.0 ;
8306 if (z < 0.0) z = 0.0 ;
8307
8308 nwidth = hw;
8309 ix_low = floor((double)x);
8310 ix_high = ceil((double)x);
8311 iy_low = floor((double)y);
8312 iy_high = ceil((double)y);
8313 iz_low = floor((double)z);
8314 iz_high = ceil((double)z);
8315
8316 coeff_x_sum = coeff_y_sum = coeff_z_sum = 0;
8317 if(iz_low>=0 && iz_high < depth)
8318 {
8319 for (jx1=IMAX(ix_high-nwidth,0), jx_rel=0;
8320 jx1<IMIN(ix_low+nwidth,width-1);
8321 jx1++,jx_rel++)
8322 {
8323 coeff_x[jx_rel] = ham_sinc((double)(x-jx1),2*nwidth);
8324 coeff_x_sum += coeff_x[jx_rel];
8325 }
8326 for (jy1=IMAX(iy_high-nwidth,0), jy_rel=0;
8327 jy1<IMIN(iy_low+nwidth,height-1);
8328 jy1++,jy_rel++)
8329 {
8330 coeff_y[jy_rel] = ham_sinc((double)(y-jy1),2*nwidth);
8331 coeff_y_sum += coeff_y[jy_rel];
8332 }
8333 for (jz1=IMAX(iz_high-nwidth,0), jz_rel=0;
8334 jz1<IMIN(iz_low+nwidth,depth-1);
8335 jz1++,jz_rel++)
8336 {
8337 coeff_z[jz_rel] = ham_sinc((double)(z-jz1),2*nwidth);
8338 coeff_z_sum += coeff_z[jz_rel];
8339 }
8340
8341 for(sum_z=0., jz1=IMAX(iz_high-nwidth,0), jz_rel = 0;
8342 jz1 < IMIN(iz_low+nwidth,depth-1);
8343 jz1++, jz_rel++)
8344 {
8345
8346 for(sum_y=0., jy1=IMAX(iy_high-nwidth,0), jy_rel = 0;
8347 jy1 < IMIN(iy_low+nwidth,height-1);
8348 jy1++, jy_rel++)
8349 {
8350 for(sum_x=0., jx1=IMAX(ix_high-nwidth,0), jx_rel = 0;
8351 jx1 < IMIN(ix_low+nwidth,width-1);
8352 jx1++, jx_rel++)
8353 {
8354
8355 switch(mri->type)
8356 {
8357 case MRI_UCHAR:
8358 sum_x += (coeff_x[jx_rel]/coeff_x_sum)
8359 * (double)MRIvox(mri,jx1,jy1,jz1);
8360 break;
8361 case MRI_SHORT:
8362 sum_x += (coeff_x[jx_rel]/coeff_x_sum)
8363 * (double)MRISvox(mri,jx1,jy1,jz1);
8364 break;
8365 case MRI_INT:
8366 sum_x += (coeff_x[jx_rel]/coeff_x_sum)
8367 * (double)MRIIvox(mri,jx1,jy1,jz1);
8368 break;
8369 case MRI_LONG:
8370 sum_x += (coeff_x[jx_rel]/coeff_x_sum)
8371 * (double)MRILvox(mri,jx1,jy1,jz1);
8372 break;
8373 case MRI_FLOAT:
8374 sum_x += (coeff_x[jx_rel]/coeff_x_sum)
8375 * (double)MRIFvox(mri,jx1,jy1,jz1);
8376 break;
8377 default:
8378 ErrorReturn(ERROR_UNSUPPORTED,
8379 (ERROR_UNSUPPORTED,
8380 "MRIsincSampleVolume: unsupported type %d",
8381 mri->type)) ;
8382 break;
8383 }
8384 }
8385 sum_y += sum_x * (coeff_y[jy_rel]/coeff_y_sum);
8386 }
8387 sum_z += sum_y * (coeff_z[jz_rel]/coeff_z_sum);
8388 }
8389 if((mri->type == MRI_UCHAR || mri->type == MRI_SHORT) && sum_z<0.0)
8390 *pval = 0.0;
8391 else if(mri->type == MRI_UCHAR && sum_z >255.0)
8392 *pval = 255.0;
8393 else if(mri->type == MRI_SHORT && sum_z > 65535.0)
8394 *pval = 65535.0;
8395 else
8396 *pval = sum_z;
8397 }
8398 else
8399 *pval = 0.0;
8400
8401 return(NO_ERROR);
8402 }
8403 /*-----------------------------------------------------------------
8404 MRIindexNotInVolume() - determines whether a col, row, slice point is
8405 in the mri volume. If it is unambiguously in the volume, then 0
8406 is returned. If it is within 0.5 of the edge of the volume, -1
8407 is returned. Otherwise 1 is returned. Flagging the case where
8408 the point is within 0.5 of the edge can be used for assigning
8409 a nearest neighbor when the point is outside but close to the
8410 volume. In this case the index of the nearest neighbor can safely
8411 be computed as the nearest integer to col, row, and slice.
8412 -----------------------------------------------------------------*/
8413 int MRIindexNotInVolume(MRI *mri, Real col, Real row, Real slice)
8414 {
8415 float nicol, nirow, nislice;
8416
8417 /* unambiguously in the volume */
8418 if(col >= 0 && col <= mri->width-1 &&
8419 row >= 0 && row <= mri->height-1 &&
8420 slice >= 0 && slice <= mri->depth-1 )
8421 return(0);
8422
8423 /* within 0.5 of the edge of the volume */
8424 nicol = rint(col);
8425 nirow = rint(row);
8426 nislice = rint(slice);
8427 if(nicol >= 0 && nicol < mri->width &&
8428 nirow >= 0 && nirow < mri->height &&
8429 nislice >= 0 && nislice < mri->depth )
8430 return(-1);
8431
8432 /* unambiguously NOT in the volume */
8433 return(1);
8434
8435 }
8436 /*-----------------------------------------------------
8437 Parameters:
8438
8439 Returns value:
8440
8441 Description
8442 Interpolate the volume directional derivative using
8443 trilinear interpolation.
8444 ------------------------------------------------------*/
8445 float
8446 MRIsampleCardinalDerivative(MRI *mri, int x, int y, int z,
8447 int xk, int yk, int zk)
8448 {
8449 float d ;
8450
8451 if (xk)
8452 d = MRIsampleXDerivative(mri, x, y, z, xk) ;
8453 else if (yk)
8454 d = MRIsampleYDerivative(mri, x, y, z, yk) ;
8455 else
8456 d = MRIsampleZDerivative(mri, x, y, z, zk) ;
8457 return(d) ;
8458 }
8459 /*-----------------------------------------------------
8460 Parameters:
8461
8462 Returns value:
8463
8464 Description
8465 Interpolate the volume directional derivative using
8466 trilinear interpolation.
8467 ------------------------------------------------------*/
8468 float
8469 MRIsampleXDerivative(MRI *mri, int x, int y, int z, int dir)
8470 {
8471 float dx ;
8472 int yk, zk, xi, yi, zi, nvox ;
8473
8474 dx = 0.0 ;
8475
8476 xi = mri->xi[x+dir] ;
8477 for (nvox = 0, zk = -1 ; zk <= 1 ; zk++)
8478 {
8479 zi = mri->zi[z+zk] ;
8480 for (yk = -1 ; yk <= 1 ; yk++)
8481 {
8482 yi = mri->yi[y+yk] ;
8483 dx += dir*MRIvox(mri, xi, yi, zi) ; /* x+dir */
8484 dx -= dir*MRIvox(mri, x, yi, zi) ; /* - x */
8485 nvox += 2 ;
8486 }
8487 }
8488 dx /= ((float)nvox*mri->xsize) ;
8489 return(dx) ;
8490 }
8491 /*-----------------------------------------------------
8492 Parameters:
8493
8494 Returns value:
8495
8496 Description
8497 Interpolate the volume directional derivative using
8498 trilinear interpolation.
8499 ------------------------------------------------------*/
8500 float
8501 MRIsampleYDerivative(MRI *mri, int x, int y, int z, int dir)
8502 {
8503 float dy ;
8504 int xk, zk, xi, yi, zi, nvox ;
8505
8506 dy = 0.0 ;
8507
8508 yi = mri->yi[y+dir] ;
8509 for (nvox = 0, zk = -1 ; zk <= 1 ; zk++)
8510 {
8511 zi = mri->zi[z+zk] ;
8512 for (xk = -1 ; xk <= 1 ; xk++)
8513 {
8514 xi = mri->xi[x+xk] ;
8515 dy += dir*MRIvox(mri, xi, yi, zi) ; /* x+dir */
8516 dy -= dir*MRIvox(mri, x, yi, zi) ; /* - x */
8517 nvox += 2 ;
8518 }
8519 }
8520 dy /= ((float)nvox*mri->ysize) ;
8521 return(dy) ;
8522 }
8523 /*-----------------------------------------------------
8524 Parameters:
8525
8526 Returns value:
8527
8528 Description
8529 Interpolate the volume directional derivative using
8530 trilinear interpolation.
8531 ------------------------------------------------------*/
8532 float
8533 MRIsampleZDerivative(MRI *mri, int x, int y, int z, int dir)
8534 {
8535 float dz ;
8536 int xk, yk, xi, yi, zi, nvox ;
8537
8538 dz = 0.0 ;
8539
8540 zi = mri->zi[z+dir] ;
8541 for (nvox = 0, xk = -1 ; xk <= 1 ; xk++)
8542 {
8543 xi = mri->xi[x+xk] ;
8544 for (yk = -1 ; yk <= 1 ; yk++)
8545 {
8546 yi = mri->yi[y+yk] ;
8547 dz += dir*MRIvox(mri, xi, yi, zi) ; /* x+dir */
8548 dz -= dir*MRIvox(mri, x, yi, zi) ; /* - x */
8549 nvox += 2 ;
8550 }
8551 }
8552 dz /= ((float)nvox*mri->zsize) ;
8553 return(dz) ;
8554 }
8555 int
8556 MRIsampleVolumeDirectionScale(MRI *mri, Real x, Real y, Real z,
8557 Real dx, Real dy, Real dz, Real *pmag,
8558 double sigma)
8559 {
8560 int width, height, depth ;
8561 Real xp1, xm1, yp1, ym1, zp1, zm1, len ;
8562 Real dist, val, k, ktotal, step_size, total_val ;
8563 int n ;
8564
8565 width = mri->width ; height = mri->height ; depth = mri->depth ;
8566 if (x >= width)
8567 x = width - 1.0 ;
8568 if (y >= height)
8569 y = height - 1.0 ;
8570 if (z >= depth)
8571 z = depth - 1.0 ;
8572 if (x < 0.0)
8573 x = 0.0 ;
8574 if (y < 0.0)
8575 y = 0.0 ;
8576 if (z < 0.0)
8577 z = 0.0 ;
8578
8579 step_size = MAX(.5,sigma/2) ;
8580 for (total_val = ktotal = 0.0,n = 0, len = 0.0, dist = step_size ;
8581 dist <= MAX(2*sigma,step_size);
8582 dist += step_size, n++)
8583 {
8584 if (FZERO(sigma))
8585 k = 1.0 ;
8586 else
8587 k = exp(-dist*dist/(2*sigma*sigma)) ;
8588 ktotal += k ;
8589 len += dist ;
8590 xp1 = x + dist*dx ; yp1 = y + dist*dy ; zp1 = z + dist*dz ;
8591 MRIsampleVolume(mri, xp1, yp1, zp1, &val) ;
8592 total_val += k*val ;
8593
8594 xm1 = x - dist*dx ; ym1 = y - dist*dy ; zm1 = z - dist*dz ;
8595 MRIsampleVolume(mri, xm1, ym1, zm1, &val) ;
8596 total_val += k*val ;
8597 if (FZERO(step_size))
8598 break ;
8599 }
8600 total_val /= (double)2.0*ktotal ;
8601
8602 *pmag = total_val ;
8603 return(NO_ERROR) ;
8604 }
8605
8606 int
8607 MRIsampleVolumeDerivativeScale(MRI *mri, Real x, Real y, Real z, Real dx,
8608 Real dy, Real dz, Real *pmag, double sigma)
8609 {
8610 int width, height, depth ;
8611 Real xp1, xm1, yp1, ym1, zp1, zm1, vp1, vm1, len ;
8612 Real dist, val, k, ktotal, step_size ;
8613 int n ;
8614
8615 width = mri->width ; height = mri->height ; depth = mri->depth ;
8616 if (x >= width)
8617 x = width - 1.0 ;
8618 if (y >= height)
8619 y = height - 1.0 ;
8620 if (z >= depth)
8621 z = depth - 1.0 ;
8622 if (x < 0.0)
8623 x = 0.0 ;
8624 if (y < 0.0)
8625 y = 0.0 ;
8626 if (z < 0.0)
8627 z = 0.0 ;
8628
8629 step_size = MAX(.5,sigma/2) ;
8630 for (ktotal = 0.0,n = 0, len = vp1 = vm1 = 0.0, dist = step_size ;
8631 dist <= MAX(2*sigma,step_size);
8632 dist += step_size, n++)
8633 {
8634 if (FZERO(sigma))
8635 k = 1.0 ;
8636 else
8637 k = exp(-dist*dist/(2*sigma*sigma)) ;
8638 ktotal += k ;
8639 len += dist ;
8640 xp1 = x + dist*dx ; yp1 = y + dist*dy ; zp1 = z + dist*dz ;
8641 MRIsampleVolume(mri, xp1, yp1, zp1, &val) ;
8642 vp1 += k*val ;
8643
8644 xm1 = x - dist*dx ; ym1 = y - dist*dy ; zm1 = z - dist*dz ;
8645 MRIsampleVolume(mri, xm1, ym1, zm1, &val) ;
8646 vm1 += k*val ;
8647 if (FZERO(step_size))
8648 break ;
8649 }
8650 vm1 /= (double)ktotal ; vp1 /= (double)ktotal ; len /= (double)ktotal ;
8651
8652 *pmag = (vp1-vm1) / (2.0*len) ;
8653 return(NO_ERROR) ;
8654 }
8655 /*-----------------------------------------------------
8656 Parameters:
8657
8658 Returns value:
8659
8660 Description
8661 Interpolate the volume directional derivative using
8662 trilinear interpolation.
8663 ------------------------------------------------------*/
8664 int
8665 MRIsampleVolumeDerivative(MRI *mri, Real x, Real y, Real z,
8666 Real dx, Real dy, Real dz, Real *pmag)
8667 {
8668 int width, height, depth ;
8669 Real xp1, xm1, yp1, ym1, zp1, zm1, vp1, vm1, len ;
8670
8671 width = mri->width ; height = mri->height ; depth = mri->depth ;
8672 if (x >= width)
8673 x = width - 1.0 ;
8674 if (y >= height)
8675 y = height - 1.0 ;
8676 if (z >= depth)
8677 z = depth - 1.0 ;
8678 if (x < 0.0)
8679 x = 0.0 ;
8680 if (y < 0.0)
8681 y = 0.0 ;
8682 if (z < 0.0)
8683 z = 0.0 ;
8684 #if 1
8685 {
8686 Real dist, val ;
8687 int n ;
8688
8689 for (n = 0, len = vp1 = vm1 = 0.0, dist = .5 ; dist <= 2 ;
8690 dist += 0.5, n++)
8691 {
8692 len += dist ;
8693 xp1 = x + dist*dx ; yp1 = y + dist*dy ; zp1 = z + dist*dz ;
8694 MRIsampleVolume(mri, xp1, yp1, zp1, &val) ;
8695 vp1 += val ;
8696
8697 xm1 = x - dist*dx ; ym1 = y - dist*dy ; zm1 = z - dist*dz ;
8698 MRIsampleVolume(mri, xm1, ym1, zm1, &val) ;
8699 vm1 += val ;
8700 }
8701 vm1 /= (double)n ; vp1 /= (double)n ; len /= (double)n ;
8702 }
8703 #else
8704 xp1 = x + dx ; xm1 = x - dx ;
8705 yp1 = y + dy ; ym1 = y - dy ;
8706 zp1 = z + dz ; zm1 = z - dz ;
8707 len = sqrt(dx*dx+dy*dy+dz*dz) ;
8708 MRIsampleVolume(mri, xp1, yp1, zp1, &vp1) ;
8709 MRIsampleVolume(mri, xm1, ym1, zm1, &vm1) ;
8710 #endif
8711
8712 *pmag = (vp1-vm1) / (2.0*len) ;
8713 return(NO_ERROR) ;
8714 }
8715 /*-----------------------------------------------------
8716 Parameters:
8717
8718 Returns value:
8719
8720 Description
8721 Interpolate the volume gradient to cubic voxels.
8722 ------------------------------------------------------*/
8723 int
8724 MRIsampleVolumeGradient(MRI *mri, Real x, Real y, Real z,
8725 Real *pdx, Real *pdy, Real *pdz)
8726 {
8727 int width, height, depth ;
8728 Real xp1, xm1, yp1, ym1, zp1, zm1 ;
8729
8730 width = mri->width ; height = mri->height ; depth = mri->depth ;
8731 if (x >= width)
8732 x = width - 1.0 ;
8733 if (y >= height)
8734 y = height - 1.0 ;
8735 if (z >= depth)
8736 z = depth - 1.0 ;
8737 if (x < 0.0)
8738 x = 0.0 ;
8739 if (y < 0.0)
8740 y = 0.0 ;
8741 if (z < 0.0)
8742 z = 0.0 ;
8743 MRIsampleVolume(mri, x+1.0, y, z, &xp1) ;
8744 MRIsampleVolume(mri, x-1.0, y, z, &xm1) ;
8745
8746 MRIsampleVolume(mri, x, y+1.0, z, &yp1) ;
8747 MRIsampleVolume(mri, x, y-1.0, z, &ym1) ;
8748
8749 MRIsampleVolume(mri, x, y, z+1.0, &zp1) ;
8750 MRIsampleVolume(mri, x, y, z-1.0, &zm1) ;
8751
8752 *pdx = (xp1-xm1)/(2.0*mri->xsize) ;
8753 *pdy = (yp1-ym1)/(2.0*mri->ysize) ;
8754 *pdz = (zp1-zm1)/(2.0*mri->zsize) ;
8755 return(NO_ERROR) ;
8756 }
8757 /*-----------------------------------------------------
8758 Parameters:
8759
8760 Returns value:
8761
8762 Description
8763 Interpolate the volume gradient to cubic voxels.
8764 ------------------------------------------------------*/
8765 int
8766 MRIsampleVolumeGradientFrame(MRI *mri, Real x, Real y, Real z,
8767 Real *pdx, Real *pdy, Real *pdz, int frame)
8768 {
8769 int width, height, depth ;
8770 Real xp1, xm1, yp1, ym1, zp1, zm1 ;
8771
8772 width = mri->width ; height = mri->height ; depth = mri->depth ;
8773 if (x >= width)
8774 x = width - 1.0 ;
8775 if (y >= height)
8776 y = height - 1.0 ;
8777 if (z >= depth)
8778 z = depth - 1.0 ;
8779 if (x < 0.0)
8780 x = 0.0 ;
8781 if (y < 0.0)
8782 y = 0.0 ;
8783 if (z < 0.0)
8784 z = 0.0 ;
8785 if (frame >= mri->nframes)
8786 frame = mri->nframes-1 ;
8787 if (frame < 0)
8788 frame = 0 ;
8789
8790 MRIsampleVolumeFrame(mri, x+1.0, y, z, frame, &xp1) ;
8791 MRIsampleVolumeFrame(mri, x-1.0, y, z, frame, &xm1) ;
8792
8793 MRIsampleVolumeFrame(mri, x, y+1.0, z, frame, &yp1) ;
8794 MRIsampleVolumeFrame(mri, x, y-1.0, z, frame, &ym1) ;
8795
8796 MRIsampleVolumeFrame(mri, x, y, z+1.0, frame, &zp1) ;
8797 MRIsampleVolumeFrame(mri, x, y, z-1.0, frame, &zm1) ;
8798
8799 *pdx = (xp1-xm1)/(2.0*mri->xsize) ;
8800 *pdy = (yp1-ym1)/(2.0*mri->ysize) ;
8801 *pdz = (zp1-zm1)/(2.0*mri->zsize) ;
8802 return(NO_ERROR) ;
8803 }
8804 /*-----------------------------------------------------
8805 Parameters:
8806
8807 Returns value:
8808
8809 Description
8810 ------------------------------------------------------*/
8811 int
8812 MRIneighborsOn(MRI *mri, int x0, int y0, int z0, int min_val)
8813 {
8814 int nbrs = 0 ;
8815
8816 if (MRIvox(mri,mri->xi[x0-1],y0,z0) >= min_val)
8817 nbrs++ ;
8818 if (MRIvox(mri,mri->xi[x0+1],y0,z0) >= min_val)
8819 nbrs++ ;
8820 if (MRIvox(mri,x0,mri->yi[y0+1],z0) >= min_val)
8821 nbrs++ ;
8822 if (MRIvox(mri,x0,mri->yi[y0-1],z0) >= min_val)
8823 nbrs++ ;
8824 if (MRIvox(mri,x0,y0,mri->zi[z0+1]) >= min_val)
8825 nbrs++ ;
8826 if (MRIvox(mri,x0,y0,mri->zi[z0-1]) >= min_val)
8827 nbrs++ ;
8828 return(nbrs) ;
8829 }
8830 /*-----------------------------------------------------
8831 Parameters:
8832
8833 Returns value:
8834
8835 Description
8836 ------------------------------------------------------*/
8837 int
8838 MRIneighborsOn3x3(MRI *mri, int x, int y, int z, int min_val)
8839 {
8840 int xk, yk, zk, xi, yi, zi, nbrs ;
8841
8842 for (nbrs = 0, zk = -1 ; zk <= 1 ; zk++)
8843 {
8844 zi = mri->zi[z+zk] ;
8845 for (yk = -1 ; yk <= 1 ; yk++)
8846 {
8847 yi = mri->yi[y+yk] ;
8848 for (xk = -1 ; xk <= 1 ; xk++)
8849 {
8850 xi = mri->xi[x+xk] ;
8851 if (!zk && !yk && !xk)
8852 continue ;
8853 if (MRIvox(mri, xi, yi, zi) > min_val)
8854 nbrs++ ;
8855 }
8856 }
8857 }
8858 return(nbrs) ;
8859 }
8860 /*-----------------------------------------------------
8861 Parameters:
8862
8863 Returns value:
8864
8865 Description
8866 ------------------------------------------------------*/
8867 int
8868 MRIneighborsInWindow(MRI *mri, int x, int y, int z, int wsize, int val)
8869 {
8870 int xk, yk, zk, xi, yi, zi, nbrs, whalf ;
8871
8872 whalf = (wsize-1)/2 ;
8873
8874 for (nbrs = 0, zk = -whalf ; zk <= whalf ; zk++)
8875 {
8876 zi = mri->zi[z+zk] ;
8877 for (yk = -whalf ; yk <= whalf ; yk++)
8878 {
8879 yi = mri->yi[y+yk] ;
8880 for (xk = -whalf ; xk <= whalf ; xk++)
8881 {
8882 xi = mri->xi[x+xk] ;
8883 if (!zk && !yk && !xk)
8884 continue ;
8885 if (MRIvox(mri, xi, yi, zi) == val)
8886 nbrs++ ;
8887 }
8888 }
8889 }
8890 return(nbrs) ;
8891 }
8892 /*-----------------------------------------------------
8893 Parameters:
8894
8895 Returns value:
8896
8897 Description
8898 ------------------------------------------------------*/
8899 int
8900 MRIneighbors(MRI *mri, int x0, int y0, int z0, int val)
8901 {
8902 int nbrs = 0 ;
8903
8904 if (nint(MRIgetVoxVal(mri,mri->xi[x0-1],y0,z0,0)) == val)
8905 nbrs++ ;
8906 if (nint(MRIgetVoxVal(mri,mri->xi[x0+1],y0,z0,0)) == val)
8907 nbrs++ ;
8908 if (nint(MRIgetVoxVal(mri,x0,mri->yi[y0+1],z0,0)) == val)
8909 nbrs++ ;
8910 if (nint(MRIgetVoxVal(mri,x0,mri->yi[y0-1],z0,0)) == val)
8911 nbrs++ ;
8912 if (nint(MRIgetVoxVal(mri,x0,y0,mri->zi[z0+1],0)) == val)
8913 nbrs++ ;
8914 if (nint(MRIgetVoxVal(mri,x0,y0,mri->zi[z0-1],0)) == val)
8915 nbrs++ ;
8916 return(nbrs) ;
8917 }
8918 /*-----------------------------------------------------
8919 Parameters:
8920
8921 Returns value:
8922
8923 Description
8924 ------------------------------------------------------*/
8925 int
8926 MRIneighbors3x3(MRI *mri, int x, int y, int z, int val)
8927 {
8928 int xk, yk, zk, xi, yi, zi, nbrs ;
8929
8930 for (nbrs = 0, zk = -1 ; zk <= 1 ; zk++)
8931 {
8932 zi = mri->zi[z+zk] ;
8933 for (yk = -1 ; yk <= 1 ; yk++)
8934 {
8935 yi = mri->yi[y+yk] ;
8936 for (xk = -1 ; xk <= 1 ; xk++)
8937 {
8938 xi = mri->xi[x+xk] ;
8939 if (!zk && !yk && !xk)
8940 continue ;
8941 if (MRIvox(mri, xi, yi, zi) == val)
8942 nbrs++ ;
8943 }
8944 }
8945 }
8946 return(nbrs) ;
8947 }
8948 /*-----------------------------------------------------
8949 ------------------------------------------------------*/
8950 int
8951 MRIneighborsOff(MRI *mri, int x0, int y0, int z0, int min_val)
8952 {
8953 int nbrs = 0 ;
8954
8955 if (MRIvox(mri,x0-1,y0,z0) < min_val)
8956 nbrs++ ;
8957 if (MRIvox(mri,x0+1,y0,z0) < min_val)
8958 nbrs++ ;
8959 if (MRIvox(mri,x0,y0+1,z0) < min_val)
8960 nbrs++ ;
8961 if (MRIvox(mri,x0,y0-1,z0) < min_val)
8962 nbrs++ ;
8963 if (MRIvox(mri,x0,y0,z0+1) < min_val)
8964 nbrs++ ;
8965 if (MRIvox(mri,x0,y0,z0-1) < min_val)
8966 nbrs++ ;
8967 return(nbrs) ;
8968 }
8969 /*-----------------------------------------------------
8970 ------------------------------------------------------*/
8971 int
8972 MRIneighborsOff3x3(MRI *mri, int x, int y, int z, int min_val)
8973 {
8974 int xk, yk, zk, xi, yi, zi, nbrs ;
8975
8976 for (nbrs = 0, zk = -1 ; zk <= 1 ; zk++)
8977 {
8978 zi = mri->zi[z+zk] ;
8979 for (yk = -1 ; yk <= 1 ; yk++)
8980 {
8981 yi = mri->yi[y+yk] ;
8982 for (xk = -1 ; xk <= 1 ; xk++)
8983 {
8984 xi = mri->xi[x+xk] ;
8985 if (!zk && !yk && !xk)
8986 continue ;
8987 if (MRIvox(mri, xi, yi, zi) < min_val)
8988 nbrs++ ;
8989 }
8990 }
8991 }
8992 return(nbrs) ;
8993 }
8994 /*-----------------------------------------------------
8995 Perform an linear coordinate transformation x' = Ax on
8996 the MRI image mri_src into mri_dst
8997 ------------------------------------------------------*/
8998 MRI *
8999 MRIinverseLinearTransform(MRI *mri_src, MRI *mri_dst, MATRIX *mA)
9000 {
9001 MATRIX *m_inv ;
9002
9003 m_inv = MatrixInverse(mA, NULL) ;
9004 if (!m_inv)
9005 ErrorReturn
9006 (NULL,
9007 (ERROR_BADPARM,
9008 "MRIinverseLinearTransform: xform is singular!")) ;
9009 fprintf
9010 (stderr,
9011 "applying the vox-to-vox linear transform (calculated inverse)\n");
9012 MatrixPrint(stderr, m_inv);
9013 mri_dst = MRIlinearTransform(mri_src, mri_dst, m_inv) ;
9014 MatrixFree(&m_inv) ;
9015 return(mri_dst) ;
9016 }
9017 /*-----------------------------------------------------
9018 Convert a transform from RAS to voxel coordinates, then apply
9019 it to an MRI.
9020 ------------------------------------------------------*/
9021 MRI *
9022 MRIapplyRASlinearTransform(MRI *mri_src, MRI *mri_dst, MATRIX *m_ras_xform)
9023 {
9024 MATRIX *m_voxel_xform ;
9025
9026 m_voxel_xform = MRIrasXformToVoxelXform(mri_src, mri_dst, m_ras_xform, NULL);
9027 fprintf(stderr, "applying the vox to vox linear transform\n");
9028 MatrixPrint(stderr, m_voxel_xform);
9029 mri_dst = MRIlinearTransform(mri_src, mri_dst, m_voxel_xform) ;
9030 MatrixFree(&m_voxel_xform) ;
9031 return(mri_dst) ;
9032 }
9033 /*-----------------------------------------------------
9034 Convert a transform from RAS to voxel coordinates, then apply
9035 it to an MRI.
9036 ------------------------------------------------------*/
9037 MRI *
9038 MRIapplyRASlinearTransformInterp
9039 (MRI *mri_src, MRI *mri_dst, MATRIX *m_ras_xform, int interp)
9040 {
9041 MATRIX *m_voxel_xform ;
9042
9043 m_voxel_xform = MRIrasXformToVoxelXform(mri_src, mri_dst, m_ras_xform, NULL);
9044 fprintf(stderr, "applying the vox to vox linear transform\n");
9045 MatrixPrint(stderr, m_voxel_xform);
9046 mri_dst = MRIlinearTransformInterp(mri_src, mri_dst, m_voxel_xform, interp) ;
9047 MatrixFree(&m_voxel_xform) ;
9048 return(mri_dst) ;
9049 }
9050 /*-----------------------------------------------------
9051 Convert a transform from RAS to voxel coordinates, then apply
9052 it to an MRI.
9053 ------------------------------------------------------*/
9054 MRI *
9055 MRIapplyRASinverseLinearTransform(MRI *mri_src, MRI *mri_dst,
9056 MATRIX *m_ras_xform)
9057 {
9058 MATRIX *m_voxel_xform ;
9059
9060 m_voxel_xform = MRIrasXformToVoxelXform(mri_src, mri_dst, m_ras_xform, NULL);
9061 mri_dst = MRIinverseLinearTransform(mri_src, mri_dst, m_voxel_xform) ;
9062 MatrixFree(&m_voxel_xform) ;
9063 return(mri_dst) ;
9064 }
9065
9066 /*-----------------------------------------------------
9067 Perform an linear coordinate transformation x' = Ax on
9068 the MRI image mri_src into mri_dst using sinc interp.
9069 ------------------------------------------------------*/
9070 MRI *
9071 MRIsincTransform(MRI *mri_src, MRI *mri_dst, MATRIX *mA, int hw)
9072 {
9073 int y1, y2, y3, width, height, depth ;
9074 VECTOR *v_X, *v_Y ; /* original and transformed coordinate systems */
9075 MATRIX *mAinv ; /* inverse of mA */
9076 Real val, x1, x2, x3 ;
9077
9078 mAinv = MatrixInverse(mA, NULL) ; /* will sample from dst back to src */
9079 if (!mAinv)
9080 ErrorReturn(NULL, (ERROR_BADPARM,
9081 "MRIsincTransform: xform is singular")) ;
9082
9083 width = mri_src->width ; height = mri_src->height ; depth = mri_src->depth ;
9084 if (!mri_dst)
9085 mri_dst = MRIclone(mri_src, NULL) ;
9086 else
9087 MRIclear(mri_dst) ;
9088
9089 v_X = VectorAlloc(4, MATRIX_REAL) ; /* input (src) coordinates */
9090 v_Y = VectorAlloc(4, MATRIX_REAL) ; /* transformed (dst) coordinates */
9091
9092 v_Y->rptr[4][1] = 1.0f ;
9093 for (y3 = 0 ; y3 < depth ; y3++)
9094 {
9095 V3_Z(v_Y) = y3 ;
9096 for (y2 = 0 ; y2 < height ; y2++)
9097 {
9098 V3_Y(v_Y) = y2 ;
9099 for (y1 = 0 ; y1 < width ; y1++)
9100 {
9101 V3_X(v_Y) = y1 ;
9102 MatrixMultiply(mAinv, v_Y, v_X) ;
9103
9104 x1 = V3_X(v_X) ; x2 = V3_Y(v_X) ; x3 = V3_Z(v_X) ;
9105
9106 if (nint(y1) == 13 && nint(y2) == 10 && nint(y3) == 7)
9107 DiagBreak() ;
9108 if (nint(x1) == 13 && nint(x2) == 10 && nint(x3) == 7)
9109 {
9110 #if 0
9111 fprintf
9112 (stderr,
9113 "(%2.1f, %2.1f, %2.1f) --> (%2.1f, %2.1f, %2.1f)\n",
9114 (float)x1, (float)x2, (float)x3,
9115 (float)y1, (float)y2, (float)y3) ;
9116 #endif
9117 DiagBreak() ;
9118 }
9119
9120 if (x1 > -1 && x1 < width &&
9121 x2 > -1 && x2 < height &&
9122 x3 > -1 && x3 < depth)
9123 {
9124 MRIsincSampleVolume(mri_src, x1, x2, x3, hw, &val);
9125 MRIvox(mri_dst,y1,y2,y3) = (BUFTYPE)nint(val) ;
9126 }
9127 }
9128 }
9129 }
9130
9131 MatrixFree(&v_X) ;
9132 MatrixFree(&mAinv) ;
9133 MatrixFree(&v_Y) ;
9134
9135 mri_dst->ras_good_flag = 0;
9136
9137 return(mri_dst) ;
9138 }
9139 /*-----------------------------------------------------------------
9140 MRIlinearTransform() - for historical reasons, this uses trilinear
9141 interpolation. This the operations under this function name can
9142 now (2/20/02) be found under MRIlinearTransformInterp().
9143 -----------------------------------------------------------------*/
9144 MRI *
9145 MRIlinearTransform(MRI *mri_src, MRI *mri_dst, MATRIX *mA)
9146 {
9147 mri_dst = MRIlinearTransformInterp(mri_src, mri_dst, mA, SAMPLE_TRILINEAR);
9148 return(mri_dst);
9149 }
9150 /*-------------------------------------------------------------------
9151 MRIlinearTransformInterp() Perform linear coordinate transformation
9152 x' = Ax on the MRI image mri_src into mri_dst using the specified
9153 interpolation method. A is a voxel-to-voxel transform.
9154 ------------------------------------------------------------------*/
9155 MRI *
9156 MRIlinearTransformInterp(MRI *mri_src, MRI *mri_dst, MATRIX *mA,
9157 int InterpMethod)
9158 {
9159 int y1, y2, y3, width, height, depth ;
9160 VECTOR *v_X, *v_Y ; /* original and transformed coordinate systems */
9161 MATRIX *mAinv ; /* inverse of mA */
9162 Real val, x1, x2, x3 ;
9163
9164 if(InterpMethod != SAMPLE_NEAREST &&
9165 InterpMethod != SAMPLE_TRILINEAR &&
9166 InterpMethod != SAMPLE_CUBIC &&
9167 InterpMethod != SAMPLE_SINC ){
9168 printf("ERROR: MRIlinearTransformInterp: unrecoginzed interpolation "
9169 "method %d\n",InterpMethod);
9170 }
9171
9172 mAinv = MatrixInverse(mA, NULL) ; /* will sample from dst back to src */
9173 if (!mAinv)
9174 ErrorReturn(NULL, (ERROR_BADPARM,
9175 "MRIlinearTransform: xform is singular")) ;
9176
9177 if (!mri_dst)
9178 mri_dst = MRIclone(mri_src, NULL) ;
9179 else
9180 MRIclear(mri_dst) ;
9181
9182 width = mri_dst->width ; height = mri_dst->height ; depth = mri_dst->depth ;
9183 v_X = VectorAlloc(4, MATRIX_REAL) ; /* input (src) coordinates */
9184 v_Y = VectorAlloc(4, MATRIX_REAL) ; /* transformed (dst) coordinates */
9185
9186 if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
9187 printf("MRIlinearTransformInterp: Applying transform\n");
9188
9189 v_Y->rptr[4][1] = 1.0f ;
9190 for (y3 = 0 ; y3 < depth ; y3++)
9191 {
9192 V3_Z(v_Y) = y3 ;
9193 for (y2 = 0 ; y2 < height ; y2++)
9194 {
9195 V3_Y(v_Y) = y2 ;
9196 for (y1 = 0 ; y1 < width ; y1++)
9197 {
9198 V3_X(v_Y) = y1 ;
9199 MatrixMultiply(mAinv, v_Y, v_X) ;
9200
9201 x1 = V3_X(v_X) ; x2 = V3_Y(v_X) ; x3 = V3_Z(v_X) ;
9202
9203 if (nint(y1) == 13 && nint(y2) == 10 && nint(y3) == 7)
9204 DiagBreak() ;
9205 if (nint(x1) == Gx && nint(x2) == Gy && nint(x3) == Gz)
9206 {
9207 #if 0
9208 fprintf
9209 (stderr,
9210 "(%2.1f, %2.1f, %2.1f) --> (%2.1f, %2.1f, %2.1f)\n",
9211 (float)x1, (float)x2, (float)x3,
9212 (float)y1, (float)y2, (float)y3) ;
9213 #endif
9214 DiagBreak() ;
9215 }
9216
9217 //MRIsampleVolume(mri_src, x1, x2, x3, &val);
9218 MRIsampleVolumeType(mri_src, x1, x2, x3, &val, InterpMethod);
9219 switch (mri_dst->type)
9220 {
9221 case MRI_UCHAR:
9222 MRIvox(mri_dst,y1,y2,y3) = (BUFTYPE)nint(val) ;
9223 break ;
9224 case MRI_SHORT:
9225 MRISvox(mri_dst,y1,y2,y3) = (short)nint(val) ;
9226 break ;
9227 case MRI_FLOAT:
9228 MRIFvox(mri_dst,y1,y2,y3) = (float)(val) ;
9229 break ;
9230 case MRI_INT:
9231 MRIIvox(mri_dst,y1,y2,y3) = nint(val) ;
9232 break ;
9233 default:
9234 ErrorReturn(NULL,
9235 (ERROR_UNSUPPORTED,
9236 "MRIlinearTransform: unsupported dst type %d",
9237 mri_dst->type)) ;
9238 break ;
9239 }
9240 }
9241 }
9242 }
9243
9244 MatrixFree(&v_X) ;
9245 MatrixFree(&mAinv) ;
9246 MatrixFree(&v_Y) ;
9247
9248 mri_dst->ras_good_flag = 1;
9249
9250 if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
9251 {
9252 printf("MRIlinearTransform: done\n");
9253 printf("mri_dst:\n");
9254 printf(" vox res: %g %g %g\n",
9255 mri_dst->xsize,mri_dst->ysize,mri_dst->zsize);
9256 printf(" vox dim: %d %d %d\n",
9257 mri_dst->width,mri_dst->height,mri_dst->depth);
9258 }
9259
9260 return(mri_dst) ;
9261 }
9262 MRI *
9263 MRIconcatenateFrames(MRI *mri_frame1, MRI *mri_frame2, MRI *mri_dst)
9264 {
9265 int width, height, depth, x, y, z ;
9266 BUFTYPE *pf1, *pf2, *pdst1, *pdst2 ;
9267
9268 if (mri_frame1->type != MRI_UCHAR || mri_frame1->type != MRI_UCHAR)
9269 ErrorReturn(NULL,
9270 (ERROR_UNSUPPORTED,"MRIconcatenateFrames: src must be UCHAR"));
9271
9272 width = mri_frame1->width ;
9273 height = mri_frame1->height ;
9274 depth = mri_frame1->depth ;
9275 if (mri_dst == NULL)
9276 {
9277 mri_dst = MRIallocSequence(width, height, depth, mri_frame1->type, 2) ;
9278 MRIcopyHeader(mri_frame1, mri_dst) ;
9279 }
9280 if (!mri_dst)
9281 ErrorExit(ERROR_NOMEMORY, "MRIconcatenateFrames: could not alloc dst") ;
9282
9283
9284 for (z = 0 ; z < depth ; z++)
9285 {
9286 for (y = 0 ; y < height ; y++)
9287 {
9288 pdst1 = &MRIvox(mri_dst, 0, y, z) ;
9289 pdst2 = &MRIseq_vox(mri_dst, 0, y, z, 1) ;
9290 pf1 = &MRIvox(mri_frame1, 0, y, z) ;
9291 pf2 = &MRIvox(mri_frame2, 0, y, z) ;
9292 for (x = 0 ; x < width ; x++)
9293 {
9294 *pdst1++ = *pf1++ ;
9295 *pdst2++ = *pf2++ ;
9296 }
9297 }
9298 }
9299 return(mri_dst) ;
9300 }
9301 /*-----------------------------------------------------
9302 ------------------------------------------------------*/
9303 MRI *
9304 MRIcopyFrame(MRI *mri_src, MRI *mri_dst, int src_frame, int dst_frame)
9305 {
9306 int width, height, depth, y, z, bytes ;
9307 BUFTYPE *psrc, *pdst ;
9308
9309 width = mri_src->width ;
9310 height = mri_src->height ;
9311 depth = mri_src->depth ;
9312
9313 if (!mri_dst)
9314 mri_dst =
9315 MRIallocSequence(width, height, depth, mri_src->type, dst_frame+1) ;
9316 if (!mri_dst)
9317 ErrorExit(ERROR_NOMEMORY, "MRIcopyFrame: could not alloc dst") ;
9318
9319 if (mri_src->type != mri_dst->type)
9320 ErrorReturn(NULL,(ERROR_UNSUPPORTED,
9321 "MRIcopyFrame: src and dst must be same type"));
9322 if (dst_frame >= mri_dst->nframes)
9323 ErrorReturn
9324 (NULL,
9325 (ERROR_BADPARM,
9326 "MRIcopyFrame: dst frame #%d out of range (nframes=%d)\n",
9327 dst_frame, mri_dst->nframes)) ;
9328 MRIcopyHeader(mri_src, mri_dst) ;
9329
9330 switch (mri_src->type)
9331 {
9332 case MRI_UCHAR:
9333 bytes = sizeof(unsigned char) ;
9334 break ;
9335 case MRI_SHORT:
9336 bytes = sizeof(short) ;
9337 break ;
9338 case MRI_INT:
9339 bytes = sizeof(int) ;
9340 break ;
9341 case MRI_FLOAT:
9342 bytes = sizeof(float) ;
9343 break ;
9344 default:
9345 ErrorReturn(NULL, (ERROR_BADPARM,
9346 "MRIcopyFrame: unsupported src format %d",
9347 mri_src->type));
9348 break ;
9349 }
9350 bytes *= width ;
9351 for (z = 0 ; z < depth ; z++)
9352 {
9353 for (y = 0 ; y < height ; y++)
9354 {
9355 switch (mri_src->type)
9356 {
9357 default: /* already handled above */
9358 case MRI_UCHAR:
9359 psrc = &MRIseq_vox(mri_src, 0, y, z, src_frame) ;
9360 pdst = &MRIseq_vox(mri_dst, 0, y, z, dst_frame) ;
9361 break ;
9362 case MRI_SHORT:
9363 psrc = (BUFTYPE *)&MRISseq_vox(mri_src, 0, y, z, src_frame) ;
9364 pdst = (BUFTYPE *)&MRISseq_vox(mri_dst, 0, y, z, dst_frame) ;
9365 break ;
9366 case MRI_INT:
9367 psrc = (BUFTYPE *)&MRIIseq_vox(mri_src, 0, y, z, src_frame) ;
9368 pdst = (BUFTYPE *)&MRIIseq_vox(mri_dst, 0, y, z, dst_frame) ;
9369 break ;
9370 case MRI_FLOAT:
9371 psrc = (BUFTYPE *)&MRIFseq_vox(mri_src, 0, y, z, src_frame) ;
9372 pdst = (BUFTYPE *)&MRIFseq_vox(mri_dst, 0, y, z, dst_frame) ;
9373 break ;
9374 }
9375 memmove(pdst, psrc, bytes) ;
9376 }
9377 }
9378 return(mri_dst) ;
9379 }
9380 /*-----------------------------------------------------
9381 Parameters:
9382
9383 Returns value:
9384
9385 Description
9386 ------------------------------------------------------*/
9387 double
9388 MRImeanFrame(MRI *mri, int frame)
9389 {
9390 int width, height, depth, x, y, z ;
9391 double mean ;
9392 Real val ;
9393
9394 width = mri->width ;
9395 height = mri->height ;
9396 depth = mri->depth ;
9397 if (mri->nframes <= frame)
9398 ErrorReturn(0.0,(ERROR_BADPARM,
9399 "MRImeanFrame: frame %d out of bounds (%d)",
9400 frame, mri->nframes));
9401
9402 for (mean = 0.0, z = 0 ; z < depth ; z++)
9403 {
9404 for (y = 0 ; y < height ; y++)
9405 {
9406 for (x = 0 ; x < width ; x++)
9407 {
9408 MRIsampleVolumeType(mri, x, y, z, &val, SAMPLE_NEAREST) ;
9409 mean += (double)val ;
9410 }
9411 }
9412 }
9413 mean /= (double)(width*height*depth) ;
9414 return(mean) ;
9415 }
9416
9417 #ifndef UCHAR_MIN
9418 #define UCHAR_MIN 0.0
9419 #endif
9420 #ifndef UCHAR_MAX
9421 #define UCHAR_MAX 255.0
9422 #endif
9423 #ifndef SHORT_MIN
9424 #define SHORT_MIN -32768.0
9425 #endif
9426 #ifndef SHORT_MAX
9427 #define SHORT_MAX 32767.0
9428 #endif
9429 #ifndef INT_MIN
9430 #define INT_MIN -2147483648.0
9431 #endif
9432 #ifndef INT_MAX
9433 #define INT_MAX 2147483647.0
9434 #endif
9435 #ifndef LONG_MIN
9436 #define LONG_MIN -2147483648.0
9437 #endif
9438 #ifndef LONG_MAX
9439 #define LONG_MAX 2147483647.0
9440 #endif
9441
9442 #define N_HIST_BINS 1000
9443
9444 /*--------------------------------------------------------------
9445 MRISeqchangeType() - changes the data type for a 3D or 4D volume.
9446 This simply changes the volume dimensions so that it appears to be a
9447 3D volume, then calls MRIchangeType(), and then resets the
9448 dimensions to their original values. The values of the volume can be
9449 rescaled between f_low and f_high.
9450 ------------------------------------------------------------*/
9451 MRI *MRISeqchangeType(MRI *vol, int dest_type, float f_low,
9452 float f_high, int no_scale_option_flag)
9453 {
9454 int nslices, nframes;
9455 MRI *mri;
9456
9457 /* Change vol dimensions to make it look like a single frame */
9458 nslices = vol->depth;
9459 nframes = vol->nframes;
9460 vol->depth = nslices*nframes;
9461 vol->nframes = 1;
9462
9463 /* Change the type */
9464 mri = MRIchangeType(vol,dest_type,f_low,f_high,no_scale_option_flag);
9465
9466 /* Change vol dimensions back to original */
9467 vol->depth = nslices;
9468 vol->nframes = nframes;
9469
9470 /* Check for error */
9471 if(mri == NULL) {
9472 fprintf(stderr,"ERROR: MRISeqchangeType: MRIchangeType\n");
9473 return(NULL);
9474 }
9475
9476 /* Change mri dimensions back to original */
9477 mri->depth = nslices;
9478 mri->nframes = nframes;
9479
9480 return(mri);
9481 }
9482 /*-----------------------------------------------------------
9483 MRIchangeType() - changes the data type of a 3D MRI volume,
9484 with optional rescaling. Use MRISeqchangeType() for 3D or
9485 4D volumes.
9486 ---------------------------------------------------------*/
9487 MRI *MRIchangeType(MRI *src, int dest_type, float f_low,
9488 float f_high, int no_scale_option_flag)
9489 {
9490
9491 MRI *dest = NULL;
9492 int i, j, k;
9493 float val;
9494 int no_scale_flag = FALSE;
9495 float scale, dest_min, dest_max; /* new = scale * (val - min) */
9496 float src_min, src_max;
9497 int hist_bins[N_HIST_BINS];
9498 float bin_size;
9499 int bin;
9500 int nth, n_passed;
9501
9502 /* ----- shut the compiler up ----- */
9503 val = 0.0;
9504 dest_min = dest_max = 0.0;
9505
9506 if(src->type == dest_type)
9507 {
9508 dest = MRIcopy(src, NULL);
9509 return(dest);
9510 }
9511
9512 if(src->type == MRI_UCHAR &&
9513 (dest_type == MRI_SHORT ||
9514 dest_type == MRI_INT ||
9515 dest_type == MRI_LONG ||
9516 dest_type == MRI_FLOAT))
9517 no_scale_flag = TRUE;
9518 else if(src->type == MRI_SHORT &&
9519 (dest_type == MRI_INT ||
9520 dest_type == MRI_LONG ||
9521 dest_type == MRI_FLOAT))
9522 no_scale_flag = TRUE;
9523 else if(src->type == MRI_LONG &&
9524 (dest_type == MRI_INT ||
9525 dest_type == MRI_FLOAT))
9526 no_scale_flag = TRUE;
9527 else if(src->type == MRI_INT &&
9528 (dest_type == MRI_LONG ||
9529 dest_type == MRI_FLOAT))
9530 no_scale_flag = TRUE;
9531 else
9532 {
9533 MRIlimits(src, &src_min, &src_max);
9534
9535 if(no_scale_option_flag)
9536 {
9537 if(dest_type == MRI_UCHAR &&
9538 src_min >= UCHAR_MIN &&
9539 src_max <= UCHAR_MAX)
9540 no_scale_flag = TRUE;
9541 if(dest_type == MRI_SHORT &&
9542 src_min >= SHORT_MIN &&
9543 src_max <= SHORT_MAX)
9544 no_scale_flag = TRUE;
9545 if(dest_type == MRI_INT &&
9546 src_min >= INT_MIN &&
9547 src_max <= INT_MAX)
9548 no_scale_flag = TRUE;
9549 if(dest_type == MRI_LONG &&
9550 src_min >= LONG_MIN &&
9551 src_max <= LONG_MAX)
9552 no_scale_flag = TRUE;
9553 }
9554 }
9555
9556 if(no_scale_flag)
9557 {
9558
9559 dest = MRIalloc(src->width, src->height, src->depth, dest_type);
9560 MRIcopyHeader(src, dest);
9561 dest->type = dest_type;
9562
9563 for(k = 0;k < src->depth;k++)
9564 for(j = 0;j < src->height;j++)
9565 for(i = 0;i < src->width;i++)
9566 {
9567
9568 if(src->type == MRI_UCHAR)
9569 val = (float)MRIvox(src, i, j, k);
9570 if(src->type == MRI_SHORT)
9571 val = (float)MRISvox(src, i, j, k);
9572 if(src->type == MRI_INT)
9573 val = (float)MRIIvox(src, i, j, k);
9574 if(src->type == MRI_LONG)
9575 val = (float)MRILvox(src, i, j, k);
9576 if(src->type == MRI_FLOAT)
9577 val = (float)MRIFvox(src, i, j, k);
9578
9579 if(dest_type == MRI_UCHAR)
9580 MRIvox(dest, i, j, k) = (unsigned char)val;
9581 if(dest_type == MRI_SHORT)
9582 MRISvox(dest, i, j, k) = (short)val;
9583 if(dest_type == MRI_INT)
9584 MRIIvox(dest, i, j, k) = (int)val;
9585 if(dest_type == MRI_LONG)
9586 MRILvox(dest, i, j, k) = (long)val;
9587 if(dest_type == MRI_FLOAT)
9588 MRIFvox(dest, i, j, k) = (float)val;
9589 }
9590 }
9591 else
9592 {
9593 long nonzero = 0 ;
9594
9595 /* ----- build a histogram ----- */
9596 printf("MRIchangeType: Building histogram \n");
9597 bin_size = (src_max - src_min) / (float)N_HIST_BINS;
9598
9599 for(i = 0;i < N_HIST_BINS;i++)
9600 hist_bins[i] = 0;
9601
9602 for(i = 0;i < src->width;i++)
9603 for(j = 0;j < src->height;j++)
9604 for(k = 0;k < src->depth;k++)
9605 {
9606
9607 if(src->type == MRI_UCHAR)
9608 val = (float)MRIvox(src, i, j, k);
9609 if(src->type == MRI_SHORT)
9610 val = (float)MRISvox(src, i, j, k);
9611 if(src->type == MRI_INT)
9612 val = (float)MRIIvox(src, i, j, k);
9613 if(src->type == MRI_LONG)
9614 val = (float)MRILvox(src, i, j, k);
9615 if(src->type == MRI_FLOAT)
9616 val = (float)MRIFvox(src, i, j, k);
9617
9618 if (!DZERO(val))
9619 nonzero++ ;
9620 bin = (int)((val - src_min) / bin_size);
9621
9622 if(bin < 0)
9623 bin = 0;
9624 if(bin >= N_HIST_BINS)
9625 bin = N_HIST_BINS-1;
9626
9627 hist_bins[bin]++;
9628
9629 }
9630
9631 nth = (int)(f_low * src->width * src->height * src->depth);
9632 for(n_passed = 0,bin = 0;n_passed < nth && bin < N_HIST_BINS;bin++)
9633 n_passed += hist_bins[bin];
9634 src_min = (float)bin * bin_size + src_min;
9635
9636 #if 1 // handle mostly empty volumes
9637 nth = (int)((1.0-f_high) * nonzero);
9638 #else
9639 nth = (int)((1.0-f_high) * src->width * src->height * src->depth);
9640 #endif
9641 for(n_passed = 0,bin = N_HIST_BINS-1;n_passed < nth && bin > 0;bin--)
9642 n_passed += hist_bins[bin];
9643 src_max = (float)bin * bin_size + src_min;
9644
9645 if(src_min >= src_max)
9646 {
9647 ErrorReturn
9648 (NULL,
9649 (ERROR_BADPARM,
9650 "MRIchangeType(): after hist: src_min = %g, "
9651 "src_max = %g (f_low = %g, f_high = %g)",
9652 src_min, src_max, f_low, f_high));
9653 }
9654
9655 /* ----- continue ----- */
9656
9657 if(dest_type == MRI_UCHAR)
9658 {
9659 dest_min = UCHAR_MIN;
9660 dest_max = UCHAR_MAX;
9661 }
9662 if(dest_type == MRI_SHORT)
9663 {
9664 dest_min = SHORT_MIN;
9665 dest_max = SHORT_MAX;
9666 }
9667 if(dest_type == MRI_INT)
9668 {
9669 dest_min = INT_MIN;
9670 dest_max = INT_MAX;
9671 }
9672 if(dest_type == MRI_LONG)
9673 {
9674 dest_min = LONG_MIN;
9675 dest_max = LONG_MAX;
9676 }
9677
9678 scale = (dest_max - dest_min) / (src_max - src_min);
9679
9680 dest = MRIalloc(src->width, src->height, src->depth, dest_type);
9681 MRIcopyHeader(src, dest);
9682 dest->type = dest_type;
9683
9684 for(i = 0;i < src->width;i++)
9685 for(j = 0;j < src->height;j++)
9686 for(k = 0;k < src->depth;k++)
9687 {
9688
9689 if(src->type == MRI_SHORT)
9690 val = MRISvox(src, i, j, k);
9691 if(src->type == MRI_INT)
9692 val = MRIIvox(src, i, j, k);
9693 if(src->type == MRI_LONG)
9694 val = MRILvox(src, i, j, k);
9695 if(src->type == MRI_FLOAT)
9696 val = MRIFvox(src, i, j, k);
9697
9698 val = dest_min + scale * (val - src_min);
9699
9700 if(dest->type == MRI_UCHAR)
9701 {
9702 if(val < UCHAR_MIN)
9703 val = UCHAR_MIN;
9704 if(val > UCHAR_MAX)
9705 val = UCHAR_MAX;
9706 MRIvox(dest, i, j, k) = (unsigned char)val;
9707 }
9708 if(dest->type == MRI_SHORT)
9709 {
9710 if(val < SHORT_MIN)
9711 val = SHORT_MIN;
9712 if(val > SHORT_MAX)
9713 val = SHORT_MAX;
9714 MRISvox(dest, i, j, k) = (short)val;
9715 }
9716 if(dest->type == MRI_INT)
9717 {
9718 if(val < INT_MIN)
9719 val = INT_MIN;
9720 if(val > INT_MAX)
9721 val = INT_MAX;
9722 MRIIvox(dest, i, j, k) = (int)val;
9723 }
9724 if(dest->type == MRI_LONG)
9725 {
9726 if(val < LONG_MIN)
9727 val = LONG_MIN;
9728 if(val > LONG_MAX)
9729 val = LONG_MAX;
9730 MRILvox(dest, i, j, k) = (long)val;
9731 }
9732
9733 }
9734
9735 }
9736
9737 return(dest);
9738
9739 } /* end MRIchangeType() */
9740
9741 /*-----------------------------------------------------*/
9742 MATRIX *MRIgetResampleMatrix(MRI *src, MRI *template_vol)
9743 {
9744
9745 MATRIX *src_mat, *dest_mat; /* from i to ras */
9746 float src_det, dest_det;
9747 MATRIX *src_inv, *m;
9748
9749 /* ----- fake the ras values if ras_good_flag is not set ----- */
9750 int src_slice_direction = getSliceDirection(src);
9751 if(!src->ras_good_flag
9752 && (src_slice_direction != MRI_CORONAL)
9753 && (src_slice_direction != MRI_SAGITTAL)
9754 && (src_slice_direction != MRI_HORIZONTAL))
9755 {
9756 ErrorReturn
9757 (NULL,
9758 (ERROR_BADPARM,
9759 "MRIresample(): source volume orientation is unknown"));
9760 }
9761
9762 /*
9763
9764 : solve each row of src_mat * [midx;midy;midz;1] = centerr, centera, centers
9765 and for dest
9766
9767 S = M * s_v
9768
9769 where M = [(x_r y_r z_r)(xsize 0 0 ) s14]
9770 s_v = (center_x) S = (c_r) etc.
9771 [(x_a y_a z_a)( 0 ysize 0 ) s24] (center_y) (c_a)
9772 [(x_s y_s z_s)( 0 0 zsize) s34] (center_z) (c_s)
9773 [ 0 0 0 1 ] ( 1 ) ( 1 )
9774
9775 Write M = [ m s], s_v = (c_v), S = (c_R), then c_R = m * c_v + s or
9776 [ 0 0 0 1] ( 1 ) ( 1 )
9777
9778 The translation s is given by s = c_R - m*c_v
9779
9780 Note the convention c_(r,a,s) being defined in
9781 terms of c_v = (width/2., height/2, depth/2.),
9782 not ((width-1)/2, (height-1)/2, (depth-1)/2).
9783
9784 */
9785
9786 src_mat = extract_i_to_r(src); // error when allocation fails
9787 if(src_mat == NULL)
9788 return NULL; // did ErrorPrintf in extract_i_to_r()
9789
9790 dest_mat = extract_i_to_r(template_vol); // error when allocation fails
9791 if(dest_mat == NULL)
9792 {
9793 MatrixFree(&src_mat);
9794 return NULL; // did ErrorPrintf in extract_i_to_r()
9795 }
9796
9797 // error check
9798 src_det = MatrixDeterminant(src_mat);
9799 dest_det = MatrixDeterminant(dest_mat);
9800
9801 if(src_det == 0.0)
9802 {
9803 errno = 0;
9804 ErrorPrintf
9805 (ERROR_BADPARM,
9806 "MRIresample(): source matrix has zero determinant; matrix is:");
9807 MatrixPrint(stderr, src_mat);
9808 MatrixFree(&src_mat);
9809 MatrixFree(&dest_mat);
9810 return(NULL);
9811 }
9812
9813 if(dest_det == 0.0)
9814 {
9815 errno = 0;
9816 ErrorPrintf
9817 (ERROR_BADPARM,
9818 "MRIresample(): destination matrix has zero determinant; matrix is:");
9819 MatrixPrint(stderr, dest_mat);
9820 MatrixFree(&src_mat);
9821 MatrixFree(&dest_mat);
9822 return(NULL);
9823 }
9824
9825 src_inv = MatrixInverse(src_mat, NULL);
9826
9827 if(src_inv == NULL)
9828 {
9829 errno = 0;
9830 ErrorPrintf
9831 (ERROR_BADPARM,
9832 "MRIresample(): error inverting matrix; determinant is "
9833 "%g, matrix is:", src_det);
9834 MatrixPrint(stderr, src_mat);
9835 MatrixFree(&src_mat);
9836 MatrixFree(&dest_mat);
9837 return(NULL);
9838 }
9839
9840 m = MatrixMultiply(src_inv, dest_mat, NULL);
9841 if(m == NULL)
9842 return(NULL);
9843
9844 MatrixFree(&src_inv);
9845 MatrixFree(&src_mat);
9846 MatrixFree(&dest_mat);
9847
9848 if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
9849 {
9850 printf("MRIresample() matrix is:\n");
9851 MatrixPrint(stdout, m);
9852 }
9853 return(m) ;
9854
9855 } /* end MRIreslice() */
9856
9857
9858 MRI *
9859 MRIresample(MRI *src, MRI *template_vol, int resample_type)
9860 {
9861 return(MRIresampleFill(src, template_vol, resample_type, 0)) ;
9862 } /* end MRIresample() */
9863
9864
9865 MRI *MRIresampleFill
9866 (MRI *src, MRI *template_vol, int resample_type, float fill_val)
9867 {
9868
9869 MRI *dest = NULL;
9870 MATRIX *m;
9871 int di, dj, dk;
9872 int si, sj, sk;
9873 float si_f, sj_f, sk_f;
9874 float si_ff, sj_ff, sk_ff;
9875 MATRIX *sp, *dp;
9876 float val, val000, val001, val010, val011, val100, val101, val110, val111;
9877 float w000, w001, w010, w011, w100, w101, w110, w111;
9878 float si_f2, sj_f2, sk_f2;
9879 float ii2, ij2, ik2, isi_f2, isj_f2, isk_f2;
9880 float w[8];
9881 int wi[8];
9882 int mwi;
9883 Real pval;
9884 int i_good_flag, i1_good_flag;
9885 int j_good_flag, j1_good_flag;
9886 int k_good_flag, k1_good_flag;
9887
9888 /* ----- keep the compiler quiet ----- */
9889 val = 0.0;
9890 val000 = val001 = val010 = val011 = val100 = val101 = val110 = val111 = 0.0;
9891
9892 #if 0
9893 if(src->type != template_vol->type)
9894 {
9895 ErrorReturn
9896 (NULL,
9897 (ERROR_UNSUPPORTED,
9898 "MRIresample(): source and destination types must be identical"));
9899 }
9900 #endif
9901
9902 /* ----- fake the ras values if ras_good_flag is not set ----- */
9903 if(!src->ras_good_flag)
9904 printf
9905 ("MRIresample(): WARNING: ras_good_flag "
9906 "is not set, changing orientation\n"
9907 "to default.\n");
9908
9909 // get dst voxel -> src voxel transform
9910 m = MRIgetResampleMatrix(src, template_vol);
9911 if(m == NULL)
9912 return(NULL);
9913
9914 if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
9915 {
9916 printf("MRIresample() matrix is:\n");
9917 MatrixPrint(stdout, m);
9918 }
9919
9920 dest = MRIalloc(template_vol->width,
9921 template_vol->height,
9922 template_vol->depth,
9923 src->type);
9924 if(dest == NULL)
9925 return(NULL);
9926 MRIreplaceValues(dest, dest, 0.0f, fill_val) ;
9927
9928 MRIcopyHeader(template_vol, dest);
9929 MRIcopyPulseParameters(src, dest) ;
9930
9931 sp = MatrixAlloc(4, 1, MATRIX_REAL);
9932 dp = MatrixAlloc(4, 1, MATRIX_REAL);
9933
9934 *MATRIX_RELT(dp, 4, 1) = 1.0;
9935
9936 for(di = 0;di < template_vol->width;di++)
9937 {
9938 for(dj = 0;dj < template_vol->height;dj++)
9939 {
9940 for(dk = 0;dk < template_vol->depth;dk++)
9941 {
9942
9943 *MATRIX_RELT(dp, 1, 1) = (float)di;
9944 *MATRIX_RELT(dp, 2, 1) = (float)dj;
9945 *MATRIX_RELT(dp, 3, 1) = (float)dk;
9946
9947 MatrixMultiply(m, dp, sp);
9948
9949 si_ff = *MATRIX_RELT(sp, 1, 1);
9950 sj_ff = *MATRIX_RELT(sp, 2, 1);
9951 sk_ff = *MATRIX_RELT(sp, 3, 1);
9952
9953 si = (int)floor(si_ff);
9954 sj = (int)floor(sj_ff);
9955 sk = (int)floor(sk_ff);
9956
9957 if (si == 147 && sj == 91 && sk == 86)
9958 DiagBreak() ;
9959 if (di == 129 && dj == 164 && dk == 147)
9960 DiagBreak() ;
9961 si_f = si_ff - si;
9962 sj_f = sj_ff - sj;
9963 sk_f = sk_ff - sk;
9964
9965 #if 0
9966 if(di % 20 == 0 && dj == di && dk == dj)
9967 {
9968 printf("MRIresample() sample point: %3d %3d %3d: "
9969 "%f (%3d + %f) %f (%3d + %f) %f (%3d + %f)\n",
9970 di, dj, dk,
9971 si_ff, si, si_f,
9972 sj_ff, sj, sj_f,
9973 sk_ff, sk, sk_f);
9974 }
9975 #endif
9976
9977 if(resample_type == SAMPLE_SINC)
9978 {
9979 MRIsincSampleVolume(src, si_ff, sj_ff, sk_ff, 5, &pval);
9980 val = (float)pval;
9981 }
9982 else if(resample_type == SAMPLE_CUBIC)
9983 {
9984 MRIcubicSampleVolume(src, si_ff, sj_ff, sk_ff, &pval);
9985 val = (float)pval;
9986 }
9987 else
9988 {
9989 i_good_flag = (si >= 0 && si < src->width);
9990 i1_good_flag = (si+1 >= 0 && si+1 < src->width);
9991 j_good_flag = (sj >= 0 && sj < src->height);
9992 j1_good_flag = (sj+1 >= 0 && sj+1 < src->height);
9993 k_good_flag = (sk >= 0 && sk < src->depth);
9994 k1_good_flag = (sk+1 >= 0 && sk+1 < src->depth);
9995
9996 if(src->type == MRI_UCHAR)
9997 {
9998 val000 = ( !i_good_flag ||
9999 !j_good_flag ||
10000 !k_good_flag ? 0.0 :
10001 (float)MRIvox(src, si , sj , sk ));
10002 val001 = ( !i_good_flag ||
10003 !j_good_flag ||
10004 !k1_good_flag ? 0.0 :
10005 (float)MRIvox(src, si , sj , sk + 1));
10006 val010 = ( !i_good_flag ||
10007 !j1_good_flag ||
10008 !k_good_flag ? 0.0 :
10009 (float)MRIvox(src, si , sj + 1, sk ));
10010 val011 = ( !i_good_flag ||
10011 !j1_good_flag ||
10012 !k1_good_flag ? 0.0 :
10013 (float)MRIvox(src, si , sj + 1, sk + 1));
10014 val100 = (!i1_good_flag ||
10015 !j_good_flag ||
10016 !k_good_flag ? 0.0 :
10017 (float)MRIvox(src, si + 1, sj , sk ));
10018 val101 = (!i1_good_flag ||
10019 !j_good_flag ||
10020 !k1_good_flag ? 0.0 :
10021 (float)MRIvox(src, si + 1, sj , sk + 1));
10022 val110 = (!i1_good_flag ||
10023 !j1_good_flag ||
10024 !k_good_flag ? 0.0 :
10025 (float)MRIvox(src, si + 1, sj + 1, sk ));
10026 val111 = (!i1_good_flag ||
10027 !j1_good_flag ||
10028 !k1_good_flag ? 0.0 :
10029 (float)MRIvox(src, si + 1, sj + 1, sk + 1));
10030 }
10031
10032 if (si == 154 && sj == 134 && sk == 136)
10033 DiagBreak() ;
10034
10035 if(src->type == MRI_SHORT)
10036 {
10037 val000 = ( !i_good_flag ||
10038 !j_good_flag ||
10039 !k_good_flag ? 0.0 :
10040 (float)MRISvox(src, si , sj , sk ));
10041 val001 = ( !i_good_flag ||
10042 !j_good_flag ||
10043 !k1_good_flag ? 0.0 :
10044 (float)MRISvox(src, si , sj , sk + 1));
10045 val010 = ( !i_good_flag ||
10046 !j1_good_flag ||
10047 !k_good_flag ? 0.0 :
10048 (float)MRISvox(src, si , sj + 1, sk ));
10049 val011 = ( !i_good_flag ||
10050 !j1_good_flag ||
10051 !k1_good_flag ? 0.0 :
10052 (float)MRISvox(src, si , sj + 1, sk + 1));
10053 val100 = (!i1_good_flag ||
10054 !j_good_flag ||
10055 !k_good_flag ? 0.0 :
10056 (float)MRISvox(src, si + 1, sj , sk ));
10057 val101 = (!i1_good_flag ||
10058 !j_good_flag ||
10059 !k1_good_flag ? 0.0 :
10060 (float)MRISvox(src, si + 1, sj , sk + 1));
10061 val110 = (!i1_good_flag ||
10062 !j1_good_flag ||
10063 !k_good_flag ? 0.0 :
10064 (float)MRISvox(src, si + 1, sj + 1, sk ));
10065 val111 = (!i1_good_flag ||
10066 !j1_good_flag ||
10067 !k1_good_flag ? 0.0 :
10068 (float)MRISvox(src, si + 1, sj + 1, sk + 1));
10069 }
10070
10071 if(src->type == MRI_INT)
10072 {
10073 val000 = ( !i_good_flag ||
10074 !j_good_flag ||
10075 !k_good_flag ? 0.0 :
10076 (float)MRIIvox(src, si , sj , sk ));
10077 val001 = ( !i_good_flag ||
10078 !j_good_flag ||
10079 !k1_good_flag ? 0.0 :
10080 (float)MRIIvox(src, si , sj , sk + 1));
10081 val010 = ( !i_good_flag ||
10082 !j1_good_flag ||
10083 !k_good_flag ? 0.0 :
10084 (float)MRIIvox(src, si , sj + 1, sk ));
10085 val011 = ( !i_good_flag ||
10086 !j1_good_flag ||
10087 !k1_good_flag ? 0.0 :
10088 (float)MRIIvox(src, si , sj + 1, sk + 1));
10089 val100 = (!i1_good_flag ||
10090 !j_good_flag ||
10091 !k_good_flag ? 0.0 :
10092 (float)MRIIvox(src, si + 1, sj , sk ));
10093 val101 = (!i1_good_flag ||
10094 !j_good_flag ||
10095 !k1_good_flag ? 0.0 :
10096 (float)MRIIvox(src, si + 1, sj , sk + 1));
10097 val110 = (!i1_good_flag ||
10098 !j1_good_flag ||
10099 !k_good_flag ? 0.0 :
10100 (float)MRIIvox(src, si + 1, sj + 1, sk ));
10101 val111 = (!i1_good_flag ||
10102 !j1_good_flag ||
10103 !k1_good_flag ? 0.0 :
10104 (float)MRIIvox(src, si + 1, sj + 1, sk + 1));
10105 }
10106
10107 if(src->type == MRI_LONG)
10108 {
10109 val000 = ( !i_good_flag ||
10110 !j_good_flag ||
10111 !k_good_flag ? 0.0 :
10112 (float)MRILvox(src, si , sj , sk ));
10113 val001 = ( !i_good_flag ||
10114 !j_good_flag ||
10115 !k1_good_flag ? 0.0 :
10116 (float)MRILvox(src, si , sj , sk + 1));
10117 val010 = ( !i_good_flag ||
10118 !j1_good_flag ||
10119 !k_good_flag ? 0.0 :
10120 (float)MRILvox(src, si , sj + 1, sk ));
10121 val011 = ( !i_good_flag ||
10122 !j1_good_flag ||
10123 !k1_good_flag ? 0.0 :
10124 (float)MRILvox(src, si , sj + 1, sk + 1));
10125 val100 = (!i1_good_flag ||
10126 !j_good_flag ||
10127 !k_good_flag ? 0.0 :
10128 (float)MRILvox(src, si + 1, sj , sk ));
10129 val101 = (!i1_good_flag ||
10130 !j_good_flag ||
10131 !k1_good_flag ? 0.0 :
10132 (float)MRILvox(src, si + 1, sj , sk + 1));
10133 val110 = (!i1_good_flag ||
10134 !j1_good_flag ||
10135 !k_good_flag ? 0.0 :
10136 (float)MRILvox(src, si + 1, sj + 1, sk ));
10137 val111 = (!i1_good_flag ||
10138 !j1_good_flag ||
10139 !k1_good_flag ? 0.0 :
10140 (float)MRILvox(src, si + 1, sj + 1, sk + 1));
10141 }
10142
10143 if(src->type == MRI_FLOAT)
10144 {
10145 val000 = ( !i_good_flag ||
10146 !j_good_flag ||
10147 !k_good_flag ? 0.0 :
10148 (float)MRIFvox(src, si , sj , sk ));
10149 val001 = ( !i_good_flag ||
10150 !j_good_flag ||
10151 !k1_good_flag ? 0.0 :
10152 (float)MRIFvox(src, si , sj , sk + 1));
10153 val010 = ( !i_good_flag ||
10154 !j1_good_flag ||
10155 !k_good_flag ? 0.0 :
10156 (float)MRIFvox(src, si , sj + 1, sk ));
10157 val011 = ( !i_good_flag ||
10158 !j1_good_flag ||
10159 !k1_good_flag ? 0.0 :
10160 (float)MRIFvox(src, si , sj + 1, sk + 1));
10161 val100 = (!i1_good_flag ||
10162 !j_good_flag ||
10163 !k_good_flag ? 0.0 :
10164 (float)MRIFvox(src, si + 1, sj , sk ));
10165 val101 = (!i1_good_flag ||
10166 !j_good_flag ||
10167 !k1_good_flag ? 0.0 :
10168 (float)MRIFvox(src, si + 1, sj , sk + 1));
10169 val110 = (!i1_good_flag ||
10170 !j1_good_flag ||
10171 !k_good_flag ? 0.0 :
10172 (float)MRIFvox(src, si + 1, sj + 1, sk ));
10173 val111 = (!i1_good_flag ||
10174 !j1_good_flag ||
10175 !k1_good_flag ? 0.0 :
10176 (float)MRIFvox(src, si + 1, sj + 1, sk + 1));
10177 }
10178
10179 if(resample_type == SAMPLE_TRILINEAR)
10180 {
10181 val = (1.0-si_f) * (1.0-sj_f) * (1.0-sk_f) * val000 +
10182 (1.0-si_f) * (1.0-sj_f) * ( sk_f) * val001 +
10183 (1.0-si_f) * ( sj_f) * (1.0-sk_f) * val010 +
10184 (1.0-si_f) * ( sj_f) * ( sk_f) * val011 +
10185 ( si_f) * (1.0-sj_f) * (1.0-sk_f) * val100 +
10186 ( si_f) * (1.0-sj_f) * ( sk_f) * val101 +
10187 ( si_f) * ( sj_f) * (1.0-sk_f) * val110 +
10188 ( si_f) * ( sj_f) * ( sk_f) * val111;
10189 }
10190
10191 if(resample_type == SAMPLE_NEAREST)
10192 {
10193 if(si_f < 0.5)
10194 {
10195 if(sj_f < 0.5)
10196 {
10197 if(sk_f < 0.5)
10198 val = val000;
10199 else
10200 val = val001;
10201 }
10202 else
10203 {
10204 if(sk_f < 0.5)
10205 val = val010;
10206 else
10207 val = val011;
10208 }
10209 }
10210 else
10211 {
10212 if(sj_f < 0.5)
10213 {
10214 if(sk_f < 0.5)
10215 val = val100;
10216 else
10217 val = val101;
10218 }
10219 else
10220 {
10221 if(sk_f < 0.5)
10222 val = val110;
10223 else
10224 val = val111;
10225 }
10226 }
10227 }
10228
10229 if(resample_type == SAMPLE_WEIGHTED)
10230 {
10231 /* unfinished */
10232 si_f2 = si_f * si_f;
10233 sj_f2 = sj_f * sj_f;
10234 sk_f2 = sk_f * sk_f;
10235
10236 ii2 = 1. / (1 - 2*si_f + si_f2);
10237 ij2 = 1. / (1 - 2*sj_f + sj_f2);
10238 ik2 = 1. / (1 - 2*sk_f + sk_f2);
10239
10240 isi_f2 = 1 / si_f2;
10241 isj_f2 = 1 / sj_f2;
10242 isk_f2 = 1 / sk_f2;
10243
10244 w000 = ii2 + ij2 + ik2;
10245 w001 = ii2 + ij2 + isk_f2;
10246 w010 = ii2 + isj_f2 + ik2;
10247 w011 = ii2 + isj_f2 + isk_f2;
10248 w100 = isi_f2 + ij2 + ik2;
10249 w101 = isi_f2 + ij2 + isk_f2;
10250 w110 = isi_f2 + isj_f2 + ik2;
10251 w111 = isi_f2 + isj_f2 + isk_f2;
10252
10253 w[0] = w[1] = w[2] = w[3] =
10254 w[4] = w[5] = w[6] = w[7] = 0.0;
10255
10256 wi[0] = 0;
10257 wi[1] = 1;
10258 wi[2] = 2;
10259 wi[3] = 3;
10260 wi[4] = 4;
10261 wi[5] = 5;
10262 wi[6] = 6;
10263 wi[7] = 7;
10264
10265 if(val001 == val000)
10266 wi[1] = 0;
10267
10268 if(val010 == val001)
10269 wi[2] = 1;
10270 if(val010 == val000)
10271 wi[2] = 0;
10272
10273 if(val011 == val010)
10274 wi[3] = 2;
10275 if(val011 == val001)
10276 wi[3] = 1;
10277 if(val011 == val000)
10278 wi[3] = 0;
10279
10280 if(val100 == val011)
10281 wi[4] = 3;
10282 if(val100 == val010)
10283 wi[4] = 2;
10284 if(val100 == val001)
10285 wi[4] = 1;
10286 if(val100 == val000)
10287 wi[4] = 0;
10288
10289 if(val101 == val100)
10290 wi[5] = 4;
10291 if(val101 == val011)
10292 wi[5] = 3;
10293 if(val101 == val010)
10294 wi[5] = 2;
10295 if(val101 == val001)
10296 wi[5] = 1;
10297 if(val101 == val000)
10298 wi[5] = 0;
10299
10300 if(val110 == val101)
10301 wi[6] = 5;
10302 if(val110 == val100)
10303 wi[6] = 4;
10304 if(val110 == val011)
10305 wi[6] = 3;
10306 if(val110 == val010)
10307 wi[6] = 2;
10308 if(val110 == val001)
10309 wi[6] = 1;
10310 if(val110 == val000)
10311 wi[6] = 0;
10312
10313 if(val111 == val110)
10314 wi[7] = 6;
10315 if(val111 == val101)
10316 wi[7] = 5;
10317 if(val111 == val100)
10318 wi[7] = 4;
10319 if(val111 == val011)
10320 wi[7] = 3;
10321 if(val111 == val010)
10322 wi[7] = 2;
10323 if(val111 == val001)
10324 wi[7] = 1;
10325 if(val111 == val000)
10326 wi[7] = 0;
10327
10328 w[wi[0]] += w000;
10329 w[wi[1]] += w001;
10330 w[wi[2]] += w010;
10331 w[wi[3]] += w011;
10332 w[wi[4]] += w100;
10333 w[wi[5]] += w101;
10334 w[wi[6]] += w110;
10335 w[wi[7]] += w111;
10336
10337 mwi = 0;
10338
10339 if(w[1] > w[mwi])
10340 mwi = 1;
10341 if(w[2] > w[mwi])
10342 mwi = 2;
10343 if(w[3] > w[mwi])
10344 mwi = 3;
10345 if(w[4] > w[mwi])
10346 mwi = 4;
10347 if(w[5] > w[mwi])
10348 mwi = 5;
10349 if(w[6] > w[mwi])
10350 mwi = 6;
10351 if(w[7] > w[mwi])
10352 mwi = 7;
10353
10354 if(mwi == 0)
10355 val = val000;
10356 if(mwi == 1)
10357 val = val001;
10358 if(mwi == 2)
10359 val = val010;
10360 if(mwi == 3)
10361 val = val011;
10362 if(mwi == 4)
10363 val = val100;
10364 if(mwi == 5)
10365 val = val101;
10366 if(mwi == 6)
10367 val = val110;
10368 if(mwi == 7)
10369 val = val111;
10370
10371 }
10372
10373 }
10374
10375 if(dest->type == MRI_UCHAR)
10376 MRIvox(dest, di, dj, dk) = (unsigned char)val;
10377 if(dest->type == MRI_SHORT)
10378 MRISvox(dest, di, dj, dk) = (short)val;
10379 if(dest->type == MRI_INT)
10380 MRIIvox(dest, di, dj, dk) = (int)val;
10381 if(dest->type == MRI_LONG)
10382 MRILvox(dest, di, dj, dk) = (long)val;
10383 if(dest->type == MRI_FLOAT)
10384 MRIFvox(dest, di, dj, dk) = (float)val;
10385
10386 }
10387 }
10388 }
10389
10390 {
10391 MATRIX *m_old_voxel_to_ras, *m_voxel_to_ras,
10392 *m_old_ras_to_voxel, *v_ras, *v_vox, *m_new_ras_to_voxel, *v_vox2 ;
10393
10394 m_old_voxel_to_ras = MRIgetVoxelToRasXform(src) ;
10395
10396 m_voxel_to_ras = MatrixMultiply(m_old_voxel_to_ras, m, NULL) ;
10397
10398 dest->x_r = *MATRIX_RELT(m_voxel_to_ras,1,1)/dest->xsize;
10399 dest->x_a = *MATRIX_RELT(m_voxel_to_ras,2,1)/dest->xsize;
10400 dest->x_s = *MATRIX_RELT(m_voxel_to_ras,3,1)/dest->xsize;
10401
10402 dest->y_r = *MATRIX_RELT(m_voxel_to_ras,1,2)/dest->ysize;
10403 dest->y_a = *MATRIX_RELT(m_voxel_to_ras,2,2)/dest->ysize;
10404 dest->y_s = *MATRIX_RELT(m_voxel_to_ras,3,2)/dest->ysize;
10405
10406 dest->z_r = *MATRIX_RELT(m_voxel_to_ras,1,3)/dest->zsize;
10407 dest->z_a = *MATRIX_RELT(m_voxel_to_ras,2,3)/dest->zsize;
10408 dest->z_s = *MATRIX_RELT(m_voxel_to_ras,3,3)/dest->zsize;
10409
10410 /* compute the RAS coordinates of the center of the dest. image
10411 and put them in c_r, c_a, and c_s.
10412
10413 C = M * c_v
10414 */
10415 v_vox = VectorAlloc(4, MATRIX_REAL) ;
10416
10417 /* voxel coords of center of dest image */
10418 VECTOR_ELT(v_vox,4) = 1.0 ;
10419 VECTOR_ELT(v_vox,1) = (dest->width)/2.0 ;
10420 VECTOR_ELT(v_vox,2) = (dest->height)/2.0 ;
10421 VECTOR_ELT(v_vox,3) = (dest->depth)/2.0 ;
10422
10423 v_vox2 =
10424 MatrixMultiply(m, v_vox, NULL) ; /* voxel coords in source image */
10425 v_ras =
10426 MatrixMultiply(m_old_voxel_to_ras, v_vox2, NULL) ; /* ras cntr of dest */
10427
10428 dest->c_r = VECTOR_ELT(v_ras, 1);
10429 dest->c_a = VECTOR_ELT(v_ras, 2);
10430 dest->c_s = VECTOR_ELT(v_ras, 3);
10431 dest->ras_good_flag = 1 ;
10432
10433 if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
10434 {
10435 m_new_ras_to_voxel = MRIgetRasToVoxelXform(dest) ;
10436 m_old_ras_to_voxel = MRIgetRasToVoxelXform(src) ;
10437 V3_X(v_ras) = V3_Y(v_ras) = V3_Z(v_ras) = 0.0 ;
10438 MatrixMultiply(m_old_ras_to_voxel, v_ras, v_vox) ;
10439 printf("old RAS (0,0,0) -> (%2.0f, %2.0f, %2.0f)\n",
10440 VECTOR_ELT(v_vox,1), VECTOR_ELT(v_vox,2), VECTOR_ELT(v_vox,3)) ;
10441 MatrixMultiply(m_new_ras_to_voxel, v_ras, v_vox) ;
10442 printf("new RAS (0,0,0) -> (%2.0f, %2.0f, %2.0f)\n",
10443 VECTOR_ELT(v_vox,1), VECTOR_ELT(v_vox,2), VECTOR_ELT(v_vox,3)) ;
10444 MatrixFree(&m_new_ras_to_voxel) ; MatrixFree(&m_old_ras_to_voxel) ;
10445 }
10446
10447 MatrixFree(&v_vox) ; MatrixFree(&v_vox2) ; MatrixFree(&v_ras) ;
10448 MatrixFree(&m_voxel_to_ras) ; MatrixFree(&m_old_voxel_to_ras) ;
10449 }
10450
10451
10452 MatrixFree(&dp);
10453 MatrixFree(&sp);
10454 MatrixFree(&m);
10455
10456 return(dest);
10457
10458 } /* end MRIresample() */
10459
10460 int MRIlimits(MRI *mri, float *min, float *max)
10461 {
10462
10463 float val;
10464 int i, j, k;
10465
10466 if(mri == NULL)
10467 return(NO_ERROR);
10468
10469 if(mri->slices == NULL)
10470 return(NO_ERROR);
10471
10472 if(mri->type == MRI_UCHAR)
10473 {
10474 *min = *max = (float)MRIvox(mri, 0, 0, 0);
10475 for(i = 0;i < mri->width;i++)
10476 for(j = 0;j < mri->height;j++)
10477 for(k = 0;k < mri->depth;k++)
10478 {
10479 val = (float)MRIvox(mri, i, j, k);
10480 if(val < *min)
10481 *min = val;
10482 if(val > *max)
10483 *max = val;
10484 }
10485
10486 }
10487
10488 if(mri->type == MRI_SHORT)
10489 {
10490
10491 *min = *max = (float)MRISvox(mri, 0, 0, 0);
10492
10493 for(i = 0;i < mri->width;i++)
10494 for(j = 0;j < mri->height;j++)
10495 for(k = 0;k < mri->depth;k++)
10496 {
10497 val = (float)MRISvox(mri, i, j, k);
10498 if(val < *min)
10499 *min = val;
10500 if(val > *max)
10501 *max = val;
10502 }
10503
10504 }
10505
10506 if(mri->type == MRI_INT)
10507 {
10508
10509 *min = *max = (float)MRILvox(mri, 0, 0, 0);
10510
10511 for(i = 0;i < mri->width;i++)
10512 for(j = 0;j < mri->height;j++)
10513 for(k = 0;k < mri->depth;k++)
10514 {
10515 val = (float)MRILvox(mri, i, j, k);
10516 if(val < *min)
10517 *min = val;
10518 if(val > *max)
10519 *max = val;
10520 }
10521
10522 }
10523
10524 if(mri->type == MRI_LONG)
10525 {
10526
10527 *min = *max = (float)MRILvox(mri, 0, 0, 0);
10528
10529 for(i = 0;i < mri->width;i++)
10530 for(j = 0;j < mri->height;j++)
10531 for(k = 0;k < mri->depth;k++)
10532 {
10533 val = (float)MRILvox(mri, i, j, k);
10534 if(val < *min)
10535 *min = val;
10536 if(val > *max)
10537 *max = val;
10538 }
10539
10540 }
10541
10542 if(mri->type == MRI_FLOAT)
10543 {
10544
10545 *min = *max = (float)MRIFvox(mri, 0, 0, 0);
10546
10547 for(i = 0;i < mri->width;i++)
10548 for(j = 0;j < mri->height;j++)
10549 for(k = 0;k < mri->depth;k++)
10550 {
10551 val = (float)MRIFvox(mri, i, j, k);
10552 if(val < *min)
10553 *min = val;
10554 if(val > *max)
10555 *max = val;
10556 }
10557
10558 }
10559
10560 return(NO_ERROR);
10561
10562 } /* end MRIlimits() */
10563
10564 int MRIprintStats(MRI *mri, FILE *stream)
10565 {
10566
10567 float min, max, mean, std;
10568 int n;
10569 double com[3];
10570
10571 MRIstats(mri, &min, &max, &n, &mean, &std);
10572
10573 fprintf(stream, "%d values\n", n);
10574 fprintf(stream, "min = %g\n", min);
10575 fprintf(stream, "max = %g\n", max);
10576 fprintf(stream, "mean = %g\n", mean);
10577 fprintf(stream, "std = %g\n", std);
10578
10579 MRIcenterOfMass(mri, com, 0);
10580
10581 fprintf(stream, "com = %g %g %g\n", com[0], com[1], com[2]);
10582
10583 return(NO_ERROR);
10584
10585 } /* end MRIprintStats() */
10586
10587 int MRIstats
10588 (MRI *mri, float *min, float *max, int *n_voxels, float *mean, float *std)
10589 {
10590
10591 float val;
10592 float sum, sq_sum;
10593 int i, j, k, t;
10594 float n;
10595
10596 if(mri == NULL)
10597 return(NO_ERROR);
10598
10599 if(mri->slices == NULL)
10600 return(NO_ERROR);
10601
10602 sum = sq_sum = 0.0;
10603 *n_voxels = mri->width * mri->height * mri->depth * mri->nframes;
10604 n = (float)(*n_voxels);
10605
10606 if(mri->type == MRI_UCHAR)
10607 {
10608
10609 *max = *min = MRIseq_vox(mri, 0, 0, 0, 0);
10610
10611 for(i = 0;i < mri->width;i++)
10612 for(j = 0;j < mri->height;j++)
10613 for(k = 0;k < mri->depth;k++)
10614 for(t = 0;t < mri->nframes;t++)
10615 {
10616
10617 val = (float)MRIseq_vox(mri, i, j, k, t);
10618
10619 if(val < *min)
10620 *min = val;
10621 if(val > *max)
10622 *max = val;
10623
10624 sum += val;
10625 sq_sum += val * val;
10626
10627 }
10628
10629 }
10630
10631 if(mri->type == MRI_SHORT)
10632 {
10633
10634 *min = *max = (float)MRISseq_vox(mri, 0, 0, 0, 0);
10635
10636 for(i = 0;i < mri->width;i++)
10637 for(j = 0;j < mri->height;j++)
10638 for(k = 0;k < mri->depth;k++)
10639 for(t = 0;t < mri->nframes;t++)
10640 {
10641
10642 val = (float)MRISseq_vox(mri, i, j, k, t);
10643
10644 if(val < *min)
10645 *min = val;
10646 if(val > *max)
10647 *max = val;
10648
10649 sum += val;
10650 sq_sum += val * val;
10651
10652 }
10653
10654 }
10655
10656 if(mri->type == MRI_INT)
10657 {
10658
10659 *min = *max = (float)MRILseq_vox(mri, 0, 0, 0, 0);
10660
10661 for(i = 0;i < mri->width;i++)
10662 for(j = 0;j < mri->height;j++)
10663 for(k = 0;k < mri->depth;k++)
10664 for(t = 0;t < mri->nframes;t++)
10665 {
10666
10667 val = (float)MRILseq_vox(mri, i, j, k, t);
10668
10669 if(val < *min)
10670 *min = val;
10671 if(val > *max)
10672 *max = val;
10673
10674 sum += val;
10675 sq_sum += val * val;
10676
10677 }
10678
10679 }
10680
10681 if(mri->type == MRI_LONG)
10682 {
10683
10684 *min = *max = (float)MRILseq_vox(mri, 0, 0, 0, 0);
10685
10686 for(i = 0;i < mri->width;i++)
10687 for(j = 0;j < mri->height;j++)
10688 for(k = 0;k < mri->depth;k++)
10689 for(t = 0;t < mri->nframes;t++)
10690 {
10691
10692 val = (float)MRILseq_vox(mri, i, j, k, t);
10693
10694 if(val < *min)
10695 *min = val;
10696 if(val > *max)
10697 *max = val;
10698
10699 sum += val;
10700 sq_sum += val * val;
10701
10702 }
10703
10704 }
10705
10706 if(mri->type == MRI_FLOAT)
10707 {
10708
10709 *min = *max = (float)MRIFseq_vox(mri, 0, 0, 0, 0);
10710
10711 for(i = 0;i < mri->width;i++)
10712 for(j = 0;j < mri->height;j++)
10713 for(k = 0;k < mri->depth;k++)
10714 for(t = 0;t < mri->nframes;t++)
10715 {
10716
10717 val = (float)MRIFseq_vox(mri, i, j, k, t);
10718
10719 if(val < *min)
10720 *min = val;
10721 if(val > *max)
10722 *max = val;
10723
10724 sum += val;
10725 sq_sum += val * val;
10726
10727 }
10728
10729 }
10730
10731 *mean = sum / n;
10732 *std = (sq_sum - n * (*mean) * (*mean)) / (n - 1.0);
10733
10734 *std = sqrt(*std);
10735
10736 return(NO_ERROR);
10737
10738 } /* end MRIstats() */
10739
10740 float MRIvolumeDeterminant(MRI *mri)
10741 {
10742
10743 MATRIX *m;
10744 float det;
10745
10746 m = MatrixAlloc(4, 4, MATRIX_REAL);
10747 if(m == NULL)
10748 return(0.0);
10749
10750 stuff_four_by_four(m, mri->x_r, mri->y_r, mri->z_r, 0.0,
10751 mri->x_a, mri->y_a, mri->z_a, 0.0,
10752 mri->x_s, mri->y_s, mri->z_s, 0.0,
10753 0.0, 0.0, 0.0, 1.0);
10754
10755 det = MatrixDeterminant(m);
10756
10757 MatrixFree(&m);
10758
10759 return(det);
10760
10761 } /* end MRIvolumeDeterminant() */
10762
10763 int stuff_four_by_four(MATRIX *m, float m11, float m12, float m13, float m14,
10764 float m21, float m22, float m23, float m24,
10765 float m31, float m32, float m33, float m34,
10766 float m41, float m42, float m43, float m44)
10767 {
10768
10769 if(m == NULL)
10770 {
10771 ErrorReturn
10772 (ERROR_BADPARM,
10773 (ERROR_BADPARM,
10774 "stuff_four_by_four(): matrix is NULL"));
10775 }
10776
10777 if(m->rows != 4 || m->cols != 4)
10778 {
10779 ErrorReturn
10780 (ERROR_BADPARM,
10781 (ERROR_BADPARM,
10782 "stuff_four_by_four(): matrix is not four-by-four"));
10783 }
10784
10785 *MATRIX_RELT(m, 1, 1) = m11;
10786 *MATRIX_RELT(m, 1, 2) = m12;
10787 *MATRIX_RELT(m, 1, 3) = m13;
10788 *MATRIX_RELT(m, 1, 4) = m14;
10789 *MATRIX_RELT(m, 2, 1) = m21;
10790 *MATRIX_RELT(m, 2, 2) = m22;
10791 *MATRIX_RELT(m, 2, 3) = m23;
10792 *MATRIX_RELT(m, 2, 4) = m24;
10793 *MATRIX_RELT(m, 3, 1) = m31;
10794 *MATRIX_RELT(m, 3, 2) = m32;
10795 *MATRIX_RELT(m, 3, 3) = m33;
10796 *MATRIX_RELT(m, 3, 4) = m34;
10797 *MATRIX_RELT(m, 4, 1) = m41;
10798 *MATRIX_RELT(m, 4, 2) = m42;
10799 *MATRIX_RELT(m, 4, 3) = m43;
10800 *MATRIX_RELT(m, 4, 4) = m44;
10801
10802 return(NO_ERROR);
10803
10804 } /* end stuff_four_by_four() */
10805
10806 int apply_i_to_r(MRI *mri, MATRIX *m)
10807 {
10808
10809 float x_r, x_a, x_s;
10810 float y_r, y_a, y_s;
10811 float z_r, z_a, z_s;
10812 float mag;
10813 MATRIX *origin, *c;
10814
10815 x_r = *MATRIX_RELT(m, 1, 1);
10816 x_a = *MATRIX_RELT(m, 2, 1);
10817 x_s = *MATRIX_RELT(m, 3, 1);
10818 mag = sqrt(x_r*x_r + x_a*x_a + x_s*x_s);
10819 mri->x_r = x_r / mag; mri->x_a = x_a / mag; mri->x_s = x_s / mag;
10820 mri->xsize = mag;
10821
10822 y_r = *MATRIX_RELT(m, 1, 2);
10823 y_a = *MATRIX_RELT(m, 2, 2);
10824 y_s = *MATRIX_RELT(m, 3, 2);
10825 mag = sqrt(y_r*y_r + y_a*y_a + y_s*y_s);
10826 mri->y_r = y_r / mag; mri->y_a = y_a / mag; mri->y_s = y_s / mag;
10827 mri->ysize = mag;
10828
10829 z_r = *MATRIX_RELT(m, 1, 3);
10830 z_a = *MATRIX_RELT(m, 2, 3);
10831 z_s = *MATRIX_RELT(m, 3, 3);
10832 mag = sqrt(z_r*z_r + z_a*z_a + z_s*z_s);
10833 mri->z_r = z_r / mag; mri->z_a = z_a / mag; mri->z_s = z_s / mag;
10834 mri->zsize = mag;
10835
10836 origin = MatrixAlloc(4, 1, MATRIX_REAL);
10837 if(origin == NULL)
10838 {
10839 ErrorReturn
10840 (ERROR_BADPARM,
10841 (ERROR_BADPARM,
10842 "apply_i_to_r(): error allocating matrix"));
10843 }
10844 *MATRIX_RELT(origin, 1, 1) = (mri->width - 1.0) / 2.0;
10845 *MATRIX_RELT(origin, 2, 1) = (mri->height - 1.0) / 2.0;
10846 *MATRIX_RELT(origin, 3, 1) = (mri->depth - 1.0) / 2.0;
10847 *MATRIX_RELT(origin, 4, 1) = 1.0;
10848
10849 c = MatrixMultiply(m, origin, NULL);
10850 if(c == NULL)
10851 {
10852 MatrixFree(&origin);
10853 ErrorReturn
10854 (ERROR_BADPARM,
10855 (ERROR_BADPARM,
10856 "apply_i_to_r(): error multiplying matrices"));
10857 }
10858
10859 mri->c_r = *MATRIX_RELT(c, 1, 1);
10860 mri->c_a = *MATRIX_RELT(c, 2, 1);
10861 mri->c_s = *MATRIX_RELT(c, 3, 1);
10862
10863 MatrixFree(&origin);
10864 MatrixFree(&c);
10865
10866 mri->ras_good_flag = 1;
10867
10868 return(NO_ERROR);
10869
10870 } /* end apply_i_to_r() */
10871
10872 MATRIX *
10873 MRIrasXformToVoxelXform(MRI *mri_src, MRI *mri_dst, MATRIX *m_ras_xform,
10874 MATRIX *m_voxel_xform)
10875 {
10876 MATRIX *m_ras_to_voxel, *m_voxel_to_ras, *m_tmp ;
10877
10878 if (!mri_dst)
10879 mri_dst = mri_src ; /* assume they will be in the same space */
10880
10881 m_voxel_to_ras = MRIgetVoxelToRasXform(mri_src) ;
10882 m_ras_to_voxel = MRIgetRasToVoxelXform(mri_dst) ;
10883
10884 m_tmp = MatrixMultiply(m_ras_xform, m_voxel_to_ras, NULL) ;
10885 m_voxel_xform = MatrixMultiply(m_ras_to_voxel, m_tmp, m_voxel_xform) ;
10886
10887 MatrixFree(&m_voxel_to_ras); MatrixFree(&m_ras_to_voxel); MatrixFree(&m_tmp);
10888
10889 return(m_voxel_xform) ;
10890 }
10891
10892 MATRIX *
10893 MRIvoxelXformToRasXform(MRI *mri_src, MRI *mri_dst, MATRIX *m_voxel_xform,
10894 MATRIX *m_ras_xform)
10895 {
10896 MATRIX *m_ras_to_voxel, *m_voxel_to_ras, *m_tmp ;
10897
10898 if (!mri_dst)
10899 mri_dst = mri_src ; /* assume they will be in the same space */
10900
10901 m_ras_to_voxel = MRIgetRasToVoxelXform(mri_src) ;
10902 m_voxel_to_ras = MRIgetVoxelToRasXform(mri_dst) ;
10903
10904 m_tmp = MatrixMultiply(m_voxel_xform, m_ras_to_voxel, NULL) ;
10905 m_ras_xform = MatrixMultiply(m_voxel_to_ras, m_tmp, m_ras_xform) ;
10906
10907 MatrixFree(&m_voxel_to_ras); MatrixFree(&m_ras_to_voxel); MatrixFree(&m_tmp);
10908
10909 return(m_ras_xform) ;
10910 }
10911
10912 MATRIX *extract_r_to_i(MRI *mri)
10913 {
10914 MATRIX *m_ras_to_voxel, *m_voxel_to_ras ;
10915
10916 m_voxel_to_ras = extract_i_to_r(mri) ;
10917 m_ras_to_voxel = MatrixInverse(m_voxel_to_ras, NULL) ;
10918 MatrixFree(&m_voxel_to_ras) ;
10919 return(m_ras_to_voxel) ;
10920 }
10921
10922 int
10923 MRIsetVoxelToRasXform(MRI *mri, MATRIX *m_vox2ras)
10924 {
10925 float ci, cj, ck;
10926
10927 mri->x_r = *MATRIX_RELT(m_vox2ras, 1, 1) / mri->xsize ;
10928 mri->y_r = *MATRIX_RELT(m_vox2ras, 1, 2) / mri->ysize ;
10929 mri->z_r = *MATRIX_RELT(m_vox2ras, 1, 3) / mri->zsize ;
10930
10931 mri->x_a = *MATRIX_RELT(m_vox2ras, 2, 1) / mri->xsize ;
10932 mri->y_a = *MATRIX_RELT(m_vox2ras, 2, 2) / mri->ysize ;
10933 mri->z_a = *MATRIX_RELT(m_vox2ras, 2, 3) / mri->zsize ;
10934
10935 mri->x_s = *MATRIX_RELT(m_vox2ras, 3, 1) / mri->xsize ;
10936 mri->y_s = *MATRIX_RELT(m_vox2ras, 3, 2) / mri->ysize ;
10937 mri->z_s = *MATRIX_RELT(m_vox2ras, 3, 3) / mri->zsize ;
10938
10939 ci = (mri->width) / 2.0;
10940 cj = (mri->height) / 2.0;
10941 ck = (mri->depth) / 2.0;
10942 mri->c_r = *MATRIX_RELT(m_vox2ras, 1, 4) +
10943 (*MATRIX_RELT(m_vox2ras, 1, 1) * ci +
10944 *MATRIX_RELT(m_vox2ras, 1, 2) * cj +
10945 *MATRIX_RELT(m_vox2ras, 1, 3) * ck);
10946 mri->c_a = *MATRIX_RELT(m_vox2ras, 2, 4) +
10947 (*MATRIX_RELT(m_vox2ras, 2, 1) * ci +
10948 *MATRIX_RELT(m_vox2ras, 2, 2) * cj +
10949 *MATRIX_RELT(m_vox2ras, 2, 3) * ck);
10950 mri->c_s = *MATRIX_RELT(m_vox2ras, 3, 4) +
10951 (*MATRIX_RELT(m_vox2ras, 3, 1) * ci +
10952 *MATRIX_RELT(m_vox2ras, 3, 2) * cj +
10953 *MATRIX_RELT(m_vox2ras, 3, 3) * ck);
10954 MRIreInitCache(mri);
10955 return(NO_ERROR) ;
10956 }
10957
10958 // allocate memory and the user must free it.
10959 MATRIX *extract_i_to_r(MRI *mri)
10960 {
10961 MATRIX *m;
10962 float m11, m12, m13, m14;
10963 float m21, m22, m23, m24;
10964 float m31, m32, m33, m34;
10965 float ci, cj, ck;
10966
10967 m = MatrixAlloc(4, 4, MATRIX_REAL);
10968 if(m == NULL)
10969 {
10970 ErrorReturn
10971 (NULL,
10972 (ERROR_BADPARM,
10973 "extract_i_to_r(): error allocating matrix"));
10974 }
10975
10976 m11 = mri->xsize * mri->x_r;
10977 m12 = mri->ysize * mri->y_r;
10978 m13 = mri->zsize * mri->z_r;
10979 m21 = mri->xsize * mri->x_a;
10980 m22 = mri->ysize * mri->y_a;
10981 m23 = mri->zsize * mri->z_a;
10982 m31 = mri->xsize * mri->x_s;
10983 m32 = mri->ysize * mri->y_s;
10984 m33 = mri->zsize * mri->z_s;
10985
10986 ci = (mri->width) / 2.0;
10987 cj = (mri->height) / 2.0;
10988 ck = (mri->depth) / 2.0;
10989
10990 m14 = mri->c_r - (m11 * ci + m12 * cj + m13 * ck);
10991 m24 = mri->c_a - (m21 * ci + m22 * cj + m23 * ck);
10992 m34 = mri->c_s - (m31 * ci + m32 * cj + m33 * ck);
10993
10994 stuff_four_by_four(m, m11, m12, m13, m14,
10995 m21, m22, m23, m24,
10996 m31, m32, m33, m34,
10997 0.0, 0.0, 0.0, 1.0);
10998
10999
11000 return(m);
11001
11002 } /* end extract_i_to_r() */
11003
11004 /* eof */
11005 MRI *
11006 MRIscaleMeanIntensities(MRI *mri_src, MRI *mri_ref, MRI *mri_dst)
11007 {
11008 int width, height, depth, x, y, z, val ;
11009 double ref_mean, src_mean, nref_vox, nsrc_vox, scale ;
11010
11011 mri_dst = MRIcopy(mri_src, mri_dst) ;
11012
11013 width = mri_dst->width ; height = mri_dst->height ; depth = mri_dst->depth;
11014
11015 nref_vox = nsrc_vox = src_mean = ref_mean = 0.0 ;
11016 for (z = 0 ; z < depth ; z++)
11017 {
11018 for (y = 0 ; y < height ; y++)
11019 {
11020 for (x = 0 ; x < width ; x++)
11021 {
11022 if (MRIvox(mri_ref,x,y,z) > 10)
11023 {
11024 nref_vox++ ;
11025 ref_mean += (double)MRIvox(mri_ref, x, y, z) ;
11026 }
11027 if (MRIvox(mri_src,x,y,z) > 10)
11028 {
11029 src_mean += (double)MRIvox(mri_src, x, y, z) ;
11030 nsrc_vox++ ;
11031 }
11032 }
11033 }
11034 }
11035
11036 ref_mean /= nref_vox ; src_mean /= nsrc_vox ;
11037 fprintf(stderr, "mean brightnesses: ref = %2.1f, in = %2.1f\n",
11038 ref_mean, src_mean) ;
11039 scale = ref_mean / src_mean ;
11040 for (z = 0 ; z < depth ; z++)
11041 {
11042 for (y = 0 ; y < height ; y++)
11043 {
11044 for (x = 0 ; x < width ; x++)
11045 {
11046 val = MRIvox(mri_src, x, y, z) ;
11047 val = nint(val*scale) ;
11048 if (val > 255)
11049 val = 255 ;
11050 MRIvox(mri_src, x, y, z) = val ;
11051 }
11052 }
11053 }
11054
11055 return(mri_dst) ;
11056 }
11057
11058 MRI *MRIsmoothParcellation(MRI *mri, int smooth_parcellation_count)
11059 {
11060
11061 MRI *mri2;
11062 int i, j, k;
11063 short vals[26];
11064 int counts[32768];
11065 int c;
11066
11067 if(mri->type != MRI_SHORT)
11068 {
11069 ErrorReturn
11070 (NULL,
11071 (ERROR_UNSUPPORTED,
11072 "MRIsmoothParcellation(): only supported for shorts data"));
11073 }
11074
11075 mri2 = MRIcopy(mri, NULL);
11076 if(mri2 == NULL)
11077 {
11078 ErrorReturn
11079 (NULL,
11080 (ERROR_NOMEMORY,
11081 "MRIsmoothParcellation(): error copying structre"));
11082 }
11083
11084 for(i = 1;i < mri->width-1;i++)
11085 {
11086 for(j = 1;j < mri->height-1;j++)
11087 {
11088 for(k = 1;k < mri->depth-1;k++)
11089 {
11090
11091 memset(counts, 0x00, 32768 * sizeof(int));
11092
11093 vals[ 0] = MRISvox(mri, i+1, j+1, k+1);
11094 vals[ 1] = MRISvox(mri, i+1, j+1, k );
11095 vals[ 2] = MRISvox(mri, i+1, j+1, k-1);
11096 vals[ 3] = MRISvox(mri, i+1, j , k+1);
11097 vals[ 4] = MRISvox(mri, i+1, j , k );
11098 vals[ 5] = MRISvox(mri, i+1, j , k-1);
11099 vals[ 6] = MRISvox(mri, i+1, j-1, k+1);
11100 vals[ 7] = MRISvox(mri, i+1, j-1, k );
11101 vals[ 8] = MRISvox(mri, i+1, j-1, k-1);
11102
11103 vals[ 9] = MRISvox(mri, i , j+1, k+1);
11104 vals[10] = MRISvox(mri, i , j+1, k );
11105 vals[11] = MRISvox(mri, i , j+1, k-1);
11106 vals[12] = MRISvox(mri, i , j , k+1);
11107 /* --- ignore the voxel itself --- */
11108 vals[13] = MRISvox(mri, i , j , k-1);
11109 vals[14] = MRISvox(mri, i , j-1, k+1);
11110 vals[15] = MRISvox(mri, i , j-1, k );
11111 vals[16] = MRISvox(mri, i , j-1, k-1);
11112
11113 vals[17] = MRISvox(mri, i-1, j+1, k+1);
11114 vals[18] = MRISvox(mri, i-1, j+1, k );
11115 vals[19] = MRISvox(mri, i-1, j+1, k-1);
11116 vals[20] = MRISvox(mri, i-1, j , k+1);
11117 vals[21] = MRISvox(mri, i-1, j , k );
11118 vals[22] = MRISvox(mri, i-1, j , k-1);
11119 vals[23] = MRISvox(mri, i-1, j-1, k+1);
11120 vals[24] = MRISvox(mri, i-1, j-1, k );
11121 vals[25] = MRISvox(mri, i-1, j-1, k-1);
11122
11123 for(c = 0;c < 26;c++)
11124 counts[vals[c]]++;
11125
11126 for(c = 0;c < 26;c++)
11127 if(counts[vals[c]] >= smooth_parcellation_count)
11128 MRISvox(mri2, i, j, k) = vals[c];
11129
11130 }
11131 }
11132 }
11133
11134 return(mri2);
11135
11136 } /* end MRIsmoothParcellation() */
11137
11138 int
11139 MRIeraseBorderPlanes(MRI *mri)
11140 {
11141 int x, y, z ;
11142
11143 for (x = 0 ; x < mri->width ; x++)
11144 for (y = 0 ; y < mri->height ; y++)
11145 {
11146 MRIvox(mri, x, y, 0) = MRIvox(mri, x, y, mri->depth-1) = 0 ;
11147 }
11148
11149 for (y = 0 ; y < mri->height ; y++)
11150 for (z = 0 ; z < mri->depth ; z++)
11151 {
11152 MRIvox(mri, 0, y, z) = MRIvox(mri, mri->width-1, y, z) = 0 ;
11153 }
11154
11155 for (x = 0 ; x < mri->width ; x++)
11156 for (z = 0 ; z < mri->depth ; z++)
11157 {
11158 MRIvox(mri, x, 0, z) = MRIvox(mri, x, mri->height-1, z) = 0 ;
11159 }
11160
11161 return(NO_ERROR) ;
11162 }
11163 int
11164 MRIcopyPulseParameters(MRI *mri_src, MRI *mri_dst)
11165 {
11166 mri_dst->flip_angle = mri_src->flip_angle ;
11167 mri_dst->tr = mri_src->tr ;
11168 mri_dst->te = mri_src->te ;
11169 mri_dst->ti = mri_src->ti ;
11170 return(NO_ERROR) ;
11171 }
11172 float
11173 MRIfindNearestNonzero(MRI *mri, int wsize, Real xr, Real yr, Real zr)
11174 {
11175 int xk, yk, zk, xi, yi, zi, whalf, x, y, z ;
11176 float dist, min_dist, min_val, dx, dy, dz ;
11177
11178 x = mri->xi[nint(xr)] ; y = mri->yi[nint(yr)] ; z = mri->zi[nint(zr)] ;
11179 if (MRIvox(mri, x, y, z) > 0)
11180 return((float)MRIvox(mri, x, y, z)) ;
11181
11182 min_dist = 100000 ; min_val = 0 ;
11183 whalf = (wsize-1)/2 ;
11184 for (zk = -whalf ; zk <= whalf ; zk++)
11185 {
11186 zi = mri->zi[z+zk] ;
11187 dz = zi-zr ;
11188 for (yk = -whalf ; yk <= whalf ; yk++)
11189 {
11190 yi = mri->yi[y+yk] ;
11191 dy = yi-yr ;
11192 for (xk = -whalf ; xk <= whalf ; xk++)
11193 {
11194 xi = mri->xi[x+xk] ;
11195 dx = xi-xr ;
11196 if (MRIgetVoxVal(mri, xi, yi, zi,0) > 0)
11197 {
11198 dist = sqrt(dx*dx + dy*dy + dz*dz) ;
11199 if (dist < min_dist)
11200 {
11201 min_dist = dist ;
11202 min_val = MRIgetVoxVal(mri, xi, yi, zi,0) ;
11203 }
11204 }
11205 }
11206 }
11207 }
11208 return(min_val) ;
11209 }
11210 int
11211 MRIcountNonzeroInNbhd(MRI *mri, int wsize, int x, int y, int z)
11212 {
11213 int xk, yk, zk, xi, yi, zi, whalf, total ;
11214
11215 whalf = (wsize-1)/2 ;
11216 for (total = 0, zk = -whalf ; zk <= whalf ; zk++)
11217 {
11218 zi = mri->zi[z+zk] ;
11219 for (yk = -whalf ; yk <= whalf ; yk++)
11220 {
11221 yi = mri->yi[y+yk] ;
11222 for (xk = -whalf ; xk <= whalf ; xk++)
11223 {
11224 xi = mri->xi[x+xk] ;
11225 if (MRIgetVoxVal(mri, xi, yi, zi,0) > 0)
11226 total++ ;
11227 }
11228 }
11229 }
11230 return(total) ;
11231 }
11232 int
11233 MRIareNonzeroInNbhd(MRI *mri, int wsize, int x, int y, int z)
11234 {
11235 int xk, yk, zk, xi, yi, zi, whalf ;
11236
11237 whalf = (wsize-1)/2 ;
11238 for (zk = -whalf ; zk <= whalf ; zk++)
11239 {
11240 zi = mri->zi[z+zk] ;
11241 for (yk = -whalf ; yk <= whalf ; yk++)
11242 {
11243 yi = mri->yi[y+yk] ;
11244 for (xk = -whalf ; xk <= whalf ; xk++)
11245 {
11246 xi = mri->xi[x+xk] ;
11247 if (MRIgetVoxVal(mri, xi, yi, zi,0) > 0)
11248 return(1) ;
11249 }
11250 }
11251 }
11252 return(0) ;
11253 }
11254 float
11255 MRIfindNearestNonzeroLocation(MRI *mri, int wsize, Real xr, Real yr, Real zr,
11256 int *pxv, int *pyv, int *pzv)
11257 {
11258 int xk, yk, zk, xi, yi, zi, whalf, x, y, z ;
11259 float dist, min_dist, min_val, dx, dy, dz ;
11260
11261 x = nint(xr) ; y = nint(yr) ; z = nint(zr) ;
11262 if (MRIvox(mri, x, y, z) > 0)
11263 return((float)MRIvox(mri, x, y, z)) ;
11264
11265 min_dist = 100000 ; min_val = 0 ;
11266 whalf = (wsize-1)/2 ;
11267 for (zk = -whalf ; zk <= whalf ; zk++)
11268 {
11269 zi = mri->zi[z+zk] ;
11270 dz = zi-zr ;
11271 for (yk = -whalf ; yk <= whalf ; yk++)
11272 {
11273 yi = mri->yi[y+yk] ;
11274 dy = yi-yr ;
11275 for (xk = -whalf ; xk <= whalf ; xk++)
11276 {
11277 xi = mri->xi[x+xk] ;
11278 dx = xi-xr ;
11279 if (MRIvox(mri, xi, yi, zi) > 0)
11280 {
11281 dist = sqrt(dx*dx + dy*dy + dz*dz) ;
11282 if (dist < min_dist)
11283 {
11284 if (pxv)
11285 { *pxv = xi ; *pyv = yi ; *pzv = zi ;}
11286 min_dist = dist ;
11287 min_val = MRIvox(mri, xi, yi, zi) ;
11288 }
11289 }
11290 }
11291 }
11292 }
11293 return(min_val) ;
11294 }
11295
11296 MRI *
11297 MRIfromTalairach(MRI *mri_src, MRI *mri_dst)
11298 {
11299 int x, y, z, xv, yv, zv ;
11300 Real xt, yt, zt, xn, yn, zn, val ;
11301
11302 if (!mri_dst)
11303 mri_dst = MRIclone(mri_src, NULL) ;
11304
11305 for (x = 0 ; x < mri_dst->width ; x++)
11306 {
11307 xn = (Real)x ;
11308 for (y = 0 ; y < mri_dst->height ; y++)
11309 {
11310 yn = (Real)y ;
11311 for (z = 0 ; z < mri_dst->depth ; z++)
11312 {
11313 zn = (Real)z ;
11314 MRIvoxelToTalairachVoxel(mri_src, xn, yn, zn, &xt, &yt, &zt) ;
11315 xv = nint(xt) ; yv = nint(yt) ; zv = nint(zt) ;
11316 if ((xv >= 0 && xv < mri_src->width) &&
11317 (yv >= 0 && yv < mri_src->height) &&
11318 (zv >= 0 && zv < mri_src->depth))
11319 {
11320 MRIsampleVolume(mri_src, xt, yt, zt, &val) ;
11321 MRIvox(mri_dst, x, y, z) = val ;
11322 }
11323 else
11324 MRIvox(mri_dst, x, y, z) = 0 ;
11325 }
11326 }
11327 }
11328
11329 return(mri_dst) ;
11330 }
11331 MRI *
11332 MRItoTalairach(MRI *mri_src, MRI *mri_dst)
11333 {
11334 int x, y, z, xv, yv, zv ;
11335 Real xt, yt, zt, xn, yn, zn, val ;
11336
11337 if (!mri_dst)
11338 mri_dst = MRIclone(mri_src, NULL) ;
11339
11340 for (x = 0 ; x < mri_dst->width ; x++)
11341 {
11342 xt = (Real)x ;
11343 for (y = 0 ; y < mri_dst->height ; y++)
11344 {
11345 yt = (Real)y ;
11346 for (z = 0 ; z < mri_dst->depth ; z++)
11347 {
11348 zt = (Real)z ;
11349 MRItalairachVoxelToVoxel(mri_src, xt, yt, zt, &xn, &yn, &zn) ;
11350 xv = nint(xn) ; yv = nint(yn) ; zv = nint(zt) ;
11351 if ((xv >= 0 && xv < mri_src->width) &&
11352 (yv >= 0 && yv < mri_src->height) &&
11353 (zv >= 0 && zv < mri_src->depth))
11354 {
11355 MRIsampleVolume(mri_src, xn, yn, zn, &val) ;
11356 MRIvox(mri_dst, x, y, z) = val ;
11357 }
11358 else
11359 MRIvox(mri_dst, x, y, z) = 0 ;
11360 }
11361 }
11362 }
11363
11364 return(mri_dst) ;
11365 }
11366 /*-------------------------------------------------------------------
11367 MRIlog10() - computes the log10 of the values at each voxel and
11368 frame. If a value is zero, the result is set to 10000000000.0. If
11369 the negflag is set, then -log10 is computed. The result is stored
11370 in outmri. If outmri is NULL, the output MRI is alloced and its
11371 pointer returned.
11372 ------------------------------------------------------------------*/
11373 MRI *MRIlog10(MRI *inmri, MRI *outmri, int negflag)
11374 {
11375 int c, r, s, f;
11376 float val;
11377
11378 if(outmri==NULL){
11379 outmri = MRIallocSequence(inmri->width, inmri->height, inmri->depth,
11380 MRI_FLOAT, inmri->nframes);
11381 MRIcopyHeader(inmri,outmri);
11382
11383 if(outmri==NULL){
11384 printf("ERROR: fMRIlog10: could not alloc\n");
11385 return(NULL);
11386 }
11387 }
11388 else{
11389 if(inmri->width != outmri->width ||
11390 inmri->height != outmri->height ||
11391 inmri->depth != outmri->depth ||
11392 inmri->nframes != outmri->nframes){
11393 printf("ERROR: MRIlog10: output dimension mismatch\n");
11394 return(NULL);
11395 }
11396 if(outmri->type != MRI_FLOAT){
11397 printf("ERROR: MRIlog10: structure passed is not MRI_FLOAT\n");
11398 return(NULL);
11399 }
11400 }
11401
11402 for(c=0; c < inmri->width; c++){
11403 for(r=0; r < inmri->height; r++){
11404 for(s=0; s < inmri->depth; s++){
11405 for(f=0; f < inmri->nframes; f++){
11406 val = MRIgetVoxVal(inmri, c, r, s, f);
11407 if(val == 0) MRIFseq_vox(outmri,c,r,s,f) = 10000000000.0;
11408 else{
11409 if(negflag){
11410 if(val < 0) MRIFseq_vox(outmri,c,r,s,f) = log10(fabs(val));
11411 else MRIFseq_vox(outmri,c,r,s,f) = -log10(val);
11412 }
11413 else{
11414 if(val < 0) MRIFseq_vox(outmri,c,r,s,f) = -log10(fabs(val));
11415 else MRIFseq_vox(outmri,c,r,s,f) = log10(val);
11416 }
11417 }
11418 }
11419 }
11420 }
11421 }
11422
11423 return(outmri);
11424 }
11425 /*---------------------------------------------------------------------
11426 MRIrandn() - fills an MRI structure with values sampled from a
11427 normal distribution with mean avg and standard devation stddev.
11428 --------------------------------------------------------*/
11429 MRI *MRIrandn(int ncols, int nrows, int nslices, int nframes,
11430 float avg, float stddev, MRI *mri)
11431 {
11432 int c, r, s, f;
11433
11434 if(mri==NULL){
11435 mri = MRIallocSequence(ncols, nrows, nslices, MRI_FLOAT, nframes);
11436 if(mri==NULL){
11437 printf("ERROR: MRIrandn: could not alloc\n");
11438 return(NULL);
11439 }
11440 }
11441 else{
11442 if(mri->width != ncols || mri->height != nrows ||
11443 mri->depth != nslices || mri->nframes != nframes){
11444 printf("ERROR: MRIrandn: dimension mismatch\n");
11445 return(NULL);
11446 }
11447 if(mri->type != MRI_FLOAT){
11448 printf("ERROR: MRIrandn: structure passed is not MRI_FLOAT\n");
11449 return(NULL);
11450 }
11451 }
11452
11453 for(f=0; f<nframes; f++){
11454 for(s=0; s<nslices; s++){
11455 for(r=0; r<nrows; r++){
11456 for(c=0; c<ncols; c++){
11457 MRIFseq_vox(mri,c,r,s,f) =
11458 stddev*PDFgaussian() + avg;
11459 }
11460 }
11461 }
11462 }
11463
11464 return(mri);
11465 }
11466 /*---------------------------------------------------------------------
11467 MRIrande() - fills an MRI structure with values sampled from an
11468 Erlang distribution with mean avg and order order. The variance
11469 will be (avg^2)/order. Theoretical distribution is
11470 r = order
11471 pdf(x) = r*((r*(x-avg+1))^(r-1)) * exp(-r*(x-avg+1)) / (r-1)!
11472 when order=1, this generates an exponential distribution.
11473 --------------------------------------------------------*/
11474 MRI *MRIrande(int ncols, int nrows, int nslices, int nframes,
11475 float avg, int order, MRI *mri)
11476 {
11477 int c, r, s, f;
11478
11479 if(mri==NULL){
11480 mri = MRIallocSequence(ncols, nrows, nslices, MRI_FLOAT, nframes);
11481 if(mri==NULL){
11482 printf("ERROR: MRIrande: could not alloc\n");
11483 return(NULL);
11484 }
11485 }
11486 else{
11487 if(mri->width != ncols || mri->height != nrows ||
11488 mri->depth != nslices || mri->nframes != nframes){
11489 printf("ERROR: MRIrande: dimension mismatch\n");
11490 return(NULL);
11491 }
11492 if(mri->type != MRI_FLOAT){
11493 printf("ERROR: MRIrande: structure passed is not MRI_FLOAT\n");
11494 return(NULL);
11495 }
11496 }
11497
11498 avg = avg - 1; // PDFrande() already has average of 1
11499 for(f=0; f<nframes; f++){
11500 for(s=0; s<nslices; s++){
11501 for(r=0; r<nrows; r++){
11502 for(c=0; c<ncols; c++){
11503 MRIFseq_vox(mri,c,r,s,f) =
11504 PDFerlang(order) + avg;
11505 }
11506 }
11507 }
11508 }
11509
11510 return(mri);
11511 }
11512 /*---------------------------------------------------------------------
11513 MRIdrand48() - fills an MRI structure with values sampled from a
11514 the drand48 uniform random number generator. The user must specify
11515 the min and max. Note: the stddev = (max-min)*0.289. If mri is NULL,
11516 it will alloc a MRI_FLOAT volume, otherwise, it will use the type
11517 as specified in mri.
11518 --------------------------------------------------------*/
11519 MRI *MRIdrand48(int ncols, int nrows, int nslices, int nframes,
11520 float min, float max, MRI *mri)
11521 {
11522 int c, r, s, f, n;
11523 float range, v;
11524 BUFTYPE *pmri=NULL;
11525 short *psmri=NULL;
11526 int *pimri=NULL;
11527 long *plmri=NULL;
11528 float *pfmri=NULL;
11529
11530 if(mri==NULL){
11531 mri = MRIallocSequence(ncols, nrows, nslices, MRI_FLOAT, nframes);
11532 if(mri==NULL){
11533 printf("ERROR: MRIdrand48: could not alloc\n");
11534 return(NULL);
11535 }
11536 }
11537 else{
11538 if(mri->width != ncols || mri->height != nrows ||
11539 mri->depth != nslices || mri->nframes != nframes){
11540 printf("ERROR: MRIdrand48: dimension mismatch\n");
11541 return(NULL);
11542 }
11543 }
11544
11545 range = max-min;
11546 n = 0;
11547 for(f=0; f<nframes; f++){
11548 for(s=0; s<nslices; s++){
11549 for(r=0; r<nrows; r++){
11550 switch(mri->type){
11551 case MRI_UCHAR: pmri = mri->slices[n][r]; break;
11552 case MRI_SHORT: psmri = (short *) mri->slices[n][r]; break;
11553 case MRI_INT: pimri = (int *) mri->slices[n][r]; break;
11554 case MRI_LONG: plmri = (long *) mri->slices[n][r]; break;
11555 case MRI_FLOAT: pfmri = (float *) mri->slices[n][r]; break;
11556 }
11557 for(c=0; c<ncols; c++) {
11558 v = range*drand48() + min;
11559 switch(mri->type){
11560 case MRI_UCHAR: *pmri++ = (BUFTYPE) v; break;
11561 case MRI_SHORT: *psmri++ = (short) v; break;
11562 case MRI_INT: *pimri++ = (int) v; break;
11563 case MRI_LONG: *plmri++ = (long) v; break;
11564 case MRI_FLOAT: *pfmri++ = (float) v; break;
11565 }
11566 }
11567 }
11568 n++;
11569 }
11570 }
11571
11572 return(mri);
11573 }
11574 /*---------------------------------------------------------------------
11575 MRIsampleCDF() - fills an MRI structure with values sampled from a
11576 the given CDF. See PDFsampleCDF(). CDF[n] is the probability that
11577 the random number is <= xCDF[n].
11578 --------------------------------------------------------------------*/
11579 MRI *MRIsampleCDF(int ncols, int nrows, int nslices, int nframes,
11580 double *xCDF, double *CDF, int nCDF, MRI *mri)
11581 {
11582 int c, r, s, f;
11583
11584 if(mri==NULL){
11585 mri = MRIallocSequence(ncols, nrows, nslices, MRI_FLOAT, nframes);
11586 if(mri==NULL){
11587 printf("ERROR: MRIsampleCDF: could not alloc\n");
11588 return(NULL);
11589 }
11590 }
11591 else{
11592 if(mri->width != ncols || mri->height != nrows ||
11593 mri->depth != nslices || mri->nframes != nframes){
11594 printf("ERROR: MRIsampleCDF: dimension mismatch\n");
11595 return(NULL);
11596 }
11597 if(mri->type != MRI_FLOAT){
11598 printf("ERROR: MRIsampleCDF: structure passed is not MRI_FLOAT\n");
11599 return(NULL);
11600 }
11601 }
11602
11603 for(f=0; f<nframes; f++){
11604 for(s=0; s<nslices; s++){
11605 for(r=0; r<nrows; r++){
11606 for(c=0; c<ncols; c++){
11607 MRIFseq_vox(mri,c,r,s,f) = PDFsampleCDF(xCDF,CDF,nCDF);
11608 }
11609 }
11610 }
11611 }
11612
11613 return(mri);
11614 }
11615 /*---------------------------------------------------------------------
11616 MRIconst() - fills an MRI structure with the given value. If mri is
11617 NULL, it will alloc a MRI_FLOAT volume, otherwise, it will use the type
11618 as specified in mri.
11619 --------------------------------------------------------*/
11620 MRI *MRIconst(int ncols, int nrows, int nslices, int nframes,
11621 float val, MRI *mri)
11622 {
11623 int c, r, s, f, n;
11624 BUFTYPE *pmri=NULL;
11625 short *psmri=NULL;
11626 int *pimri=NULL;
11627 long *plmri=NULL;
11628 float *pfmri=NULL;
11629
11630 if(mri==NULL){
11631 mri = MRIallocSequence(ncols, nrows, nslices, MRI_FLOAT, nframes);
11632 if(mri==NULL){
11633 printf("ERROR: MRIdconst: could not alloc\n");
11634 return(NULL);
11635 }
11636 }
11637 else{
11638 if(mri->width != ncols || mri->height != nrows ||
11639 mri->depth != nslices || mri->nframes != nframes){
11640 printf("ERROR: MRIconst: dimension mismatch\n");
11641 return(NULL);
11642 }
11643 }
11644
11645 n = 0;
11646 for(f=0; f<nframes; f++){
11647 for(s=0; s<nslices; s++){
11648 for(r=0; r<nrows; r++){
11649 switch(mri->type){
11650 case MRI_UCHAR: pmri = mri->slices[n][r]; break;
11651 case MRI_SHORT: psmri = (short *) mri->slices[n][r]; break;
11652 case MRI_INT: pimri = (int *) mri->slices[n][r]; break;
11653 case MRI_LONG: plmri = (long *) mri->slices[n][r]; break;
11654 case MRI_FLOAT: pfmri = (float *) mri->slices[n][r]; break;
11655 }
11656 for(c=0; c<ncols; c++) {
11657 switch(mri->type){
11658 case MRI_UCHAR: *pmri++ = (BUFTYPE) val; break;
11659 case MRI_SHORT: *psmri++ = (short) val; break;
11660 case MRI_INT: *pimri++ = (int) val; break;
11661 case MRI_LONG: *plmri++ = (long) val; break;
11662 case MRI_FLOAT: *pfmri++ = (float) val; break;
11663 }
11664 }
11665 }
11666 n++;
11667 }
11668 }
11669
11670 return(mri);
11671 }
11672 /*--------------------------------------------------------------*/
11673
11674 int
11675 MRInormalizeSequence(MRI *mri, float target)
11676 {
11677 int x, y, z, frame ;
11678 double norm ;
11679 Real val ;
11680
11681 for (x = 0 ; x < mri->width ; x++)
11682 {
11683 for (y = 0 ; y < mri->height ; y++)
11684 {
11685 for (z = 0 ; z < mri->depth ; z++)
11686 {
11687 for (frame = 0, norm = 0 ; frame < mri->nframes ; frame++)
11688 {
11689 MRIsampleVolumeFrame(mri, x, y, z, frame, &val) ;
11690 norm += (val*val) ;
11691 }
11692 norm = sqrt(norm) / target ;
11693 if (FZERO(norm))
11694 norm = 1 ;
11695 for (frame = 0 ; frame < mri->nframes ; frame++)
11696 {
11697 switch (mri->type)
11698 {
11699 default:
11700 ErrorReturn
11701 (ERROR_UNSUPPORTED,
11702 (ERROR_UNSUPPORTED,
11703 "MRInormalizeSequence: unsupported input type %d",
11704 mri->type)) ;
11705 break ;
11706 case MRI_SHORT:
11707 MRISseq_vox(mri, x, y, z, frame) =
11708 MRISseq_vox(mri, x, y, z, frame) / norm ;
11709 break ;
11710 case MRI_FLOAT:
11711 MRIFseq_vox(mri, x, y, z, frame) /= norm ;
11712 break ;
11713 case MRI_UCHAR:
11714 MRIseq_vox(mri, x, y, z, frame) /= norm ;
11715 break ;
11716 }
11717 }
11718 }
11719 }
11720 }
11721
11722 return(NO_ERROR) ;
11723 }
11724
11725 double
11726 MRImeanInLabel(MRI *mri_src, MRI *mri_labeled, int label)
11727 {
11728 int x, y, z, nvox, l ;
11729 double mean = 0.0 ;
11730 float val ;
11731
11732 nvox = 0 ;
11733 for (x = 0 ; x < mri_src->width ; x++)
11734 {
11735 for (y = 0 ; y < mri_src->height ; y++)
11736 {
11737 for (z = 0 ; z < mri_src->depth ; z++)
11738 {
11739 l = nint(MRIgetVoxVal(mri_labeled, x, y, z, 0)) ;
11740 if (l == label)
11741 {
11742 val = MRIgetVoxVal(mri_src, x, y, z, 0) ;
11743 mean += val ;
11744 nvox++ ;
11745 }
11746 }
11747 }
11748 }
11749 if (!nvox)
11750 nvox = 1 ;
11751 return(mean/nvox) ;
11752 }
11753
11754 MRI *
11755 MRImakePositive(MRI *mri_src, MRI *mri_dst)
11756 {
11757 float fmin, fmax, val ;
11758 int x, y, z,f ;
11759
11760 MRIvalRange(mri_src, &fmin, &fmax) ;
11761 mri_dst = MRIcopy(mri_src, mri_dst) ;
11762 if (fmin >= 0)
11763 return(mri_dst) ;
11764
11765 for (f = 0 ; f < mri_dst->nframes ; f++)
11766 {
11767 for (x = 0 ; x < mri_dst->width ; x++)
11768 {
11769 for (y = 0 ; y < mri_dst->height ; y++)
11770 {
11771 for (z = 0 ; z < mri_dst->depth ; z++)
11772 {
11773 val = MRIgetVoxVal(mri_src, x, y, z, f) ;
11774 val -= fmin ;
11775 MRIsetVoxVal(mri_dst, x, y, z, f, val) ;
11776 }
11777 }
11778 }
11779 }
11780
11781 return(mri_dst) ;
11782 }
11783 MRI *
11784 MRIeraseNegative(MRI *mri_src, MRI *mri_dst)
11785 {
11786 int x, y, z ;
11787 float val ;
11788
11789 mri_dst = MRIcopy(mri_src, mri_dst) ;
11790
11791 for (x = 0 ; x < mri_src->width ; x++)
11792 {
11793 for (y = 0 ; y < mri_src->height ; y++)
11794 {
11795 for (z = 0 ; z < mri_src->depth ; z++)
11796 {
11797 val = MRIgetVoxVal(mri_src, x, y, z, 0) ;
11798 if (val < 0)
11799 MRIsetVoxVal(mri_dst, x, y, z, 0, 0) ;
11800 }
11801 }
11802 }
11803 return(mri_dst) ;
11804 }
11805 int
11806 MRIsampleVolumeSlice
11807 (MRI *mri, Real x, Real y, Real z, Real *pval, int slice_direction)
11808 {
11809 int OutOfBounds;
11810 int xm, xp, ym, yp, zm, zp, width, height, depth ;
11811 Real val, xmd, ymd, xpd, ypd ; /* d's are distances */
11812 Real val11, val12, val21, val22 ;
11813
11814 if (FEQUAL((int)x,x) && FEQUAL((int)y,y) && FEQUAL((int)z, z))
11815 return(MRIsampleVolumeType(mri, x, y, z, pval, SAMPLE_NEAREST)) ;
11816
11817 OutOfBounds = MRIindexNotInVolume(mri, x, y, z);
11818 if(OutOfBounds == 1){
11819 /* unambiguously out of bounds */
11820 *pval = 0.0;
11821 return(NO_ERROR) ;
11822 }
11823
11824 width = mri->width ; height = mri->height ; depth = mri->depth ;
11825
11826 if (x >= width) x = width - 1.0 ;
11827 if (y >= height) y = height - 1.0 ;
11828 if (z >= depth) z = depth - 1.0 ;
11829 if (x < 0.0) x = 0.0 ;
11830 if (y < 0.0) y = 0.0 ;
11831 if (z < 0.0) z = 0.0 ;
11832
11833 xm = MAX((int)x, 0) ;
11834 xp = MIN(width-1, xm+1) ;
11835 ym = MAX((int)y, 0) ;
11836 yp = MIN(height-1, ym+1) ;
11837 zm = MAX((int)z, 0) ;
11838 zp = MIN(depth-1, zm+1) ;
11839
11840 xmd = x - (float)xm ;
11841 ymd = y - (float)ym ;
11842 xpd = (1.0f - xmd) ;
11843 ypd = (1.0f - ymd) ;
11844
11845 switch (slice_direction)
11846 {
11847 case MRI_CORONAL:
11848 zp = nint(z) ;
11849 val11 = MRIgetVoxVal(mri, xm, ym, zp, 0) ;
11850 val12 = MRIgetVoxVal(mri, xm, yp, zp, 0) ;
11851 val21 = MRIgetVoxVal(mri, xp, ym, zp, 0) ;
11852 val22 = MRIgetVoxVal(mri, xp, yp, zp, 0) ;
11853 *pval = val = xpd * ypd * val11 + xpd * ymd * val12 + xmd * ypd * val21 +
11854 xmd * ymd * val22 ;
11855 break ;
11856 default:
11857 ErrorReturn
11858 (ERROR_UNSUPPORTED,
11859 (ERROR_UNSUPPORTED,
11860 "MRIsampleVolumeSlice: unsupported direction %d", slice_direction)) ;
11861 break ;
11862 }
11863 return(NO_ERROR) ;
11864 }
11865
11866 float
11867 MRIvoxelsInLabelWithPartialVolumeEffects(MRI *mri, MRI *mri_vals, int label)
11868 {
11869 float volume, vox_vol ;
11870 int x, y, z, nbr_label_counts[MAX_CMA_LABELS];
11871 int label_counts[MAX_CMA_LABELS], this_label, border;
11872 int nbr_label, max_count, vox_label ;
11873 MRI *mri_border ;
11874 float label_means[MAX_CMA_LABELS], pv, mean_label, mean_nbr, val ;
11875
11876 vox_vol = mri->xsize*mri->ysize*mri->zsize ;
11877
11878 /* first find border voxels */
11879 mri_border = MRImarkLabelBorderVoxels(mri, NULL, label, 1, 1) ;
11880 if (DIAG_VERBOSE_ON && (Gdiag & DIAG_WRITE))
11881 MRIwrite(mri_border, "b.mgz") ;
11882 volume = 0 ;
11883 for (x = 0 ; x < mri->width ; x++)
11884 {
11885 for (y = 0 ; y < mri->height ; y++)
11886 {
11887 for (z = 0 ; z < mri->depth ; z++)
11888 {
11889 if (x == Gx && y == Gy && z == Gz)
11890 DiagBreak() ;
11891 vox_label = MRIgetVoxVal(mri, x, y, z, 0) ;
11892 border = MRIgetVoxVal(mri_border, x, y, z, 0) ;
11893 if ((vox_label != label) && (border == 0))
11894 continue ;
11895
11896 if (border == 0)
11897 volume += vox_vol ;
11898 else /* compute partial volume */
11899 {
11900 MRIcomputeLabelNbhd
11901 (mri, mri_vals, x, y, z,
11902 nbr_label_counts, label_means, 1, MAX_CMA_LABELS) ;
11903 MRIcomputeLabelNbhd
11904 (mri, mri_vals, x, y, z,
11905 label_counts, label_means, 7, MAX_CMA_LABELS) ;
11906 val =
11907 MRIgetVoxVal(mri_vals, x, y, z, 0) ; /* compute partial
11908 volume based on
11909 intensity */
11910 mean_label = label_means[vox_label] ;
11911 nbr_label = -1 ; max_count = 0 ;
11912 /* look for a label that is a nbr and is
11913 on the other side of val from the label mean */
11914 for (this_label = 0 ;
11915 this_label < MAX_CMA_LABELS ;
11916 this_label++)
11917 {
11918 if (this_label == vox_label)
11919 continue ;
11920 if (nbr_label_counts[this_label] == 0) /* not a nbr */
11921 continue ;
11922
11923 if ((label_counts[this_label] > max_count) &&
11924 ((label_means[this_label] - val) *
11925 (mean_label - val) < 0))
11926 {
11927 max_count = label_means[this_label] ;
11928 nbr_label = this_label ;
11929 }
11930 }
11931 if (vox_label != label &&
11932 nbr_label != label) /* this struct not in voxel */
11933 continue ;
11934
11935 if (max_count == 0) /* couldn't find an appropriate label */
11936 volume += vox_vol ;
11937 else /* compute partial volume pct */
11938 {
11939 mean_nbr = label_means[nbr_label] ;
11940 pv = (val - mean_nbr) / (mean_label - mean_nbr) ;
11941 if (vox_label == label)
11942 volume += vox_vol * pv ;
11943 else
11944 volume += vox_vol * (1-pv) ;
11945 if (pv < 0 || pv > 1)
11946 DiagBreak() ;
11947 }
11948 }
11949 }
11950 }
11951 }
11952
11953 MRIfree(&mri_border) ;
11954 return(volume) ;
11955 }
11956
11957 MRI *
11958 MRImakeDensityMap(MRI *mri, MRI *mri_vals, int label, MRI *mri_dst)
11959 {
11960 float vox_vol, volume ;
11961 int x, y, z, nbr_label_counts[MAX_CMA_LABELS];
11962 int label_counts[MAX_CMA_LABELS], this_label, border;
11963 int nbr_label, max_count, vox_label ;
11964 MRI *mri_border ;
11965 float label_means[MAX_CMA_LABELS], pv, mean_label, mean_nbr, val ;
11966
11967 if (mri_dst == NULL)
11968 mri_dst = MRIalloc(mri->width, mri->height, mri->depth, MRI_FLOAT) ;
11969
11970 /* first find border voxels */
11971 mri_border = MRImarkLabelBorderVoxels(mri, NULL, label, 1, 1) ;
11972 if (DIAG_VERBOSE_ON && (Gdiag & DIAG_WRITE))
11973 MRIwrite(mri_border, "b.mgz") ;
11974 vox_vol = mri->xsize*mri->ysize*mri->zsize ;
11975 for (x = 0 ; x < mri->width ; x++)
11976 {
11977 for (y = 0 ; y < mri->height ; y++)
11978 {
11979 for (z = 0 ; z < mri->depth ; z++)
11980 {
11981 if (x == Gx && y == Gy && z == Gz)
11982 DiagBreak() ;
11983 vox_label = MRIgetVoxVal(mri, x, y, z, 0) ;
11984 border = MRIgetVoxVal(mri_border, x, y, z, 0) ;
11985 if ((vox_label != label) && (border == 0))
11986 continue ;
11987
11988 volume = vox_vol ;
11989 if (border == 0)
11990 volume = vox_vol ;
11991 else /* compute partial volume */
11992 {
11993 MRIcomputeLabelNbhd
11994 (mri, mri_vals, x, y, z,
11995 nbr_label_counts, label_means, 1, MAX_CMA_LABELS) ;
11996 MRIcomputeLabelNbhd
11997 (mri, mri_vals, x, y, z,
11998 label_counts, label_means, 7, MAX_CMA_LABELS) ;
11999 val =
12000 MRIgetVoxVal(mri_vals, x, y, z, 0) ; /* compute partial
12001 volume based on
12002 intensity */
12003 mean_label = label_means[vox_label] ;
12004 nbr_label = -1 ; max_count = 0 ;
12005 /* look for a label that is a nbr and is
12006 on the other side of val from the label mean */
12007 for (this_label = 0 ;
12008 this_label < MAX_CMA_LABELS ;
12009 this_label++)
12010 {
12011 if (this_label == vox_label)
12012 continue ;
12013 if (nbr_label_counts[this_label] == 0) /* not a nbr */
12014 continue ;
12015
12016 if ((label_counts[this_label] > max_count) &&
12017 ((label_means[this_label] - val) *
12018 (mean_label - val) < 0))
12019 {
12020 max_count = label_means[this_label] ;
12021 nbr_label = this_label ;
12022 }
12023 }
12024 if (vox_label != label &&
12025 nbr_label != label) /* this struct not in voxel */
12026 continue ;
12027
12028 if (max_count > 0) /* compute partial volume pct */
12029 {
12030 mean_nbr = label_means[nbr_label] ;
12031 pv = (val - mean_nbr) / (mean_label - mean_nbr) ;
12032 if (vox_label == label)
12033 volume = pv*vox_vol ;
12034 else
12035 volume = vox_vol * (1-pv) ;
12036 if (pv < 0 || pv > 1)
12037 DiagBreak() ;
12038 }
12039 }
12040 MRIsetVoxVal(mri_dst, x, y, z, 0, volume) ;
12041 }
12042 }
12043 }
12044
12045 MRIfree(&mri_border) ;
12046 return(mri_dst) ;
12047 }
12048
12049 MRI *
12050 MRImarkLabelBorderVoxels
12051 (MRI *mri_src, MRI *mri_dst, int label, int mark, int six_connected)
12052 {
12053 int x, y, z, xk, yk, zk, xi, yi, zi, this_label, that_label, border ;
12054
12055 if (mri_dst == NULL)
12056 mri_dst = MRIclone(mri_src, NULL) ;
12057
12058 for (x = 0 ; x < mri_src->width ; x++)
12059 {
12060 for (y = 0 ; y < mri_src->height ; y++)
12061 {
12062 for (z = 0 ; z < mri_src->depth ; z++)
12063 {
12064 this_label = MRIgetVoxVal(mri_src, x, y, z, 0) ;
12065 border = 0 ;
12066 for (xk = -1 ; xk <= 1 && !border ; xk++)
12067 {
12068 xi = mri_src->xi[x+xk] ;
12069 for (yk = -1 ; yk <= 1 && !border ; yk++)
12070 {
12071 yi = mri_src->yi[y+yk] ;
12072 for (zk = -1 ; zk <= 1 ; zk++)
12073 {
12074 if (six_connected && (abs(xk)+abs(yk)+abs(zk) != 1))
12075 continue ;
12076 zi = mri_src->zi[z+zk] ;
12077 that_label = MRIgetVoxVal(mri_src, xi, yi, zi, 0) ;
12078 if (((this_label == label) &&
12079 (that_label != label)) ||
12080 ((this_label != label) &&
12081 (that_label == label)))
12082 {
12083 border = 1 ;
12084 break ;
12085 }
12086 }
12087 }
12088 }
12089 if (border)
12090 MRIsetVoxVal(mri_dst, x, y, z, 0, mark) ;
12091 }
12092 }
12093 }
12094
12095 return(mri_dst) ;
12096 }
12097
12098 int
12099 MRIcomputeLabelNbhd
12100 (MRI *mri_labels, MRI *mri_vals,
12101 int x, int y, int z, int *label_counts, float *label_means,
12102 int whalf, int max_labels)
12103 {
12104 int xi, yi, zi, xk, yk, zk, label ;
12105 float val ;
12106
12107 memset(label_counts, 0, sizeof(label_counts[0])*max_labels) ;
12108 memset(label_means, 0, sizeof(label_means[0])*max_labels) ;
12109 for (xk = -whalf ; xk <= whalf ; xk++)
12110 {
12111 xi = mri_vals->xi[x+xk] ;
12112 for (yk = -whalf ; yk <= whalf ; yk++)
12113 {
12114 yi = mri_vals->yi[y+yk] ;
12115 for (zk = -whalf ; zk <= whalf ; zk++)
12116 {
12117 zi = mri_vals->zi[z+zk] ;
12118 label = MRIgetVoxVal(mri_labels, xi, yi, zi, 0) ;
12119 val = MRIgetVoxVal(mri_vals, xi, yi, zi, 0) ;
12120 label_counts[label]++ ;
12121 label_means[label] += val ;
12122 }
12123 }
12124 }
12125
12126 for (label = 0 ; label < max_labels ; label++)
12127 if (label_counts[label] > 0)
12128 label_means[label] /= label_counts[label] ;
12129 return(NO_ERROR) ;
12130 }
12131
12132 /**
12133 * void MRIcalCRASforSampledVolume
12134 *
12135 * @param src MRI* volume
12136 * @param dst MRI* sampled volume
12137 * @param pr output ptr to c_r
12138 * @param pa output ptr to c_a
12139 * @param ps output ptr to c_s
12140 */
12141 void MRIcalcCRASforSampledVolume
12142 (MRI *src, MRI *dst, Real *pr, Real *pa, Real *ps)
12143 {
12144 // get the voxel position of the "center" voxel of the dst in the src volume
12145 // i.e. sample is 2, then get the voxel position 64 in the src volume
12146 // thus it is 128.5 (in the src) for 64 (in the dst)
12147 Real sx, sy, sz;
12148 int dx, dy, dz;
12149 int samplex, sampley, samplez;
12150
12151 // error check first
12152 if ((src->width)%(dst->width) != 0)
12153 ErrorExit
12154 (ERROR_BADPARM, "src width must be integer multiple of dst width");
12155 if ((src->height)%(dst->height) != 0)
12156 ErrorExit
12157 (ERROR_BADPARM, "src height must be integer multiple of dst height");
12158 if ((src->depth)%(dst->depth) != 0)
12159 ErrorExit
12160 (ERROR_BADPARM, "src depth must be integer multiple of dst depth");
12161
12162 samplex = src->width/dst->width;
12163 sampley = src->height/dst->height;
12164 samplez = src->depth/dst->depth;
12165
12166 // "center" voxel position in dst
12167 dx = dst->width/2; // if the length is odd,
12168 // then it does the right thing (truncation)
12169 dy = dst->height/2;// i.e. 0 1 2 then 3/2 = 1, 0 1 2 3 then 4/2=2
12170 dz = dst->depth/2;
12171 // corresponding position in src
12172 sx = dx*samplex + (samplex-1.)/2.; // ((dx*samplex - 0.5) +
12173 // ((dx+1)*samplex -0.5))/2.
12174 sy = dy*sampley + (sampley-1.)/2.;
12175 sz = dz*samplez + (samplez-1.)/2.;
12176 //
12177 // Example
12178 // | 0 1 2 | 3 4 5 | 6 7 8 | -(sample by 3).
12179 // | 0 | 1 | 2 |
12180 // 1 (3/2) in dst corresponds
12181 // to 1*3+(3-1)/2 = 4! in src
12182 //
12183 // | 0 1 2 3 | 4 5 6 7 | -(sample by 4)->0 1
12184 // | 0 | 1 | 1 (2/2) in dst corresponds
12185 // to 1*4+(4-1)/2 = 5.5 in src
12186
12187 // get ras of the "center" voxel position in dst
12188 if (!src->i_to_r__)
12189 {
12190 src->i_to_r__ = extract_i_to_r(src);
12191 src->r_to_i__ = extract_r_to_i(src);
12192 }
12193 TransformWithMatrix(src->i_to_r__, sx, sy, sz, pr, pa, ps);
12194
12195 if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
12196 fprintf(stderr, "c_ras for sample volume is (%f, %f, %f) "
12197 "compared with the src (%f, %f, %f)\n",
12198 *pr, *pa, *ps, src->c_r, src->c_a, src->c_s);
12199 }
12200
12201 /**
12202 * MRIcalcCRASfroExtractedVolume
12203 *
12204 * @param src MRI* src volume
12205 * @param x0 src start position of the extraction region
12206 * @param y0
12207 * @param z0
12208 * @param x1 target start position of the extracted region
12209 * @param y1
12210 * @param z1
12211 * @param pr output Real* c_r
12212 * @param pa c_a
12213 * @param ps c_s
12214 */
12215 void MRIcalcCRASforExtractedVolume
12216 (MRI *src, MRI *dst, int x0, int y0, int z0, int x1, int y1, int z1,
12217 Real *pr, Real *pa, Real *ps)
12218 {
12219 Real cx, cy, cz;
12220 // The "center" voxel position of the
12221 // extracted volume in the original voxel position
12222 // x1 of dst corresponds to x0 of src
12223 // Thus, the "center" of dst corresponds to that of the src is
12224 cx = x0+(Real)dst->width/2 - x1; // integer divide cutoff extra
12225 cy = y0+(Real)dst->height/2 - y1;
12226 cz = z0+(Real)dst->depth/2 - z1;
12227
12228 if (!src->i_to_r__)
12229 {
12230 src->i_to_r__ = extract_i_to_r(src);
12231 src->r_to_i__ = extract_r_to_i(src);
12232 }
12233 TransformWithMatrix(src->i_to_r__, cx, cy, cz, pr, pa, ps);
12234 // got where the RAS position of the new volume position
12235 // we have to translate so that we can get the same value
12236 // under the new volume
12237
12238 if (Gdiag & DIAG_SHOW && DIAG_VERBOSE_ON)
12239 fprintf(stderr, "c_ras for sample volume is (%f, %f, %f) "
12240 "compared with the src (%f, %f, %f)\n",
12241 *pr, *pa, *ps, src->c_r, src->c_a, src->c_s);
12242 }
12243
12244 // transform is the hires to lowres vox-to-vox transform
12245 void MRIcalcCRASforHiresVolume
12246 (MRI *hires, MRI *lowres, MATRIX *vox_xform, Real *pr, Real *pa, Real *ps)
12247 {
12248 // get where the center of hires volume goes to in the lowres volume
12249 Real cx, cy, cz;
12250 Real dx, dy, dz;
12251 cx = hires->width/2; cy = hires->height/2; cz = hires->depth/2;
12252 TransformWithMatrix(vox_xform, cx, cy, cz, &dx, &dy, &dz);
12253 // get the c_ras values for this position
12254 TransformWithMatrix(lowres->i_to_r__, dx, dy, dz, pr, pa, ps);
12255 // if we use this c_ras value for the transformed hires volume, then
12256 // the volume will be containing the original points
12257 }
12258
12259 // transform is src to dst vox to vox transform
12260 // return rotated src whose center is at the right place
12261 // Just rotating the original volume make the non-zero voxels go
12262 // outside of the rotated volume. This routine will keep the
12263 // center of the rotated volume at the right location.
12264 MRI *
12265 MRIsrcTransformedCentered
12266 (MRI *src, MRI *dst, MATRIX *stod_voxtovox, int interp_method)
12267 {
12268 Real cr, ca, cs;
12269 MRI *rotated;
12270 MATRIX *stosrotVox;
12271 MATRIX *tmp;
12272
12273 // get the c_ras value for the rotated volume
12274 MRIcalcCRASforHiresVolume(src, dst, stod_voxtovox, &cr, &ca, &cs);
12275 rotated = MRIclone(src, NULL);
12276 // reset the rotated volume
12277 rotated->c_r = cr;
12278 rotated->c_a = ca;
12279 rotated->c_s = cs;
12280 MRIreInitCache(rotated); // recalculate the transform
12281 // the map is the following
12282 //
12283 // src --> RAS
12284 // | |
12285 // |given |
12286 // V V
12287 // dst --> RAS
12288 // | |
12289 // | (identity)
12290 // V |
12291 // src' --> RAS
12292 // new rotated src volume whose center is at the right location
12293 //
12294 tmp = MatrixMultiply(rotated->r_to_i__, dst->i_to_r__, NULL);
12295 stosrotVox = MatrixMultiply(tmp, stod_voxtovox, NULL);
12296 MRIlinearTransformInterp(src, rotated, stosrotVox, interp_method);
12297 return rotated;
12298 }
12299
12300 ////////////////////////////////////////////////////////////////////////////
12301 // No sample method ////////////////////////////////////////////////////////
12302 // using the src and orig_dst to modify
12303 // the direction cosines and c_(ras) value
12304 // so that it will be rotated in the RAS space but no pixel is sampled
12305 MRI *MRITransformedCenteredMatrix(MRI *src, MRI *orig_dst, MATRIX *m_L)
12306 {
12307 LTA *lta ;
12308 MRI *mri_dst ;
12309
12310 lta = LTAalloc(1, NULL) ;
12311 MatrixCopy(m_L, lta->xforms[0].m_L) ;
12312 lta->type = LINEAR_VOX_TO_VOX ;
12313 mri_dst = MRITransformedCentered(src, orig_dst, lta) ;
12314 LTAfree(<a) ;
12315 return(mri_dst) ;
12316 }
12317 MRI *MRITransformedCentered(MRI *src, MRI *orig_dst, LTA *lta)
12318 {
12319 MRI *dst = 0;
12320 Real cx, cy, cz;
12321 Real cr, ca, cs;
12322 MATRIX *dstToRas = 0;
12323 MATRIX *SI = 0;
12324 MATRIX *D = 0;
12325 LT *tran = <a->xforms[0];
12326
12327 dst = MRIcopy(src, NULL);
12328
12329 if (lta->num_xforms > 1)
12330 ErrorExit(ERROR_BADPARM, "The LTA contains more than one transforms.");
12331
12332 // first verify the consistency of the transform stored geometry vs. argument
12333 if (tran->dst.valid == 1)
12334 {
12335 // compare the one with orig_dst to the stored one
12336 VG dstvg, storedvg;
12337 getVolGeom(orig_dst, &dstvg);
12338 storedvg.valid = tran->dst.valid;
12339 storedvg.width = tran->dst.width;
12340 storedvg.height = tran->dst.height;
12341 storedvg.depth = tran->dst.depth;
12342 storedvg.xsize = tran->dst.xsize;
12343 storedvg.ysize = tran->dst.ysize;
12344 storedvg.zsize = tran->dst.zsize;
12345 storedvg.x_r = tran->dst.x_r;
12346 storedvg.x_a = tran->dst.x_a;
12347 storedvg.x_s = tran->dst.x_s;
12348 storedvg.y_r = tran->dst.y_r;
12349 storedvg.y_a = tran->dst.y_a;
12350 storedvg.y_s = tran->dst.y_s;
12351 storedvg.z_r = tran->dst.z_r;
12352 storedvg.z_a = tran->dst.z_a;
12353 storedvg.z_s = tran->dst.z_s;
12354 storedvg.c_r = tran->dst.c_r;
12355 storedvg.c_a = tran->dst.c_a;
12356 storedvg.c_s = tran->dst.c_s;
12357 if (!vg_isEqual(&dstvg, &storedvg))
12358 {
12359 fprintf
12360 (stderr,
12361 "WARNING: stored destination volume for the "
12362 "transform differes from the argument.");
12363 }
12364 }
12365 if (tran->src.valid == 1)
12366 {
12367 // compare the one with orig_dst to the stored one
12368 VG srcvg, storedvg;
12369 getVolGeom(src, &srcvg);
12370 storedvg.valid = tran->src.valid;
12371 storedvg.width = tran->src.width;
12372 storedvg.height = tran->src.height;
12373 storedvg.depth = tran->src.depth;
12374 storedvg.xsize = tran->src.xsize;
12375 storedvg.ysize = tran->src.ysize;
12376 storedvg.zsize = tran->src.zsize;
12377 storedvg.x_r = tran->src.x_r;
12378 storedvg.x_a = tran->src.x_a;
12379 storedvg.x_s = tran->src.x_s;
12380 storedvg.y_r = tran->src.y_r;
12381 storedvg.y_a = tran->src.y_a;
12382 storedvg.y_s = tran->src.y_s;
12383 storedvg.z_r = tran->src.z_r;
12384 storedvg.z_a = tran->src.z_a;
12385 storedvg.z_s = tran->src.z_s;
12386 storedvg.c_r = tran->src.c_r;
12387 storedvg.c_a = tran->src.c_a;
12388 storedvg.c_s = tran->src.c_s;
12389 if (!vg_isEqual(&srcvg, &storedvg))
12390 {
12391 fprintf(stderr, "WARNING: stored destination volume for the "
12392 "transform differes from the argument.");
12393 }
12394 }
12395
12396 if (lta->type == LINEAR_RAS_TO_RAS)
12397 {
12398 MATRIX *tmp;
12399 //
12400 // src --> RAS
12401 // | |
12402 // | M | Y
12403 // V V
12404 // orig_dst --> RAS
12405 //
12406 // transform it to the vox-to-vox
12407 // now calculate M
12408 tmp = MatrixMultiply(tran->m_L, src->i_to_r__, NULL);
12409 MatrixFree(&tran->m_L);
12410 tran->m_L = MatrixMultiply(orig_dst->r_to_i__, tmp, NULL);
12411 MatrixFree(&tmp);
12412 lta->type = LINEAR_VOX_TO_VOX;
12413 }
12414
12415 if (lta->type != LINEAR_VOX_TO_VOX)
12416 ErrorExit
12417 (ERROR_BADPARM,
12418 "The LTA does not contain LINEASR_RAS_TO_RAS nor LINEAR_VOX_TO_VOX.");
12419 //
12420 // src --> RAS
12421 // | |
12422 // | M | Y
12423 // V V
12424 // orig_dst --> RAS
12425 // | |
12426 // | (identity)
12427 // V |
12428 // dst --> RAS
12429 // new rotated src volume whose center is at the right location
12430 // ?
12431 // we try src->dst is identity (no sampling)
12432 //
12433 // Y = i_to_r(orig_dst) * M * r_to_i(src)
12434 //
12435 // Thus we have simpler picture
12436 //
12437 // src -----> RAS
12438 // | |
12439 // (identity) (Y)
12440 // | |
12441 // V V
12442 // dst -----> RAS
12443 // (???)
12444 //
12445 // Thus
12446 // (???) = Y * i_to_r(src)
12447 // = i_to_r(orig_dst) * M * r_to_i(src) * i_to_r(src)
12448 //
12449 // (???) = i_to_r(orig_dst) * M (A)
12450 //
12451 // Thus we derive direction cosines and c_(ras) from ???
12452 //
12453 // (???) = ( X T ) ( S 0 ) where S is the voxel size
12454 // ( 0 1 ) ( 0 1 )
12455 // or
12456 // ( X T ) = (???) * (S^(-1) 0 ) (B)
12457 // ( 0 1 ) ( 0 1 )
12458 //
12459 //
12460 dstToRas = MatrixMultiply(orig_dst->i_to_r__, tran->m_L, NULL);
12461
12462 SI = MatrixAlloc(4, 4, MATRIX_REAL);
12463 *MATRIX_RELT(SI, 1, 1) = 1./dst->xsize ;
12464 *MATRIX_RELT(SI, 2, 2) = 1./dst->ysize ;
12465 *MATRIX_RELT(SI, 3, 3) = 1./dst->zsize ;
12466 *MATRIX_RELT(SI, 4, 4) = 1. ;
12467
12468 D = MatrixMultiply(dstToRas, SI, NULL);
12469
12470 dst->x_r = *MATRIX_RELT(D, 1, 1);
12471 dst->x_a = *MATRIX_RELT(D, 2, 1);
12472 dst->x_s = *MATRIX_RELT(D, 3, 1);
12473 dst->y_r = *MATRIX_RELT(D, 1, 2);
12474 dst->y_a = *MATRIX_RELT(D, 2, 2);
12475 dst->y_s = *MATRIX_RELT(D, 3, 2);
12476 dst->z_r = *MATRIX_RELT(D, 1, 3);
12477 dst->z_a = *MATRIX_RELT(D, 2, 3);
12478 dst->z_s = *MATRIX_RELT(D, 3, 3);
12479
12480 MatrixFree(&D);
12481 MatrixFree(&SI);
12482
12483 // c_ras is calculated by
12484 //
12485 // ( X T )(S 0)(dstwidth/2 ) = (c_r)
12486 // or i_to_r(orig_dst) * M * (dstwidth/2 ) = C'
12487 // ( 0 1 )(0 1)(dstheight/2) (c_a)
12488 // (dstheight/2)
12489 // (dstdepth/2 ) (c_s)
12490 // (dstdepth/2 )
12491 // ( 1 ) ( 1 ) ( 1 )
12492 //
12493 // This is the same as the original center point
12494 // is mapped to orig_dst and then obtaining
12495 // its ras position! (because src and dst has the
12496 // same volume size). The only difference
12497 // is its orientation with respect to orig_dst RAS. Good
12498 //
12499 // get where the center of hires volume goes to in the lowres volume
12500 cx = dst->width/2; cy = dst->height/2; cz = dst->depth/2;
12501 // get the c_ras values for this position
12502 TransformWithMatrix(dstToRas, cx, cy, cz, &cr, &ca, &cs);
12503 // if we use this c_ras value for the transformed hires volume, then
12504 // the volume will be containing the original points
12505 dst->c_r = cr;
12506 dst->c_a = ca;
12507 dst->c_s = cs;
12508
12509 // when you change the direction cosine, you have to do this
12510 MRIreInitCache(dst);
12511
12512 MatrixFree(&dstToRas);
12513
12514 return dst;
12515 }
12516 int
12517 MRIcropBoundingBox(MRI *mri, MRI_REGION *box)
12518 {
12519 box->x = MAX(0, box->x) ; box->y = MAX(0, box->y) ;box->z = MAX(0, box->z) ;
12520 box->dx = MIN(mri->width-box->x-1, box->dx) ;
12521 box->dy = MIN(mri->height-box->y-1, box->dy) ;
12522 box->dz = MIN(mri->depth-box->z-1, box->dz) ;
12523 return(NO_ERROR) ;
12524 }
12525
12526 MATRIX *
12527 MRIgetVoxelToVoxelXform(MRI *mri_src, MRI *mri_dst)
12528 {
12529 MATRIX *m_ras2vox_dst, *m_vox2ras_src, *m_vox2vox ;
12530
12531 m_vox2ras_src = MRIgetVoxelToRasXform(mri_src) ;
12532 m_ras2vox_dst = MRIgetRasToVoxelXform(mri_dst) ;
12533 m_vox2vox = MatrixMultiply(m_ras2vox_dst, m_vox2ras_src, NULL) ;
12534 MatrixFree(&m_vox2ras_src) ; MatrixFree(&m_ras2vox_dst) ;
12535 return(m_vox2vox) ;
12536 }
12537
12538 /*--------------------------------------------------------------
12539 MRIfovCol(mri) - computes the edge-to-edge FOV in the column
12540 direction. fov is in mm.
12541 -------------------------------------------------------------*/
12542 float MRIfovCol(MRI *mri)
12543 {
12544 MATRIX *M,*v,*a,*b,*d;
12545 float fov;
12546
12547 M = MRIgetVoxelToRasXform(mri) ;
12548 v = MatrixAlloc(4,1,MATRIX_REAL);
12549 v->rptr[1][4] = 1;
12550 v->rptr[1][1] = mri->width-1+0.5; // edge of last column
12551 a = MatrixMultiply(M,v,NULL); // xyz of last column
12552 v->rptr[1][1] = -0.5; // edge of first column
12553 b = MatrixMultiply(M,v,NULL); // xyz of first column
12554 d = MatrixSubtract(a,b,NULL); // xyz difference
12555 fov = VectorLen(d); // fov is in mm
12556 MatrixFree(&M);
12557 MatrixFree(&v);
12558 MatrixFree(&a);
12559 MatrixFree(&b);
12560 MatrixFree(&d);
12561
12562 //printf("MRIfovCol() %g\n",fov);
12563 return(fov);
12564 }
12565 /* ---------------------------------------------------------------------
12566 MRIorientationStringToDircos() - sets the direction cosines of to
12567 be that dictated by the Orientation String. This is helpful for
12568 setting the direction cosines when the information is not present
12569 in a header (eg, with FSL analyze format). The Orientation String
12570 is a three character string indicating the primary direction of
12571 each axis in the 3d matrix. The characters can be L,R,A,P,I,S. The
12572 string must be valid (see MRIcheckOrientationString). If the string
12573 is not valid, the errors are printed and a 1 is returned. Eg, of
12574 valid strings are RAS, LPS, LAI. Invalid are ABC (B and C are not
12575 valid), RAP (the AP axis is represented twice, IS axis not at all).
12576 There are 48 possible valid strings. This should only be used to
12577 get the direction cosines "about right".
12578 --------------------------------------------------------------------*/
12579
12580 int MRIorientationStringToDircos(MRI *mri, char *ostr)
12581 {
12582 int c,r=0;
12583 double Mdc[3][3], v=0;
12584 char *errstr;
12585
12586 errstr = MRIcheckOrientationString(ostr);
12587 if(errstr != NULL){
12588 printf("ERROR: in orientation string %s\n",ostr);
12589 printf("%s",errstr);
12590 free(errstr);
12591 return(1);
12592 }
12593
12594 // Initialize the matrix of direction cosines (Mdc)
12595 for(c=0; c<3; c++) for(r=0; r<3; r++) Mdc[r][c] = 0;
12596
12597 // Each column of Mdc corresponds to a different axis which corresonds to
12598 // a different letter in the orientation string. The value of the letter
12599 // determine which row of the Mdc will be affected.
12600 for(c=0; c<3; c++){
12601 switch(toupper(ostr[c])){
12602 case 'L': r=0; v=-1; break;
12603 case 'R': r=0; v=+1; break;
12604 case 'P': r=1; v=-1; break;
12605 case 'A': r=1; v=+1; break;
12606 case 'I': r=2; v=-1; break;
12607 case 'S': r=2; v=+1; break;
12608 }
12609 Mdc[r][c] = v;
12610 }
12611 mri->x_r = Mdc[0][0];
12612 mri->x_a = Mdc[1][0];
12613 mri->x_s = Mdc[2][0];
12614
12615 mri->y_r = Mdc[0][1];
12616 mri->y_a = Mdc[1][1];
12617 mri->y_s = Mdc[2][1];
12618
12619 mri->z_r = Mdc[0][2];
12620 mri->z_a = Mdc[1][2];
12621 mri->z_s = Mdc[2][2];
12622
12623 return(0);
12624 }
12625 /* ---------------------------------------------------------------
12626 MRIcheckOrientationString() - this checks the orientation string
12627 to make sure that it is valid. "Valid" means that all axes are
12628 represented exactly once and no invalid characters are present
12629 in the string. Case-insensitive. Returns NULL if everything is
12630 ok, otherwise is returns a string that lists all the errors
12631 it encountered.
12632 ---------------------------------------------------------------*/
12633 char *MRIcheckOrientationString(char *ostr)
12634 {
12635 int c, nsag=0, ncor=0, nax=0, err;
12636 char errstr[1000], *errstrret=NULL;
12637
12638 errstr[0] = '\0';
12639 err = 0;
12640
12641 for(c=0; c<3; c++){
12642 switch(toupper(ostr[c])){
12643 case 'L': nsag++; break;
12644 case 'R': nsag++; break;
12645 case 'P': ncor++; break;
12646 case 'A': ncor++; break;
12647 case 'I': nax++; break;
12648 case 'S': nax++; break;
12649 default:
12650 sprintf(errstr,"%s Character %c in position %d is invalid.\n",
12651 errstr,ostr[c],c+1);
12652 err = 1;
12653 break;
12654 }
12655 }
12656
12657 if(nsag > 1){
12658 sprintf(errstr,"%s LR axis represented multiple times.\n",errstr);
12659 err = 1;
12660 }
12661 if(ncor > 1){
12662 sprintf(errstr,"%s PA axis represented multiple times.\n",errstr);
12663 err = 1;
12664 }
12665 if(nax > 1){
12666 sprintf(errstr,"%s IS axis represented multiple times.\n",errstr);
12667 err = 1;
12668 }
12669 if(nsag == 0){
12670 sprintf(errstr,"%s LR axis not represented.\n",errstr);
12671 err = 1;
12672 }
12673 if(ncor == 0){
12674 sprintf(errstr,"%s PA axis not represented.\n",errstr);
12675 err = 1;
12676 }
12677 if(nax == 0){
12678 sprintf(errstr,"%s IS axis not represented.\n",errstr);
12679 err = 1;
12680 }
12681
12682 if(err){
12683 errstrret = (char *) calloc(sizeof(char),strlen(errstr)+1);
12684 memcpy(errstrret,errstr,strlen(errstr));
12685 }
12686
12687 return(errstrret);
12688 }
12689 /*------------------------------------------------------------------
12690 MRIdircosToOrientationString() - examines the direction cosines and
12691 creates an Orientation String. The Orientation String is a three
12692 character string indicating the primary direction of each axis
12693 in the 3d matrix. The characters can be L,R,A,P,I,S. Case is not
12694 important, but upper case is used here. If ras_good_flag == 0,
12695 then ostr = ??? and 1 is returned.
12696 ------------------------------------------------------------------*/
12697 int MRIdircosToOrientationString(MRI *mri, char *ostr)
12698 {
12699 int c;
12700 float Mdc[3][3], sag, cor, ax;
12701
12702 if(! mri->ras_good_flag){
12703 ostr[0] = '?';
12704 ostr[1] = '?';
12705 ostr[2] = '?';
12706 return(1);
12707 }
12708
12709 Mdc[0][0] = mri->x_r;
12710 Mdc[1][0] = mri->x_a;
12711 Mdc[2][0] = mri->x_s;
12712
12713 Mdc[0][1] = mri->y_r;
12714 Mdc[1][1] = mri->y_a;
12715 Mdc[2][1] = mri->y_s;
12716
12717 Mdc[0][2] = mri->z_r;
12718 Mdc[1][2] = mri->z_a;
12719 Mdc[2][2] = mri->z_s;
12720
12721 for(c=0; c<3; c++) ostr[c] = '\0';
12722
12723 for(c=0; c<3; c++){
12724 sag = Mdc[0][c]; // LR axis
12725 cor = Mdc[1][c]; // PA axis
12726 ax = Mdc[2][c]; // IS axis
12727 //printf("c = %d, sag = %g, cor = %g, ax = %g\n",c,sag,cor,ax);
12728 if(fabs(sag) > fabs(cor) && fabs(sag) > fabs(ax)){
12729 if(sag > 0) ostr[c] = 'R';
12730 else ostr[c] = 'L';
12731 continue;
12732 }
12733 if(fabs(cor) > fabs(ax)){
12734 if(cor > 0) ostr[c] = 'A';
12735 else ostr[c] = 'P';
12736 continue;
12737 }
12738 if(ax > 0) ostr[c] = 'S';
12739 else ostr[c] = 'I';
12740 }
12741 return(0);
12742
12743 }
12744 /*-------------------------------------------------------------------
12745 MRIsliceDirectionName() - returns the name of the primary slice
12746 orientation base on the direction cosine. If mri->ras_good_flag=0,
12747 then "unknown" is returned.
12748 -------------------------------------------------------------------*/
12749 char *MRIsliceDirectionName(MRI *mri)
12750 {
12751 char ostr[4];
12752 char *slicedir = NULL;
12753 char *rtstr;
12754 int len;
12755
12756 ostr[3] = '\0';
12757
12758 MRIdircosToOrientationString(mri, ostr);
12759 if(toupper(ostr[2]) == 'L'|| toupper(ostr[2]) == 'R')
12760 slicedir = "sagittal";
12761 if(toupper(ostr[2]) == 'P'|| toupper(ostr[2]) == 'A')
12762 slicedir = "coronal";
12763 if(toupper(ostr[2]) == 'I'|| toupper(ostr[2]) == 'S')
12764 slicedir = "axial";
12765 if(! mri->ras_good_flag) slicedir = "unknown";
12766
12767 len = strlen(slicedir);
12768 rtstr = (char *) calloc(sizeof(char),len+1);
12769 memcpy(rtstr,slicedir,len);
12770
12771 return(rtstr);
12772 }
12773 MRI *
12774 MRIdistanceTransform
12775 (MRI *mri_src, MRI *mri_dist, int label, float max_dist, int mode)
12776 {
12777 int x, y, z, width, height, depth, xi, yi, zi;
12778 int xk, yk, zk, changed, found, i ;
12779 MRI *mri_processed ;
12780 float dist, min_dist ;
12781 VOXEL_LIST *vl_current, *vl_new ;
12782
12783 width = mri_src->width ; height = mri_src->height ; depth = mri_src->depth ;
12784 if (max_dist < 0)
12785 max_dist = 2*MAX(MAX(width,height),depth);
12786 if (mri_dist == NULL)
12787 {
12788 mri_dist = MRIalloc(width, height, depth, MRI_FLOAT) ;
12789 MRIcopyHeader(mri_src, mri_dist) ;
12790 }
12791 else
12792 MRIclear(mri_dist) ;
12793
12794 if (mode != DTRANS_MODE_OUTSIDE)
12795 vl_current = VLSTcreate(mri_src, label, label, NULL, 0, 1) ;
12796 else
12797 vl_current = VLSTcreate(mri_src, label, label, NULL, 0, 0) ;
12798 vl_new = VLSTdilate(vl_current, VL_DILATE_REPLACE, NULL) ;
12799
12800 mri_processed = VLSTcreateMri(vl_current, 128) ;
12801 if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
12802 MRIwrite(mri_processed, "p.mgz") ;
12803
12804 do
12805 {
12806 for (i = 0 ; i < vl_new->nvox ; i++)
12807 {
12808 x = vl_new->xi[i] ;
12809 y = vl_new->yi[i] ;
12810 z = vl_new->zi[i] ;
12811 found = 0 ; min_dist = 1e8 ;
12812 for (xk = -1 ; xk <= 1 ; xk++) // find min dist of nbrs
12813 {
12814 xi = mri_src->xi[x+xk] ;
12815 for (yk = -1 ; yk <= 1 ; yk++)
12816 {
12817 yi = mri_src->yi[y+yk] ;
12818 for (zk = -1 ; zk <= 1 ; zk++)
12819 {
12820 zi = mri_src->zi[z+zk] ;
12821 if (MRIvox(mri_processed, xi, yi, zi) == 0)
12822 continue ;
12823 dist = MRIgetVoxVal(mri_dist, xi, yi, zi, 0) ;
12824 dist += sqrt(xk*xk+yk*yk+zk*zk) ;
12825 if (found == 0 || dist < min_dist)
12826 {
12827 found = 1 ;
12828 min_dist = dist ;
12829 }
12830 }
12831 }
12832 }
12833
12834 if (found > 0)
12835 {
12836 changed++ ;
12837 MRIsetVoxVal(mri_dist, x, y, z, 0, min_dist) ;
12838 }
12839 else
12840 DiagBreak() ;
12841 }
12842
12843 VLSTfree(&vl_current) ;
12844 VLSTaddToMri(vl_new, mri_processed, 128) ;
12845 vl_current = vl_new ;
12846 vl_new = VLSTdilate(vl_current, VL_DILATE_REPLACE, mri_processed) ;
12847 #if 0
12848 if (vl_new == NULL)
12849 printf("complete\n") ;
12850 else
12851 printf("examining %d voxels...\n", vl_new->nvox) ;
12852 #endif
12853 } while (vl_new != NULL) ;
12854
12855 if (mode != DTRANS_MODE_OUTSIDE) // set interior distances to negative vals
12856 {
12857 int x, y, z ;
12858
12859 for (x = 0 ; x < mri_src->width ; x++)
12860 {
12861 for (y = 0 ; y < mri_src->height ; y++)
12862 {
12863 for (z = 0 ; z < mri_src->depth ; z++)
12864 {
12865 if (x == Gx && y == Gy && z == Gz)
12866 DiagBreak() ;
12867 if (FEQUAL(MRIgetVoxVal(mri_src, x, y, z, 0), label))
12868 {
12869 dist = MRIgetVoxVal(mri_dist, x, y, z, 0) ;
12870 if (!FZERO(dist))
12871 MRIsetVoxVal(mri_dist, x, y, z, 0, -dist) ;
12872 }
12873 }
12874 }
12875 }
12876 }
12877
12878 if (Gdiag & DIAG_WRITE && DIAG_VERBOSE_ON)
12879 MRIwrite(mri_dist, "dist.mgz") ;
12880 VLSTfree(&vl_current) ;
12881 MRIfree(&mri_processed) ;
12882
12883 if (mode == DTRANS_MODE_UNSIGNED)
12884 MRIabs(mri_dist, mri_dist) ;
12885 return(mri_dist) ;
12886 }
12887
12888 /*-------------------------------------------------------------------
12889 MRIreverseSliceOrder() - reverses the order of the slices WITHOUT
12890 changing the gemoetry information. This is specially desgined to
12891 undo the reversal that Siemens sometimes makes to volumes. If
12892 using FreeSurfer unpacking (ie, DICOMRead.c), it should only need
12893 to be done to mosaics. Note: cannot be done in-place!
12894 -------------------------------------------------------------------*/
12895 MRI *MRIreverseSliceOrder(MRI *invol, MRI *outvol)
12896 {
12897 int c,r,s1,s2,f;
12898 double val;
12899
12900 if(invol == outvol){
12901 printf("ERROR: MRIreverseSliceOrder: cannot be done in-place\n");
12902 return(NULL);
12903 }
12904
12905 outvol = MRIclone(invol,outvol);
12906
12907 s2 = invol->depth;
12908 for(s1=0; s1 < invol->depth; s1++){
12909 s2--;
12910 for(c=0; c < invol->width; c++){
12911 for(r=0; r < invol->height; r++){
12912 for(f=0; f < invol->nframes; f++){
12913 val = MRIgetVoxVal(invol,c,r,s1,f);
12914 MRIsetVoxVal(outvol,c,r,s2,f,val);
12915 }
12916 }
12917 }
12918 }
12919
12920 return(outvol);
12921 }
12922 /*-------------------------------------------------------------------
12923 MRIcopyVolGeomToMRI - copies the volume geometry passed in into the MRI
12924 structure.
12925 -------------------------------------------------------------------*/
12926 int
12927 MRIcopyVolGeomToMRI(MRI *mri, VOL_GEOM *vg)
12928 {
12929 mri->xsize = vg->xsize ;
12930 mri->ysize = vg->ysize ;
12931 mri->zsize = vg->zsize ;
12932 mri->x_r = vg->x_r;
12933 mri->y_r = vg->y_r;
12934 mri->z_r = vg->z_r;
12935 mri->c_r = vg->c_r;
12936 mri->x_a = vg->x_a;
12937 mri->y_a = vg->y_a;
12938 mri->z_a = vg->z_a;
12939 mri->c_a = vg->c_a;
12940 mri->x_s = vg->x_s;
12941 mri->y_s = vg->y_s;
12942 mri->z_s = vg->z_s;
12943 mri->c_s = vg->c_s;
12944 return(NO_ERROR) ;
12945 }
12946
12947 #define NDIRS 3
12948 static int dirs[NDIRS][3] =
12949 {
12950 { 0, 0, 1},
12951 { 0, 1, 0},
12952 { 1, 0, 0}
12953 } ;
12954
12955 MRI *
12956 MRInonMaxSuppress(MRI *mri_src, MRI *mri_sup, float thresh, int thresh_dir)
12957 {
12958 int x, y, z, i, max_i ;
12959 Real val, dx, dy, dz, Ix, Iy, Iz;
12960 Real dot, max_dot, p1_x, p1_y, p1_z, p2_x, p2_y, p2_z;
12961 Real p3_x, p3_y, p3_z, nx, ny, nz, u, xf, yf, zf, oval, numer, denom ;
12962
12963 mri_sup = MRIcopy(mri_src, mri_sup) ;
12964
12965 for (x = 0 ; x < mri_src->width ; x++)
12966 {
12967 for (y = 0 ; y < mri_src->height ; y++)
12968 {
12969 for (z = 0 ; z < mri_src->depth ; z++)
12970 {
12971 if (x == Gx && y == Gy && z == Gz)
12972 DiagBreak() ;
12973 val = MRIgetVoxVal(mri_src, x, y, z,0) ;
12974 val = val*thresh_dir ;
12975 if (val <= thresh)
12976 {
12977 MRIsetVoxVal(mri_sup, x, y, z, 0, 0.0) ;
12978 continue ;
12979 }
12980 MRIsampleVolumeGradient(mri_src, x, y, z, &Ix, &Iy, &Iz) ;
12981 dx = dirs[0][0] ; dy = dirs[0][1] ; dz = dirs[0][2] ;
12982 max_i = 0 ;
12983 max_dot = fabs(dx*Ix+dy*Iy+dz*Iz) ;
12984 for (i = 1 ; i < NDIRS ; i++)
12985 {
12986 // compute intersection of gradient
12987 // direction with coordinate planes
12988 dx = dirs[i][0] ; dy = dirs[i][1] ; dz = dirs[i][2] ;
12989 dot = fabs(dx*Ix+dy*Iy+dz*Iz) ;
12990 if (dot > max_dot)
12991 {
12992 max_i = i ;
12993 max_dot = dot ;
12994 }
12995 }
12996 // normal to coordinate plane -
12997 // compute intersections of gradient dir with plane
12998 nx = dirs[max_i][0] ;
12999 ny = dirs[max_i][1] ;
13000 nz = dirs[max_i][2] ;
13001 p1_x = x ; p1_y = y ; p1_z = z ; // point on line
13002 p2_x = x+Ix ; p2_y = y+Iy ; p2_z = z+Iz ; // 2nd point on
13003 // gradient line
13004 p3_x = x+nx ; p3_y = y+ny ; p3_z = z+nz ; // point on plane
13005 numer =
13006 nx * (p3_x - p1_x) +
13007 ny * (p3_y - p1_y) +
13008 nz * (p3_z - p1_z) ;
13009 denom =
13010 nx * (p2_x - p1_x) +
13011 ny * (p2_y - p1_y) +
13012 nz * (p2_z - p1_z) ;
13013 if (DZERO(denom))
13014 {
13015 DiagBreak() ;
13016 continue ;
13017 }
13018 u = numer / denom ;
13019 xf = p1_x + u * Ix ; yf = p1_y + u * Iy ; zf = p1_z + u * Iz ;
13020 MRIsampleVolume(mri_src, xf, yf, zf, &oval) ;
13021 oval = oval*thresh_dir ;
13022 if (oval > val) // not at a maximum
13023 {
13024 MRIsetVoxVal(mri_sup, x, y, z, 0, 0) ;
13025 continue ;
13026 }
13027 xf = p1_x - u * Ix ; yf = p1_y - u * Iy ; zf = p1_z - u * Iz ;
13028 MRIsampleVolume(mri_src, xf, yf, zf, &oval) ;
13029 oval = oval*thresh_dir ;
13030 if (oval > val) // not at a maximum
13031 {
13032 MRIsetVoxVal(mri_sup, x, y, z, 0, 0) ;
13033 continue ;
13034 }
13035 }
13036 }
13037 }
13038
13039 return(mri_sup) ;
13040 }
13041 MRI *
13042 MRIextractRegionAndPad
13043 (MRI *mri_src, MRI *mri_dst, MRI_REGION *region, int pad)
13044 {
13045 MRI *mri_tmp ;
13046 MRI_REGION box ;
13047
13048 if (region == NULL)
13049 {
13050 region = & box ;
13051 box.x = box.y = box.z = 0 ;
13052 box.dx = mri_src->width ;
13053 box.dy = mri_src->height ;
13054 box.dz = mri_src->depth ;
13055 }
13056 mri_dst =
13057 MRIalloc
13058 (region->dx+2*pad, region->dy+2*pad, region->dz+2*pad, mri_src->type) ;
13059 MRIcopyHeader(mri_src, mri_dst) ;
13060 mri_tmp = MRIextractInto(mri_src, NULL, region->x, region->y, region->z,
13061 region->dx, region->dy, region->dz, 0, 0, 0) ;
13062 MRIextractInto
13063 (mri_tmp, mri_dst, 0, 0, 0,
13064 region->dx, region->dy, region->dz, pad, pad, pad);
13065 return(mri_dst) ;
13066 }
13067
13068 MRI *
13069 MRIsetValuesOutsideRegion
13070 (MRI *mri_src, MRI_REGION *region, MRI *mri_dst, float val)
13071 {
13072 int x, y, z ;
13073
13074 mri_dst = MRIcopy(mri_src, mri_dst) ;
13075
13076 for (x = 0 ; x < mri_dst->width ; x++)
13077 {
13078 if (x >= region->x && x < region->x+region->dx)
13079 continue ;
13080 for (y = 0 ; y < mri_dst->height ; y++)
13081 {
13082 if (y >= region->y && y < region->y+region->dy)
13083 continue ;
13084 for (z = 0 ; z < mri_dst->depth ; z++)
13085 {
13086 if (z >= region->z && z < region->z+region->dz)
13087 continue ;
13088 MRIsetVoxVal(mri_dst, x, y, z, 0, val) ;
13089 }
13090 }
13091 }
13092
13093 return(mri_dst) ;
13094 }
13095
13096 int
13097 MRIlabelsInNbhd(MRI *mri, int x, int y, int z, int whalf, int label)
13098 {
13099 int xi, yi, zi, xk, yk, zk, count ;
13100
13101 for (count = 0, zk = -whalf ; zk <= whalf ; zk++)
13102 {
13103 zi = mri->zi[z+zk] ;
13104 for (yk = -whalf ; yk <= whalf ; yk++)
13105 {
13106 yi = mri->yi[y+yk] ;
13107 for (xk = -whalf ; xk <= whalf ; xk++)
13108 {
13109 xi = mri->xi[x+xk] ;
13110 if (MRIvox(mri, xi, yi, zi) == label)
13111 count++;
13112 }
13113 }
13114 }
13115 return(count) ;
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.You are not allowed to attach a file to this page.
