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(&lta) ;
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 = &lta->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.
  • [get | view] (2009-01-26 22:35:32, 12.9 KB) [[attachment:fio.c]]
  • [get | view] (2009-01-26 22:35:32, 1.3 KB) [[attachment:fio.h]]
  • [get | view] (2009-01-26 22:35:32, 5.9 KB) [[attachment:load_mgh.m]]
  • [get | view] (2009-01-26 22:35:32, 9.3 KB) [[attachment:matrix.h]]
  • [get | view] (2009-01-26 22:35:32, 390.2 KB) [[attachment:mri.c]]
  • [get | view] (2009-01-26 22:35:32, 48.5 KB) [[attachment:mri.h]]
  • [get | view] (2009-01-26 22:35:32, 94.4 KB) [[attachment:mri_convert.c]]
  • [get | view] (2009-01-26 22:35:32, 14.1 KB) [[attachment:mri_info.c]]
  • [get | view] (2009-01-26 22:35:32, 395.4 KB) [[attachment:mriio.c]]
  • [get | view] (2009-01-26 22:35:32, 2.4 KB) [[attachment:save_mgh.m]]
  • [get | view] (2009-01-26 22:35:32, 2.2 KB) [[attachment:tags.c]]
  • [get | view] (2009-01-26 22:35:32, 0.9 KB) [[attachment:tags.h]]
 All files | Selected Files: delete move to page copy to page

You are not allowed to attach a file to this page.